diff --git a/DEPS b/DEPS
index 97c34429..56b1f728 100644
--- a/DEPS
+++ b/DEPS
@@ -241,7 +241,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:8a8b4f2ea65c7ff5fde8a0c522008aed78d42d9d',
+  'luci_go': 'git_revision:67696c7e93f9dbf03f7bcf7f8fafe9c5728e1ebe',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -299,7 +299,7 @@
   # 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': '2e7bee153d7841be4da26b30dc878221671408c5',
+  'skia_revision': 'a8c24d4e8c20de0c20d104c3ecf6e80e359589b8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -307,11 +307,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '8875ba4e4cd28a8a08d51f60ea8bc967cb26659d',
+  'angle_revision': 'a841f24aad0c34d938f3bce981b03fbdc2949ffd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'dca80fc3a894149ecf4d5cd4d4fe665fe0274bb3',
+  'swiftshader_revision': '0ba0b45490cd209448c5f976f41b34a746c9de5d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -370,7 +370,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': '8a26fb906ec1c2acb00aeeab74c284f8993ab867',
+  'catapult_revision': 'dc83184d4c087c501309328a8baaf301c826cfc8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -426,7 +426,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': '35df626efa2ac803d9a578594914d26dc4f27ab6',
+  'dawn_revision': '8812918fa40624e23204522b9dcc9894b229646c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -462,7 +462,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.
-  'cros_components_revision': '28731ebe744897c527854c2acdcd2f89f1496384',
+  'cros_components_revision': '5be058bb935df1cb1a4f257ae326c8942c716d0a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -764,7 +764,7 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'fb4c24b186737efcb3eefadd72ca483fa7c83e45',
+    '898f6a1fa91b8771b40b8fd1ea1b7ee60e27abc7',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1206,13 +1206,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '03b4ba83f3be6bf61d87f13ce4b73eaa8d1e2c0f',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7bf7e06945109cad2881d8a55022bdbfb2587721',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '121754bf3a97650be9bc188355ed80b667bc4bad',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '947604daf1d5797516cb1333449a657dae05bec4',
     'condition': 'checkout_src_internal',
   },
 
@@ -1470,7 +1470,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd',
 
   'src/third_party/libaom/source/libaom':
-    Var('aomedia_git') + '/aom.git' + '@' +  '70b12695e1967d9589dd15b345a039e575e8f429',
+    Var('aomedia_git') + '/aom.git' + '@' +  'ba3388ace34eab65010dc12e2c0c4c009cb39f4b',
 
   'src/third_party/libavif/src':
     Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'),
@@ -1869,7 +1869,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6c8361e98f1daba65902f5e2fc1297893ac14b67',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '419b6fcd080a7c6d50180c892f8a30581ccf9d34',
+    Var('webrtc_git') + '/src.git' + '@' + '832ce5eae6cd1d9ba8ad0b332fb3ac1c0c67c2c5',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1896,7 +1896,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': '-G9gUusEGDPsbf_GULdyJo9DYyeNBuqD8gHfdxCvIbYC',
+          'version': 'Y_kEjj2xNjDDzIdGOexbyqLLOhJCcncyCu5lC51g5AsC',
         },
       ],
       'dep_type': 'cipd',
@@ -1906,7 +1906,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'BZ0EL-KSkwCzJciJf9MbwmZAJPRhlKOp0LEYiTV6lWIC',
+          'version': 'huSAWf6X6Ecewacj_voW4JDySIedvh6nH3ePRAn3YW0C',
         },
       ],
       'dep_type': 'cipd',
@@ -1917,7 +1917,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': '0GVvuvDBNt6KJ7UzxBRUW5ShTWCliifyzaCkudNzmrkC',
+          'version': 'LNbaoDsQEefkZnHbXNqyXSyOmpBQdSXqAV0zIYsUui8C',
         },
       ],
       'dep_type': 'cipd',
@@ -1928,7 +1928,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-arm64',
-          'version': '8vKG1ZGA0f7asv5AHh_7yBxVD2h-I-yR2oY4TOjwo6kC',
+          'version': 'dImBH_u2g-eDmw3VFCZ0E70ynaXS2QWXSEvComqAx9MC',
         },
       ],
       'dep_type': 'cipd',
@@ -1939,7 +1939,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a60650a8e08a020776c5803bacff27322e1ae450',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1e809e1871e3c23d86f2298ac17e30d8670a136a',
     'condition': 'checkout_src_internal',
   },
 
@@ -1958,7 +1958,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/eche_app/app',
-        'version': 'WyNqAPOj-HR5fZBbkHIXf7YeyCvf0GpXuhdv6EqzNJsC',
+        'version': 'fcdW2L_2QSEBD_VRjl8jkq_CzEb7dVivkcS7bnsUQB8C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc
index a7a0b24..f082aa7 100644
--- a/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc
+++ b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc
@@ -16,6 +16,7 @@
 #include "components/js_injection/browser/web_message.h"
 #include "components/js_injection/browser/web_message_host.h"
 #include "components/js_injection/common/origin_matcher.h"
+#include "content/public/browser/android/message_payload.h"
 #include "content/public/browser/android/message_port_helper.h"
 
 namespace android_webview {
@@ -43,8 +44,7 @@
         content::android::CreateJavaMessagePort(std::move(message->ports));
     Java_WebMessageListenerHolder_onPostMessage(
         env, listener_,
-        base::android::ConvertUTF16ToJavaString(
-            env, absl::get<std::u16string>(message->message)),
+        content::android::ConvertWebMessagePayloadToJava(message->message),
         base::android::ConvertUTF8ToJavaString(env, origin_string_),
         is_main_frame_, jports, reply_proxy_.GetJavaPeer());
   }
diff --git a/android_webview/java/src/org/chromium/android_webview/WebMessageListener.java b/android_webview/java/src/org/chromium/android_webview/WebMessageListener.java
index 78c3f9c..ab34e18 100644
--- a/android_webview/java/src/org/chromium/android_webview/WebMessageListener.java
+++ b/android_webview/java/src/org/chromium/android_webview/WebMessageListener.java
@@ -6,6 +6,7 @@
 
 import android.net.Uri;
 
+import org.chromium.content_public.browser.MessagePayload;
 import org.chromium.content_public.browser.MessagePort;
 
 /**
@@ -16,14 +17,14 @@
 public interface WebMessageListener {
     /**
      * Receives postMessage information.
-     * @param message      The message from JavaScript.
+     * @param payload      The message payload from JavaScript.
      * @param sourceOrigin The origin of the frame where the message is from.
-     * @param isMainframe  If the message is from a main frame.
+     * @param isMainFrame  If the message is from a main frame.
      * @param jsReplyProxy Used for reply message to the injected JavaScript object.
      * @param ports        JavaScript code could post message with additional message ports. Receive
      *                     ports to establish new communication channels. Could be empty array but
      *                     won't be null.
      */
-    void onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame,
+    void onPostMessage(MessagePayload payload, Uri sourceOrigin, boolean isMainFrame,
             JsReplyProxy jsReplyProxy, MessagePort[] ports);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/WebMessageListenerHolder.java b/android_webview/java/src/org/chromium/android_webview/WebMessageListenerHolder.java
index da5d3c0..8a8254ca 100644
--- a/android_webview/java/src/org/chromium/android_webview/WebMessageListenerHolder.java
+++ b/android_webview/java/src/org/chromium/android_webview/WebMessageListenerHolder.java
@@ -10,6 +10,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.content_public.browser.MessagePayload;
 import org.chromium.content_public.browser.MessagePort;
 
 /**
@@ -25,9 +26,9 @@
     }
 
     @CalledByNative
-    public void onPostMessage(String message, String sourceOrigin, boolean isMainFrame,
+    public void onPostMessage(MessagePayload payload, String sourceOrigin, boolean isMainFrame,
             MessagePort[] ports, JsReplyProxy replyProxy) {
-        mListener.onPostMessage(message, Uri.parse(sourceOrigin), isMainFrame, replyProxy, ports);
+        mListener.onPostMessage(payload, Uri.parse(sourceOrigin), isMainFrame, replyProxy, ports);
     }
 
     public WebMessageListener getListener() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java
index b9cdec25..df60cb2 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java
@@ -24,6 +24,7 @@
 import org.chromium.android_webview.test.TestAwContentsClient.OnReceivedTitleHelper;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content_public.browser.MessagePayload;
 import org.chromium.content_public.browser.MessagePort;
@@ -55,12 +56,16 @@
             RESOURCE_PATH + "/post_message_with_ports.html";
     private static final String POST_MESSAGE_REPEAT_HTML =
             RESOURCE_PATH + "/post_message_repeat.html";
+    private static final String POST_MESSAGE_NULL_OR_UNDEFINED_HTML =
+            RESOURCE_PATH + "/post_message_null_or_undefined.html";
     private static final String POST_MESSAGE_REPLY_HTML =
             RESOURCE_PATH + "/post_message_receives_reply.html";
     private static final String POST_MESSAGE_ARRAYBUFFER_REPLY_HTML =
             RESOURCE_PATH + "/post_message_array_buffer_reply.html";
     private static final String POST_MESSAGE_ARRAYBUFFER_TITLE_HTML =
             RESOURCE_PATH + "/post_message_array_buffer_title.html";
+    private static final String POST_MESSAGE_ARRAYBUFFER_TRANSFER_HTML =
+            RESOURCE_PATH + "/post_message_array_buffer_transfer.html";
     private static final String FILE_URI = "file:///android_asset/asset_file.html";
     private static final String HELLO_WORLD_HTML = RESOURCE_PATH + "/hello_world.html";
 
@@ -80,26 +85,34 @@
         private LinkedBlockingQueue<Data> mQueue = new LinkedBlockingQueue<>();
 
         public static class Data {
-            public String mMessage;
+            private MessagePayload mPayload;
             public Uri mSourceOrigin;
             public boolean mIsMainFrame;
             public JsReplyProxy mReplyProxy;
             public MessagePort[] mPorts;
 
-            public Data(String message, Uri sourceOrigin, boolean isMainFrame,
+            public Data(MessagePayload payload, Uri sourceOrigin, boolean isMainFrame,
                     JsReplyProxy replyProxy, MessagePort[] ports) {
-                mMessage = message;
+                mPayload = payload;
                 mSourceOrigin = sourceOrigin;
                 mIsMainFrame = isMainFrame;
                 mReplyProxy = replyProxy;
                 mPorts = ports;
             }
+
+            public String getAsString() {
+                return mPayload.getAsString();
+            }
+
+            public byte[] getAsArrayBuffer() {
+                return mPayload.getAsArrayBuffer();
+            }
         }
 
         @Override
-        public void onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame,
+        public void onPostMessage(MessagePayload payload, Uri sourceOrigin, boolean isMainFrame,
                 JsReplyProxy replyProxy, MessagePort[] ports) {
-            mQueue.add(new Data(message, sourceOrigin, isMainFrame, replyProxy, ports));
+            mQueue.add(new Data(payload, sourceOrigin, isMainFrame, replyProxy, ports));
         }
 
         public Data waitForOnPostMessage() throws Exception {
@@ -133,7 +146,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -159,7 +172,7 @@
         Assert.assertNotNull(data.mSourceOrigin);
         Assert.assertEquals("null", data.mSourceOrigin.toString());
 
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -178,7 +191,7 @@
 
         final MessagePort[] ports = data.mPorts;
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertEquals(1, ports.length);
 
         // JavaScript code in the page will change the title to NEW_TITLE if postMessage on
@@ -204,7 +217,7 @@
         for (int i = 0; i < MESSAGE_COUNT; ++i) {
             TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
             assertUrlHasOrigin(url, data.mSourceOrigin);
-            Assert.assertEquals(HELLO + ":" + i, data.mMessage);
+            Assert.assertEquals(HELLO + ":" + i, data.getAsString());
         }
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
@@ -227,7 +240,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(frameUrl, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertFalse(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -262,13 +275,13 @@
         loadUrlFromPath(POST_MESSAGE_SIMPLE_HTML);
 
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
 
         mActivityTestRule.executeJavaScriptAndWaitForResult(
                 mAwContents, mContentsClient, JS_OBJECT_NAME_2 + ".postMessage('" + HELLO + "');");
 
         TestWebMessageListener.Data data2 = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data2.mMessage);
+        Assert.assertEquals(HELLO, data2.getAsString());
     }
 
     @Test
@@ -323,7 +336,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertEquals(0, data.mPorts.length);
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
@@ -351,7 +364,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertEquals(0, data.mPorts.length);
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
@@ -376,7 +389,7 @@
 
         // The iframe should have myObject injected.
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
 
@@ -395,7 +408,7 @@
         loadUrlFromPath(POST_MESSAGE_SIMPLE_HTML);
 
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
 
@@ -419,7 +432,7 @@
         loadUrlFromPath(POST_MESSAGE_SIMPLE_HTML);
 
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
 
@@ -704,21 +717,34 @@
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
     }
 
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView", "JsJavaInteraction"})
+    public void testPostArrayBufferFeatureDisabled() throws Throwable {
+        final byte[] content = (HELLO + "FromJava").getBytes(StandardCharsets.UTF_8);
+        addWebMessageListenerOnUiThread(mAwContents, JS_OBJECT_NAME, new String[] {"*"}, mListener);
+        final String url = loadUrlFromPath(POST_MESSAGE_ARRAYBUFFER_REPLY_HTML);
+        TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
+        data.mReplyProxy.postMessage(new MessagePayload(content));
+        data = mListener.waitForOnPostMessage();
+        final String errorString = data.getAsString();
+        Assert.assertTrue(errorString.contains("Error"));
+    }
+
     private void verifyPostArrayBufferWorks(byte[] content) throws Exception {
         addWebMessageListenerOnUiThread(mAwContents, JS_OBJECT_NAME, new String[] {"*"}, mListener);
         final String url = loadUrlFromPath(POST_MESSAGE_ARRAYBUFFER_REPLY_HTML);
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
         data.mReplyProxy.postMessage(new MessagePayload(content));
         data = mListener.waitForOnPostMessage();
-        // TODO(crbug.com/1374142): Add support for ArrayBuffer message from
-        // JS to Java. Right now we only check length.
-        Assert.assertEquals(content.length, Integer.parseInt(data.mMessage));
+        Assert.assertArrayEquals(content, data.getAsArrayBuffer());
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
     }
 
     @Test
     @MediumTest
     @Feature({"AndroidWebView", "JsJavaInteraction"})
+    @CommandLineFlags.Add({"enable-features=JsInjectionArrayBufferJsToBrowser"})
     public void testPostArrayBufferWorks() throws Throwable {
         final byte[] content = (HELLO + "FromJava").getBytes(StandardCharsets.UTF_8);
         verifyPostArrayBufferWorks(content);
@@ -727,6 +753,7 @@
     @Test
     @MediumTest
     @Feature({"AndroidWebView", "JsJavaInteraction"})
+    @CommandLineFlags.Add({"enable-features=JsInjectionArrayBufferJsToBrowser"})
     public void testPostEmptyArrayBuffer() throws Throwable {
         final byte[] content = new byte[0];
         verifyPostArrayBufferWorks(content);
@@ -735,12 +762,48 @@
     @Test
     @MediumTest
     @Feature({"AndroidWebView", "JsJavaInteraction"})
+    @CommandLineFlags.Add({"enable-features=JsInjectionArrayBufferJsToBrowser"})
     public void testPostLargeArrayBuffer() throws Throwable {
         final byte[] content = new byte[500 * 1000]; // 500 Kib
         new Random(42).nextBytes(content);
         verifyPostArrayBufferWorks(content);
     }
 
+    private void verifyPostNullOrUndefinedShouldThrowException() throws Throwable {
+        final byte[] content = (HELLO + "FromJava").getBytes(StandardCharsets.UTF_8);
+        addWebMessageListenerOnUiThread(mAwContents, JS_OBJECT_NAME, new String[] {"*"}, mListener);
+        final String url = loadUrlFromPath(POST_MESSAGE_NULL_OR_UNDEFINED_HTML);
+        TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
+        data.mReplyProxy.postMessage(new MessagePayload(content));
+
+        // Null
+        data = mListener.waitForOnPostMessage();
+        String errorString = data.getAsString();
+        Assert.assertTrue(errorString.contains("Error"));
+
+        // Undefined
+        data = mListener.waitForOnPostMessage();
+        errorString = data.getAsString();
+        Assert.assertTrue(errorString.contains("Error"));
+        Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView", "JsJavaInteraction"})
+    public void testPostNullOrUndefinedShouldThrowException() throws Throwable {
+        verifyPostNullOrUndefinedShouldThrowException();
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView", "JsJavaInteraction"})
+    @CommandLineFlags.Add({"enable-features=JsInjectionArrayBufferJsToBrowser"})
+    public void testPostNullOrUndefinedShouldThrowExceptionWithArrayBufferFeature()
+            throws Throwable {
+        verifyPostNullOrUndefinedShouldThrowException();
+    }
+
     @Test
     @MediumTest
     @Feature({"AndroidWebView", "JsJavaInteraction"})
@@ -775,7 +838,7 @@
                 JS_OBJECT_NAME_2 + ".postMessage('" + message + "');");
         TestWebMessageListener.Data data2 = webMessageListener2.waitForOnPostMessage();
 
-        Assert.assertEquals(message, data2.mMessage);
+        Assert.assertEquals(message, data2.getAsString());
 
         // Targeting myObject.
         data.mReplyProxy.postMessage(new MessagePayload(HELLO));
@@ -785,8 +848,8 @@
         TestWebMessageListener.Data replyData1 = mListener.waitForOnPostMessage();
         TestWebMessageListener.Data replyData2 = webMessageListener2.waitForOnPostMessage();
 
-        Assert.assertEquals("ack1" + HELLO, replyData1.mMessage);
-        Assert.assertEquals("ack2" + HELLO, replyData2.mMessage);
+        Assert.assertEquals("ack1" + HELLO, replyData1.getAsString());
+        Assert.assertEquals("ack2" + HELLO, replyData2.getAsString());
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
         Assert.assertTrue(webMessageListener2.hasNoMoreOnPostMessage());
@@ -860,8 +923,8 @@
         TestWebMessageListener.Data replyData1 = mListener.waitForOnPostMessage();
         TestWebMessageListener.Data replyData2 = mListener.waitForOnPostMessage();
 
-        Assert.assertEquals("ack1:1", replyData1.mMessage);
-        Assert.assertEquals("ack2:1", replyData2.mMessage);
+        Assert.assertEquals("ack1:1", replyData1.getAsString());
+        Assert.assertEquals("ack2:1", replyData2.getAsString());
 
         removeEventListener(
                 "listener2", JS_OBJECT_NAME, mActivityTestRule, mAwContents, mContentsClient);
@@ -871,7 +934,7 @@
 
         // listener 1 should add message again.
         TestWebMessageListener.Data replyData3 = mListener.waitForOnPostMessage();
-        Assert.assertEquals("ack1:2", replyData3.mMessage);
+        Assert.assertEquals("ack1:2", replyData3.getAsString());
 
         // Should be no more messages.
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
@@ -914,7 +977,7 @@
 
         Assert.assertEquals("null", data.mSourceOrigin.toString());
 
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -1021,7 +1084,7 @@
 
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
 
         webServer.shutdown();
@@ -1083,7 +1146,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -1104,12 +1167,12 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO + "1", data.mMessage);
+        Assert.assertEquals(HELLO + "1", data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
         TestWebMessageListener.Data data2 = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO, data2.mMessage);
+        Assert.assertEquals(HELLO, data2.getAsString());
         Assert.assertTrue(data2.mIsMainFrame);
 
         Assert.assertTrue(mListener.hasNoMoreOnPostMessage());
@@ -1131,7 +1194,7 @@
             TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
             assertUrlHasOrigin(url, data.mSourceOrigin);
-            Assert.assertEquals(HELLO + Integer.toString(i), data.mMessage);
+            Assert.assertEquals(HELLO + Integer.toString(i), data.getAsString());
             Assert.assertTrue(data.mIsMainFrame);
             Assert.assertEquals(0, data.mPorts.length);
         }
@@ -1154,7 +1217,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO + "0", data.mMessage);
+        Assert.assertEquals(HELLO + "0", data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -1164,7 +1227,7 @@
         for (int i = 0; i < 2; ++i) {
             TestWebMessageListener.Data data2 = mListener.waitForOnPostMessage();
 
-            Assert.assertEquals(HELLO + Integer.toString(i), data2.mMessage);
+            Assert.assertEquals(HELLO + Integer.toString(i), data2.getAsString());
             Assert.assertTrue(data2.mIsMainFrame);
         }
 
@@ -1248,7 +1311,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(frameUrl, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertFalse(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
@@ -1276,7 +1339,7 @@
             TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
             assertUrlHasOrigin(url, data.mSourceOrigin);
-            Assert.assertEquals(HELLO + Integer.toString(i), data.mMessage);
+            Assert.assertEquals(HELLO + Integer.toString(i), data.getAsString());
         }
 
         TestThreadUtils.runOnUiThreadBlocking(() -> handlers[0].remove());
@@ -1284,7 +1347,7 @@
         loadUrlFromPath(HELLO_WORLD_HTML);
 
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
-        Assert.assertEquals(HELLO + "1", data.mMessage);
+        Assert.assertEquals(HELLO + "1", data.getAsString());
 
         TestThreadUtils.runOnUiThreadBlocking(() -> handlers[1].remove());
         // Load the page again.
@@ -1308,7 +1371,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         assertUrlHasOrigin(url, data.mSourceOrigin);
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
 
         // Remove twice, the second time should take no effect.
         TestThreadUtils.runOnUiThreadBlocking(() -> handler.remove());
@@ -1340,7 +1403,7 @@
         TestWebMessageListener.Data data = mListener.waitForOnPostMessage();
 
         Assert.assertEquals("http://www.google.com", data.mSourceOrigin.toString());
-        Assert.assertEquals(HELLO, data.mMessage);
+        Assert.assertEquals(HELLO, data.getAsString());
         Assert.assertTrue(data.mIsMainFrame);
         Assert.assertEquals(0, data.mPorts.length);
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
index 5de9d8b..62c20d9 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -402,9 +402,9 @@
         }
 
         @Override
-        public void onPostMessage(String message, Uri sourceOrigin, boolean isMainFrame,
+        public void onPostMessage(MessagePayload payload, Uri sourceOrigin, boolean isMainFrame,
                 JsReplyProxy replyProxy, MessagePort[] ports) {
-            mQueue.add(new Data(message, isMainFrame, replyProxy));
+            mQueue.add(new Data(payload.getAsString(), isMainFrame, replyProxy));
         }
 
         public Data waitForOnPostMessage() throws Exception {
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebMessageListenerAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebMessageListenerAdapter.java
index b4711932..c0c0ad59 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebMessageListenerAdapter.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebMessageListenerAdapter.java
@@ -11,6 +11,7 @@
 import org.chromium.android_webview.WebMessageListener;
 import org.chromium.base.Log;
 import org.chromium.content_public.browser.MessagePayload;
+import org.chromium.content_public.browser.MessagePayloadType;
 import org.chromium.content_public.browser.MessagePort;
 import org.chromium.support_lib_boundary.WebMessageListenerBoundaryInterface;
 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
@@ -45,7 +46,7 @@
     }
 
     @Override
-    public void onPostMessage(final String message, final Uri sourceOrigin,
+    public void onPostMessage(final MessagePayload payload, final Uri sourceOrigin,
             final boolean isMainFrame, final JsReplyProxy replyProxy, final MessagePort[] ports) {
         if (!BoundaryInterfaceReflectionUtil.containsFeature(
                     mSupportedFeatures, Features.WEB_MESSAGE_LISTENER)) {
@@ -53,9 +54,14 @@
             return;
         }
 
+        // TODO(crbug.com/1374142): Add array buffer type support.
+        if (payload.getType() != MessagePayloadType.STRING) {
+            return;
+        }
+
         mImpl.onPostMessage(mWebView,
                 BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
-                        new SupportLibWebMessageAdapter(new MessagePayload(message), ports)),
+                        new SupportLibWebMessageAdapter(payload, ports)),
                 sourceOrigin, isMainFrame,
                 BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
                         new SupportLibJsReplyProxyAdapter(replyProxy)));
diff --git a/android_webview/test/data/post_message_array_buffer_reply.html b/android_webview/test/data/post_message_array_buffer_reply.html
index 3464067..6c30d24 100644
--- a/android_webview/test/data/post_message_array_buffer_reply.html
+++ b/android_webview/test/data/post_message_array_buffer_reply.html
@@ -4,7 +4,12 @@
   <title>reply</title>
   <script>
     myObject.onmessage = function (event) {
-      myObject.postMessage(event.data.byteLength.toString());
+      try {
+        myObject.postMessage(event.data);
+      } catch (e) {
+        // ArrayBuffer may not supported, echo error back.
+        myObject.postMessage(e.toString());
+      }
     };
     myObject.postMessage("Hello");
   </script>
diff --git a/android_webview/test/data/post_message_null_or_undefined.html b/android_webview/test/data/post_message_null_or_undefined.html
new file mode 100644
index 0000000..97033cb8
--- /dev/null
+++ b/android_webview/test/data/post_message_null_or_undefined.html
@@ -0,0 +1,26 @@
+<html>
+
+<head>
+  <title>reply</title>
+  <script>
+    myObject.onmessage = function (event) {
+      try {
+        myObject.postMessage(null);
+      } catch (e) {
+        myObject.postMessage(e.toString());
+      }
+      try {
+        myObject.postMessage(undefined);
+      } catch (e) {
+        myObject.postMessage(e.toString());
+      }
+    };
+    myObject.postMessage("Hello");
+  </script>
+</head>
+
+<body>
+  <div>post message waiting for reply</div>
+</body>
+
+</html>
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 82a3558e..1320fd61b 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1737,10 +1737,9 @@
     "system/privacy/privacy_indicators_controller.h",
     "system/privacy/privacy_indicators_tray_item_view.cc",
     "system/privacy/privacy_indicators_tray_item_view.h",
-    "system/privacy/screen_capture_observer.h",
     "system/privacy/screen_security_controller.cc",
     "system/privacy/screen_security_controller.h",
-    "system/privacy/screen_share_observer.h",
+    "system/privacy/screen_security_observer.h",
     "system/privacy/screen_switch_check_controller.cc",
     "system/privacy/screen_switch_check_controller.h",
     "system/privacy_hub/camera_privacy_switch_controller.cc",
@@ -2347,8 +2346,6 @@
     "wm/tablet_mode/internal_input_devices_event_blocker.h",
     "wm/tablet_mode/scoped_skip_user_session_blocked_check.cc",
     "wm/tablet_mode/scoped_skip_user_session_blocked_check.h",
-    "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc",
-    "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h",
     "wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.cc",
     "wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h",
     "wm/tablet_mode/tablet_mode_controller.cc",
@@ -2361,14 +2358,8 @@
     "wm/tablet_mode/tablet_mode_multitask_menu_event_handler.h",
     "wm/tablet_mode/tablet_mode_toggle_fullscreen_event_handler.cc",
     "wm/tablet_mode/tablet_mode_toggle_fullscreen_event_handler.h",
-    "wm/tablet_mode/tablet_mode_window_drag_delegate.cc",
-    "wm/tablet_mode/tablet_mode_window_drag_delegate.h",
-    "wm/tablet_mode/tablet_mode_window_drag_metrics.cc",
-    "wm/tablet_mode/tablet_mode_window_drag_metrics.h",
     "wm/tablet_mode/tablet_mode_window_manager.cc",
     "wm/tablet_mode/tablet_mode_window_manager.h",
-    "wm/tablet_mode/tablet_mode_window_resizer.cc",
-    "wm/tablet_mode/tablet_mode_window_resizer.h",
     "wm/tablet_mode/tablet_mode_window_state.cc",
     "wm/tablet_mode/tablet_mode_window_state.h",
     "wm/toplevel_window_event_handler.cc",
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.cc b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
index 5bff9234..adce9ba 100644
--- a/ash/ambient/backdrop/ambient_backend_controller_impl.cc
+++ b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
@@ -393,9 +393,9 @@
 }
 
 void AmbientBackendControllerImpl::FetchPreviewImages(
+    const gfx::Size& preview_size,
     OnPreviewImagesFetchedCallback callback) {
   constexpr int num_topics = 3;
-  const gfx::Size preview_size = gfx::Size(360, 130);
   OnScreenUpdateInfoFetchedCallback combined_callback =
       base::BindOnce(&ToPreviewUrls).Then(std::move(callback));
   Shell::Get()->ambient_controller()->RequestAccessToken(base::BindOnce(
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.h b/ash/ambient/backdrop/ambient_backend_controller_impl.h
index 252e173e..8fb6b6b 100644
--- a/ash/ambient/backdrop/ambient_backend_controller_impl.h
+++ b/ash/ambient/backdrop/ambient_backend_controller_impl.h
@@ -33,7 +33,8 @@
       bool show_pair_personal_portraits,
       const gfx::Size& screen_size,
       OnScreenUpdateInfoFetchedCallback callback) override;
-  void FetchPreviewImages(OnPreviewImagesFetchedCallback callback) override;
+  void FetchPreviewImages(const gfx::Size& preview_size,
+                          OnPreviewImagesFetchedCallback callback) override;
   void GetSettings(GetSettingsCallback callback) override;
   void UpdateSettings(const AmbientSettings& settings,
                       UpdateSettingsCallback callback) override;
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 0462c71..e628e41 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -2600,13 +2600,19 @@
         Continue
       </message>
 
-      <!-- Status tray screen capture strings. -->
-      <message name="IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_STOP" desc="label used for screen capture stop button">
+      <!-- Status tray screen security strings. -->
+      <message name="IDS_ASH_STATUS_TRAY_SCREEN_ACCESS_STOP" desc="label used for screen access or screen sharing stop button">
         Stop
       </message>
       <message name="IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_CHANGE_SOURCE" desc="label used for screen capture change source button">
         Change source
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_TITLE" desc="The title for screen sharing notification">
+        You're sharing your screen
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED" desc="label for screen sharing notification">
+        Sharing control of your screen via Remote Assistance.
+      </message>
 
       <!-- Status tray media recording state strings. -->
       <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO" desc="label used to indicate that the microphone is used by a background user">
@@ -2619,20 +2625,6 @@
         Camera and microphone are in use.
       </message>
 
-      <!-- Status tray screen share strings. -->
-      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_TITLE" desc="The title for screen sharing notification">
-        You're sharing your screen
-      </message>
-      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_STOP" desc="label used for screen sharing stop button">
-        Stop
-      </message>
-      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED" desc="label for screen sharing notification">
-        Sharing control of your screen via Remote Assistance.
-      </message>
-      <message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED_NAME" desc="label for screen sharing notification with name">
-        Sharing control of your screen with <ph name="HELPER_NAME">$1<ex>Walder Frey</ex></ph> via Remote Assistance.
-      </message>
-
       <!-- Status tray audio strings. -->
       <message name="IDS_ASH_STATUS_TRAY_AUDIO_FRONT_MIC" desc="label used for front microphone">
         Front microphone
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_SCREEN_ACCESS_STOP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_SCREEN_ACCESS_STOP.png.sha1
new file mode 100644
index 0000000..55c46bc
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_SCREEN_ACCESS_STOP.png.sha1
@@ -0,0 +1 @@
+4c79ebaed80c00cd17b26da8ceddf718c924665a
\ No newline at end of file
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 62f9a63..52f70e1 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -3273,20 +3273,5 @@
          base::FeatureList::IsEnabled(kCryptAuthV2DeviceSync);
 }
 
-namespace {
-
-// The boolean flag indicating if "WebUITabStrip" feature is enabled in Chrome.
-bool g_webui_tab_strip_enabled = false;
-
-}  // namespace
-
-void SetWebUITabStripEnabled(bool enabled) {
-  g_webui_tab_strip_enabled = enabled;
-}
-
-bool IsWebUITabStripEnabled() {
-  return g_webui_tab_strip_enabled;
-}
-
 }  // namespace features
 }  // namespace ash
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 27d9c63..8e9b1dd5 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -901,11 +901,6 @@
 
 // Keep alphabetized.
 
-// These two functions are supposed to be temporary functions to set or get
-// whether "WebUITabStrip" feature is enabled from Chrome.
-COMPONENT_EXPORT(ASH_CONSTANTS) void SetWebUITabStripEnabled(bool enabled);
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWebUITabStripEnabled();
-
 }  // namespace ash::features
 
 #endif  // ASH_CONSTANTS_ASH_FEATURES_H_
diff --git a/ash/constants/ash_pref_names.cc b/ash/constants/ash_pref_names.cc
index b0a75eb..27d1c48 100644
--- a/ash/constants/ash_pref_names.cc
+++ b/ash/constants/ash_pref_names.cc
@@ -1398,6 +1398,19 @@
 const char kTouchpadHapticClickSensitivity[] =
     "settings.touchpad.haptic_click_sensitivity";
 
+// A integer pref for pointing stick sensitivity.
+const char kPointingStickSensitivity[] = "settings.pointing_stick.sensitivity";
+
+// A boolean pref set to true if primary pointing stick button is the left
+// button.
+const char kPrimaryPointingStickButtonRight[] =
+    "settings.pointing_stick.primary_right";
+
+// A boolean pref set to true if pointing stick acceleration is enabled. When
+// disabled only simple linear scaling is applied based on sensitivity.
+const char kPointingStickAcceleration[] =
+    "settings.pointing_stick.acceleration";
+
 // NOTE: New prefs should start with the "ash." prefix. Existing prefs moved
 // into this file should not be renamed, since they may be synced.
 
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h
index fdedb7be..4d5517af 100644
--- a/ash/constants/ash_pref_names.h
+++ b/ash/constants/ash_pref_names.h
@@ -657,6 +657,14 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kTouchpadHapticClickSensitivity[];
 
+COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const char kPointingStickSensitivity[];
+
+COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const char kPrimaryPointingStickButtonRight[];
+
+COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const char kPointingStickAcceleration[];
 }  // namespace prefs
 }  // namespace ash
 
diff --git a/ash/drag_drop/tab_drag_drop_delegate_unittest.cc b/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
index 88caf61..da9c149 100644
--- a/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
+++ b/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
@@ -74,7 +74,6 @@
 class TabDragDropDelegateTest : public AshTestBase {
  public:
   TabDragDropDelegateTest() {
-    ash::features::SetWebUITabStripEnabled(true);
     scoped_feature_list_.InitAndEnableFeature(
         ash::features::kWebUITabStripTabDragIntegration);
   }
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index 7a0067a..ad22fd3 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -569,13 +569,11 @@
 class FrameSizeButtonNonResizableTest : public FrameSizeButtonTest {
  public:
   FrameSizeButtonNonResizableTest() : FrameSizeButtonTest(false) {}
-
   FrameSizeButtonNonResizableTest(const FrameSizeButtonNonResizableTest&) =
       delete;
   FrameSizeButtonNonResizableTest& operator=(
       const FrameSizeButtonNonResizableTest&) = delete;
-
-  ~FrameSizeButtonNonResizableTest() override {}
+  ~FrameSizeButtonNonResizableTest() override = default;
 };
 
 }  // namespace
@@ -661,13 +659,20 @@
 // setup.
 class MultitaskMenuTest : public FrameSizeButtonTest {
  public:
-  MultitaskMenuTest() = default;
-
+  MultitaskMenuTest()
+      : scoped_feature_list_(chromeos::wm::features::kWindowLayoutMenu) {}
   MultitaskMenuTest(const MultitaskMenuTest&) = delete;
   MultitaskMenuTest& operator=(const MultitaskMenuTest&) = delete;
-
   ~MultitaskMenuTest() override = default;
 
+  MultitaskMenu* GetMultitaskMenu() {
+    views::Widget* widget = static_cast<FrameSizeButton*>(size_button())
+                                ->multitask_menu_widget_for_testing();
+    return widget ? static_cast<MultitaskMenu*>(
+                        widget->widget_delegate()->AsDialogDelegate())
+                  : nullptr;
+  }
+
   void ShowMultitaskMenu() {
     DCHECK(size_button());
 
@@ -676,30 +681,11 @@
         std::string(kMultitaskMenuBubbleWidgetName));
     static_cast<FrameSizeButton*>(size_button())
         ->ShowMultitaskMenu(MultitaskMenuEntryType::kFrameSizeButtonHover);
-    views::WidgetDelegate* delegate =
-        waiter.WaitIfNeededAndGet()->widget_delegate();
-    multitask_menu_ = static_cast<MultitaskMenu*>(delegate->AsDialogDelegate());
-
-    // Note that this is sync because we use `views::Widget::CloseNow()` in
-    // `MultitaskMenu.`
-    delegate->RegisterWindowClosingCallback(base::BindOnce(
-        &MultitaskMenuTest::OnMultitaskMenuClosed, base::Unretained(this)));
+    waiter.WaitIfNeededAndGet();
   }
 
-  void OnMultitaskMenuClosed() { multitask_menu_ = nullptr; }
-
-  void SetUp() override {
-    // Ensure float feature is enabled.
-    scoped_feature_list_.InitWithFeatures(
-        {chromeos::wm::features::kWindowLayoutMenu}, {});
-    FrameSizeButtonTest::SetUp();
-  }
-
-  MultitaskMenu* multitask_menu() { return multitask_menu_; }
-
- protected:
+ private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  MultitaskMenu* multitask_menu_ = nullptr;
 };
 
 // Test Float Button Functionality.
@@ -709,7 +695,7 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
   ShowMultitaskMenu();
   generator->MoveMouseTo(CenterPointInScreen(
-      multitask_menu()->multitask_menu_view()->float_button_for_testing()));
+      GetMultitaskMenu()->multitask_menu_view()->float_button_for_testing()));
   generator->ClickLeftButton();
   EXPECT_TRUE(window_state()->IsFloated());
   histogram_tester.ExpectBucketCount(
@@ -723,7 +709,7 @@
   EXPECT_TRUE(window_state()->IsNormalStateType());
   ui::test::EventGenerator* generator = GetEventGenerator();
   ShowMultitaskMenu();
-  generator->MoveMouseTo(multitask_menu()
+  generator->MoveMouseTo(GetMultitaskMenu()
                              ->multitask_menu_view()
                              ->half_button_for_testing()
                              ->GetBoundsInScreen()
@@ -743,7 +729,7 @@
   base::i18n::SetRTLForTesting(true);
 
   ShowMultitaskMenu();
-  GetEventGenerator()->MoveMouseTo(multitask_menu()
+  GetEventGenerator()->MoveMouseTo(GetMultitaskMenu()
                                        ->multitask_menu_view()
                                        ->half_button_for_testing()
                                        ->GetBoundsInScreen()
@@ -771,7 +757,7 @@
   // Click on the left side of the half button. It should be in secondary
   // snapped state, because in this orientation secondary snapped is actually
   // physically on the left side.
-  GetEventGenerator()->MoveMouseToInHost(multitask_menu()
+  GetEventGenerator()->MoveMouseToInHost(GetMultitaskMenu()
                                              ->multitask_menu_view()
                                              ->half_button_for_testing()
                                              ->GetBoundsInScreen()
@@ -799,7 +785,7 @@
 
   // Snap to primary with 0.67f screen ratio.
   ShowMultitaskMenu();
-  generator->MoveMouseTo(multitask_menu()
+  generator->MoveMouseTo(GetMultitaskMenu()
                              ->multitask_menu_view()
                              ->partial_button()
                              ->GetBoundsInScreen()
@@ -817,7 +803,7 @@
 
   // Snap to secondary with 0.33f screen ratio.
   ShowMultitaskMenu();
-  gfx::Rect partial_bounds(multitask_menu()
+  gfx::Rect partial_bounds(GetMultitaskMenu()
                                ->multitask_menu_view()
                                ->partial_button()
                                ->GetBoundsInScreen());
@@ -844,7 +830,7 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
   ShowMultitaskMenu();
   generator->MoveMouseTo(CenterPointInScreen(
-      multitask_menu()->multitask_menu_view()->full_button_for_testing()));
+      GetMultitaskMenu()->multitask_menu_view()->full_button_for_testing()));
   generator->ClickLeftButton();
   EXPECT_TRUE(window_state()->IsFullscreen());
   histogram_tester.ExpectBucketCount(
@@ -854,11 +840,13 @@
 
 TEST_F(MultitaskMenuTest, MultitaskMenuClosesOnTabletMode) {
   ShowMultitaskMenu();
-  ASSERT_TRUE(multitask_menu());
-  ASSERT_TRUE(multitask_menu()->GetWidget());
+  ASSERT_TRUE(GetMultitaskMenu());
 
-  ash::TabletMode::Get()->SetEnabledForTest(true);
-  EXPECT_FALSE(multitask_menu()->IsBubbleShown());
+  TabletMode::Get()->SetEnabledForTest(true);
+
+  // Closing the widget is done on a post task.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(GetMultitaskMenu());
 }
 
 // Verifies that long touch on the size button shows the multitask menu.
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 09b017c6..e145300c 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -511,6 +511,8 @@
     "test/in_process_image_decoder.h",
     "test/mock_in_session_auth_token_provider.cc",
     "test/mock_in_session_auth_token_provider.h",
+    "test/mock_input_device_settings_controller.cc",
+    "test/mock_input_device_settings_controller.h",
     "test/mock_projector_client.cc",
     "test/mock_projector_client.h",
     "test/mock_projector_controller.cc",
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.h b/ash/public/cpp/ambient/ambient_backend_controller.h
index 88e958e..3c54c48 100644
--- a/ash/public/cpp/ambient/ambient_backend_controller.h
+++ b/ash/public/cpp/ambient/ambient_backend_controller.h
@@ -131,7 +131,8 @@
       const gfx::Size& screen_size,
       OnScreenUpdateInfoFetchedCallback callback) = 0;
 
-  virtual void FetchPreviewImages(OnPreviewImagesFetchedCallback callback) = 0;
+  virtual void FetchPreviewImages(const gfx::Size& preview_size,
+                                  OnPreviewImagesFetchedCallback callback) = 0;
 
   // Get ambient mode Settings from server.
   virtual void GetSettings(GetSettingsCallback callback) = 0;
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
index cdcbcfeb..7089ab89 100644
--- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
+++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
@@ -15,6 +15,7 @@
 #include "base/functional/callback.h"
 #include "base/task/sequenced_task_runner.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
 namespace ash {
@@ -129,6 +130,7 @@
 }
 
 void FakeAmbientBackendControllerImpl::FetchPreviewImages(
+    const gfx::Size& preview_size,
     OnPreviewImagesFetchedCallback callback) {
   std::vector<GURL> urls = {GURL(kFakeUrl)};
   // Pretend to respond asynchronously.
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
index a9efe51..cb8009c 100644
--- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
+++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h
@@ -31,7 +31,8 @@
       bool show_pair_personal_portraits,
       const gfx::Size& screen_size,
       OnScreenUpdateInfoFetchedCallback callback) override;
-  void FetchPreviewImages(OnPreviewImagesFetchedCallback callback) override;
+  void FetchPreviewImages(const gfx::Size& preview_size,
+                          OnPreviewImagesFetchedCallback callback) override;
   void GetSettings(GetSettingsCallback callback) override;
   void UpdateSettings(const AmbientSettings& settings,
                       UpdateSettingsCallback callback) override;
diff --git a/ash/public/cpp/test/mock_input_device_settings_controller.cc b/ash/public/cpp/test/mock_input_device_settings_controller.cc
new file mode 100644
index 0000000..5ba4104
--- /dev/null
+++ b/ash/public/cpp/test/mock_input_device_settings_controller.cc
@@ -0,0 +1,15 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/test/mock_input_device_settings_controller.h"
+
+namespace ash {
+
+MockInputDeviceSettingsController::MockInputDeviceSettingsController() =
+    default;
+
+MockInputDeviceSettingsController::~MockInputDeviceSettingsController() =
+    default;
+
+}  // namespace ash
diff --git a/ash/public/cpp/test/mock_input_device_settings_controller.h b/ash/public/cpp/test/mock_input_device_settings_controller.h
new file mode 100644
index 0000000..c2189d85
--- /dev/null
+++ b/ash/public/cpp/test/mock_input_device_settings_controller.h
@@ -0,0 +1,65 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_TEST_MOCK_INPUT_DEVICE_SETTINGS_CONTROLLER_H_
+#define ASH_PUBLIC_CPP_TEST_MOCK_INPUT_DEVICE_SETTINGS_CONTROLLER_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/input_device_settings_controller.h"
+#include "ash/public/mojom/input_device_settings.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace ash {
+
+class ASH_PUBLIC_EXPORT MockInputDeviceSettingsController
+    : public InputDeviceSettingsController {
+ public:
+  MockInputDeviceSettingsController();
+  MockInputDeviceSettingsController(const MockInputDeviceSettingsController&) =
+      delete;
+  MockInputDeviceSettingsController& operator=(
+      const MockInputDeviceSettingsController&) = delete;
+  ~MockInputDeviceSettingsController() override;
+
+  // InputDeviceSettingsController:
+  MOCK_METHOD(std::vector<mojom::KeyboardPtr>,
+              GetConnectedKeyboards,
+              (),
+              (override));
+  MOCK_METHOD(std::vector<mojom::TouchpadPtr>,
+              GetConnectedTouchpads,
+              (),
+              (override));
+  MOCK_METHOD(std::vector<mojom::MousePtr>, GetConnectedMice, (), (override));
+  MOCK_METHOD(std::vector<mojom::PointingStickPtr>,
+              GetConnectedPointingSticks,
+              (),
+              (override));
+  MOCK_METHOD(const mojom::KeyboardSettings*,
+              GetKeyboardSettings,
+              (DeviceId id),
+              (override));
+  MOCK_METHOD(const mojom::MouseSettings*,
+              GetMouseSettings,
+              (DeviceId id),
+              (override));
+  MOCK_METHOD(const mojom::TouchpadSettings*,
+              GetTouchpadSettings,
+              (DeviceId id),
+              (override));
+  MOCK_METHOD(const mojom::PointingStickSettings*,
+              GetPointingStickSettings,
+              (DeviceId id),
+              (override));
+  MOCK_METHOD(void,
+              SetKeyboardSettings,
+              (DeviceId id, const mojom::KeyboardSettings& settings),
+              (override));
+  MOCK_METHOD(void, AddObserver, (Observer * observer), (override));
+  MOCK_METHOD(void, RemoveObserver, (Observer * observer), (override));
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_TEST_MOCK_INPUT_DEVICE_SETTINGS_CONTROLLER_H_
diff --git a/ash/session/session_controller_impl_unittest.cc b/ash/session/session_controller_impl_unittest.cc
index 3193fdfe..b69b46f 100644
--- a/ash/session/session_controller_impl_unittest.cc
+++ b/ash/session/session_controller_impl_unittest.cc
@@ -655,7 +655,7 @@
   // Accessing the capture session functionality.
   // Simulates a screen capture session start.
   void StartCaptureSession() {
-    Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+    Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
         base::BindRepeating(&CanSwitchUserTest::StopCaptureCallback,
                             base::Unretained(this)),
         base::RepeatingClosure(), std::u16string());
@@ -663,7 +663,7 @@
 
   // The callback which gets called when the screen capture gets stopped.
   void StopCaptureSession() {
-    Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+    Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
   }
 
   // Simulates a screen capture session stop.
@@ -672,15 +672,14 @@
   // Accessing the share session functionality.
   // Simulate a Screen share session start.
   void StartShareSession() {
-    Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
+    Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
         base::BindRepeating(&CanSwitchUserTest::StopShareCallback,
-                            base::Unretained(this)),
-        std::u16string());
+                            base::Unretained(this)));
   }
 
   // Simulates a screen share session stop.
   void StopShareSession() {
-    Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+    Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
   }
 
   // The callback which gets called when the screen share gets stopped.
diff --git a/ash/style/knob_switch.cc b/ash/style/knob_switch.cc
index ff439ec0..f77e9675 100644
--- a/ash/style/knob_switch.cc
+++ b/ash/style/knob_switch.cc
@@ -122,6 +122,10 @@
   knob_->SetPosition(gfx::Point(knob_x, knob_y));
 }
 
+int KnobSwitch::GetHeightForWidth(int w) const {
+  return kSwitchHeight;
+}
+
 void KnobSwitch::StateChanged(ButtonState old_state) {
   if (GetState() == ButtonState::STATE_DISABLED) {
     track_->SetEnabled(false);
diff --git a/ash/style/knob_switch.h b/ash/style/knob_switch.h
index 1d77f01b..5a6c102 100644
--- a/ash/style/knob_switch.h
+++ b/ash/style/knob_switch.h
@@ -27,6 +27,7 @@
 
   // views::View:
   void Layout() override;
+  int GetHeightForWidth(int w) const override;
 
  private:
   // views::Button:
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.cc b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
index e94bf15..4f6d8970 100644
--- a/ash/system/input_device_settings/input_device_settings_controller_impl.cc
+++ b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
@@ -17,6 +17,9 @@
 #include "ash/system/input_device_settings/input_device_settings_pref_names.h"
 #include "ash/system/input_device_settings/input_device_settings_utils.h"
 #include "ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h"
+#include "ash/system/input_device_settings/pref_handlers/mouse_pref_handler_impl.h"
+#include "ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h"
+#include "ash/system/input_device_settings/pref_handlers/touchpad_pref_handler_impl.h"
 #include "base/containers/contains.h"
 #include "base/containers/flat_map.h"
 #include "base/functional/bind.h"
@@ -67,13 +70,23 @@
 }  // namespace
 
 InputDeviceSettingsControllerImpl::InputDeviceSettingsControllerImpl()
-    : keyboard_pref_handler_(std::make_unique<KeyboardPrefHandlerImpl>()) {
+    : keyboard_pref_handler_(std::make_unique<KeyboardPrefHandlerImpl>()),
+      touchpad_pref_handler_(std::make_unique<TouchpadPrefHandlerImpl>()),
+      mouse_pref_handler_(std::make_unique<MousePrefHandlerImpl>()),
+      pointing_stick_pref_handler_(
+          std::make_unique<PointingStickPrefHandlerImpl>()) {
   Init();
 }
 
 InputDeviceSettingsControllerImpl::InputDeviceSettingsControllerImpl(
-    std::unique_ptr<KeyboardPrefHandler> keyboard_pref_handler)
-    : keyboard_pref_handler_(std::move(keyboard_pref_handler)) {
+    std::unique_ptr<KeyboardPrefHandler> keyboard_pref_handler,
+    std::unique_ptr<TouchpadPrefHandler> touchpad_pref_handler,
+    std::unique_ptr<MousePrefHandler> mouse_pref_handler,
+    std::unique_ptr<PointingStickPrefHandler> pointing_stick_pref_handler)
+    : keyboard_pref_handler_(std::move(keyboard_pref_handler)),
+      touchpad_pref_handler_(std::move(touchpad_pref_handler)),
+      mouse_pref_handler_(std::move(mouse_pref_handler)),
+      pointing_stick_pref_handler_(std::move(pointing_stick_pref_handler)) {
   Init();
 }
 
@@ -324,6 +337,10 @@
     std::vector<DeviceId> touchpad_ids_to_remove) {
   for (const auto& touchpad : touchpads_to_add) {
     auto mojom_touchpad = BuildMojomTouchpad(touchpad);
+    if (active_pref_service_) {
+      touchpad_pref_handler_->InitializeTouchpadSettings(active_pref_service_,
+                                                         mojom_touchpad.get());
+    }
     touchpads_.insert_or_assign(touchpad.id, std::move(mojom_touchpad));
     DispatchTouchpadConnected(touchpad.id);
   }
@@ -339,6 +356,10 @@
     std::vector<DeviceId> mouse_ids_to_remove) {
   for (const auto& mouse : mice_to_add) {
     auto mojom_mouse = BuildMojomMouse(mouse);
+    if (active_pref_service_) {
+      mouse_pref_handler_->InitializeMouseSettings(active_pref_service_,
+                                                   mojom_mouse.get());
+    }
     mice_.insert_or_assign(mouse.id, std::move(mojom_mouse));
     DispatchMouseConnected(mouse.id);
   }
@@ -354,6 +375,10 @@
     std::vector<DeviceId> pointing_stick_ids_to_remove) {
   for (const auto& pointing_stick : pointing_sticks_to_add) {
     auto mojom_pointing_stick = BuildMojomPointingStick(pointing_stick);
+    if (active_pref_service_) {
+      pointing_stick_pref_handler_->InitializePointingStickSettings(
+          active_pref_service_, mojom_pointing_stick.get());
+    }
     pointing_sticks_.insert_or_assign(pointing_stick.id,
                                       std::move(mojom_pointing_stick));
     DispatchPointingStickConnected(pointing_stick.id);
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.h b/ash/system/input_device_settings/input_device_settings_controller_impl.h
index 21cbbad..a349a03 100644
--- a/ash/system/input_device_settings/input_device_settings_controller_impl.h
+++ b/ash/system/input_device_settings/input_device_settings_controller_impl.h
@@ -13,6 +13,9 @@
 #include "ash/public/mojom/input_device_settings.mojom.h"
 #include "ash/system/input_device_settings/input_device_notifier.h"
 #include "ash/system/input_device_settings/pref_handlers/keyboard_pref_handler.h"
+#include "ash/system/input_device_settings/pref_handlers/mouse_pref_handler.h"
+#include "ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler.h"
+#include "ash/system/input_device_settings/pref_handlers/touchpad_pref_handler.h"
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
@@ -28,8 +31,11 @@
       public SessionObserver {
  public:
   InputDeviceSettingsControllerImpl();
-  explicit InputDeviceSettingsControllerImpl(
-      std::unique_ptr<KeyboardPrefHandler> keyboard_pref_handler);
+  InputDeviceSettingsControllerImpl(
+      std::unique_ptr<KeyboardPrefHandler> keyboard_pref_handler,
+      std::unique_ptr<TouchpadPrefHandler> touchpad_pref_handler,
+      std::unique_ptr<MousePrefHandler> mouse_pref_handler,
+      std::unique_ptr<PointingStickPrefHandler> pointing_stick_pref_handler);
   InputDeviceSettingsControllerImpl(const InputDeviceSettingsControllerImpl&) =
       delete;
   InputDeviceSettingsControllerImpl& operator=(
@@ -87,6 +93,9 @@
   base::ObserverList<InputDeviceSettingsController::Observer> observers_;
 
   std::unique_ptr<KeyboardPrefHandler> keyboard_pref_handler_;
+  std::unique_ptr<TouchpadPrefHandler> touchpad_pref_handler_;
+  std::unique_ptr<MousePrefHandler> mouse_pref_handler_;
+  std::unique_ptr<PointingStickPrefHandler> pointing_stick_pref_handler_;
 
   base::flat_map<DeviceId, mojom::KeyboardPtr> keyboards_;
   base::flat_map<DeviceId, mojom::TouchpadPtr> touchpads_;
diff --git a/ash/system/input_device_settings/pref_handlers/mouse_pref_handler.h b/ash/system/input_device_settings/pref_handlers/mouse_pref_handler.h
index 9293a11..c75ef06 100644
--- a/ash/system/input_device_settings/pref_handlers/mouse_pref_handler.h
+++ b/ash/system/input_device_settings/pref_handlers/mouse_pref_handler.h
@@ -15,6 +15,8 @@
 // Handles reading and updating prefs that store mouse settings.
 class ASH_EXPORT MousePrefHandler {
  public:
+  virtual ~MousePrefHandler() = default;
+
   // Initializes device settings in prefs and update the `settings` member of
   // the `mojom::Mouse` object.
   virtual void InitializeMouseSettings(PrefService* pref_service,
@@ -24,9 +26,6 @@
   // `mouse.settings`.
   virtual void UpdateMouseSettings(PrefService* pref_service,
                                    const mojom::Mouse& mouse) = 0;
-
- protected:
-  virtual ~MousePrefHandler() = default;
 };
 
 }  // namespace ash
diff --git a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler.h b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler.h
index 2c77a7fc..2a443e8c 100644
--- a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler.h
+++ b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler.h
@@ -15,6 +15,8 @@
 // Handles reading and updating prefs that store pointing stick settings.
 class ASH_EXPORT PointingStickPrefHandler {
  public:
+  virtual ~PointingStickPrefHandler() = default;
+
   // Initializes device settings in prefs and update the `settings` member of
   // the `mojom::PointingStick` object.
   virtual void InitializePointingStickSettings(
@@ -26,9 +28,6 @@
   virtual void UpdatePointingStickSettings(
       PrefService* pref_service,
       const mojom::PointingStick& pointing_stick) = 0;
-
- protected:
-  virtual ~PointingStickPrefHandler() = default;
 };
 
 }  // namespace ash
diff --git a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.cc b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.cc
index 279120f..39130624 100644
--- a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.cc
+++ b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.cc
@@ -7,12 +7,40 @@
 #include "ash/constants/ash_pref_names.h"
 #include "ash/public/mojom/input_device_settings.mojom-forward.h"
 #include "ash/public/mojom/input_device_settings.mojom.h"
+#include "ash/shell.h"
 #include "ash/system/input_device_settings/input_device_settings_defaults.h"
 #include "ash/system/input_device_settings/input_device_settings_pref_names.h"
+#include "ash/system/input_device_settings/input_device_tracker.h"
 #include "base/check.h"
 #include "components/prefs/pref_service.h"
 
 namespace ash {
+namespace {
+
+mojom::PointingStickSettingsPtr GetDefaultPointingStickSettings() {
+  mojom::PointingStickSettingsPtr settings =
+      mojom::PointingStickSettings::New();
+  settings->sensitivity = kDefaultSensitivity;
+  settings->swap_right = kDefaultSwapRight;
+  settings->acceleration_enabled = kDefaultAccelerationEnabled;
+  return settings;
+}
+
+// GetPointingStickSettingsFromPrefs returns pointing stick settings based on
+// user prefs to be used as settings for new pointing sticks.
+mojom::PointingStickSettingsPtr GetPointingStickSettingsFromPrefs(
+    PrefService* prefs) {
+  mojom::PointingStickSettingsPtr settings =
+      mojom::PointingStickSettings::New();
+  settings->sensitivity = prefs->GetInteger(prefs::kPointingStickSensitivity);
+  settings->swap_right =
+      prefs->GetBoolean(prefs::kPrimaryPointingStickButtonRight);
+  settings->acceleration_enabled =
+      prefs->GetBoolean(prefs::kPointingStickAcceleration);
+  return settings;
+}
+
+}  // namespace
 
 PointingStickPrefHandlerImpl::PointingStickPrefHandlerImpl() = default;
 PointingStickPrefHandlerImpl::~PointingStickPrefHandlerImpl() = default;
@@ -24,7 +52,8 @@
       pref_service->GetDict(prefs::kPointingStickDeviceSettingsDictPref);
   const auto* settings_dict = devices_dict.FindDict(pointing_stick->device_key);
   if (!settings_dict) {
-    pointing_stick->settings = GetNewPointingStickSettings(*pointing_stick);
+    pointing_stick->settings =
+        GetNewPointingStickSettings(pref_service, *pointing_stick);
   } else {
     pointing_stick->settings = RetreivePointingStickSettings(
         pref_service, *pointing_stick, *settings_dict);
@@ -71,15 +100,16 @@
 
 mojom::PointingStickSettingsPtr
 PointingStickPrefHandlerImpl::GetNewPointingStickSettings(
+    PrefService* pref_service,
     const mojom::PointingStick& pointing_stick) {
-  // TODO(michaelcheco): Implement pulling from old device settings if the
-  // device was observed in the transition period.
-  mojom::PointingStickSettingsPtr settings =
-      mojom::PointingStickSettings::New();
-  settings->sensitivity = kDefaultSensitivity;
-  settings->swap_right = kDefaultReverseScrolling;
-  settings->acceleration_enabled = kDefaultAccelerationEnabled;
-  return settings;
+  // TODO(michaelcheco): Remove once transitioned to per-device settings.
+  if (Shell::Get()->input_device_tracker()->WasDevicePreviouslyConnected(
+          InputDeviceTracker::InputDeviceCategory::kPointingStick,
+          pointing_stick.device_key)) {
+    return GetPointingStickSettingsFromPrefs(pref_service);
+  }
+
+  return GetDefaultPointingStickSettings();
 }
 
 mojom::PointingStickSettingsPtr
diff --git a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h
index 5919268..42b34a3 100644
--- a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h
+++ b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h
@@ -32,6 +32,7 @@
 
  private:
   mojom::PointingStickSettingsPtr GetNewPointingStickSettings(
+      PrefService* prefs,
       const mojom::PointingStick& pointing_stick);
   mojom::PointingStickSettingsPtr RetreivePointingStickSettings(
       PrefService* prefs,
diff --git a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_unittest.cc b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_unittest.cc
index 3a7da40e..56cdab5 100644
--- a/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_unittest.cc
+++ b/ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_unittest.cc
@@ -4,9 +4,12 @@
 
 #include "ash/system/input_device_settings/pref_handlers/pointing_stick_pref_handler_impl.h"
 
+#include "ash/constants/ash_pref_names.h"
 #include "ash/public/mojom/input_device_settings.mojom.h"
+#include "ash/shell.h"
 #include "ash/system/input_device_settings/input_device_settings_defaults.h"
 #include "ash/system/input_device_settings/input_device_settings_pref_names.h"
+#include "ash/system/input_device_settings/input_device_tracker.h"
 #include "ash/test/ash_test_base.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
@@ -20,6 +23,10 @@
 const std::string kPointingStickKey1 = "device_key1";
 const std::string kPointingStickKey2 = "device_key2";
 
+const int kTestSensitivity = 2;
+const bool kTestSwapRight = false;
+const bool kTestAccelerationEnabled = false;
+
 const mojom::PointingStickSettings kPointingStickSettingsDefault(
     /*swap_right=*/kDefaultSwapRight,
     /*sensitivity=*/kDefaultSensitivity,
@@ -62,6 +69,12 @@
 
     pref_service_->registry()->RegisterDictionaryPref(
         prefs::kPointingStickDeviceSettingsDictPref);
+    pref_service_->registry()->RegisterIntegerPref(
+        prefs::kPointingStickSensitivity, kTestSensitivity);
+    pref_service_->registry()->RegisterBooleanPref(
+        prefs::kPrimaryPointingStickButtonRight, kTestSwapRight);
+    pref_service_->registry()->RegisterBooleanPref(
+        prefs::kPointingStickAcceleration, kTestAccelerationEnabled);
   }
 
   void CheckPointingStickSettingsAndDictAreEqual(
@@ -244,6 +257,21 @@
                                             *settings_dict);
 }
 
+TEST_F(PointingStickPrefHandlerTest,
+       PointingStickObserveredInTransitionPeriod) {
+  mojom::PointingStick pointing_stick;
+  pointing_stick.device_key = kPointingStickKey1;
+  Shell::Get()->input_device_tracker()->OnPointingStickConnected(
+      pointing_stick);
+  // Initialize PointingStick settings for the device and check that the global
+  // prefs were used as defaults.
+  mojom::PointingStickSettingsPtr settings =
+      CallInitializePointingStickSettings(pointing_stick.device_key);
+  ASSERT_EQ(settings->sensitivity, kTestSensitivity);
+  ASSERT_EQ(settings->swap_right, kTestSwapRight);
+  ASSERT_EQ(settings->acceleration_enabled, kTestAccelerationEnabled);
+}
+
 class PointingStickSettingsPrefConversionTest
     : public PointingStickPrefHandlerTest,
       public testing::WithParamInterface<
diff --git a/ash/system/input_device_settings/pref_handlers/touchpad_pref_handler.h b/ash/system/input_device_settings/pref_handlers/touchpad_pref_handler.h
index ba163a542..7d1a7b32 100644
--- a/ash/system/input_device_settings/pref_handlers/touchpad_pref_handler.h
+++ b/ash/system/input_device_settings/pref_handlers/touchpad_pref_handler.h
@@ -15,6 +15,8 @@
 // Handles reading and updating prefs that store touchpad settings.
 class ASH_EXPORT TouchpadPrefHandler {
  public:
+  virtual ~TouchpadPrefHandler() = default;
+
   // Initializes device settings in prefs and update the `settings` member of
   // the `mojom::Touchpad` object.
   virtual void InitializeTouchpadSettings(PrefService* pref_service,
@@ -24,9 +26,6 @@
   // `touchpad.settings`.
   virtual void UpdateTouchpadSettings(PrefService* pref_service,
                                       const mojom::Touchpad& touchpad) = 0;
-
- protected:
-  virtual ~TouchpadPrefHandler() = default;
 };
 
 }  // namespace ash
diff --git a/ash/system/privacy/screen_capture_observer.h b/ash/system/privacy/screen_capture_observer.h
deleted file mode 100644
index fc83805..0000000
--- a/ash/system/privacy/screen_capture_observer.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_PRIVACY_SCREEN_CAPTURE_OBSERVER_H_
-#define ASH_SYSTEM_PRIVACY_SCREEN_CAPTURE_OBSERVER_H_
-
-#include <string>
-
-#include "base/functional/callback.h"
-
-namespace ash {
-
-class ScreenCaptureObserver {
- public:
-  // Called when screen capture is started.
-  // |stop_callback| is a callback to stop the stream.
-  // |source_callback| is a callback to change the desktop capture source.
-  virtual void OnScreenCaptureStart(
-      base::OnceClosure stop_callback,
-      const base::RepeatingClosure& source_callback,
-      const std::u16string& screen_capture_status) = 0;
-
-  // Called when screen capture is stopped.
-  virtual void OnScreenCaptureStop() = 0;
-
- protected:
-  virtual ~ScreenCaptureObserver() {}
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_PRIVACY_SCREEN_CAPTURE_OBSERVER_H_
diff --git a/ash/system/privacy/screen_security_controller.cc b/ash/system/privacy/screen_security_controller.cc
index 3baaa7c9..d2ca736 100644
--- a/ash/system/privacy/screen_security_controller.cc
+++ b/ash/system/privacy/screen_security_controller.cc
@@ -28,58 +28,59 @@
 
 // It is possible that we are capturing and sharing screen at the same time, so
 // we cannot share the notification IDs for capturing and sharing.
-const char kScreenCaptureNotificationId[] = "chrome://screen/capture";
-const char kScreenShareNotificationId[] = "chrome://screen/share";
-const char kNotifierScreenCapture[] = "ash.screen-capture";
-const char kNotifierScreenShare[] = "ash.screen-share";
+const char kScreenAccessNotificationId[] = "chrome://screen/access";
+const char kRemotingScreenShareNotificationId[] =
+    "chrome://screen/remoting-share";
+const char kNotifierScreenAccess[] = "ash.screen-access";
+const char kNotifierRemotingScreenShare[] = "ash.remoting-screen-share";
 
 ScreenSecurityController::ScreenSecurityController() {
   Shell::Get()->AddShellObserver(this);
-  Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
-  Shell::Get()->system_tray_notifier()->AddScreenShareObserver(this);
+  Shell::Get()->system_tray_notifier()->AddScreenSecurityObserver(this);
 }
 
 ScreenSecurityController::~ScreenSecurityController() {
-  Shell::Get()->system_tray_notifier()->RemoveScreenShareObserver(this);
-  Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
+  Shell::Get()->system_tray_notifier()->RemoveScreenSecurityObserver(this);
   Shell::Get()->RemoveShellObserver(this);
 }
 
-void ScreenSecurityController::CreateNotification(const std::u16string& message,
-                                                  bool is_capture) {
+void ScreenSecurityController::CreateNotification(
+    const std::u16string& message,
+    bool is_screen_access_notification) {
   if (features::IsVideoConferenceEnabled()) {
     // Don't send screen share notifications, because the VideoConferenceTray
     // serves as the notifier for screen share. As for screen capture, continue
     // to show these notifications for now, although they may end up in the
     // `VideoConferenceTray` as well. See b/269486186 for details.
-    DCHECK(is_capture);
+    DCHECK(is_screen_access_notification);
   }
 
   message_center::RichNotificationData data;
-  data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
-      is_capture ? IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_STOP
-                 : IDS_ASH_STATUS_TRAY_SCREEN_SHARE_STOP)));
+  data.buttons.emplace_back(
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SCREEN_ACCESS_STOP));
   // Only add "Change source" button when there is one session, since there
   // isn't a good UI to distinguish between the different sessions.
-  if (is_capture && change_source_callback_ &&
-      capture_stop_callbacks_.size() == 1) {
-    data.buttons.push_back(message_center::ButtonInfo(l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_CHANGE_SOURCE)));
+  if (is_screen_access_notification && change_source_callback_ &&
+      screen_access_stop_callbacks_.size() == 1) {
+    data.buttons.emplace_back(l10n_util::GetStringUTF16(
+        IDS_ASH_STATUS_TRAY_SCREEN_CAPTURE_CHANGE_SOURCE));
   }
 
   auto delegate =
       base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
           base::BindRepeating(
               [](base::WeakPtr<ScreenSecurityController> controller,
-                 bool is_capture, absl::optional<int> button_index) {
+                 bool is_screen_access_notification,
+                 absl::optional<int> button_index) {
                 if (!button_index)
                   return;
 
                 if (*button_index == 0) {
-                  controller->StopAllSessions(is_capture);
+                  controller->StopAllSessions(
+                      /*is_screen_access=*/is_screen_access_notification);
                 } else if (*button_index == 1) {
                   controller->ChangeSource();
-                  if (is_capture) {
+                  if (is_screen_access_notification) {
                     base::RecordAction(base::UserMetricsAction(
                         "StatusArea_ScreenCapture_Change_Source"));
                   }
@@ -87,18 +88,20 @@
                   NOTREACHED();
                 }
               },
-              weak_ptr_factory_.GetWeakPtr(), is_capture));
+              weak_ptr_factory_.GetWeakPtr(), is_screen_access_notification));
 
   // If the feature is enabled, the notification should have the style of
   // privacy indicators notification.
   auto* notifier_id =
       features::IsPrivacyIndicatorsEnabled()
           ? kPrivacyIndicatorsNotifierId
-          : (is_capture ? kNotifierScreenCapture : kNotifierScreenShare);
+          : (is_screen_access_notification ? kNotifierScreenAccess
+                                           : kNotifierRemotingScreenShare);
 
   std::unique_ptr<Notification> notification = CreateSystemNotificationPtr(
       message_center::NOTIFICATION_TYPE_SIMPLE,
-      is_capture ? kScreenCaptureNotificationId : kScreenShareNotificationId,
+      is_screen_access_notification ? kScreenAccessNotificationId
+                                    : kRemotingScreenShareNotificationId,
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SCREEN_SHARE_TITLE),
       message, std::u16string() /* display_source */, GURL(),
       message_center::NotifierId(
@@ -122,18 +125,19 @@
       std::move(notification));
 }
 
-void ScreenSecurityController::StopAllSessions(bool is_capture) {
-  if (features::IsVideoConferenceEnabled() && !is_capture) {
+void ScreenSecurityController::StopAllSessions(bool is_screen_access) {
+  if (features::IsVideoConferenceEnabled() && !is_screen_access) {
     return;
   }
 
   message_center::MessageCenter::Get()->RemoveNotification(
-      is_capture ? kScreenCaptureNotificationId : kScreenShareNotificationId,
+      is_screen_access ? kScreenAccessNotificationId
+                       : kRemotingScreenShareNotificationId,
       false /* by_user */);
 
   std::vector<base::OnceClosure> callbacks;
-  std::swap(callbacks,
-            is_capture ? capture_stop_callbacks_ : share_stop_callbacks_);
+  std::swap(callbacks, is_screen_access ? screen_access_stop_callbacks_
+                                        : remoting_share_stop_callbacks_);
   for (base::OnceClosure& callback : callbacks) {
     if (callback)
       std::move(callback).Run();
@@ -143,15 +147,22 @@
 }
 
 void ScreenSecurityController::ChangeSource() {
-  if (change_source_callback_ && capture_stop_callbacks_.size() == 1)
+  if (change_source_callback_ && screen_access_stop_callbacks_.size() == 1) {
     change_source_callback_.Run();
+  }
 }
 
-void ScreenSecurityController::OnScreenCaptureStart(
+void ScreenSecurityController::OnScreenAccessStart(
     base::OnceClosure stop_callback,
     const base::RepeatingClosure& source_callback,
-    const std::u16string& screen_capture_status) {
-  capture_stop_callbacks_.emplace_back(std::move(stop_callback));
+    const std::u16string& access_app_name) {
+  // Don't send screen access notifications, because the VideoConferenceTray
+  // serves as the notifier for this.
+  if (features::IsVideoConferenceEnabled()) {
+    return;
+  }
+
+  screen_access_stop_callbacks_.emplace_back(std::move(stop_callback));
   change_source_callback_ = source_callback;
 
   // We do not want to show the screen capture notification and the chromecast
@@ -164,46 +175,41 @@
   if (is_casting_)
     return;
 
-  CreateNotification(screen_capture_status, true /* is_capture */);
+  CreateNotification(access_app_name, /*is_screen_access_notification=*/true);
 }
 
-void ScreenSecurityController::OnScreenCaptureStop() {
-  StopAllSessions(true /* is_capture */);
-}
-
-void ScreenSecurityController::OnScreenShareStart(
-    base::OnceClosure stop_callback,
-    const std::u16string& helper_name) {
-  // Don't send screen share notifications, because the VideoConferenceTray
-  // serves as the notifier for screen share. As for screen capture, continue to
-  // show these notifications for now, although they may end up in the
-  // `VideoConferenceTray` as well. See b/269486186 for details.
+void ScreenSecurityController::OnScreenAccessStop() {
   if (features::IsVideoConferenceEnabled()) {
     return;
   }
 
-  share_stop_callbacks_.emplace_back(std::move(stop_callback));
+  StopAllSessions(/*is_screen_access=*/true);
+}
 
-  std::u16string help_label_text;
-  if (!helper_name.empty()) {
-    help_label_text = l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED_NAME, helper_name);
-  } else {
-    help_label_text = l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED);
+void ScreenSecurityController::OnRemotingScreenShareStart(
+    base::OnceClosure stop_callback) {
+  // Don't send screen share notifications, because the VideoConferenceTray
+  // serves as the notifier for screen share.
+  if (features::IsVideoConferenceEnabled()) {
+    return;
   }
 
-  CreateNotification(help_label_text, false /* is_capture */);
+  remoting_share_stop_callbacks_.emplace_back(std::move(stop_callback));
+
+  CreateNotification(
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SCREEN_SHARE_BEING_HELPED),
+      /*is_screen_access_notification=*/false);
 
   if (features::IsPrivacyIndicatorsEnabled())
     UpdatePrivacyIndicatorsScreenShareStatus(/*is_screen_sharing=*/true);
 }
 
-void ScreenSecurityController::OnScreenShareStop() {
+void ScreenSecurityController::OnRemotingScreenShareStop() {
   if (features::IsVideoConferenceEnabled()) {
     return;
   }
-  StopAllSessions(false /* is_capture */);
+
+  StopAllSessions(/*is_screen_access=*/false);
 
   if (features::IsPrivacyIndicatorsEnabled())
     UpdatePrivacyIndicatorsScreenShareStatus(/*is_screen_sharing=*/false);
diff --git a/ash/system/privacy/screen_security_controller.h b/ash/system/privacy/screen_security_controller.h
index 869e3bb..1991730d 100644
--- a/ash/system/privacy/screen_security_controller.h
+++ b/ash/system/privacy/screen_security_controller.h
@@ -9,20 +9,18 @@
 #include <vector>
 
 #include "ash/shell_observer.h"
-#include "ash/system/privacy/screen_capture_observer.h"
-#include "ash/system/privacy/screen_share_observer.h"
+#include "ash/system/privacy/screen_security_observer.h"
 #include "base/memory/weak_ptr.h"
 
 namespace ash {
 
-extern ASH_EXPORT const char kScreenCaptureNotificationId[];
-extern ASH_EXPORT const char kScreenShareNotificationId[];
-extern ASH_EXPORT const char kNotifierScreenCapture[];
-extern ASH_EXPORT const char kNotifierScreenShare[];
+extern ASH_EXPORT const char kScreenAccessNotificationId[];
+extern ASH_EXPORT const char kRemotingScreenShareNotificationId[];
+extern ASH_EXPORT const char kNotifierScreenAccess[];
+extern ASH_EXPORT const char kNotifierRemotingScreenShare[];
 
 // Controller class to manage screen security notifications.
-class ASH_EXPORT ScreenSecurityController : public ScreenCaptureObserver,
-                                            public ScreenShareObserver,
+class ASH_EXPORT ScreenSecurityController : public ScreenSecurityObserver,
                                             public ShellObserver {
  public:
   ScreenSecurityController();
@@ -33,26 +31,28 @@
   ~ScreenSecurityController() override;
 
  private:
-  void CreateNotification(const std::u16string& message, bool is_capture);
-  // Remove the notification and call all the callbacks in
-  // |capture_stop_callbacks_| or |share_stop_callbacks_|, depending on
-  // |is_capture| argument.
-  void StopAllSessions(bool is_capture);
-  // Change the source of current capture session by bringing up the picker
+  // Creates the screen security notification. If
+  // `is_screen_access_notification`, the notification is created for screen
+  // access. Otherwise it is for remoting screen share.
+  void CreateNotification(const std::u16string& message,
+                          bool is_screen_access_notification);
+
+  // Removes the notification and calls all the callbacks in
+  // `screen_access_stop_callbacks_` or `remoting_share_stop_callbacks_`,
+  // depending on `is_screen_access` argument.
+  void StopAllSessions(bool is_screen_access);
+
+  // Changes the source of current capture session by bringing up the picker
   // again, only if there is only one screen capture session.
   void ChangeSource();
 
-  // ScreenCaptureObserver:
-  void OnScreenCaptureStart(
-      base::OnceClosure stop_callback,
-      const base::RepeatingClosure& source_callback,
-      const std::u16string& screen_capture_status) override;
-  void OnScreenCaptureStop() override;
-
-  // ScreenShareObserver:
-  void OnScreenShareStart(base::OnceClosure stop_callback,
-                          const std::u16string& helper_name) override;
-  void OnScreenShareStop() override;
+  // ScreenSecurityObserver:
+  void OnScreenAccessStart(base::OnceClosure stop_callback,
+                           const base::RepeatingClosure& source_callback,
+                           const std::u16string& access_app_name) override;
+  void OnScreenAccessStop() override;
+  void OnRemotingScreenShareStart(base::OnceClosure stop_callback) override;
+  void OnRemotingScreenShareStop() override;
 
   // ShellObserver:
   void OnCastingSessionStartedOrStopped(bool started) override;
@@ -60,10 +60,10 @@
   bool is_casting_ = false;
 
   // There can be multiple cast sessions at the same time. If the user hits the
-  // stop button, stop all sessions since there is not a good UI to distinguish
+  // stop button, stops all sessions since there is not a good UI to distinguish
   // between the different sessions.
-  std::vector<base::OnceClosure> capture_stop_callbacks_;
-  std::vector<base::OnceClosure> share_stop_callbacks_;
+  std::vector<base::OnceClosure> screen_access_stop_callbacks_;
+  std::vector<base::OnceClosure> remoting_share_stop_callbacks_;
   base::RepeatingClosure change_source_callback_;
 
   base::WeakPtrFactory<ScreenSecurityController> weak_ptr_factory_{this};
diff --git a/ash/system/privacy/screen_security_controller_unittest.cc b/ash/system/privacy/screen_security_controller_unittest.cc
index 127fcd3..e2cedde 100644
--- a/ash/system/privacy/screen_security_controller_unittest.cc
+++ b/ash/system/privacy/screen_security_controller_unittest.cc
@@ -69,34 +69,34 @@
     /*IsPrivacyIndicatorsFeatureEnabled()=*/::testing::Bool());
 
 TEST_P(ScreenSecurityControllerTest, ShowScreenCaptureNotification) {
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::DoNothing(), base::RepeatingClosure(), std::u16string());
-  EXPECT_TRUE(FindNotification(kScreenCaptureNotificationId));
+  EXPECT_TRUE(FindNotification(kScreenAccessNotificationId));
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
 
-  EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
+  EXPECT_FALSE(FindNotification(kScreenAccessNotificationId));
 }
 
 TEST_P(ScreenSecurityControllerTest, ShowScreenShareNotification) {
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
-      base::DoNothing(), std::u16string());
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
+      base::DoNothing());
 
-  EXPECT_TRUE(FindNotification(kScreenShareNotificationId));
+  EXPECT_TRUE(FindNotification(kRemotingScreenShareNotificationId));
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
 
-  EXPECT_FALSE(FindNotification(kScreenShareNotificationId));
+  EXPECT_FALSE(FindNotification(kRemotingScreenShareNotificationId));
 }
 
-// Tests that `NotifyScreenShareStop()` does not crash if called with no
+// Tests that `NotifyRemotingScreenShareStop()` does not crash if called with no
 // notification with VideoConference enabled and disabled.
 TEST_P(ScreenSecurityControllerTest, NotifyScreenShareStopNoNotification) {
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
 
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(features::kVideoConference);
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
 }
 
 // Tests that screen share notifications do not show when VideoConference is
@@ -106,48 +106,45 @@
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(features::kVideoConference);
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
-      base::DoNothing(), std::u16string());
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
+      base::DoNothing());
 
-  EXPECT_FALSE(FindNotification(kScreenShareNotificationId));
+  EXPECT_FALSE(FindNotification(kRemotingScreenShareNotificationId));
 }
 
-// Tests that calling `NotifyScreenCaptureStop()` does not crash if called with
+// Tests that calling `NotifyScreenAccessStop()` does not crash if called with
 // no notification with VideoConference enabled and disabled.
 TEST_P(ScreenSecurityControllerTest, NotifyScreenCaptureStopNoNotification) {
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
 
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(features::kVideoConference);
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
 }
 
-// Tests that screen capture notifications show with video conference enabled.
+// Tests that screen capture notifications do not show with video conference
+// enabled.
 TEST_P(ScreenSecurityControllerTest,
        ScreenCaptureShowsNotificationWithVideoConference) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(features::kVideoConference);
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::DoNothing(), base::RepeatingClosure(), std::u16string());
 
-  EXPECT_TRUE(FindNotification(kScreenCaptureNotificationId));
-
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
-
-  EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
+  EXPECT_FALSE(FindNotification(kScreenAccessNotificationId));
 }
 
 TEST_P(ScreenSecurityControllerTest,
        DoNotShowScreenCaptureNotificationWhenCasting) {
   Shell::Get()->OnCastingSessionStartedOrStopped(true /* started */);
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::DoNothing(), base::RepeatingClosure(), std::u16string());
-  EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
+  EXPECT_FALSE(FindNotification(kScreenAccessNotificationId));
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
   Shell::Get()->OnCastingSessionStartedOrStopped(false /* started */);
-  EXPECT_FALSE(FindNotification(kScreenCaptureNotificationId));
+  EXPECT_FALSE(FindNotification(kScreenAccessNotificationId));
 }
 
 class PrivacyIndicatorsScreenSecurityTest : public AshTestBase {
@@ -173,10 +170,10 @@
 // Tests that the screen share notification is created with proper metadata when
 // the `SystemTrayNotifier` notifies observers of screen share start.
 TEST_F(PrivacyIndicatorsScreenSecurityTest, ScreenShareNotification) {
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
-      base::DoNothing(), std::u16string());
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
+      base::DoNothing());
 
-  auto* notification = FindNotification(kScreenShareNotificationId);
+  auto* notification = FindNotification(kRemotingScreenShareNotificationId);
   EXPECT_TRUE(notification);
 
   // Notification should have the correct notifier id so that it will be grouped
@@ -195,11 +192,11 @@
 
   ExpectPrivacyIndicatorsVisible(/*visible=*/false);
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
-      base::DoNothing(), std::u16string());
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
+      base::DoNothing());
   ExpectPrivacyIndicatorsVisible(/*visible=*/true);
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+  Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
   ExpectPrivacyIndicatorsVisible(/*visible=*/false);
 }
 
diff --git a/ash/system/privacy/screen_security_observer.h b/ash/system/privacy/screen_security_observer.h
new file mode 100644
index 0000000..2ecd834
--- /dev/null
+++ b/ash/system/privacy/screen_security_observer.h
@@ -0,0 +1,42 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_OBSERVER_H_
+#define ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_OBSERVER_H_
+
+#include <string>
+
+#include "base/functional/callback.h"
+
+namespace ash {
+
+class ScreenSecurityObserver {
+ public:
+  // Called when the screen starts being accessed (i.e. screen sharing, screen
+  // capture). Note that this function will not be called during system screen
+  // capture (please consult the owners of //ash/capture_mode for this) and
+  // during screen sharing via remoting (see functions below for this).
+  // `stop_callback` is the callback to stop the stream.
+  // `source_callback` is the callback to change the desktop capture source.
+  virtual void OnScreenAccessStart(
+      base::OnceClosure stop_callback,
+      const base::RepeatingClosure& source_callback,
+      const std::u16string& access_app_name) {}
+
+  // Called when the screen is no longer being accessed.
+  virtual void OnScreenAccessStop() {}
+
+  // Called when screen share via remoting is started.
+  virtual void OnRemotingScreenShareStart(base::OnceClosure stop_callback) {}
+
+  // Called when screen share via remoting is stopped.
+  virtual void OnRemotingScreenShareStop() {}
+
+ protected:
+  virtual ~ScreenSecurityObserver() = default;
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_PRIVACY_SCREEN_SECURITY_OBSERVER_H_
diff --git a/ash/system/privacy/screen_share_observer.h b/ash/system/privacy/screen_share_observer.h
deleted file mode 100644
index afcd980d..0000000
--- a/ash/system/privacy/screen_share_observer.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_PRIVACY_SCREEN_SHARE_OBSERVER_H_
-#define ASH_SYSTEM_PRIVACY_SCREEN_SHARE_OBSERVER_H_
-
-#include <string>
-
-#include "base/functional/callback.h"
-
-namespace ash {
-
-class ScreenShareObserver {
- public:
-  // Called when screen share is started.
-  virtual void OnScreenShareStart(base::OnceClosure stop_callback,
-                                  const std::u16string& helper_name) = 0;
-
-  // Called when screen share is stopped.
-  virtual void OnScreenShareStop() = 0;
-
- protected:
-  virtual ~ScreenShareObserver() = default;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_PRIVACY_SCREEN_SHARE_OBSERVER_H_
diff --git a/ash/system/privacy/screen_switch_check_controller.cc b/ash/system/privacy/screen_switch_check_controller.cc
index 9a77f428..5560550 100644
--- a/ash/system/privacy/screen_switch_check_controller.cc
+++ b/ash/system/privacy/screen_switch_check_controller.cc
@@ -9,7 +9,6 @@
 #include "ash/system/tray/system_tray_notifier.h"
 #include "base/functional/bind.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/controls/message_box_view.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/window/dialog_delegate.h"
@@ -46,11 +45,11 @@
   void OnDialogCancelled() { std::move(callback_).Run(false); }
 
   void OnDialogAccepted() {
-    // Stop screen sharing and capturing. When notified, all capture sessions or
-    // all share sessions will be stopped.
-    // Currently, the logic is in ScreenSecurityNotificationController.
-    Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
-    Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+    // Stop all screen access and sharing. When notified, all screen access and
+    // sharing sessions will be stopped. Currently, the logic is in
+    // ScreenSecurityNotificationController.
+    Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
+    Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
 
     std::move(callback_).Run(true);
   }
@@ -62,20 +61,18 @@
 }  // namespace
 
 ScreenSwitchCheckController::ScreenSwitchCheckController() {
-  Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
-  Shell::Get()->system_tray_notifier()->AddScreenShareObserver(this);
+  Shell::Get()->system_tray_notifier()->AddScreenSecurityObserver(this);
 }
 
 ScreenSwitchCheckController::~ScreenSwitchCheckController() {
-  Shell::Get()->system_tray_notifier()->RemoveScreenShareObserver(this);
-  Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
+  Shell::Get()->system_tray_notifier()->RemoveScreenSecurityObserver(this);
 }
 
 void ScreenSwitchCheckController::CanSwitchAwayFromActiveUser(
     base::OnceCallback<void(bool)> callback) {
   // If neither screen sharing nor capturing is going on we can immediately
   // switch users.
-  if (!has_capture_ && !has_share_) {
+  if (!is_screen_accessed_ && !is_remoting_share_) {
     std::move(callback).Run(true);
     return;
   }
@@ -86,29 +83,28 @@
       ->Show();
 }
 
-void ScreenSwitchCheckController::OnScreenCaptureStart(
+void ScreenSwitchCheckController::OnScreenAccessStart(
     base::OnceClosure stop_callback,
     const base::RepeatingClosure& source_callback,
-    const std::u16string& screen_capture_status) {
-  has_capture_ = true;
+    const std::u16string& access_app_name) {
+  is_screen_accessed_ = true;
 }
 
-void ScreenSwitchCheckController::OnScreenCaptureStop() {
+void ScreenSwitchCheckController::OnScreenAccessStop() {
   // Multiple screen capture sessions can exist, but they are stopped at once
   // for simplicity.
-  has_capture_ = false;
+  is_screen_accessed_ = false;
 }
 
-void ScreenSwitchCheckController::OnScreenShareStart(
-    base::OnceClosure stop_callback,
-    const std::u16string& helper_name) {
-  has_share_ = true;
+void ScreenSwitchCheckController::OnRemotingScreenShareStart(
+    base::OnceClosure stop_callback) {
+  is_remoting_share_ = true;
 }
 
-void ScreenSwitchCheckController::OnScreenShareStop() {
+void ScreenSwitchCheckController::OnRemotingScreenShareStop() {
   // Multiple screen share sessions can exist, but they are stopped at once for
   // simplicity.
-  has_share_ = false;
+  is_remoting_share_ = false;
 }
 
 }  // namespace ash
diff --git a/ash/system/privacy/screen_switch_check_controller.h b/ash/system/privacy/screen_switch_check_controller.h
index e203b97..de2cc66 100644
--- a/ash/system/privacy/screen_switch_check_controller.h
+++ b/ash/system/privacy/screen_switch_check_controller.h
@@ -5,15 +5,13 @@
 #ifndef ASH_SYSTEM_PRIVACY_SCREEN_SWITCH_CHECK_CONTROLLER_H_
 #define ASH_SYSTEM_PRIVACY_SCREEN_SWITCH_CHECK_CONTROLLER_H_
 
-#include "ash/system/privacy/screen_capture_observer.h"
-#include "ash/system/privacy/screen_share_observer.h"
+#include "ash/system/privacy/screen_security_observer.h"
 
 namespace ash {
 
 // Controller of a dialog that confirms the user wants to stop screen share/cast
 // on user profile switching.
-class ScreenSwitchCheckController : public ScreenCaptureObserver,
-                                    public ScreenShareObserver {
+class ScreenSwitchCheckController : public ScreenSecurityObserver {
  public:
   ScreenSwitchCheckController();
 
@@ -29,20 +27,16 @@
   void CanSwitchAwayFromActiveUser(base::OnceCallback<void(bool)> callback);
 
  private:
-  // ScreenCaptureObserver:
-  void OnScreenCaptureStart(
-      base::OnceClosure stop_callback,
-      const base::RepeatingClosure& source_callback,
-      const std::u16string& screen_capture_status) override;
-  void OnScreenCaptureStop() override;
+  // ScreenSecurityObserver:
+  void OnScreenAccessStart(base::OnceClosure stop_callback,
+                           const base::RepeatingClosure& source_callback,
+                           const std::u16string& access_app_name) override;
+  void OnScreenAccessStop() override;
+  void OnRemotingScreenShareStart(base::OnceClosure stop_callback) override;
+  void OnRemotingScreenShareStop() override;
 
-  // ScreenShareObserver:
-  void OnScreenShareStart(base::OnceClosure stop_callback,
-                          const std::u16string& helper_name) override;
-  void OnScreenShareStop() override;
-
-  bool has_capture_ = false;
-  bool has_share_ = false;
+  bool is_screen_accessed_ = false;
+  bool is_remoting_share_ = false;
 };
 
 }  // namespace ash
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc
index 73fb826..46be2e6 100644
--- a/ash/system/tray/system_tray_notifier.cc
+++ b/ash/system/tray/system_tray_notifier.cc
@@ -7,8 +7,7 @@
 #include "ash/public/cpp/system_tray_observer.h"
 #include "ash/system/ime/ime_observer.h"
 #include "ash/system/network/network_observer.h"
-#include "ash/system/privacy/screen_capture_observer.h"
-#include "ash/system/privacy/screen_share_observer.h"
+#include "ash/system/privacy/screen_security_observer.h"
 #include "ash/system/virtual_keyboard/virtual_keyboard_observer.h"
 
 namespace ash {
@@ -48,49 +47,43 @@
     observer.RequestToggleWifi();
 }
 
-void SystemTrayNotifier::AddScreenCaptureObserver(
-    ScreenCaptureObserver* observer) {
-  screen_capture_observers_.AddObserver(observer);
+void SystemTrayNotifier::AddScreenSecurityObserver(
+    ScreenSecurityObserver* observer) {
+  screen_security_observers_.AddObserver(observer);
 }
 
-void SystemTrayNotifier::RemoveScreenCaptureObserver(
-    ScreenCaptureObserver* observer) {
-  screen_capture_observers_.RemoveObserver(observer);
+void SystemTrayNotifier::RemoveScreenSecurityObserver(
+    ScreenSecurityObserver* observer) {
+  screen_security_observers_.RemoveObserver(observer);
 }
 
-void SystemTrayNotifier::NotifyScreenCaptureStart(
+void SystemTrayNotifier::NotifyScreenAccessStart(
     base::RepeatingClosure stop_callback,
     base::RepeatingClosure source_callback,
-    const std::u16string& sharing_app_name) {
-  for (auto& observer : screen_capture_observers_)
-    observer.OnScreenCaptureStart(stop_callback, source_callback,
-                                  sharing_app_name);
+    const std::u16string& access_app_name) {
+  for (auto& observer : screen_security_observers_) {
+    observer.OnScreenAccessStart(stop_callback, source_callback,
+                                 access_app_name);
+  }
 }
 
-void SystemTrayNotifier::NotifyScreenCaptureStop() {
-  for (auto& observer : screen_capture_observers_)
-    observer.OnScreenCaptureStop();
+void SystemTrayNotifier::NotifyScreenAccessStop() {
+  for (auto& observer : screen_security_observers_) {
+    observer.OnScreenAccessStop();
+  }
 }
 
-void SystemTrayNotifier::AddScreenShareObserver(ScreenShareObserver* observer) {
-  screen_share_observers_.AddObserver(observer);
+void SystemTrayNotifier::NotifyRemotingScreenShareStart(
+    base::RepeatingClosure stop_callback) {
+  for (auto& observer : screen_security_observers_) {
+    observer.OnRemotingScreenShareStart(stop_callback);
+  }
 }
 
-void SystemTrayNotifier::RemoveScreenShareObserver(
-    ScreenShareObserver* observer) {
-  screen_share_observers_.RemoveObserver(observer);
-}
-
-void SystemTrayNotifier::NotifyScreenShareStart(
-    base::RepeatingClosure stop_callback,
-    const std::u16string& helper_name) {
-  for (auto& observer : screen_share_observers_)
-    observer.OnScreenShareStart(stop_callback, helper_name);
-}
-
-void SystemTrayNotifier::NotifyScreenShareStop() {
-  for (auto& observer : screen_share_observers_)
-    observer.OnScreenShareStop();
+void SystemTrayNotifier::NotifyRemotingScreenShareStop() {
+  for (auto& observer : screen_security_observers_) {
+    observer.OnRemotingScreenShareStop();
+  }
 }
 
 void SystemTrayNotifier::AddSystemTrayObserver(SystemTrayObserver* observer) {
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h
index 8887816..6942208 100644
--- a/ash/system/tray/system_tray_notifier.h
+++ b/ash/system/tray/system_tray_notifier.h
@@ -15,8 +15,7 @@
 
 class IMEObserver;
 class NetworkObserver;
-class ScreenCaptureObserver;
-class ScreenShareObserver;
+class ScreenSecurityObserver;
 class SystemTrayObserver;
 class VirtualKeyboardObserver;
 
@@ -45,20 +44,15 @@
   void RemoveNetworkObserver(NetworkObserver* observer);
   void NotifyRequestToggleWifi();
 
-  // Screen capture.
-  void AddScreenCaptureObserver(ScreenCaptureObserver* observer);
-  void RemoveScreenCaptureObserver(ScreenCaptureObserver* observer);
-  void NotifyScreenCaptureStart(base::RepeatingClosure stop_callback,
-                                base::RepeatingClosure source_callback,
-                                const std::u16string& sharing_app_name);
-  void NotifyScreenCaptureStop();
-
-  // Screen share.
-  void AddScreenShareObserver(ScreenShareObserver* observer);
-  void RemoveScreenShareObserver(ScreenShareObserver* observer);
-  void NotifyScreenShareStart(base::RepeatingClosure stop_callback,
-                              const std::u16string& helper_name);
-  void NotifyScreenShareStop();
+  // Screen security.
+  void AddScreenSecurityObserver(ScreenSecurityObserver* observer);
+  void RemoveScreenSecurityObserver(ScreenSecurityObserver* observer);
+  void NotifyScreenAccessStart(base::RepeatingClosure stop_callback,
+                               base::RepeatingClosure source_callback,
+                               const std::u16string& access_app_name);
+  void NotifyScreenAccessStop();
+  void NotifyRemotingScreenShareStart(base::RepeatingClosure stop_callback);
+  void NotifyRemotingScreenShareStop();
 
   // System tray focus.
   void AddSystemTrayObserver(SystemTrayObserver* observer);
@@ -74,9 +68,8 @@
  private:
   base::ObserverList<IMEObserver>::Unchecked ime_observers_;
   base::ObserverList<NetworkObserver>::Unchecked network_observers_;
-  base::ObserverList<ScreenCaptureObserver>::Unchecked
-      screen_capture_observers_;
-  base::ObserverList<ScreenShareObserver>::Unchecked screen_share_observers_;
+  base::ObserverList<ScreenSecurityObserver>::Unchecked
+      screen_security_observers_;
   base::ObserverList<SystemTrayObserver>::Unchecked system_tray_observers_;
   base::ObserverList<VirtualKeyboardObserver>::Unchecked
       virtual_keyboard_observers_;
diff --git a/ash/webui/common/resources/hotspot/BUILD.gn b/ash/webui/common/resources/hotspot/BUILD.gn
index 03180845..304890a8 100644
--- a/ash/webui/common/resources/hotspot/BUILD.gn
+++ b/ash/webui/common/resources/hotspot/BUILD.gn
@@ -21,17 +21,17 @@
 }
 
 copy("copy_files") {
-  deps =
-      [ "//chromeos/ash/services/hotspot_config/public/mojom:mojom_webui_js" ]
-  sources = [ "$root_gen_dir/mojom-webui/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js" ]
+  deps = [
+    "//chromeos/ash/services/hotspot_config/public/mojom:mojom_ts__generator",
+  ]
+  sources = [ "$root_gen_dir/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.ts" ]
   outputs = [ "$preprocessed_dir/{{source_file_part}}" ]
 }
 
 ts_library("build_ts") {
-  allow_js = true
   root_dir = preprocessed_dir
   out_dir = "$root_gen_dir/ash/webui/common/resources/preprocessed/hotspot"
-  in_files = ts_files + [ "cros_hotspot_config.mojom-webui.js" ]
+  in_files = ts_files + [ "cros_hotspot_config.mojom-webui.ts" ]
   composite = true
   definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ]
   deps = [
diff --git a/ash/webui/common/resources/network/BUILD.gn b/ash/webui/common/resources/network/BUILD.gn
index a7fd0ec..b286d63 100644
--- a/ash/webui/common/resources/network/BUILD.gn
+++ b/ash/webui/common/resources/network/BUILD.gn
@@ -150,7 +150,6 @@
     ":network_password_input",
     "//ash/webui/common/resources:i18n_behavior",
     "//ash/webui/common/resources:load_time_data.m",
-    "//chrome/browser/ui/webui/settings/ash/search:mojo_bindings_js_library_for_compile",
     "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes",
     "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon",
     "//third_party/polymer/v3_0/components-chromium/paper-spinner:paper-spinner-lite",
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc
index 04cf23ab..e5d83c1 100644
--- a/ash/webui/personalization_app/personalization_app_ui.cc
+++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -250,6 +250,8 @@
        IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_NUDGE_TEXT},
       {"zoneCustomize",
        IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_ZONE_CUSTOMIZATION_BUTTON},
+      {"wallpaperColorDescription",
+       IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_DESCRIPTION},
 
       // Google Photos strings
       // TODO(b/229149314): Finalize error and retry strings.
diff --git a/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_element.html b/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_element.html
index 6c46956..c03f3bf 100644
--- a/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_element.html
+++ b/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_element.html
@@ -13,6 +13,20 @@
     grid-template-rows: auto 1fr 20px;
   }
 
+  @media (max-width: 700px) {
+    #container.preview-container {
+      grid-template-rows: auto 1fr 8px;
+    }
+
+    #container > #selector {
+      column-gap: 11px;
+    }
+
+    #selector > #wallpaperColorDescription {
+      margin-inline-start: -6px;
+    }
+  }
+
   #keyboardBacklightLabel {
     align-items: center;
     background: none;
@@ -60,10 +74,10 @@
     align-items: center;
     border-radius: 50%;
     display: flex;
-    height: 24px;
+    height: 28px;
     justify-content: center;
     position: relative;
-    width: 24px;
+    width: 28px;
   }
 
   .dark-icon {
@@ -121,6 +135,14 @@
     margin-inline-end: 14px;
   }
 
+  #wallpaperColorDescription {
+    color: var(--cros-text-color-secondary);
+    font-size: 12px;
+    height: 48px;
+    line-height: 48px;
+    margin-inline-start: 5.5px;
+  }
+
   #zoneCustomizationButton {
     align-self: center;
     display: flex;
@@ -144,31 +166,33 @@
   <iron-selector id="selector" selected="0" selectable=".color-container"
       selected-item="{{ironSelectedColor_}}"
       role="radiogroup" aria-describedby="keyboardBacklightLabel">
-    <div id$="[[wallpaperColorId_]]"
-        class$="[[getWallpaperColorContainerClass_(backlightColor_)]]"
-        tabindex="0"
-        on-click="onWallpaperColorSelected_"
-        on-keypress="onWallpaperColorSelected_"
-        aria-label="$i18n{wallpaperColor}"
-        aria-checked$="[[getWallpaperColorAriaChecked_(backlightColor_)]]"
-        title$="[[getWallpaperColorTitle_()]]"
-        role="radio">
-      <div class="color-inner-container"
-          style$="[[getWallpaperColorInnerContainerStyle_(wallpaperColor_)]]">
-        <svg class$="[[getWallpaperIconColorClass_(wallpaperColor_)]]" viewBox="0 0 20 20" width="16" height="16">
-          <path fill-rule="evenodd" clip-rule="evenodd" d="M12.0605 5.585L13.5805 6.935C14.3705 7.715 14.2005 8.985 13.4105 9.765L4.76469 18.4108C3.98364 19.1918 2.71731 19.1918 1.93626 18.4108L0.583834 17.0584C-0.196879 16.2776 -0.197265 15.012 0.582974 14.2308L7.40048 7.405L9.23048 5.585C10.0105 4.805 11.2805 4.805 12.0605 5.585ZM8.82101 8.81494L1.95101 15.6849L3.36101 17.1049L10.231 10.2249L8.82101 8.81494Z">
-          </path>
-          <path d="M16 6L15.06 3.94L13 3L15.06 2.06L16 0L16.94 2.06L19 3L16.94 3.94L16 6Z">
-          </path>
-          <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
-          </path>
-          <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
-          </path>
-          <path d="M3.06 4.94L4 7L4.94 4.94L7 4L4.94 3.06L4 1L3.06 3.06L1 4L3.06 4.94Z">
-          </path>
-        </svg>
+    <template is="dom-if" if="[[!isMultiZoneRgbKeyboardSupported_]]">
+      <div id$="[[wallpaperColorId_]]"
+          class$="[[getWallpaperColorContainerClass_(backlightColor_)]]"
+          tabindex="0"
+          on-click="onWallpaperColorSelected_"
+          on-keypress="onWallpaperColorSelected_"
+          aria-label="$i18n{wallpaperColor}"
+          aria-checked$="[[getWallpaperColorAriaChecked_(backlightColor_)]]"
+          title$="[[getWallpaperColorTitle_()]]"
+          role="radio">
+        <div class="color-inner-container"
+            style$="[[getWallpaperColorInnerContainerStyle_(wallpaperColor_)]]">
+          <svg class$="[[getWallpaperIconColorClass_(wallpaperColor_)]]" viewBox="0 0 20 20" width="16" height="16">
+            <path fill-rule="evenodd" clip-rule="evenodd" d="M12.0605 5.585L13.5805 6.935C14.3705 7.715 14.2005 8.985 13.4105 9.765L4.76469 18.4108C3.98364 19.1918 2.71731 19.1918 1.93626 18.4108L0.583834 17.0584C-0.196879 16.2776 -0.197265 15.012 0.582974 14.2308L7.40048 7.405L9.23048 5.585C10.0105 4.805 11.2805 4.805 12.0605 5.585ZM8.82101 8.81494L1.95101 15.6849L3.36101 17.1049L10.231 10.2249L8.82101 8.81494Z">
+            </path>
+            <path d="M16 6L15.06 3.94L13 3L15.06 2.06L16 0L16.94 2.06L19 3L16.94 3.94L16 6Z">
+            </path>
+            <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
+            </path>
+            <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
+            </path>
+            <path d="M3.06 4.94L4 7L4.94 4.94L7 4L4.94 3.06L4 1L3.06 3.06L1 4L3.06 4.94Z">
+            </path>
+          </svg>
+        </div>
       </div>
-    </div>
+    </template>
     <template is="dom-if" if="[[shouldShowNudge_]]">
       <div id="toast">
         <div id="toastDot"></div>
@@ -180,7 +204,9 @@
         </div>
       </div>
     </template>
-    <div class="divider"></div>
+    <template is="dom-if" if="[[!isMultiZoneRgbKeyboardSupported_]]">
+      <div class="divider"></div>
+    </template>
     <template is="dom-repeat" items="[[presetColorIds_]]" as="presetColorId">
       <div id$="[[presetColorId]]"
           class$="[[getPresetColorContainerClass_(presetColorId, presetColors_, backlightColor_)]]"
@@ -206,6 +232,34 @@
       </div>
     </div>
     <template is="dom-if" if="[[isMultiZoneRgbKeyboardSupported_]]">
+      <div id$="[[wallpaperColorId_]]"
+          class$="[[getWallpaperColorContainerClass_(backlightColor_)]]"
+          tabindex="0"
+          on-click="onWallpaperColorSelected_"
+          on-keypress="onWallpaperColorSelected_"
+          aria-label="$i18n{wallpaperColor}"
+          aria-checked$="[[getWallpaperColorAriaChecked_(backlightColor_)]]"
+          title$="[[getWallpaperColorTitle_()]]"
+          role="radio">
+        <div class="color-inner-container"
+            style$="[[getWallpaperColorInnerContainerStyle_(wallpaperColor_)]]">
+          <svg class$="[[getWallpaperIconColorClass_(wallpaperColor_)]]" viewBox="0 0 20 20" width="16" height="16">
+            <path fill-rule="evenodd" clip-rule="evenodd" d="M12.0605 5.585L13.5805 6.935C14.3705 7.715 14.2005 8.985 13.4105 9.765L4.76469 18.4108C3.98364 19.1918 2.71731 19.1918 1.93626 18.4108L0.583834 17.0584C-0.196879 16.2776 -0.197265 15.012 0.582974 14.2308L7.40048 7.405L9.23048 5.585C10.0105 4.805 11.2805 4.805 12.0605 5.585ZM8.82101 8.81494L1.95101 15.6849L3.36101 17.1049L10.231 10.2249L8.82101 8.81494Z">
+            </path>
+            <path d="M16 6L15.06 3.94L13 3L15.06 2.06L16 0L16.94 2.06L19 3L16.94 3.94L16 6Z">
+            </path>
+            <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
+            </path>
+            <path d="M17.001 17L16.061 14.94L14.001 14L16.061 13.06L17.001 11L17.941 13.06L20.001 14L17.941 14.94L17.001 17Z">
+            </path>
+            <path d="M3.06 4.94L4 7L4.94 4.94L7 4L4.94 3.06L4 1L3.06 3.06L1 4L3.06 4.94Z">
+            </path>
+          </svg>
+        </div>
+      </div>
+      <div id="wallpaperColorDescription">
+        $i18n{wallpaperColorDescription}
+      </div>
       <cr-button id="zoneCustomizationButton" on-click="showZoneCustomizationDialog_"
           class="secondary"
           aria-pressed$="[[getZoneCustomizationButtonAriaPressed_(backlightColor_)]]">
diff --git a/ash/webui/personalization_app/tools/gen_tsconfig.py b/ash/webui/personalization_app/tools/gen_tsconfig.py
index 79dc046..efd691f4 100755
--- a/ash/webui/personalization_app/tools/gen_tsconfig.py
+++ b/ash/webui/personalization_app/tools/gen_tsconfig.py
@@ -78,6 +78,7 @@
         'extends': normalize_path(out_json_dir, out_json['extends']),
         'compilerOptions': {
             'baseUrl': '.',
+            'allowJs': out_json['compilerOptions']['allowJs'],
             'rootDirs': [
                 '.',
                 normalize_path(out_json_dir,
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn b/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn
index 48f86d8..b6f920c 100644
--- a/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn
+++ b/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn
@@ -19,10 +19,7 @@
     "inter_frame_communication.ts",
     "main.ts",
     "page_handler.ts",
-
-    # TODO(crbug.com/1002798): Migrate these Shared Worker files to TS.
-    "timer.js",
-    "worker.js",
+    "timer.ts",
   ]
 
   composite = true
@@ -33,11 +30,22 @@
       [ "/*|" + rebase_path("$root_gen_dir/mojom-webui/*", target_gen_dir) ]
 
   deps = [
+    ":worker_ts",
     "../../mojom:mojom_ts",
     "//ui/webui/resources/cr_components/color_change_listener:build_ts",
   ]
 }
 
+ts_library("worker_ts") {
+  tsconfig_base = "tsconfig_worker.json"
+  root_dir = "."
+  out_dir = "$target_gen_dir/tsc"
+
+  in_files = [ "worker.ts" ]
+
+  composite = true
+}
+
 generate_grd("trusted_grd") {
   # Note: Don't forget to:
   #
@@ -66,6 +74,8 @@
   # to the grd.
   manifest_files =
       filter_include(get_target_outputs(":trusted_ts"), [ "*.manifest" ])
+  manifest_files +=
+      filter_include(get_target_outputs(":worker_ts"), [ "*.manifest" ])
 
   # Flatten out the dependency tree of your mojom and add generated bindings
   # grdp files here.
@@ -79,6 +89,7 @@
 
   deps = [
     ":trusted_ts",
+    ":worker_ts",
     "../../mojom:shared_webui_grdp",
     "../../mojom:trusted_webui_grdp",
   ]
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/main.ts b/ash/webui/sample_system_web_app_ui/resources/trusted/main.ts
index 80d070f7..6c20a9d 100644
--- a/ash/webui/sample_system_web_app_ui/resources/trusted/main.ts
+++ b/ash/webui/sample_system_web_app_ui/resources/trusted/main.ts
@@ -12,9 +12,6 @@
 
 const result = document.querySelector('#result')!;
 
-// TODO(crbug.com/1002798): Replace this with real type definitions.
-declare const trustedTypes: any;
-
 declare global {
   interface Window {
     pageHandler: PageHandlerRemote;
@@ -23,10 +20,15 @@
   }
 }
 
-const workerUrlPolicy = trustedTypes.createPolicy(
-    'worker-js-static',
-    {createScriptURL: () => 'chrome://sample-system-web-app/worker.js'});
-const myWorker = new SharedWorker(workerUrlPolicy.createScriptURL(''));
+const workerUrlPolicy = window.trustedTypes!.createPolicy('worker-js-static', {
+  createScriptURL: (_ignored: string) =>
+      'chrome://sample-system-web-app/worker.js',
+});
+
+// Currently TypeScript doesn't support trusted types so cast TrustedScriptURL
+// to URL. See https://github.com/microsoft/TypeScript/issues/30024.
+const myWorker = new SharedWorker(
+    workerUrlPolicy.createScriptURL('') as unknown as URL, {type: 'module'});
 
 first.onchange = () => {
   myWorker.port.postMessage([first.value, second.value]);
@@ -41,7 +43,6 @@
   additional.value = event.data[1];
 };
 
-
 // Exposes the pageHandler to the user as a window's global variable for
 // testing.
 window.pageHandler = pageHandler;
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/timer.js b/ash/webui/sample_system_web_app_ui/resources/trusted/timer.js
deleted file mode 100644
index 0b98333..0000000
--- a/ash/webui/sample_system_web_app_ui/resources/trusted/timer.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-const workerUrlPolicy = trustedTypes.createPolicy(
-    'worker-js-static',
-    {createScriptURL: () => 'chrome://sample-system-web-app/worker.js'});
-const myWorker = new SharedWorker(workerUrlPolicy.createScriptURL(''));
-
-myWorker.port.onmessage = (e) => {
-  window.close();
-  myWorker.port.close();
-};
-
-myWorker.port.postMessage(['doubler', Math.floor(Math.random() * 3)]);
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/timer.ts b/ash/webui/sample_system_web_app_ui/resources/trusted/timer.ts
new file mode 100644
index 0000000..a73a2591
--- /dev/null
+++ b/ash/webui/sample_system_web_app_ui/resources/trusted/timer.ts
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const workerUrlPolicy = window.trustedTypes!.createPolicy('worker-js-static', {
+  createScriptURL: (_ignored: string) =>
+      'chrome://sample-system-web-app/worker.js',
+});
+
+// Currently TypeScript doesn't support trusted types so cast TrustedScriptURL
+// to URL. See https://github.com/microsoft/TypeScript/issues/30024.
+const myWorker = new SharedWorker(
+    workerUrlPolicy.createScriptURL('') as unknown as URL, {type: 'module'});
+
+myWorker.port.onmessage = () => {
+  window.close();
+  myWorker.port.close();
+};
+
+myWorker.port.postMessage(['doubler', Math.floor(Math.random() * 3)]);
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/tsconfig_worker.json b/ash/webui/sample_system_web_app_ui/resources/trusted/tsconfig_worker.json
new file mode 100644
index 0000000..48c8bf0
--- /dev/null
+++ b/ash/webui/sample_system_web_app_ui/resources/trusted/tsconfig_worker.json
@@ -0,0 +1,6 @@
+{
+  "extends": "../../../../../tools/typescript/tsconfig_base.json",
+  "compilerOptions": {
+    "lib": ["webworker", "esnext"]
+  }
+}
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/worker.js b/ash/webui/sample_system_web_app_ui/resources/trusted/worker.ts
similarity index 70%
rename from ash/webui/sample_system_web_app_ui/resources/trusted/worker.js
rename to ash/webui/sample_system_web_app_ui/resources/trusted/worker.ts
index ade4fae..b8622ec8 100644
--- a/ash/webui/sample_system_web_app_ui/resources/trusted/worker.js
+++ b/ash/webui/sample_system_web_app_ui/resources/trusted/worker.ts
@@ -12,16 +12,23 @@
 // the 2 values in e.data with the doubler, and returns the value to the caller.
 // This is meant to be called by the foreground page.
 
+// Add an empty export to tell TypeScript this is a module so we can re-declare
+// `self` below.
+export {};
+// Re-declare self as a SharedWorkerGlobalScope so we can use shared worker
+// functions.
+declare const self: SharedWorkerGlobalScope;
+
 let doubler = 2;
-const connectedPagePorts = new Set();
-onconnect = (event) => {
-  const port = event.ports[0];
+const connectedPagePorts = new Set<MessagePort>();
+self.onconnect = (event) => {
+  const port = event.ports[0]!;
   port.onmessage = function(e) {
     if (e.data[0] == 'doubler') {
       doubler = e.data[1];
       port.postMessage(e.data[1]);
-      connectedPagePorts.forEach(foreground_port => {
-        foreground_port.postMessage(
+      connectedPagePorts.forEach(foregroundPort => {
+        foregroundPort.postMessage(
             ['New additional value: ' + doubler, doubler]);
       });
     } else {
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 25f1954..aed4ffa 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -286,9 +286,8 @@
   widget->Init(std::move(params));
   widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE);
 
-  // Show plus icon if drag a tab from a multi-tab window.
-  widget->SetContentsView(std::make_unique<DropTargetView>(
-      dragged_window->GetProperty(kTabDraggingSourceWindowKey)));
+  widget->SetContentsView(
+      std::make_unique<DropTargetView>(/*has_plus_icon=*/false));
   aura::Window* drop_target_window = widget->GetNativeWindow();
   drop_target_window->parent()->StackChildAtBottom(drop_target_window);
   widget->Show();
@@ -407,75 +406,6 @@
   std::unique_ptr<views::Widget> desks_widget_;
 };
 
-// The class to observe the overview window that the dragged tabs will merge
-// into. After the dragged tabs merge into the overview window, and if the
-// overview window represents a minimized window, we need to update the
-// overview minimized widget's content view so that it reflects the merge.
-class OverviewGrid::TargetWindowObserver : public aura::WindowObserver {
- public:
-  TargetWindowObserver() = default;
-
-  TargetWindowObserver(const TargetWindowObserver&) = delete;
-  TargetWindowObserver& operator=(const TargetWindowObserver&) = delete;
-
-  ~TargetWindowObserver() override { StopObserving(); }
-
-  void StartObserving(aura::Window* window) {
-    if (target_window_)
-      StopObserving();
-
-    target_window_ = window;
-    target_window_->AddObserver(this);
-  }
-
-  // aura::WindowObserver:
-  void OnWindowPropertyChanged(aura::Window* window,
-                               const void* key,
-                               intptr_t old) override {
-    DCHECK_EQ(window, target_window_);
-    // When the property is cleared, the dragged window should have been merged
-    // into |target_window_|, update the corresponding window item in overview.
-    if (key == chromeos::kIsDeferredTabDraggingTargetWindowKey &&
-        !window->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey)) {
-      UpdateWindowItemInOverviewContaining(window);
-      StopObserving();
-    }
-  }
-
-  void OnWindowDestroying(aura::Window* window) override {
-    DCHECK_EQ(window, target_window_);
-    StopObserving();
-  }
-
- private:
-  void UpdateWindowItemInOverviewContaining(aura::Window* window) {
-    OverviewController* overview_controller =
-        Shell::Get()->overview_controller();
-    if (!overview_controller->InOverviewSession())
-      return;
-
-    OverviewGrid* grid =
-        overview_controller->overview_session()->GetGridWithRootWindow(
-            window->GetRootWindow());
-    if (!grid)
-      return;
-
-    OverviewItem* item = grid->GetOverviewItemContaining(window);
-    if (!item)
-      return;
-
-    item->UpdateItemContentViewForMinimizedWindow();
-  }
-
-  void StopObserving() {
-    if (target_window_)
-      target_window_->RemoveObserver(this);
-    target_window_ = nullptr;
-  }
-
-  aura::Window* target_window_ = nullptr;
-};
-
 OverviewGrid::OverviewGrid(aura::Window* root_window,
                            const std::vector<aura::Window*>& windows,
                            OverviewSession* overview_session)
@@ -1000,40 +930,6 @@
 
   RearrangeDuringDrag(nullptr, window_dragging_state);
   UpdateDropTargetBackgroundVisibility(nullptr, location_in_screen);
-
-  aura::Window* target_window =
-      GetTargetWindowOnLocation(location_in_screen, /*ignored_item=*/nullptr);
-
-  if (SplitViewDragIndicators::GetSnapPosition(window_dragging_state) !=
-      SplitViewController::SnapPosition::kNone) {
-    // If the dragged window is currently dragged into preview window area,
-    // hide the highlight.
-    overview_session_->highlight_controller()->HideTabDragHighlight();
-
-    // Also clear chromeos::kIsDeferredTabDraggingTargetWindowKey key on the
-    // target overview item so that it can't merge into this overview item if
-    // the dragged window is currently in preview window area.
-    if (target_window && !IsDropTargetWindow(target_window))
-      target_window->ClearProperty(
-          chromeos::kIsDeferredTabDraggingTargetWindowKey);
-
-    return;
-  }
-
-  // Show the tab drag highlight if |location_in_screen| is contained by the
-  // browser windows' overview item in overview.
-  if (target_window && target_window->GetProperty(
-                           chromeos::kIsDeferredTabDraggingTargetWindowKey)) {
-    auto* item = GetOverviewItemContaining(target_window);
-    if (!item)
-      return;
-
-    overview_session_->highlight_controller()->ShowTabDragHighlight(
-        item->overview_item_view());
-    return;
-  }
-
-  overview_session_->highlight_controller()->HideTabDragHighlight();
 }
 
 void OverviewGrid::OnWindowDragEnded(aura::Window* dragged_window,
@@ -1046,35 +942,16 @@
   dragged_window_ = nullptr;
 
   // Add the dragged window into drop target in overview if
-  // |should_drop_window_into_overview| is true. Only consider add the dragged
-  // window into drop target if SelectedWindow is false since drop target will
-  // not be selected and tab dragging might drag a tab window to merge it into a
-  // browser window in overview.
-  if (overview_session_->highlight_controller()->IsTabDragHighlightVisible())
-    overview_session_->highlight_controller()->HideTabDragHighlight();
-  else if (should_drop_window_into_overview)
+  // |should_drop_window_into_overview| is true.
+  if (should_drop_window_into_overview) {
     AddDraggedWindowIntoOverviewOnDragEnd(dragged_window);
+  }
 
   RemoveDropTarget();
 
   // Called to reset caption and title visibility after dragging.
   OnSelectorItemDragEnded(snap);
 
-  // After drag ends, if the dragged window needs to merge into another window
-  // |target_window|, and we may need to update |minimized_widget_| that holds
-  // the contents of |target_window| if |target_window| is a minimized window
-  // in overview.
-  aura::Window* target_window =
-      GetTargetWindowOnLocation(location_in_screen, /*ignored_item=*/nullptr);
-  if (target_window && target_window->GetProperty(
-                           chromeos::kIsDeferredTabDraggingTargetWindowKey)) {
-    // Create an window observer and update the minimized window widget after
-    // the dragged window merges into |target_window|.
-    if (!target_window_observer_)
-      target_window_observer_ = std::make_unique<TargetWindowObserver>();
-    target_window_observer_->StartObserving(target_window);
-  }
-
   // Update the grid bounds and reposition windows. Since the grid bounds might
   // be updated based on the preview area during drag, but the window finally
   // didn't be snapped to the preview area.
@@ -2561,29 +2438,6 @@
   if (overview_session_->IsWindowInOverview(dragged_window))
     return;
 
-  // Update the dragged window's bounds before adding it to overview. The
-  // dragged window might have resized to a smaller size if the drag
-  // happens on tab(s).
-  if (window_util::IsDraggingTabs(dragged_window)) {
-    const gfx::Rect old_bounds = dragged_window->bounds();
-    // We need to temporarily disable the dragged window's ability to merge
-    // into another window when changing the dragged window's bounds, so
-    // that the dragged window doesn't merge into another window because of
-    // its changed bounds.
-    dragged_window->SetProperty(chromeos::kCanAttachToAnotherWindowKey, false);
-    TabletModeWindowState::UpdateWindowPosition(
-        WindowState::Get(dragged_window),
-        WindowState::BoundsChangeAnimationType::kNone);
-    const gfx::Rect new_bounds = dragged_window->bounds();
-    if (old_bounds != new_bounds) {
-      // It's for smoother animation.
-      const gfx::Transform transform = gfx::TransformBetweenRects(
-          gfx::RectF(new_bounds), gfx::RectF(old_bounds));
-      dragged_window->SetTransform(transform);
-    }
-    dragged_window->ClearProperty(chromeos::kCanAttachToAnotherWindowKey);
-  }
-
   overview_session_->AddItemInMruOrder(dragged_window, /*reposition=*/false,
                                        /*animate=*/false, /*restack=*/true,
                                        /*use_spawn_animation=*/false);
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h
index ce7bbc3..9f7cd36 100644
--- a/ash/wm/overview/overview_grid.h
+++ b/ash/wm/overview/overview_grid.h
@@ -451,7 +451,6 @@
   float scroll_offset_for_testing() const { return scroll_offset_; }
 
  private:
-  class TargetWindowObserver;
   friend class DesksTemplatesTest;
   friend class OverviewTestBase;
 
@@ -572,17 +571,9 @@
   // overview item is being dragged, and is destroyed when the drag ends or
   // overview mode is ended. The drop target is hidden when a snap preview area
   // is shown. You can drop a window into overview by dragging to the drop
-  // target or by dragging to almost anywhere while the drop target is shown. A
-  // plus sign in the center of the drop target indicates tab dragging.
+  // target or by dragging to almost anywhere while the drop target is shown.
   std::unique_ptr<views::Widget> drop_target_widget_;
 
-  // The observer of the target window, which is the window that the dragged
-  // tabs are going to merge into after the drag ends. After the dragged tabs
-  // merge into the target window, and if the target window is a minimized
-  // window in overview and is not destroyed yet, we need to update the overview
-  // minimized widget's content view so that it reflects the merge.
-  std::unique_ptr<TargetWindowObserver> target_window_observer_;
-
   // True if the overview grid should animate when exiting overview mode. Note
   // even if it's true, it doesn't mean all window items in the grid should
   // animate when exiting overview, instead each window item's animation status
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc
index 31197e4..81110e7c 100644
--- a/ash/wm/overview/overview_highlight_controller.cc
+++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -276,24 +276,6 @@
   highlighted_view_ = nullptr;
 }
 
-void OverviewHighlightController::HideTabDragHighlight() {
-  if (tab_dragged_view_)
-    tab_dragged_view_->SetHighlightVisibility(false);
-  tab_dragged_view_ = nullptr;
-}
-
-void OverviewHighlightController::ShowTabDragHighlight(
-    OverviewHighlightableView* view) {
-  if (tab_dragged_view_)
-    tab_dragged_view_->SetHighlightVisibility(false);
-  tab_dragged_view_ = view;
-  tab_dragged_view_->SetHighlightVisibility(true);
-}
-
-bool OverviewHighlightController::IsTabDragHighlightVisible() const {
-  return !!tab_dragged_view_;
-}
-
 std::vector<OverviewHighlightableView*>
 OverviewHighlightController::GetTraversableViews() const {
   std::vector<OverviewHighlightableView*> traversable_views;
diff --git a/ash/wm/overview/overview_highlight_controller.h b/ash/wm/overview/overview_highlight_controller.h
index 9617b8d..b515de8 100644
--- a/ash/wm/overview/overview_highlight_controller.h
+++ b/ash/wm/overview/overview_highlight_controller.h
@@ -18,13 +18,12 @@
 class ScopedA11yOverrideWindowSetter;
 
 // Manages highlighting items while in overview. Responsible for telling
-// highlightable items to show or hide their focus ring borders, when tabbing
-// through highlightable items with arrow keys and trackpad swipes, or when tab
-// dragging. In this context, an highlightable item can represent anything
-// focusable in overview mode such as a desk textfield, saved desk button and an
-// `OverviewItem`. The idea behind the movement strategy is that it should be
-// possible to access any highlightable view via keyboard by pressing the tab or
-// arrow keys repeatedly.
+// highlightable items to show or hide their focus ring borders, or when tabbing
+// through highlightable items with arrow keys and trackpad swipes. In this
+// context, an highlightable item can represent anything focusable in overview
+// mode such as a desk textfield, saved desk button and an `OverviewItem`. The
+// idea behind the movement strategy is that it should be possible to access any
+// highlightable view via keyboard by pressing the tab or arrow keys repeatedly.
 // +-------+  +-------+  +-------+
 // |   0   |  |   1   |  |   2   |
 // +-------+  +-------+  +-------+
@@ -97,11 +96,6 @@
   // expanded to zero state.
   void ResetHighlightedView();
 
-  // Hides or shows the tab dragging highlight.
-  void HideTabDragHighlight();
-  void ShowTabDragHighlight(OverviewHighlightableView* view);
-  bool IsTabDragHighlightVisible() const;
-
  private:
   // Returns a vector of views that can be traversed via overview tabbing.
   // Includes desk mini views, the new desk button and overview items.
@@ -125,9 +119,6 @@
   // The current view that is being highlighted, if any.
   OverviewHighlightableView* highlighted_view_ = nullptr;
 
-  // The current view that is being tab dragged, if any.
-  OverviewHighlightableView* tab_dragged_view_ = nullptr;
-
   // Helps to update the current a11y override window. And accessibility
   // features will focus on the window that is being set. Once `this` goes out
   // of scope, the a11y override window is set to nullptr.
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index f49314c..ba638118 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -63,10 +63,8 @@
 #include "ash/wm/splitview/split_view_divider.h"
 #include "ash/wm/splitview/split_view_drag_indicators.h"
 #include "ash/wm/splitview/split_view_utils.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
 #include "ash/wm/window_preview_view.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_delegate.h"
@@ -1093,56 +1091,6 @@
   EXPECT_EQ(window1.get(), window_util::GetFocusedWindow());
 }
 
-// Tests that if a window is dragged while overview is open, the activation
-// of the dragged window does not cancel overview.
-TEST_P(OverviewSessionTest, ActivateDraggedWindowNotCancelOverview) {
-  UpdateDisplay("800x600");
-  EnterTabletMode();
-  std::unique_ptr<aura::Window> window1(CreateTestWindow());
-  window1->SetProperty(aura::client::kAppType,
-                       static_cast<int>(AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(CreateTestWindow());
-  EXPECT_FALSE(InOverviewSession());
-
-  // Start drag on |window1|.
-  std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
-      window1.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_TOUCH));
-  EXPECT_TRUE(InOverviewSession());
-
-  resizer->Drag(gfx::PointF(400, 0), 0);
-  EXPECT_TRUE(InOverviewSession());
-
-  wm::ActivateWindow(window1.get());
-  EXPECT_TRUE(InOverviewSession());
-
-  resizer->CompleteDrag();
-  EXPECT_FALSE(InOverviewSession());
-}
-
-// Tests that activate a non-dragged window during window drag will not cancel
-// overview mode.
-TEST_P(OverviewSessionTest, ActivateAnotherWindowDuringDragNotCancelOverview) {
-  UpdateDisplay("800x600");
-  EnterTabletMode();
-  std::unique_ptr<aura::Window> window1(CreateTestWindow());
-  window1->SetProperty(aura::client::kAppType,
-                       static_cast<int>(AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(CreateTestWindow());
-  EXPECT_FALSE(InOverviewSession());
-
-  // Start drag on |window1|.
-  wm::ActivateWindow(window1.get());
-  std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
-      window1.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_TOUCH));
-  EXPECT_TRUE(InOverviewSession());
-
-  // Activate |window2| should not cancel overview mode.
-  wm::ActivateWindow(window2.get());
-  EXPECT_FALSE(WindowState::Get(window2.get())->is_dragged());
-  EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
-  EXPECT_TRUE(InOverviewSession());
-}
-
 // Tests that if an overview item is dragged, the activation of the
 // corresponding window does not cancel overview.
 TEST_P(OverviewSessionTest, ActivateDraggedOverviewWindowNotCancelOverview) {
@@ -1486,26 +1434,6 @@
   EXPECT_FALSE(GetDropTarget(1));
 }
 
-// Tests that the drop target is removed if a window is destroyed while being
-// dragged from the top.
-TEST_P(OverviewSessionTest,
-       DropTargetRemovedIfWindowDraggedFromTopIsDestroyed) {
-  EnterTabletMode();
-  std::unique_ptr<aura::Window> window = CreateTestWindow();
-  std::unique_ptr<aura::Window> window2 = CreateTestWindow();
-  window->SetProperty(aura::client::kAppType,
-                      static_cast<int>(AppType::BROWSER));
-  std::unique_ptr<WindowResizer> resizer =
-      CreateWindowResizer(window.get(), gfx::PointF(400, 0), HTCAPTION,
-                          ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-  ASSERT_TRUE(InOverviewSession());
-  EXPECT_TRUE(GetDropTarget(0));
-  resizer.reset();
-  window.reset();
-  ASSERT_TRUE(InOverviewSession());
-  EXPECT_FALSE(GetDropTarget(0));
-}
-
 namespace {
 
 // A simple window delegate that returns the specified hit-test code when
@@ -2468,29 +2396,6 @@
       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 1);
 }
 
-// Test that dragging a window from the top creates a drop target stacked at the
-// bottom. Test that dropping into overview removes the drop target.
-TEST_P(OverviewSessionTest, DropTargetStackedAtBottomForWindowDraggedFromTop) {
-  UpdateDisplay("800x600");
-  EnterTabletMode();
-  std::unique_ptr<aura::Window> window1(CreateTestWindow());
-  window1->SetProperty(aura::client::kAppType,
-                       static_cast<int>(AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(CreateTestWindow());
-  aura::Window* parent = window1->parent();
-  ASSERT_EQ(parent, window2->parent());
-  wm::ActivateWindow(window2.get());
-  wm::ActivateWindow(window1.get());
-  std::unique_ptr<WindowResizer> resizer =
-      CreateWindowResizer(window1.get(), gfx::PointF(400, 0), HTCAPTION,
-                          ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-  ASSERT_TRUE(GetDropTarget(0));
-  EXPECT_TRUE(IsStackedBelow(GetDropTarget(0)->GetWindow(), window2.get()));
-  resizer->Drag(gfx::PointF(400, 500), ui::EF_NONE);
-  resizer->CompleteDrag();
-  EXPECT_FALSE(GetDropTarget(0));
-}
-
 // Test that dragging an overview item to snap creates a drop target stacked at
 // the bottom. Test that ending the drag removes the drop target.
 TEST_P(OverviewSessionTest, DropTargetStackedAtBottomForOverviewItem) {
@@ -2868,32 +2773,6 @@
   EXPECT_NE(bounds3, item3->target_bounds());
 }
 
-// Tests that overview mode is entered with kWindowDragged mode when a window is
-// dragged from the top of the screen. For the purposes of this test, we use a
-// browser window.
-TEST_P(OverviewSessionTest, DraggingFromTopAnimation) {
-  EnterTabletMode();
-  std::unique_ptr<views::Widget> widget(CreateTestWidget(
-      nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect(200, 200)));
-  widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, 20);
-
-  // Drag from the the top of the app to enter overview.
-  ui::GestureEvent event(0, 0, 0, base::TimeTicks(),
-                         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
-  WindowState* window_state = WindowState::Get(widget->GetNativeWindow());
-  window_state->CreateDragDetails(event.location_f(), HTCAPTION,
-                                  ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-  auto drag_controller = std::make_unique<TabletModeWindowResizer>(
-      window_state, std::make_unique<TabletModeBrowserWindowDragDelegate>());
-  ui::Event::DispatcherApi dispatch_helper(&event);
-  dispatch_helper.set_target(widget->GetNativeWindow());
-  drag_controller->Drag(event.location_f(), event.flags());
-
-  ASSERT_TRUE(InOverviewSession());
-  EXPECT_EQ(OverviewEnterExitType::kImmediateEnter,
-            GetOverviewSession()->enter_exit_overview_type());
-}
-
 // Tests the grid bounds are as expected with different shelf auto hide
 // behaviors and alignments.
 TEST_P(OverviewSessionTest, GridBounds) {
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index f639edc..536dd6a 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -250,93 +250,6 @@
 }  // namespace
 
 // -----------------------------------------------------------------------------
-// TabDraggedWindowObserver:
-
-// The window observer that observes the current tab-dragged window. When it's
-// created, it observes the dragged window, and there are two possible results
-// after the user finishes dragging: 1) the dragged window stays a new window
-// and SplitViewController needs to decide where to put the window; 2) the
-// dragged window's tabs are attached into another browser window and thus is
-// destroyed.
-class SplitViewController::TabDraggedWindowObserver
-    : public aura::WindowObserver {
- public:
-  TabDraggedWindowObserver(
-      SplitViewController* split_view_controller,
-      aura::Window* dragged_window,
-      SplitViewController::SnapPosition desired_snap_position,
-      const gfx::Point& last_location_in_screen)
-      : split_view_controller_(split_view_controller),
-        dragged_window_(dragged_window),
-        desired_snap_position_(desired_snap_position),
-        last_location_in_screen_(last_location_in_screen) {
-    DCHECK(window_util::IsDraggingTabs(dragged_window_));
-    dragged_window_->AddObserver(this);
-  }
-
-  TabDraggedWindowObserver(const TabDraggedWindowObserver&) = delete;
-  TabDraggedWindowObserver& operator=(const TabDraggedWindowObserver&) = delete;
-
-  ~TabDraggedWindowObserver() override {
-    if (dragged_window_)
-      dragged_window_->RemoveObserver(this);
-  }
-
-  // aura::WindowObserver:
-  void OnWindowDestroying(aura::Window* window) override {
-    // At this point we know the newly created dragged window is going to be
-    // destroyed due to all of its tabs are attaching into another window.
-    EndTabDragging(window, /*is_being_destroyed=*/true);
-  }
-
-  void OnWindowPropertyChanged(aura::Window* window,
-                               const void* key,
-                               intptr_t old) override {
-    DCHECK_EQ(window, dragged_window_);
-    if (key == kIsDraggingTabsKey && !window_util::IsDraggingTabs(window)) {
-      // At this point we know the newly created dragged window just finished
-      // dragging.
-      EndTabDragging(window, /*is_being_destroyed=*/false);
-    }
-  }
-
- private:
-  // Called after the tab dragging is ended, the dragged window is either
-  // destroyed because of merging into another window, or stays as a separate
-  // window.
-  void EndTabDragging(aura::Window* window, bool is_being_destroyed) {
-    dragged_window_->RemoveObserver(this);
-    dragged_window_ = nullptr;
-
-    WindowState::Get(window)->set_snap_action_source(
-        WindowSnapActionSource::kDragTabToSnap);
-    split_view_controller_->EndWindowDragImpl(window, is_being_destroyed,
-                                              desired_snap_position_,
-                                              last_location_in_screen_);
-
-    // Update the source window's bounds if applicable.
-    UpdateSourceWindowBoundsAfterDragEnds(window);
-  }
-
-  // The source window might have been scaled down during dragging, we should
-  // update its bounds to ensure it has the right bounds after the drag ends.
-  void UpdateSourceWindowBoundsAfterDragEnds(aura::Window* window) {
-    aura::Window* source_window =
-        window->GetProperty(kTabDraggingSourceWindowKey);
-    if (source_window) {
-      TabletModeWindowState::UpdateWindowPosition(
-          WindowState::Get(source_window),
-          WindowState::BoundsChangeAnimationType::kAnimate);
-    }
-  }
-
-  SplitViewController* split_view_controller_;
-  aura::Window* dragged_window_;
-  SplitViewController::SnapPosition desired_snap_position_;
-  gfx::Point last_location_in_screen_;
-};
-
-// -----------------------------------------------------------------------------
 // DividerSnapAnimation:
 
 // Animates the divider to its closest fixed position.
@@ -560,15 +473,8 @@
     DCHECK(split_view_controller_->InTabletSplitViewMode());
 
     // Do not snap the window if the activation change is caused by dragging a
-    // window, or by dragging a tab. Note the two values
-    // WindowState::is_dragged() and IsDraggingTabs() might not be exactly the
-    // same under certain circumstance, e.g., when a tab is dragged out from a
-    // browser window, a new browser window will be created for the dragged tab
-    // and then be activated, and at that time, IsDraggingTabs() is true, but
-    // WindowState::is_dragged() is still false. And later after the window drag
-    // starts, WindowState::is_dragged() will then be true.
-    if (WindowState::Get(window)->is_dragged() ||
-        window_util::IsDraggingTabs(window)) {
+    // window.
+    if (WindowState::Get(window)->is_dragged()) {
       return;
     }
 
@@ -1636,13 +1542,9 @@
     aura::Window* dragged_window,
     SnapPosition desired_snap_position,
     const gfx::Point& last_location_in_screen) {
-  if (window_util::IsDraggingTabs(dragged_window)) {
-    dragged_window_observer_ = std::make_unique<TabDraggedWindowObserver>(
-        this, dragged_window, desired_snap_position, last_location_in_screen);
-  } else {
-    EndWindowDragImpl(dragged_window, dragged_window->is_destroying(),
-                      desired_snap_position, last_location_in_screen);
-  }
+  DCHECK(!window_util::IsDraggingTabs(dragged_window));
+  EndWindowDragImpl(dragged_window, dragged_window->is_destroying(),
+                    desired_snap_position, last_location_in_screen);
 }
 
 void SplitViewController::OnWindowDragCanceled() {
@@ -3044,22 +2946,9 @@
           WindowState::BoundsChangeAnimationType::kAnimate);
     }
   } else {
-    aura::Window* initiator_window =
-        window->GetProperty(kTabDraggingSourceWindowKey);
     // Note SnapWindow() might put the previous window that was snapped at the
     // |desired_snap_position| in overview.
     SnapWindow(window, desired_snap_position, /*activate_window=*/true);
-
-    if (!was_splitview_active && initiator_window &&
-        initiator_window != window) {
-      // If splitview mode was not active before snapping the dragged
-      // window, snap the initiator window to the other side of the screen
-      // if it's not the same window as the dragged window.
-      SnapWindow(initiator_window,
-                 (desired_snap_position == SnapPosition::kPrimary)
-                     ? SnapPosition::kSecondary
-                     : SnapPosition::kPrimary);
-    }
   }
 }
 
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h
index 4835ddee..0f04716 100644
--- a/ash/wm/splitview/split_view_controller.h
+++ b/ash/wm/splitview/split_view_controller.h
@@ -397,7 +397,6 @@
  private:
   friend class SplitViewControllerTest;
   friend class SplitViewOverviewSessionTest;
-  class TabDraggedWindowObserver;
   class DividerSnapAnimation;
   class AutoSnapController;
   class ToBeSnappedWindowsObserver;
@@ -604,9 +603,6 @@
   std::unique_ptr<ui::Layer> left_resize_backdrop_layer_;
   std::unique_ptr<ui::Layer> right_resize_backdrop_layer_;
 
-  // The window observer that obseves the tab-dragged window in tablet mode.
-  std::unique_ptr<TabDraggedWindowObserver> dragged_window_observer_;
-
   // The distance between the origin of the `split_view_divider_` and the origin
   // of the current display's work area in screen coordinates.
   //     |<---     divider_position_    --->|
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index 06a8e55..f8a3b9f0 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -47,10 +47,7 @@
 #include "ash/wm/splitview/split_view_drag_indicators.h"
 #include "ash/wm/splitview/split_view_metrics_controller.h"
 #include "ash/wm/splitview/split_view_utils.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_resizer.h"
 #include "ash/wm/window_state.h"
@@ -90,7 +87,7 @@
 // The observer to observe the overview states in |root_window_|.
 class OverviewStatesObserver : public OverviewObserver {
  public:
-  OverviewStatesObserver(aura::Window* root_window)
+  explicit OverviewStatesObserver(aura::Window* root_window)
       : root_window_(root_window) {
     Shell::Get()->overview_controller()->AddObserver(this);
   }
@@ -109,8 +106,9 @@
   }
   void OnOverviewModeEnding(OverviewSession* overview_session) override {
     OverviewGrid* grid = overview_session->GetGridWithRootWindow(root_window_);
-    if (!grid)
+    if (!grid) {
       return;
+    }
     overview_animate_when_exiting_ = grid->should_animate_when_exiting();
   }
 
@@ -166,8 +164,9 @@
     auto* ime = keyboard::KeyboardUIController::Get()->GetInputMethodForTest();
     ime->SetFocusedTextInputClient(this);
 
-    if (window_)
+    if (window_) {
       window_->Focus();
+    }
 
     ime->SetVirtualKeyboardVisibilityIfEnabled(true);
     ASSERT_TRUE(keyboard::WaitUntilShown());
@@ -187,10 +186,6 @@
   gfx::Rect caret_bounds_;
 };
 
-bool IsTabletMode() {
-  return Shell::Get()->tablet_mode_controller()->InTabletMode();
-}
-
 }  // namespace
 
 class SplitViewControllerTest : public AshTestBase {
@@ -254,8 +249,9 @@
   }
 
   void SkipDividerSnapAnimation() {
-    if (!IsDividerAnimating())
+    if (!IsDividerAnimating()) {
       return;
+    }
     split_view_controller()->StopAndShoveAnimatedDivider();
     split_view_controller()->EndResizeWithDividerImpl();
     split_view_controller()->EndTabletSplitViewAfterResizingIfAppropriate();
@@ -822,49 +818,6 @@
 }
 
 // Tests that the split divider has correct state after a window is destroyed
-// while being dragged from the top.
-TEST_F(SplitViewControllerTest,
-       DividerSetAsAlwaysOnTopAfterWindowDestroyedDuringDraggingFromTop) {
-  std::unique_ptr<aura::Window> window1 = CreateTestWindow();
-  std::unique_ptr<aura::Window> window2 = CreateTestWindow();
-  std::unique_ptr<aura::Window> window3 = CreateTestWindow();
-  window2->SetProperty(aura::client::kAppType,
-                       static_cast<int>(AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  // The divider should start always on top.
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-  // The divider should not be always on top while a window is being dragged.
-  std::unique_ptr<WindowResizer> resizer =
-      CreateWindowResizer(window2.get(), gfx::PointF(400, 0), HTCAPTION,
-                          ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-  EXPECT_EQ(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-  // If the dragged window is destroyed, the divider should be back to always on
-  // top, consistent with if the drag ends gracefully.
-  resizer.reset();
-  window2.reset();
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-  // |SplitViewDivider::is_dragging_window_| should be false, but instead of
-  // checking its value directly, we test for what may go wrong if it is true.
-  // If |SplitViewDivider::is_dragging_window_| is true, then the following call
-  // to |SplitViewController::SnapWindow| will set the divider to always on top,
-  // which is fine, but then the call to |wm::ActivateWindow| will change it
-  // back to not always on top (see |SplitViewDivider::OnWindowActivated|).
-  split_view_controller()->SnapWindow(
-      window3.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-  wm::ActivateWindow(window3.get());
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-}
-
-// Tests that the split divider has correct state after a window is destroyed
 // while being dragged from overview.
 TEST_F(SplitViewControllerTest,
        DividerSetAsAlwaysOnTopAfterWindowDestroyedDuringDraggingFromOverview) {
@@ -3558,2345 +3511,6 @@
       SplitViewMetricsController::DeviceOrientation::kLandscape, 1);
 }
 
-// Test the tab-dragging related functionalities in tablet mode. Tab(s) can be
-// dragged out of a window and then put in split view mode or merge into another
-// window.
-class SplitViewTabDraggingTest : public SplitViewControllerTest {
- public:
-  SplitViewTabDraggingTest() = default;
-
-  SplitViewTabDraggingTest(const SplitViewTabDraggingTest&) = delete;
-  SplitViewTabDraggingTest& operator=(const SplitViewTabDraggingTest&) = delete;
-
-  ~SplitViewTabDraggingTest() override = default;
-
- protected:
-  aura::Window* CreateWindowWithType(
-      const gfx::Rect& bounds,
-      AppType app_type,
-      aura::client::WindowType window_type = aura::client::WINDOW_TYPE_NORMAL) {
-    aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
-        new SplitViewTestWindowDelegate, window_type, -1, bounds);
-    window->SetProperty(aura::client::kAppType, static_cast<int>(app_type));
-    WindowState::Get(window)->Maximize();
-    return window;
-  }
-
-  // Starts tab dragging on |dragged_window|. |source_window| indicates which
-  // window the drag originates from. Returns the newly created WindowResizer
-  // for the |dragged_window|.
-  std::unique_ptr<WindowResizer> StartDrag(aura::Window* dragged_window,
-                                           aura::Window* source_window) {
-    // Drag operation activates the window first, then activates the dragged
-    // window.  Emulate this behavior.
-    wm::ActivateWindow(source_window);
-    SetIsInTabDragging(dragged_window, /*is_dragging=*/true, source_window);
-    wm::ActivateWindow(dragged_window);
-    std::unique_ptr<WindowResizer> resizer = CreateResizerForTest(
-        dragged_window, dragged_window->bounds().origin(), HTCAPTION);
-    GetBrowserWindowDragController(resizer.get())
-        ->drag_delegate_for_testing()
-        ->set_drag_start_deadline_for_testing(base::Time::Now());
-    return resizer;
-  }
-
-  // Drags the window to |end_position|.
-  void DragWindowTo(WindowResizer* resizer, const gfx::Point& end_position) {
-    ASSERT_TRUE(resizer);
-    resizer->Drag(gfx::PointF(end_position), 0);
-  }
-
-  // Drags the window with offest (delta_x, delta_y) to its initial position.
-  void DragWindowWithOffset(WindowResizer* resizer, int delta_x, int delta_y) {
-    ASSERT_TRUE(resizer);
-    gfx::PointF location = resizer->GetInitialLocation();
-    location.set_x(location.x() + delta_x);
-    location.set_y(location.y() + delta_y);
-    resizer->Drag(location, 0);
-  }
-
-  // Ends the drag. |resizer| will be deleted after exiting this function.
-  void CompleteDrag(std::unique_ptr<WindowResizer> resizer) {
-    ASSERT_TRUE(resizer.get());
-    resizer->CompleteDrag();
-    SetIsInTabDragging(resizer->GetTarget(), /*is_dragging=*/false);
-  }
-
-  // Fling to end the drag. |resizer| will be deleted after exiting this
-  // function.
-  void Fling(std::unique_ptr<WindowResizer> resizer, float velocity_y) {
-    ASSERT_TRUE(resizer.get());
-    aura::Window* target_window = resizer->GetTarget();
-    base::TimeTicks timestamp = base::TimeTicks::Now();
-    ui::GestureEventDetails details =
-        ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 0.f, velocity_y);
-    ui::GestureEvent event = ui::GestureEvent(
-        target_window->bounds().origin().x(),
-        target_window->bounds().origin().y(), ui::EF_NONE, timestamp, details);
-    ui::Event::DispatcherApi(&event).set_target(target_window);
-    resizer->FlingOrSwipe(&event);
-    SetIsInTabDragging(resizer->GetTarget(), /*is_dragging=*/false);
-  }
-
-  std::unique_ptr<WindowResizer> CreateResizerForTest(
-      aura::Window* window,
-      const gfx::Point& point_in_parent,
-      int window_component,
-      ::wm::WindowMoveSource source = ::wm::WINDOW_MOVE_SOURCE_TOUCH) {
-    return CreateWindowResizer(window, gfx::PointF(point_in_parent),
-                               window_component, source);
-  }
-
-  // Sets if |dragged_window| is currently in tab-dragging process.
-  // |source_window| is the window that the drag originates from. This method is
-  // used to simulate the start/stop of a window's tab-dragging by setting the
-  // two window properties, which are usually set in TabDragController::
-  // UpdateTabDraggingInfo() function.
-  void SetIsInTabDragging(aura::Window* dragged_window,
-                          bool is_dragging,
-                          aura::Window* source_window = nullptr) {
-    if (!is_dragging) {
-      dragged_window->ClearProperty(kIsDraggingTabsKey);
-      dragged_window->ClearProperty(kTabDraggingSourceWindowKey);
-    } else {
-      dragged_window->SetProperty(kIsDraggingTabsKey, is_dragging);
-      if (source_window != dragged_window)
-        dragged_window->SetProperty(kTabDraggingSourceWindowKey, source_window);
-    }
-  }
-
-  TabletModeWindowResizer* GetBrowserWindowDragController(
-      WindowResizer* resizer) {
-    WindowResizer* real_window_resizer;
-    // TODO(xdai): This piece of codes seems knowing too much impl details about
-    // WindowResizer. Revisit the logic here later to see if there is anything
-    // we can do to simplify the logic and hide impl details.
-    real_window_resizer = static_cast<DragWindowResizer*>(resizer)
-                              ->next_window_resizer_for_testing();
-    return static_cast<TabletModeWindowResizer*>(real_window_resizer);
-  }
-
-  SplitViewDragIndicators::WindowDraggingState GetWindowDraggingState(
-      WindowResizer* resizer) {
-    return GetBrowserWindowDragController(resizer)
-        ->drag_delegate_for_testing()
-        ->split_view_drag_indicators_for_testing()
-        ->current_window_dragging_state();
-  }
-
-  int GetIndicatorsThreshold(aura::Window* dragged_window) {
-    static const float kIndicatorsThresholdRatio = 0.1f;
-    const gfx::Rect work_area_bounds =
-        display::Screen::GetScreen()
-            ->GetDisplayNearestWindow(dragged_window)
-            .work_area();
-    return work_area_bounds.y() +
-           work_area_bounds.height() * kIndicatorsThresholdRatio;
-  }
-
-  gfx::Rect GetDropTargetBoundsDuringDrag(aura::Window* window) const {
-    OverviewSession* overview_session =
-        Shell::Get()->overview_controller()->overview_session();
-    DCHECK(overview_session);
-    OverviewGrid* current_grid =
-        overview_session->GetGridWithRootWindow(window->GetRootWindow());
-    DCHECK(current_grid);
-
-    OverviewItem* overview_item = current_grid->GetDropTarget();
-    return gfx::ToEnclosedRect(overview_item->GetTransformedBounds());
-  }
-};
-
-// Test that in tablet mode, we only allow dragging on browser or chrome app
-// window's caption area.
-TEST_F(SplitViewTabDraggingTest, OnlyAllowDraggingOnBrowserOrChromeAppWindow) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::CHROME_APP));
-  std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
-  std::unique_ptr<aura::Window> window4(
-      CreateWindowWithType(bounds, AppType::ARC_APP));
-
-  std::unique_ptr<WindowResizer> resizer =
-      CreateResizerForTest(window1.get(), gfx::Point(), HTCAPTION);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-
-  resizer = CreateResizerForTest(window2.get(), gfx::Point(), HTCAPTION);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-
-  resizer = CreateResizerForTest(window3.get(), gfx::Point(), HTCAPTION);
-  EXPECT_FALSE(resizer.get());
-
-  resizer = CreateResizerForTest(window4.get(), gfx::Point(), HTCAPTION);
-  EXPECT_FALSE(resizer.get());
-}
-
-// Test that in tablet mode, we only allow dragging that happens on window
-// caption or top area.
-TEST_F(SplitViewTabDraggingTest, OnlyAllowDraggingOnCaptionOrTopArea) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  // Only dragging on HTCAPTION or HTTOP area is allowed.
-  std::unique_ptr<WindowResizer> resizer =
-      CreateResizerForTest(window.get(), gfx::Point(), HTLEFT);
-  EXPECT_FALSE(resizer.get());
-  resizer = CreateResizerForTest(window.get(), gfx::Point(), HTRIGHT);
-  EXPECT_FALSE(resizer.get());
-  resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-  resizer = CreateResizerForTest(window.get(), gfx::Point(), HTTOP);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-
-  // No matter if we're in tab-dragging process, as long as the drag happens on
-  // the caption or top area, it should be able to drag the window.
-  SetIsInTabDragging(window.get(), /*is_dragging=*/true);
-  resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-
-  SetIsInTabDragging(window.get(), /*is_dragging=*/false);
-  resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
-  EXPECT_TRUE(resizer.get());
-  resizer->CompleteDrag();
-  resizer.reset();
-}
-
-// Test that in tablet mode, if the dragging is from mouse event, the mouse
-// cursor should be properly locked.
-TEST_F(SplitViewTabDraggingTest, LockCursor) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  SetIsInTabDragging(window.get(), /*is_dragging=*/true);
-  EXPECT_FALSE(Shell::Get()->cursor_manager()->IsCursorLocked());
-
-  std::unique_ptr<WindowResizer> resizer = CreateResizerForTest(
-      window.get(), gfx::Point(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE);
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(Shell::Get()->cursor_manager()->IsCursorLocked());
-
-  resizer->CompleteDrag();
-  resizer.reset();
-  EXPECT_FALSE(Shell::Get()->cursor_manager()->IsCursorLocked());
-}
-
-// Test that in tablet mode, if a window is in tab-dragging process, its
-// backdrop is disabled during dragging process.
-TEST_F(SplitViewTabDraggingTest, NoBackDropDuringDragging) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  WindowBackdrop* window_backdrop = WindowBackdrop::Get(window.get());
-  EXPECT_EQ(window_backdrop->mode(), WindowBackdrop::BackdropMode::kAuto);
-  EXPECT_EQ(window_backdrop->type(), WindowBackdrop::BackdropType::kOpaque);
-
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window.get(), window.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(window_backdrop->temporarily_disabled());
-  EXPECT_EQ(window_backdrop->mode(), WindowBackdrop::BackdropMode::kAuto);
-  EXPECT_EQ(window_backdrop->type(), WindowBackdrop::BackdropType::kOpaque);
-
-  resizer->Drag(gfx::PointF(), 0);
-  EXPECT_TRUE(window_backdrop->temporarily_disabled());
-  EXPECT_EQ(window_backdrop->mode(), WindowBackdrop::BackdropMode::kAuto);
-  EXPECT_EQ(window_backdrop->type(), WindowBackdrop::BackdropType::kOpaque);
-
-  resizer->CompleteDrag();
-  EXPECT_FALSE(window_backdrop->temporarily_disabled());
-  EXPECT_EQ(window_backdrop->mode(), WindowBackdrop::BackdropMode::kAuto);
-  EXPECT_EQ(window_backdrop->type(), WindowBackdrop::BackdropType::kOpaque);
-}
-
-// Test that in tablet mode, the window that is in tab-dragging process should
-// not be shown in overview mode.
-TEST_F(SplitViewTabDraggingTest, DoNotShowDraggedWindowInOverview) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  ToggleOverview();
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  OverviewSession* overview_session =
-      Shell::Get()->overview_controller()->overview_session();
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window2.get()));
-  ToggleOverview();
-
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-
-  // Since the source window is the dragged window, the overview should have
-  // been opened.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  overview_session = Shell::Get()->overview_controller()->overview_session();
-  EXPECT_FALSE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window2.get()));
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-}
-
-// Test that if a window is in tab-dragging process, the split divider is placed
-// below the current dragged window.
-TEST_F(SplitViewTabDraggingTest, DividerIsBelowDraggedWindow) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  views::Widget* split_divider_widget =
-      split_view_controller()->split_view_divider()->divider_widget();
-  EXPECT_NE(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
-
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_EQ(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
-
-  resizer->Drag(gfx::PointF(), 0);
-  EXPECT_EQ(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_NE(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
-}
-
-// Test the functionalities that are related to dragging a maximized window's
-// tabs. See the expected behaviors described in go/tab-dragging-in-tablet-mode.
-TEST_F(SplitViewTabDraggingTest, DragMaximizedWindow) {
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  WindowState::Get(window1.get())->Maximize();
-  WindowState::Get(window2.get())->Maximize();
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
-  EXPECT_TRUE(WindowState::Get(window2.get())->IsMaximized());
-
-  // 1. If the dragged window is the source window:
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  // Overview should have been opened because the dragged window is the source
-  // window.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // 1.a. Drag the window to move a small amount of distance will maximize the
-  // window again.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag the window past the indicators threshold to show the indicators.
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window1.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
-  EXPECT_TRUE(WindowState::Get(window2.get())->IsMaximized());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // 1.b. Drag the window long enough (pass one fourth of the screen vertical
-  // height) to snap the window to splitscreen.
-  resizer = StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  DragWindowTo(resizer.get(), gfx::Point(0, 300));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // Maximize the snapped window to end split view mode and overview mode.
-  WindowState::Get(window1.get())->Maximize();
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // 2. If the dragged window is not the source window:
-  resizer = StartDrag(window1.get(), window2.get());
-  ASSERT_TRUE(resizer.get());
-  // Overview is not opened for this case.
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  // When the drag starts, the source window's bounds are the same with the
-  // work area's bounds.
-  const display::Display display =
-      display::Screen::GetScreen()->GetDisplayNearestWindow(window1.get());
-  const gfx::Rect work_area_bounds = display.work_area();
-  EXPECT_EQ(window2->GetBoundsInScreen(), work_area_bounds);
-  EXPECT_TRUE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-
-  // 2.a. Drag the window a small amount of distance and release will maximize
-  // the window.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag the window past the indicators threshold to show the indicators.
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window1.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  // The source window should also have been scaled.
-  EXPECT_NE(window2->GetBoundsInScreen(), work_area_bounds);
-  EXPECT_FALSE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
-  EXPECT_TRUE(WindowState::Get(window2.get())->IsMaximized());
-  // The source window should have restored its bounds.
-  EXPECT_EQ(window2->GetBoundsInScreen(), work_area_bounds);
-  EXPECT_TRUE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-
-  // 2.b. Drag the window long enough to snap the window. The source window will
-  // snap to the other side of the splitscreen.
-  resizer = StartDrag(window1.get(), window2.get());
-  ASSERT_TRUE(resizer.get());
-  DragWindowTo(resizer.get(), gfx::Point(600, 300));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary,
-            GetWindowDraggingState(resizer.get()));
-  // The source window's bounds should be the same as the left snapped window
-  // bounds as it's to be snapped to LEFT.
-  EXPECT_EQ(window2->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kPrimary, window2.get()));
-  EXPECT_FALSE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(0, 300));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  // The source window's bounds should be the same as the right snapped window
-  // bounds as it's to be snapped to RIGHT.
-  EXPECT_EQ(window2->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kSecondary, window2.get()));
-  EXPECT_FALSE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window2.get());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_TRUE(window1->GetProperty(chromeos::kCanAttachToAnotherWindowKey));
-  EXPECT_EQ(window1.get(), window_util::GetActiveWindow());
-
-  EndSplitView();
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-
-  // 3. If the dragged window is destroyed during dragging (may happen due to
-  // all its tabs are attached into another window), nothing changes.
-  resizer = StartDrag(window1.get(), window2.get());
-  ASSERT_TRUE(resizer.get());
-  resizer->Drag(gfx::PointF(0, 300), 0);
-  resizer->CompleteDrag();
-  resizer.reset();
-  window1.reset();
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_TRUE(WindowState::Get(window2.get())->IsMaximized());
-
-  // 4. If the dragged window can't be snapped, then the source window should
-  // not be put to the snapped position during drag.
-  const gfx::Rect display_bounds = display.bounds();
-  window1 = std::unique_ptr<aura::Window>(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  aura::test::TestWindowDelegate* delegate =
-      static_cast<aura::test::TestWindowDelegate*>(window1->delegate());
-  delegate->set_minimum_size(
-      gfx::Size(display_bounds.width() * 0.67f, display_bounds.height()));
-  EXPECT_FALSE(split_view_controller()->CanSnapWindow(window1.get()));
-  resizer = StartDrag(window1.get(), window2.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  DragWindowTo(resizer.get(),
-               gfx::Point(0, GetIndicatorsThreshold(window1.get()) + 10));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  // The souce window should has been scaled but not put to the right snapped
-  // window's position.
-  EXPECT_NE(window2->GetBoundsInScreen(), work_area_bounds);
-  EXPECT_NE(window2->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kSecondary, window2.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-}
-
-// Test the functionalities that are related to dragging a snapped window in
-// splitscreen. There are always two snapped window when the drag starts (i.e.,
-// the overview mode is not active). See the expected behaviors described in
-// go/tab-dragging-in-tablet-mode.
-TEST_F(SplitViewTabDraggingTest, DragSnappedWindow) {
-  ui::ScopedAnimationDurationScaleMode anmatin_scale(
-      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
-
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window2.get());
-
-  // 1. If the dragged window is the source window:
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  // In this case overview grid will be opened, containing |window3|.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  OverviewSession* overview_session =
-      Shell::Get()->overview_controller()->overview_session();
-  EXPECT_FALSE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_FALSE(overview_session->IsWindowInOverview(window2.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window3.get()));
-  // Drag to enter doesn't trigger animation.
-  CheckOverviewEnterExitHistogram("EnterInSplitViewByDrag", {0, 0}, {0, 0});
-
-  // 1.a. If the window is only dragged for a small distance, the window will
-  // be put back to its original position. Overview mode will be ended.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  CompleteDrag(std::move(resizer));
-  WaitForOverviewExitAnimation();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window2.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("ExitInSplitViewByDrag", {0, 0}, {0, 1});
-
-  // 1.b. If the window is dragged long enough, it can replace the other split
-  // window.
-  resizer = StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  DragWindowTo(resizer.get(), gfx::Point(600, 300));
-  // Preview window shows up on overview side of screen.
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary,
-            GetWindowDraggingState(resizer.get()));
-  CheckOverviewEnterExitHistogram("EnterInSplitViewByDrag2", {0, 0}, {0, 1});
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  overview_session = Shell::Get()->overview_controller()->overview_session();
-  EXPECT_FALSE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window2.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window3.get()));
-  // Still in overview.
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitViewByDrag", {0, 0}, {0, 1});
-  // Snap |window2| again to test 1.c.
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kPrimary);
-  WaitForOverviewExitAnimation();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  CheckOverviewEnterExitHistogram("ExitInSplitViewBySnap", {0, 0}, {0, 2});
-
-  // 1.c. If the dragged window is destroyed during dragging (may happen due to
-  // all its tabs are attached into another window), nothing changes.
-  resizer = StartDrag(window1.get(), window1.get());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("EnterInSplitViewByDrag3", {0, 0}, {0, 2});
-  resizer->Drag(gfx::PointF(100, 100), 0);
-  resizer->CompleteDrag();
-  resizer.reset();
-  window1.reset();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  // Still in overview.
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitViewByDrag3", {0, 0},
-                                  {0, 2});
-
-  // Recreate |window1| and snap it to test the following senarioes.
-  window1.reset(CreateWindowWithType(bounds, AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kSecondary);
-  WaitForOverviewExitAnimation();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window2.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  CheckOverviewEnterExitHistogram("ExitInSplitViewBySnap2", {0, 0}, {0, 3});
-
-  // 2. If the dragged window is not the source window:
-  // In this case, |window3| can be regarded as a window that originates from
-  // |window2|.
-  resizer = StartDrag(window3.get(), window2.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window2.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  EXPECT_EQ(window2->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kPrimary, window2.get()));
-  // Not in overview.
-  CheckOverviewEnterExitHistogram("DoNotEnterInSplitViewByDrag", {0, 0},
-                                  {0, 3});
-
-  // 2.a. If the window is only dragged for a small amount of distance, it will
-  // replace the same side of the split window that it originates from.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag the window past the indicators threshold to "show the indicators" (see
-  // the comment about this whole unit test).
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window1.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  // The source window's bounds should remain the same.
-  EXPECT_EQ(window2->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kPrimary, window2.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window3.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("DoNotEnterInSplitViewByDrag2", {0, 0},
-                                  {0, 3});
-
-  // 2.b. If the window is dragged long enough, it can replace the other side of
-  // the split window.
-  resizer = StartDrag(window2.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window3.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("DoNotEnterInSplitViewByDrag3", {0, 0},
-                                  {0, 3});
-
-  DragWindowTo(resizer.get(), gfx::Point(0, 300));
-  // Preview window shows up on overview side of screen.
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("DoNotEnterInSplitViewByDrag4", {0, 0},
-                                  {0, 3});
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window2.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-}
-
-// Test the functionalities that are related to dragging a snapped window while
-// overview grid is open on the other side of the screen. See the expected
-// behaviors described in go/tab-dragging-in-tablet-mode.
-// TODO(crbug.com/1337266): Remove this test when classic view tab dragging is
-// removed.
-TEST_F(SplitViewTabDraggingTest, DISABLED_DragSnappedWindowWhileOverviewOpen) {
-  ui::ScopedAnimationDurationScaleMode anmatin_scale(
-      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
-
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  // Prepare the testing senario:
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  ToggleOverview();
-  WaitForOverviewEnterAnimation();
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  CheckOverviewEnterExitHistogram("EnterInSplitView", {0, 1}, {0, 0});
-
-  // 1. If the dragged window is the source window:
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  // Overivew mode is still active, but split view mode is ended due to dragging
-  // the only snapped window.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-
-  // 1.a. If the window is only dragged for a small amount of distance
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag the window past the indicators threshold should "show the indicators"
-  // (see the comment on SplitViewTabDraggingTest.DragSnappedWindow).
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window1.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  CompleteDrag(std::move(resizer));
-  WaitForOverviewExitAnimation();
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  // It exits SplitView during drag, so exit animation is performed in tablet
-  // mode.
-  CheckOverviewEnterExitHistogram("ExitInSplitViewToTablet", {0, 1}, {1, 0});
-
-  // 1.b. If the window is dragged long enough, it can be snappped again.
-  // Prepare the testing senario first.
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  ToggleOverview();
-  WaitForOverviewEnterAnimation();
-  CheckOverviewEnterExitHistogram("EnterInSplitView2", {0, 2}, {1, 0});
-
-  resizer = StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitView2", {0, 2}, {1, 0});
-
-  DragWindowTo(resizer.get(), gfx::Point(0, 300));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  OverviewSession* overview_session =
-      Shell::Get()->overview_controller()->overview_session();
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window2.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window3.get()));
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitView3", {0, 2}, {1, 0});
-
-  // 2. If the dragged window is not the source window:
-  // Prepare the testing senario first. Remove |window2| from overview first
-  // before tab-dragging.
-  OverviewGrid* current_grid =
-      overview_session->GetGridWithRootWindow(window2->GetRootWindow());
-  ASSERT_TRUE(current_grid);
-  overview_session->RemoveItem(
-      current_grid->GetOverviewItemContaining(window2.get()));
-
-  resizer = StartDrag(window2.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag a samll amount of distance.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
-            GetWindowDraggingState(resizer.get()));
-  // Drag the window past the indicators threshold to "show the indicators" (see
-  // the comment on SplitViewTabDraggingTest.DragSnappedWindow).
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window1.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  // The source window still remains the same bounds.
-  EXPECT_EQ(window1->GetBoundsInScreen(),
-            split_view_controller()->GetSnappedWindowBoundsInScreen(
-                SplitViewController::SnapPosition::kPrimary, window1.get()));
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitView4", {0, 2}, {1, 0});
-
-  // 2.a. The dragged window can replace the only snapped window in the split
-  // screen. After that, the old snapped window will be put back in overview.
-  DragWindowTo(resizer.get(), gfx::Point(0, 500));
-  // Preview window shows up on overview side of screen.
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window2.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  overview_session = Shell::Get()->overview_controller()->overview_session();
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window3.get()));
-  CheckOverviewEnterExitHistogram("DoNotExitInSplitView5", {0, 2}, {1, 0});
-
-  // 2.b. The dragged window can snap to the other side of the splitscreen,
-  // causing overview mode to end.
-  // Remove |window1| from overview first before tab dragging.
-  overview_session->RemoveItem(
-      current_grid->GetOverviewItemContaining(window1.get()));
-  resizer = StartDrag(window1.get(), window2.get());
-  ASSERT_TRUE(resizer.get());
-  DragWindowTo(resizer.get(), gfx::Point(600, 500));
-  // Preview window shows up on overview side of screen.
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  WaitForOverviewExitAnimation();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_EQ(split_view_controller()->primary_window(), window2.get());
-  EXPECT_EQ(split_view_controller()->secondary_window(), window1.get());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  CheckOverviewEnterExitHistogram("ExitInSplitView", {0, 2}, {1, 1});
-}
-
-// Test that if a window is in tab-dragging process when overview is open, the
-// new window item widget shows up when the drag starts, and is destroyed after
-// the drag ends.
-TEST_F(SplitViewTabDraggingTest, ShowNewWindowItemWhenDragStarts) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // Now drags |window1|.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  // Overview should have been opened.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-
-  // Test that the new window item widget shows up as the first one of the
-  // windows in the grid.
-  OverviewSession* overview_session =
-      Shell::Get()->overview_controller()->overview_session();
-  OverviewGrid* current_grid =
-      overview_session->GetGridWithRootWindow(window1->GetRootWindow());
-  ASSERT_TRUE(current_grid);
-  views::Widget* drop_target_widget = current_grid->drop_target_widget();
-  EXPECT_TRUE(drop_target_widget);
-
-  OverviewItem* drop_target = current_grid->GetOverviewItemContaining(
-      drop_target_widget->GetNativeWindow());
-  ASSERT_TRUE(drop_target);
-  EXPECT_EQ(drop_target, current_grid->window_list().front().get());
-  const gfx::Rect drop_target_bounds =
-      gfx::ToEnclosingRect(drop_target->target_bounds());
-  // We want to drag onto the drop target, but not too close to the edge of the
-  // screen, as we do not want to snap the window.
-  DragWindowTo(resizer.get(), gfx::Point(drop_target_bounds.right() - 2,
-                                         drop_target_bounds.CenterPoint().y()));
-  CompleteDrag(std::move(resizer));
-
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  // Test that the dragged window has been added to the overview mode, and it is
-  // added at the front of the grid.
-  EXPECT_EQ(current_grid->window_list().size(), 2u);
-  OverviewItem* first_overview_item =
-      current_grid->GetOverviewItemContaining(window1.get());
-  EXPECT_EQ(first_overview_item, current_grid->window_list().front().get());
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window1.get()));
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window3.get()));
-  // Test that the new window item widget has been destroyed.
-  EXPECT_FALSE(current_grid->drop_target_widget());
-}
-
-// Tests that if overview is ended because of releasing the dragged window, we
-// should not do animation when exiting overview.
-TEST_F(SplitViewTabDraggingTest, OverviewExitAnimationTest) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<OverviewStatesObserver> overview_observer =
-      std::make_unique<OverviewStatesObserver>(window1->GetRootWindow());
-
-  // 1) If dragging a maximized window:
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  // Overview should have been opened because the dragged window is the source
-  // window.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  // The value should be properly initialized.
-  EXPECT_TRUE(overview_observer->overview_animate_when_exiting());
-
-  // Now release the dragged window. There should be no animation when exiting
-  // overview.
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_FALSE(overview_observer->overview_animate_when_exiting());
-
-  // 2) If dragging a snapped window:
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  overview_observer =
-      std::make_unique<OverviewStatesObserver>(window1->GetRootWindow());
-  resizer = StartDrag(window1.get(), window1.get());
-  ASSERT_TRUE(resizer.get());
-  // Overview should have been opened behind the dragged window.
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  // Split view should still be active.
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  // The value should be properly initialized.
-  EXPECT_TRUE(overview_observer->overview_animate_when_exiting());
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_FALSE(overview_observer->overview_animate_when_exiting());
-}
-
-// Checks the drag indicators window dragging state for dragging from the top.
-TEST_F(SplitViewTabDraggingTest, DragIndicatorsInPortraitOrientationTest) {
-  UpdateDisplay("800x600");
-  int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-  display::test::ScopedSetInternalDisplayId set_internal(display_manager,
-                                                         display_id);
-  ScreenOrientationControllerTestApi test_api(
-      Shell::Get()->screen_orientation_controller());
-  ASSERT_EQ(test_api.GetCurrentOrientation(),
-            chromeos::OrientationType::kLandscapePrimary);
-
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  WindowState::Get(window.get())->Maximize();
-  EXPECT_TRUE(WindowState::Get(window.get())->IsMaximized());
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window.get(), window.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  // Drag the window past the indicators threshold to show the indicators.
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(window.get())->IsMaximized());
-
-  // Rotate the screen by 270 degree to portrait primary orientation.
-  test_api.SetDisplayRotation(display::Display::ROTATE_270,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            chromeos::OrientationType::kPortraitPrimary);
-  resizer = StartDrag(window.get(), window.get());
-  ASSERT_TRUE(resizer.get());
-  // Drag the window past the indicators threshold to show the indicators.
-  DragWindowTo(resizer.get(),
-               gfx::Point(200, GetIndicatorsThreshold(window.get())));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromTop,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(window.get())->IsMaximized());
-}
-
-// Tests that if dragging a window into the preview split area, overview bounds
-// should be adjusted accordingly.
-TEST_F(SplitViewTabDraggingTest, AdjustOverviewBoundsDuringDragging) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  OverviewController* selector_controller = Shell::Get()->overview_controller();
-  EXPECT_FALSE(selector_controller->InOverviewSession());
-
-  // Start dragging |window1|.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  // Overview should have been opened.
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-
-  // Test that the drop target shows up as the first item in overview.
-  OverviewGrid* current_grid =
-      selector_controller->overview_session()->GetGridWithRootWindow(
-          window1->GetRootWindow());
-  EXPECT_TRUE(current_grid->GetDropTarget());
-  const gfx::Rect work_area_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window1.get());
-  const gfx::Rect expected_grid_bounds =
-      ShrinkBoundsByHotseatInset(work_area_bounds);
-  EXPECT_EQ(expected_grid_bounds, current_grid->bounds_for_testing());
-
-  auto target_opacity = [](views::Widget* widget) {
-    return widget->GetNativeWindow()->layer()->GetTargetOpacity();
-  };
-  // The drop target should be visible.
-  views::Widget* drop_target_widget = current_grid->drop_target_widget();
-  EXPECT_TRUE(drop_target_widget);
-  // Drop target's bounds has been set when added it into overview, which is not
-  // equals to the window's bounds.
-  EXPECT_EQ(drop_target_widget->GetNativeWindow()->bounds(),
-            GetDropTargetBoundsDuringDrag(window1.get()));
-  EXPECT_NE(drop_target_widget->GetNativeWindow()->bounds(), window1->bounds());
-  EXPECT_EQ(1.f, target_opacity(drop_target_widget));
-
-  // Now drag |window1| to the left preview split area.
-  DragWindowTo(resizer.get(),
-               gfx::Point(0, work_area_bounds.CenterPoint().y()));
-  EXPECT_EQ(current_grid->bounds_for_testing(),
-            ShrinkBoundsByHotseatInset(
-                split_view_controller()->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kSecondary,
-                    /*window_for_minimum_size=*/nullptr)));
-  EXPECT_EQ(0.f, target_opacity(drop_target_widget));
-
-  // Drag it to middle.
-  DragWindowTo(resizer.get(), work_area_bounds.CenterPoint());
-  EXPECT_EQ(expected_grid_bounds, current_grid->bounds_for_testing());
-  EXPECT_EQ(1.f, target_opacity(drop_target_widget));
-
-  // Drag |window1| to the right preview split area.
-  DragWindowTo(resizer.get(), gfx::Point(work_area_bounds.right(),
-                                         work_area_bounds.CenterPoint().y()));
-  EXPECT_EQ(current_grid->bounds_for_testing(),
-            ShrinkBoundsByHotseatInset(
-                split_view_controller()->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kPrimary,
-                    /*window_for_minimum_size=*/nullptr)));
-  EXPECT_EQ(0.f, target_opacity(drop_target_widget));
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-
-  // Snap another window should end overview.
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kPrimary);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_FALSE(selector_controller->InOverviewSession());
-
-  // Now drag |window1| again. Overview and splitview should be both active at
-  // the same time during dragging. Since one window is snapped, the hotseat
-  // should not be visible and should not affect the grid bounds.
-  resizer = StartDrag(window1.get(), window1.get());
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-
-  current_grid = selector_controller->overview_session()->GetGridWithRootWindow(
-      window1->GetRootWindow());
-  // The drop target should be visible.
-  drop_target_widget = current_grid->drop_target_widget();
-  EXPECT_TRUE(drop_target_widget);
-  EXPECT_EQ(1.f, target_opacity(drop_target_widget));
-  EXPECT_EQ(drop_target_widget->GetNativeWindow()->bounds(),
-            GetDropTargetBoundsDuringDrag(window1.get()));
-  EXPECT_NE(drop_target_widget->GetNativeWindow()->bounds(), window1->bounds());
-  EXPECT_EQ(current_grid->bounds_for_testing(),
-            ShrinkBoundsByHotseatInset(
-                split_view_controller()->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kSecondary,
-                    /*window_for_minimum_size=*/nullptr)));
-
-  // Drag |window1| to the right preview split area.
-  DragWindowTo(resizer.get(), gfx::Point(work_area_bounds.right(),
-                                         work_area_bounds.CenterPoint().y()));
-
-  // Overview bounds stays the same.
-  EXPECT_EQ(current_grid->bounds_for_testing(),
-            ShrinkBoundsByHotseatInset(
-                split_view_controller()->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kSecondary,
-                    /*window_for_minimum_size=*/nullptr)));
-  EXPECT_EQ(0.f, target_opacity(drop_target_widget));
-
-  // Drag |window1| to the left preview split area.
-  DragWindowTo(resizer.get(),
-               gfx::Point(0, work_area_bounds.CenterPoint().y()));
-  EXPECT_EQ(current_grid->bounds_for_testing(),
-            ShrinkBoundsByHotseatInset(
-                split_view_controller()->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kSecondary,
-                    /*window_for_minimum_size=*/nullptr)));
-  EXPECT_EQ(0.f, target_opacity(drop_target_widget));
-
-  CompleteDrag(std::move(resizer));
-
-  // |window1| should now snap to left. |window2| is put back in overview.
-  EXPECT_EQ(split_view_controller()->primary_window(), window1.get());
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-  EXPECT_TRUE(selector_controller->overview_session()->IsWindowInOverview(
-      window2.get()));
-
-  // Now drag |window1| again.
-  resizer = StartDrag(window1.get(), window1.get());
-  // Splitview should end now, but overview should still active.
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-  // The size of drop target should still not be the same as the dragged
-  // window's size.
-  current_grid = selector_controller->overview_session()->GetGridWithRootWindow(
-      window1->GetRootWindow());
-  drop_target_widget = current_grid->drop_target_widget();
-  EXPECT_TRUE(drop_target_widget);
-  EXPECT_EQ(1.f, target_opacity(drop_target_widget));
-  EXPECT_EQ(drop_target_widget->GetNativeWindow()->bounds(),
-            GetDropTargetBoundsDuringDrag(window1.get()));
-  EXPECT_NE(drop_target_widget->GetNativeWindow()->bounds(), window1->bounds());
-  CompleteDrag(std::move(resizer));
-}
-
-// Tests that a dragged window's bounds should be updated before dropping onto
-// the drop target to add into overview.
-TEST_F(SplitViewTabDraggingTest, WindowBoundsUpdatedBeforeAddingToOverview) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  wm::ActivateWindow(window1.get());
-  gfx::Rect tablet_mode_bounds = window1->bounds();
-  EXPECT_NE(bounds, tablet_mode_bounds);
-
-  // Drag |window1|. Overview should open behind the dragged window.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // Change the |window1|'s bounds to simulate what might happen in reality.
-  window1->SetBounds(bounds);
-  EXPECT_EQ(bounds, window1->bounds());
-
-  // Drop |window1| to the drop target in overview.
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  OverviewSession* overview_session = overview_controller->overview_session();
-  OverviewGrid* current_grid =
-      overview_session->GetGridWithRootWindow(window1->GetRootWindow());
-  ASSERT_TRUE(current_grid);
-  EXPECT_EQ(1u, current_grid->window_list().size());
-
-  OverviewItem* overview_item = current_grid->GetDropTarget();
-  ASSERT_TRUE(overview_item);
-  gfx::Rect drop_target_bounds =
-      gfx::ToEnclosingRect(overview_item->target_bounds());
-  DragWindowTo(resizer.get(), drop_target_bounds.CenterPoint());
-
-  CompleteDrag(std::move(resizer));
-  // |window1| should have been merged into overview.
-  EXPECT_EQ(current_grid->window_list().size(), 1u);
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window1.get()));
-  // |window1|'s bounds should have been updated to its tablet mode bounds.
-  EXPECT_EQ(tablet_mode_bounds, window1->bounds());
-  overview_item = current_grid->window_list().front().get();
-  // The new overview item's bounds should be the same during drag and after
-  // drag.
-  EXPECT_EQ(drop_target_bounds,
-            gfx::ToEnclosingRect(overview_item->target_bounds()));
-  ToggleOverview();
-  EXPECT_FALSE(overview_controller->InOverviewSession());
-
-  // Drag |window1|. Overview should open behind the dragged window.
-  resizer = StartDrag(window1.get(), window1.get());
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-
-  // Change the |window1|'s bounds to simulate what might happen in reality.
-  window1->SetBounds(bounds);
-  EXPECT_EQ(bounds, window1->bounds());
-
-  // Drag the window to right bottom outside the drop target, the window's
-  // bounds should also be updated before being dropped into overview.
-  drop_target_bounds = GetDropTargetBoundsDuringDrag(window1.get());
-  DragWindowTo(resizer.get(),
-               drop_target_bounds.bottom_right() + gfx::Vector2d(10, 10));
-  CompleteDrag(std::move(resizer));
-  // |window1| should have been merged into overview.
-  EXPECT_TRUE(overview_controller->overview_session()->IsWindowInOverview(
-      window1.get()));
-  // |window1|'s bounds should have been updated to its tablet mode bounds.
-  EXPECT_EQ(tablet_mode_bounds, window1->bounds());
-}
-
-// Tests that window should be dropped into overview if has been dragged further
-// than half of the distance from top of display to the top of drop target.
-TEST_F(SplitViewTabDraggingTest, DropWindowIntoOverviewOnDragPositionTest) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> browser_window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  WindowState::Get(browser_window1.get())->Maximize();
-  gfx::Rect work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(browser_window1.get())
-          .work_area();
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(browser_window1.get(), browser_window1.get());
-
-  // Restore window back to maximized if it has been dragged less than the
-  // distance threshold.
-  gfx::Rect drop_target_bounds =
-      GetDropTargetBoundsDuringDrag(browser_window1.get());
-  DragWindowTo(
-      resizer.get(),
-      gfx::Point(
-          200, work_area_bounds.y() +
-                   TabletModeWindowDragDelegate::kDragPositionToOverviewRatio *
-                       (drop_target_bounds.y() - work_area_bounds.y()) -
-                   10));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(browser_window1.get())->IsMaximized());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // Drop window into overview if it has been dragged further than the distance
-  // threshold.
-  resizer = StartDrag(browser_window1.get(), browser_window1.get());
-  drop_target_bounds = GetDropTargetBoundsDuringDrag(browser_window1.get());
-  DragWindowTo(
-      resizer.get(),
-      gfx::Point(
-          200, work_area_bounds.y() +
-                   TabletModeWindowDragDelegate::kDragPositionToOverviewRatio *
-                       (drop_target_bounds.y() - work_area_bounds.y()) +
-                   10));
-  CompleteDrag(std::move(resizer));
-  OverviewSession* overview_session =
-      Shell::Get()->overview_controller()->overview_session();
-  EXPECT_TRUE(overview_session->IsWindowInOverview(browser_window1.get()));
-  ToggleOverview();
-
-  // Do not consider the drag position if preview area is shown. Window should
-  // to be snapped in this case.
-  resizer = StartDrag(browser_window1.get(), browser_window1.get());
-  drop_target_bounds = GetDropTargetBoundsDuringDrag(browser_window1.get());
-  DragWindowTo(resizer.get(), gfx::Point(0, drop_target_bounds.y() + 10));
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState(resizer.get()));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(browser_window1.get())->IsSnapped());
-  EXPECT_EQ(SplitViewController::State::kPrimarySnapped,
-            split_view_controller()->state());
-
-  // Should not consider the drag position if splitview is active. Window should
-  // still back to be snapped.
-  std::unique_ptr<aura::Window> browser_window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      browser_window2.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  resizer = StartDrag(browser_window1.get(), browser_window1.get());
-  drop_target_bounds = GetDropTargetBoundsDuringDrag(browser_window1.get());
-  DragWindowTo(resizer.get(), gfx::Point(0, drop_target_bounds.y() + 10));
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EndSplitView();
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-
-  // Restore window back to maximized if it has been dragged less than the
-  // distance threshold when dock magnifier is enabled.
-  Shell::Get()->docked_magnifier_controller()->SetEnabled(true);
-  work_area_bounds = display::Screen::GetScreen()
-                         ->GetDisplayNearestWindow(browser_window1.get())
-                         .work_area();
-  resizer = StartDrag(browser_window1.get(), browser_window1.get());
-  drop_target_bounds = GetDropTargetBoundsDuringDrag(browser_window1.get());
-  DragWindowTo(
-      resizer.get(),
-      gfx::Point(
-          200, work_area_bounds.y() +
-                   TabletModeWindowDragDelegate::kDragPositionToOverviewRatio *
-                       (drop_target_bounds.y() - work_area_bounds.y()) -
-                   10));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(WindowState::Get(browser_window1.get())->IsMaximized());
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-}
-
-// Tests that a dragged window should have the active window shadow during
-// dragging.
-TEST_F(SplitViewTabDraggingTest, DraggedWindowShouldHaveActiveWindowShadow) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  wm::ActivateWindow(window1.get());
-  wm::ActivateWindow(window2.get());
-  window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
-  window2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
-
-  // 1) Start dragging |window2|. |window2| is the source window.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window2.get(), window2.get());
-  // |window2| should have the active window shadow.
-  ::wm::ShadowController* shadow_controller = Shell::Get()->shadow_controller();
-  ui::Shadow* shadow = shadow_controller->GetShadowForWindow(window2.get());
-  ASSERT_TRUE(shadow);
-  EXPECT_EQ(shadow->desired_elevation(), ::wm::kShadowElevationActiveWindow);
-  EXPECT_TRUE(shadow_controller->IsShadowVisibleForWindow(window2.get()));
-
-  CompleteDrag(std::move(resizer));
-  Shell::Get()->shadow_controller()->UpdateShadowForWindow(window2.get());
-  shadow = shadow_controller->GetShadowForWindow(window2.get());
-  ASSERT_TRUE(shadow);
-  EXPECT_FALSE(shadow_controller->IsShadowVisibleForWindow(window2.get()));
-
-  // 2) Start dragging |window2|, but |window2| is not the source window.
-  resizer = StartDrag(window2.get(), window1.get());
-  shadow = shadow_controller->GetShadowForWindow(window2.get());
-  ASSERT_TRUE(shadow);
-  EXPECT_EQ(shadow->desired_elevation(), ::wm::kShadowElevationActiveWindow);
-  EXPECT_TRUE(shadow_controller->IsShadowVisibleForWindow(window2.get()));
-
-  CompleteDrag(std::move(resizer));
-  Shell::Get()->shadow_controller()->UpdateShadowForWindow(window2.get());
-  shadow = shadow_controller->GetShadowForWindow(window2.get());
-  ASSERT_TRUE(shadow);
-  EXPECT_FALSE(shadow_controller->IsShadowVisibleForWindow(window2.get()));
-}
-
-// Test that if the source window needs to be scaled up/down because of dragging
-// a tab window out of it, other windows' visibilities and the home launcher's
-// visibility should change accordingly.
-TEST_F(SplitViewTabDraggingTest, SourceWindowBackgroundTest) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window4(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  EXPECT_TRUE(window1->IsVisible());
-  EXPECT_TRUE(window2->IsVisible());
-  EXPECT_TRUE(window3->IsVisible());
-  EXPECT_TRUE(window4->IsVisible());
-
-  // Home launcher should be shown because none of these windows are activated.
-  EXPECT_TRUE(Shell::Get()->app_list_controller()->IsVisible());
-
-  // 1) Start dragging |window1|. |window2| is the source window.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window2.get());
-  DragWindowWithOffset(resizer.get(), 10, 10);
-
-  // Test that |window3| should be hidden now. |window1| and |window2| should
-  // stay visible during dragging.
-  EXPECT_TRUE(window1->IsVisible());
-  EXPECT_TRUE(window2->IsVisible());
-  EXPECT_FALSE(window3->IsVisible());
-  EXPECT_FALSE(window4->IsVisible());
-
-  // Test that home launcher is not shown because a window is active.
-  EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible());
-
-  // Test that during dragging, we could not show a hidden window.
-  window3->Show();
-  EXPECT_FALSE(window3->IsVisible());
-
-  // After dragging, the windows' visibilities should have restored.
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(window1->IsVisible());
-  EXPECT_TRUE(window2->IsVisible());
-  EXPECT_TRUE(window3->IsVisible());
-  EXPECT_TRUE(window4->IsVisible());
-
-  // Test that home launcher is still not shown, because a window is active.
-  EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible());
-}
-
-// Tests that the dragged window should be the active and top window if overview
-// ended because of window drag.
-TEST_F(SplitViewTabDraggingTest, OverviewEndedOnWindowDrag) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  auto* window_state1 = WindowState::Get(window1.get());
-  auto* window_state2 = WindowState::Get(window2.get());
-
-  // Drags |window2| to overview.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window2.get(), window2.get());
-  gfx::Rect drop_target_bounds = GetDropTargetBoundsDuringDrag(window1.get());
-  DragWindowTo(resizer.get(), drop_target_bounds.CenterPoint());
-  EXPECT_TRUE(window_state2->IsSnapped());
-  CompleteDrag(std::move(resizer));
-  OverviewController* selector_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(selector_controller->InOverviewSession());
-  EXPECT_TRUE(selector_controller->overview_session()->IsWindowInOverview(
-      window2.get()));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(window_state2->IsSnapped());
-
-  // Drags |window1| by a small distance. Both splitview and overview should be
-  // ended and |window1| is the active window and above |window2|.
-  resizer = StartDrag(window1.get(), window1.get());
-  DragWindowTo(resizer.get(), gfx::Point(10, 10));
-  EXPECT_TRUE(window_state1->IsSnapped());
-  EXPECT_TRUE(window_state2->IsSnapped());
-
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(selector_controller->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_TRUE(window_state1->IsMaximized());
-  EXPECT_TRUE(window_state2->IsMaximized());
-  EXPECT_TRUE(window_state1->IsActive());
-  EXPECT_FALSE(window_state2->IsActive());
-  // |window1| should above |window2|.
-  const aura::Window::Windows windows = window1->parent()->children();
-  auto window1_layer = base::ranges::find(windows, window1.get());
-  auto window2_layer = base::ranges::find(windows, window2.get());
-  EXPECT_TRUE(window1_layer > window2_layer);
-}
-
-// When tab dragging a window, the dragged window might need to merge back into
-// the source window when the drag ends. Tests the related functionalities.
-TEST_F(SplitViewTabDraggingTest, MergeBackToSourceWindow) {
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> source_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  // 1. If splitview is not active and the dragged window is not the source
-  // window.
-  // a. Drag the window to less than half of the display height, and not in the
-  // snap preview area.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_window.get(), source_window.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(300, 200));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  source_window->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-
-  // b. Drag the window to more than half of the display height and not in the
-  // snap preview area.
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(300, 500));
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-
-  // c. Drag the window to the snap preview area.
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  ASSERT_TRUE(resizer.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(0, 200));
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EndSplitView();
-
-  // 2. If splitview is active and the dragged window is not the source window.
-  // a. Drag the window to less than half of the display height, in the same
-  // split of the source window, and not in the snap preview area.
-  split_view_controller()->SnapWindow(
-      source_window.get(), SplitViewController::SnapPosition::kPrimary);
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(0, 200));
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EndSplitView();
-  source_window->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-
-  // b. Drag the window to less than half of the display height, in the
-  // different split of the source window, and not in the snap preview area.
-  split_view_controller()->SnapWindow(
-      source_window.get(), SplitViewController::SnapPosition::kPrimary);
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(500, 200));
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EndSplitView();
-
-  // c. Drag the window to move a small distance, but is still in the different
-  // split of the source window, and not in the snap preview area.
-  split_view_controller()->SnapWindow(
-      source_window.get(), SplitViewController::SnapPosition::kPrimary);
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  DragWindowTo(resizer.get(), gfx::Point(500, 20));
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EndSplitView();
-}
-
-// Tests that if a fling event happens on a tab, the tab might or might not
-// merge back into the source window depending on the fling event velocity.
-TEST_F(SplitViewTabDraggingTest, FlingTest) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> source_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_window.get(), source_window.get());
-  ASSERT_TRUE(resizer.get());
-  Fling(std::move(resizer), /*velocity_y=*/3000.f);
-  EXPECT_FALSE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-
-  resizer = StartDrag(dragged_window.get(), source_window.get());
-  ASSERT_TRUE(resizer.get());
-  Fling(std::move(resizer), /*velocity_y=*/1000.f);
-  EXPECT_TRUE(source_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-}
-
-// Tests that in various cases, after the tab drag ends, the dragged window and
-// the source window should have correct bounds.
-TEST_F(SplitViewTabDraggingTest, BoundsTest) {
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  wm::ActivateWindow(window1.get());
-  const gfx::Rect bounds1 = window1->bounds();
-  const gfx::Rect bounds2 = window2->bounds();
-  EXPECT_EQ(bounds1, bounds2);
-
-  // 1. If splitview is not active and the dragged window is the source window.
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(window1.get(), window1.get());
-  // Drag for a small distance.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_NE(window1->bounds(), bounds1);
-  CompleteDrag(std::move(resizer));
-  // The window should be maximized again and the bounds should restore to its
-  // maximized window size.
-  EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
-  EXPECT_EQ(window1->bounds(), bounds1);
-
-  // 2. If splitview is not active and the dragged window is not the source
-  // window.
-  resizer = StartDrag(window1.get(), window2.get());
-  // a). Drag for a small distance.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_NE(window1->bounds(), bounds1);
-  EXPECT_EQ(window2->bounds(), bounds2);
-  // Now drag for a longer distance so that the source window scales down.
-  DragWindowTo(resizer.get(), gfx::Point(300, 200));
-  EXPECT_NE(window2->bounds(), bounds2);
-  CompleteDrag(std::move(resizer));
-  // As in this case the dragged window should merge back to source window,
-  // which we can't test here. We only test the source window's bounds restore
-  // to its maximized window size.
-  EXPECT_TRUE(
-      window2->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EXPECT_EQ(window2->bounds(), bounds2);
-  window2->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-
-  // b) Drag the window far enough so that the dragged window doesn't merge back
-  // into the source window.
-  resizer = StartDrag(window1.get(), window2.get());
-  DragWindowTo(resizer.get(), gfx::Point(300, 400));
-  EXPECT_NE(window1->bounds(), bounds1);
-  EXPECT_NE(window2->bounds(), bounds2);
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(
-      window2->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  EXPECT_EQ(window1->bounds(), bounds1);
-  EXPECT_EQ(window2->bounds(), bounds2);
-
-  // 3. If splitview is active and the dragged window is the source window.
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  const gfx::Rect snapped_bounds1 = window1->bounds();
-  const gfx::Rect snapped_bounds2 = window2->bounds();
-  resizer = StartDrag(window1.get(), window1.get());
-  // Drag the window for a small distance and release.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_NE(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-
-  // 4. If splitview is active and the dragged window is not the source window.
-  resizer = StartDrag(window3.get(), window1.get());
-  // a). Drag the window for a small distance and release.
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  EXPECT_EQ(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  // Drag the window for a long distance (but is still in merge-back distance
-  // range), the source window should not scale down.
-  DragWindowTo(resizer.get(), gfx::Point(100, 200));
-  EXPECT_EQ(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-
-  CompleteDrag(std::move(resizer));
-  // In this case |window3| is supposed to merge back its source window
-  // |window1|, so we only test the source window's bounds here.
-  EXPECT_EQ(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  EXPECT_TRUE(
-      window1->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  window1->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-
-  // b). Drag the window far enough so that the dragged window doesn't merge
-  // back into its source window.
-  resizer = StartDrag(window3.get(), window1.get());
-  DragWindowTo(resizer.get(), gfx::Point(100, 400));
-  EXPECT_EQ(window1->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-  CompleteDrag(std::move(resizer));
-  EXPECT_FALSE(
-      window1->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey));
-  // |window3| replaced |window1| as the left snapped window.
-  EXPECT_EQ(window3->bounds(), snapped_bounds1);
-  EXPECT_EQ(window2->bounds(), snapped_bounds2);
-}
-
-// Tests that press overview key in keyboard during drag should not put the
-// dragged window into overview.
-TEST_F(SplitViewTabDraggingTest, PressOverviewKeyDuringDrag) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  WindowState::Get(dragged_window.get())->Maximize();
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_window.get(), dragged_window.get());
-  DragWindowTo(resizer.get(), gfx::Point(300, 300));
-  EXPECT_TRUE(WindowState::Get(dragged_window.get())->is_dragged());
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  GetEventGenerator()->PressKey(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_FALSE(Shell::Get()
-                   ->overview_controller()
-                   ->overview_session()
-                   ->IsWindowInOverview(dragged_window.get()));
-  EXPECT_TRUE(WindowState::Get(dragged_window.get())->is_dragged());
-  resizer->CompleteDrag();
-}
-
-// Tests that if the dragged window is activated after the drag ends, but before
-// the dragged window gets snapped, the divider bar is placed correctly above
-// the snapped windows.
-TEST_F(SplitViewTabDraggingTest, DragActiveWindow) {
-  UpdateDisplay("600x500");
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window2(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> window3(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-
-  split_view_controller()->SnapWindow(
-      window1.get(), SplitViewController::SnapPosition::kPrimary);
-  EXPECT_EQ(split_view_controller()->InSplitViewMode(), true);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  EXPECT_EQ(split_view_controller()->InSplitViewMode(), true);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_window.get(), window1.get());
-
-  // Drag window to the other side of the split screen.
-  DragWindowTo(resizer.get(), gfx::Point(580, 600));
-  resizer->CompleteDrag();
-
-  // To simulate what might happen in real situation, we activate the dragged
-  // window first before clearing the window's tab dragging properties.
-  wm::ActivateWindow(dragged_window.get());
-  SetIsInTabDragging(resizer->GetTarget(), /*is_dragging=*/false);
-
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-}
-
-// Tests that the divider bar should be placed on top after the drag ends, no
-// matter the dragged window is destroyed during the drag or not.
-TEST_F(SplitViewTabDraggingTest, DividerBarOnTopAfterDragEnds) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> another_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      dragged_window.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      another_window.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-
-  // If the dragged window stays as a separate window after drag ends:
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_window.get(), dragged_window.get());
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  CompleteDrag(std::move(resizer));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kBothSnapped);
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-
-  // If the dragged window is destroyed after drag ends:
-  resizer = StartDrag(dragged_window.get(), dragged_window.get());
-  DragWindowWithOffset(resizer.get(), 10, 10);
-  resizer->CompleteDrag();
-  resizer.reset();
-  dragged_window.reset();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kSecondarySnapped);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_NE(ui::ZOrderLevel::kNormal,
-            split_view_divider()->divider_widget()->GetZOrderLevel());
-}
-
-TEST_F(SplitViewTabDraggingTest, IgnoreActivatedTabDraggingWindow) {
-  const gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> dragged_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> left_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  std::unique_ptr<aura::Window> right_window(
-      CreateWindowWithType(bounds, AppType::BROWSER));
-  split_view_controller()->SnapWindow(
-      left_window.get(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      right_window.get(), SplitViewController::SnapPosition::kSecondary);
-
-  // Simulate what might happen in reality.
-  SetIsInTabDragging(dragged_window.get(), /*is_dragging=*/true,
-                     left_window.get());
-  wm::ActivateWindow(dragged_window.get());
-
-  // Test that |left_window| and |right_window| is still snapped in splitview
-  // and overview is not opened behind the dragged window.
-  EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(left_window.get()));
-  EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(right_window.get()));
-  EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-}
-
-TEST_F(SplitViewTabDraggingTest,
-       DragTabFromSnappedWindowToOverviewAndThenExitTablet) {
-  // Snap a browser window in split view.
-  std::unique_ptr<aura::Window> snapped_window(
-      CreateWindowWithType(gfx::Rect(), AppType::BROWSER));
-  ToggleOverview();
-  split_view_controller()->SnapWindow(
-      snapped_window.get(), SplitViewController::SnapPosition::kPrimary);
-
-  // Drag a tab out of the browser window and into overview.
-  std::unique_ptr<aura::Window> dragged_tab(
-      CreateWindowWithType(gfx::Rect(), AppType::BROWSER));
-  std::unique_ptr<WindowResizer> resizer =
-      StartDrag(dragged_tab.get(), snapped_window.get());
-  DragWindowTo(resizer.get(),
-               gfx::ToEnclosingRect(
-                   Shell::Get()
-                       ->overview_controller()
-                       ->overview_session()
-                       ->GetGridWithRootWindow(snapped_window->GetRootWindow())
-                       ->GetDropTarget()
-                       ->target_bounds())
-                   .CenterPoint());
-  CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(dragged_tab->GetProperty(chromeos::kIsShowingInOverviewKey));
-
-  // Switch to clamshell mode and check that |snapped_window| keeps its snapped
-  // window state.
-  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
-  EXPECT_EQ(chromeos::WindowStateType::kPrimarySnapped,
-            WindowState::Get(snapped_window.get())->GetStateType());
-}
-
-class TestWindowDelegateWithWidget : public views::WidgetDelegate {
- public:
-  TestWindowDelegateWithWidget(bool can_resize) {
-    SetCanMaximize(true);
-    SetCanResize(can_resize);
-    SetOwnedByWidget(true);
-    SetFocusTraversesOut(true);
-  }
-
-  TestWindowDelegateWithWidget(const TestWindowDelegateWithWidget&) = delete;
-  TestWindowDelegateWithWidget& operator=(const TestWindowDelegateWithWidget&) =
-      delete;
-
-  ~TestWindowDelegateWithWidget() override = default;
-
-  // views::WidgetDelegate:
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
-  bool CanActivate() const override { return true; }
-
-  void set_widget(views::Widget* widget) { widget_ = widget; }
-
- private:
-  views::Widget* widget_ = nullptr;
-};
-
-class SplitViewAppDraggingTest : public SplitViewControllerTest {
- public:
-  SplitViewAppDraggingTest() = default;
-
-  SplitViewAppDraggingTest(const SplitViewAppDraggingTest&) = delete;
-  SplitViewAppDraggingTest& operator=(const SplitViewAppDraggingTest&) = delete;
-
-  ~SplitViewAppDraggingTest() override = default;
-
-  // SplitViewControllerTest:
-  void TearDown() override {
-    window_.reset();
-    controller_.reset();
-    SplitViewControllerTest::TearDown();
-  }
-
- protected:
-  std::unique_ptr<aura::Window> CreateTestWindowWithWidget(bool can_resize) {
-    views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
-    params.show_state = ui::SHOW_STATE_MAXIMIZED;
-    views::Widget* widget = new views::Widget;
-    std::unique_ptr<TestWindowDelegateWithWidget> widget_delegate =
-        std::make_unique<TestWindowDelegateWithWidget>(can_resize);
-    widget_delegate->set_widget(widget);
-    params.delegate = widget_delegate.release();
-    params.context = GetContext();
-    widget->Init(std::move(params));
-    widget->Show();
-    return base::WrapUnique<aura::Window>(widget->GetNativeView());
-  }
-
-  void InitializeWindow(bool can_resize = true) {
-    window_ = CreateTestWindowWithWidget(can_resize);
-  }
-
-  // Sends a gesture scroll sequence to TabletModeAppWindowDragController.
-  void SendGestureEvents(const gfx::PointF& location) {
-    SendScrollStartAndUpdate(location);
-    EndScrollSequence();
-  }
-
-  void SendScrollStartAndUpdate(const gfx::PointF& location) {
-    WindowState* window_state = WindowState::Get(window());
-    window_state->CreateDragDetails(location, HTCAPTION,
-                                    ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-    controller_ = std::make_unique<TabletModeWindowResizer>(
-        window_state, std::make_unique<TabletModeBrowserWindowDragDelegate>());
-    controller_->drag_delegate_for_testing()
-        ->set_drag_start_deadline_for_testing(base::Time::Now());
-    controller_->Drag(location, 0);
-  }
-
-  void EndScrollSequence() {
-    controller_->CompleteDrag();
-    WindowState::Get(window())->DeleteDragDetails();
-  }
-
-  void Fling(const gfx::PointF& location, float velocity_y, float velocity_x) {
-    ui::GestureEvent event = ui::GestureEvent(
-        location.x(), location.y(), ui::EF_NONE, base::TimeTicks::Now(),
-        ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, velocity_x,
-                                velocity_y));
-    ui::Event::DispatcherApi(&event).set_target(window());
-    controller_->FlingOrSwipe(&event);
-    WindowState::Get(window())->DeleteDragDetails();
-  }
-
-  SplitViewDragIndicators::WindowDraggingState GetWindowDraggingState() {
-    return controller_->drag_delegate_for_testing()
-        ->split_view_drag_indicators_for_testing()
-        ->current_window_dragging_state();
-  }
-
-  aura::Window* window() { return window_.get(); }
-
-  std::unique_ptr<TabletModeWindowResizer> controller_;
-
-  std::unique_ptr<aura::Window> window_;
-};
-
-// Tests that drag the window that cannot be snapped from top of the display
-// will not snap the window into splitscreen.
-TEST_F(SplitViewAppDraggingTest, DragNonActiveMaximizedWindow) {
-  UpdateDisplay("800x600");
-  InitializeWindow(false);
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window());
-  const float long_scroll_delta = display_bounds.height() / 4 + 5;
-
-  const gfx::PointF location(0, long_scroll_delta);
-  // Drag the window that cannot be snapped long enough, the window will be
-  // dropped into overview.
-  SendScrollStartAndUpdate(location);
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_FALSE(
-      overview_controller->overview_session()->IsWindowInOverview(window()));
-  EndScrollSequence();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
-  EXPECT_TRUE(
-      overview_controller->overview_session()->IsWindowInOverview(window()));
-}
-
-// Tests the functionalities that are related to dragging a maximized window
-// into splitscreen.
-TEST_F(SplitViewAppDraggingTest, DragActiveMaximizedWindow) {
-  UpdateDisplay("800x600");
-  InitializeWindow();
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window());
-
-  // Move the window by a small amount of distance will maximize the window
-  // again.
-  gfx::PointF location(0, 10);
-  SendGestureEvents(location);
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-
-  // Drag the window long enough (pass one fourth of the screen vertical
-  // height) to snap the window to splitscreen.
-  const float long_scroll_delta = display_bounds.height() / 4 + 5;
-  location.set_y(long_scroll_delta);
-  SendScrollStartAndUpdate(location);
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_FALSE(
-      overview_controller->overview_session()->IsWindowInOverview(window()));
-  EndScrollSequence();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-  EXPECT_EQ(split_view_controller()->primary_window(), window());
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_TRUE(WindowState::Get(window())->IsSnapped());
-
-  // FLING the window with small velocity (smaller than
-  // kFlingToOverviewThreshold) will not able to drop the window into overview.
-  location.set_y(10);
-  SendScrollStartAndUpdate(location);
-  overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  Fling(location,
-        TabletModeWindowDragDelegate::kFlingToOverviewThreshold - 10.f, 0);
-  EXPECT_FALSE(overview_controller->InOverviewSession());
-
-  // FLING the window with large velocity (larger than
-  // kFlingToOverviewThreshold) will drop the window into overview.
-  SendScrollStartAndUpdate(location);
-  overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  Fling(location,
-        TabletModeWindowDragDelegate::kFlingToOverviewThreshold + 10.f, 0);
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-}
-
-// Tests the shelf visibility when a fullscreened window is being dragged.
-TEST_F(SplitViewAppDraggingTest, ShelfVisibilityIfDraggingFullscreenedWindow) {
-  UpdateDisplay("800x600");
-  InitializeWindow();
-  ShelfLayoutManager* shelf_layout_manager =
-      AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window());
-
-  // Shelf will be auto-hidden if the window requests to be fullscreened.
-  WindowState* window_state = WindowState::Get(window());
-  const WMEvent fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
-  window_state->OnWMEvent(&fullscreen_event);
-  window_state->SetHideShelfWhenFullscreen(false);
-  window()->SetProperty(chromeos::kImmersiveIsActive, true);
-  shelf_layout_manager->UpdateVisibilityState();
-  EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_FALSE(shelf_layout_manager->IsVisible());
-
-  // Drag the window by a small amount of distance, the window will back to
-  // fullscreened, and shelf will be hidden again.
-  gfx::PointF location(0, 10);
-  SendGestureEvents(location);
-  shelf_layout_manager->UpdateVisibilityState();
-  EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_FALSE(shelf_layout_manager->IsVisible());
-
-  // Shelf is visible during dragging.
-  location.set_y(display_bounds.height() / 4 + 5);
-  SendScrollStartAndUpdate(location);
-  EXPECT_TRUE(shelf_layout_manager->IsVisible());
-  EndScrollSequence();
-  EXPECT_TRUE(split_view_controller()->InSplitViewMode());
-  EXPECT_TRUE(WindowState::Get(window())->IsSnapped());
-  EXPECT_TRUE(shelf_layout_manager->IsVisible());
-}
-
-// Tests the auto-hide shelf state during window dragging.
-TEST_F(SplitViewAppDraggingTest, AutoHideShelf) {
-  UpdateDisplay("800x600");
-  Shelf* shelf = GetPrimaryShelf();
-  shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
-  InitializeWindow();
-  gfx::Rect display_bounds =
-      display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
-  ShelfLayoutManager* shelf_layout_manager =
-      AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
-  shelf_layout_manager->LayoutShelf();
-  EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-
-  shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
-  shelf_layout_manager->LayoutShelf();
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
-  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
-
-  const gfx::PointF location(0, display_bounds.height() / 4 + 5);
-  SendScrollStartAndUpdate(location);
-  EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
-  // Shelf should be shown during drag.
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
-  EndScrollSequence();
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::State::kPrimarySnapped);
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
-  // Shelf should be shown after drag and snapped window should be covered by
-  // the auto-hide-shown shelf.
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
-  EXPECT_EQ(split_view_controller()
-                ->GetSnappedWindowBoundsInScreen(
-                    SplitViewController::SnapPosition::kPrimary, window())
-                .height(),
-            display_bounds.height());
-}
-
-// Tests the functionalities that fling the window when preview area is shown.
-TEST_F(SplitViewAppDraggingTest, FlingWhenPreviewAreaIsShown) {
-  InitializeWindow();
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window());
-
-  const float long_scroll_delta = display_bounds.height() / 4 + 5;
-  float large_velocity =
-      TabletModeWindowDragDelegate::kFlingToOverviewFromSnappingAreaThreshold +
-      10.f;
-  float small_velocity =
-      TabletModeWindowDragDelegate::kFlingToOverviewFromSnappingAreaThreshold -
-      10.f;
-
-  // Fling to the right with large enough velocity when trying to snap the
-  // window to the left should drop the window to overview.
-  gfx::PointF location(0, long_scroll_delta);
-  SendScrollStartAndUpdate(location);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState());
-  Fling(location, /*velocity_y*/ 0, /*velocity_x=*/large_velocity);
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  OverviewSession* overview_session = overview_controller->overview_session();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window()));
-  ToggleOverview();
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-
-  // Fling to the right with small velocity when trying to snap the
-  // window to the left should still snap the window to left.
-  SendScrollStartAndUpdate(location);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary,
-            GetWindowDraggingState());
-  Fling(location, /*velocity_y*/ 0, /*velocity_x=*/small_velocity);
-  EXPECT_TRUE(WindowState::Get(window())->IsSnapped());
-  EndSplitView();
-  EXPECT_TRUE(WindowState::Get(window())->IsMaximized());
-
-  // Fling to the left with large enough velocity when trying to snap the window
-  // to the right should drop the window to overvie.
-  location = gfx::PointF(display_bounds.right(), long_scroll_delta);
-  SendScrollStartAndUpdate(location);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary,
-            GetWindowDraggingState());
-  Fling(location, /*velocity_y*/ 0, /*velocity_x=*/-large_velocity);
-  overview_session = overview_controller->overview_session();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_TRUE(overview_session->IsWindowInOverview(window()));
-  ToggleOverview();
-
-  // Fling to the left with small velocity when trying to snap the
-  // window to the right should still snap the window to right.
-  SendScrollStartAndUpdate(location);
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary,
-            GetWindowDraggingState());
-  Fling(location, /*velocity_y*/ 0, /*velocity_x=*/-small_velocity);
-  EXPECT_TRUE(WindowState::Get(window())->IsSnapped());
-}
-
-// Tests the functionalities that fling a window when splitview is active.
-TEST_F(SplitViewAppDraggingTest, FlingWhenSplitViewIsActive) {
-  InitializeWindow();
-  std::unique_ptr<aura::Window> window2 = CreateTestWindowWithWidget(true);
-
-  split_view_controller()->SnapWindow(
-      window(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window());
-  const float long_scroll_y = display_bounds.bottom() - 10;
-  float large_velocity =
-      TabletModeWindowDragDelegate::kFlingToOverviewFromSnappingAreaThreshold +
-      10.f;
-
-  // Fling the window in left snapping area to left should still snap the
-  // window.
-  gfx::PointF location(0, long_scroll_y);
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/-large_velocity);
-  EXPECT_TRUE(WindowState::Get(window())->IsSnapped());
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-
-  // Fling the window in left snapping area to right should drop the window
-  // into overview.
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/large_velocity);
-  OverviewController* selector_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  EXPECT_TRUE(IsTabletMode());
-  ToggleOverview();
-  EXPECT_TRUE(IsTabletMode());
-
-  // If the window is to the left of the divider but outside the left snapping
-  // area, then flinging to the left should drop the window into overview (like
-  // just ending the drag).
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  location.set_x(display_bounds.CenterPoint().x() - 10);
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/-large_velocity);
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  ToggleOverview();
-
-  // If the window is to the left of the divider but outside the left snapping
-  // area, then flinging to the right should drop the window into overview (like
-  // just ending the drag).
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/large_velocity);
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  ToggleOverview();
-
-  // If the window is to the right of the divider but outside the right snapping
-  // area, then flinging to the left should drop the window into overview (like
-  // just ending the drag).
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  location.set_x(display_bounds.CenterPoint().x() + 10);
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/-large_velocity);
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  ToggleOverview();
-
-  // If the window is to the right of the divider but outside the right snapping
-  // area, then flinging to the right should drop the window into overview (like
-  // just ending the drag).
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/large_velocity);
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  ToggleOverview();
-
-  // Fling the window in right snapping area to left should drop the window into
-  // overview.
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  location.set_x(display_bounds.right() - 1);
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/-large_velocity);
-  EXPECT_TRUE(
-      selector_controller->overview_session()->IsWindowInOverview(window()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-  ToggleOverview();
-
-  // Fling the window in right snapping area to right should snap the window to
-  // right side.
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller()->state());
-  SendScrollStartAndUpdate(location);
-  Fling(location, /*velocity_y=*/0, /*velocity_x=*/large_velocity);
-  EXPECT_EQ(split_view_controller()->secondary_window(), window());
-  EXPECT_TRUE(selector_controller->overview_session()->IsWindowInOverview(
-      window2.get()));
-  EXPECT_EQ(SplitViewController::State::kSecondarySnapped,
-            split_view_controller()->state());
-}
-
-// Tests the backdrop bounds during window drag.
-TEST_F(SplitViewAppDraggingTest, BackdropBoundsDuringDrag) {
-  InitializeWindow();
-  std::unique_ptr<aura::Window> window2 = CreateTestWindowWithWidget(true);
-  ToggleOverview();
-  split_view_controller()->SnapWindow(
-      window(), SplitViewController::SnapPosition::kPrimary);
-  split_view_controller()->SnapWindow(
-      window2.get(), SplitViewController::SnapPosition::kSecondary);
-  EXPECT_EQ(window2.get(), window_util::GetActiveWindow());
-
-  const aura::Window* active_desk_container =
-      Shell::GetPrimaryRootWindowController()->GetContainer(
-          desks_util::GetActiveDeskContainerId());
-
-  // Backdrop window should below two snapped windows and its bounds should be
-  // the same as the container bounds.
-  EXPECT_EQ(3U, active_desk_container->children().size());
-  EXPECT_EQ(window(), active_desk_container->children()[1]);
-  EXPECT_EQ(window2.get(), active_desk_container->children()[2]);
-  EXPECT_EQ(active_desk_container->bounds(),
-            active_desk_container->children()[0]->bounds());
-
-  // Start window drag and activate the dragged window during drag.
-  gfx::PointF location(0, 10);
-  SendScrollStartAndUpdate(location);
-  wm::ActivateWindow(window());
-
-  aura::Window::Windows windows = active_desk_container->children();
-  auto it = base::ranges::find(windows, window2.get());
-  // Backdrop window should be the window that just below the snapped |window2|
-  // and its bounds should be the same as the snapped window during drag.
-  aura::Window* backdrop_window = nullptr;
-  if (it != windows.begin())
-    backdrop_window = *(--it);
-  DCHECK(backdrop_window);
-  EXPECT_EQ(window2->bounds(), backdrop_window->bounds());
-
-  // Backdrop should restore back to container bounds after drag.
-  EndScrollSequence();
-  EXPECT_EQ(window(), window_util::GetActiveWindow());
-  windows = active_desk_container->children();
-  it = base::ranges::find(windows, window2.get());
-  if (it != windows.begin())
-    backdrop_window = *(--it);
-  DCHECK(backdrop_window);
-  EXPECT_EQ(backdrop_window->bounds(), active_desk_container->bounds());
-}
-
 // The test class that enables the feature flag of portrait mode split view
 // virtual keyboard improvement and the virtual keyboard.
 class SplitViewKeyboardTest : public SplitViewControllerTest {
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
deleted file mode 100644
index 7dcbe14..0000000
--- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
-
-#include <vector>
-
-#include "ash/display/screen_orientation_controller.h"
-#include "ash/shell.h"
-#include "ash/wm/splitview/split_view_constants.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_state.h"
-#include "ash/wm/window_util.h"
-#include "chromeos/ui/base/window_properties.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/display/screen.h"
-#include "ui/views/widget/widget.h"
-#include "ui/wm/core/coordinate_conversion.h"
-
-namespace ash {
-
-namespace {
-
-// The scale factor that the source window should scale if the source window is
-// not the dragged window && is not in splitscreen when drag starts && the user
-// has dragged the window to pass the |kIndicatorThresholdRatio| vertical
-// threshold.
-constexpr float kSourceWindowScale = 0.85;
-
-// Threshold of the fling velocity to keep the dragged window as a new separate
-// window after drag ends and do not try to merge it back into source window.
-constexpr float kFlingToStayAsNewWindowThreshold = 2000.f;
-
-// The class to observe the source window's bounds change animation. It's used
-// to prevent the dragged window to merge back into the source window during
-// dragging. Only when the source window restores to its maximized window size,
-// the dragged window can be merged back into the source window.
-class SourceWindowAnimationObserver : public ui::ImplicitAnimationObserver,
-                                      public aura::WindowObserver {
- public:
-  SourceWindowAnimationObserver(aura::Window* source_window,
-                                aura::Window* dragged_window)
-      : source_window_(source_window), dragged_window_(dragged_window) {
-    source_window_->AddObserver(this);
-    dragged_window_->AddObserver(this);
-  }
-
-  SourceWindowAnimationObserver(const SourceWindowAnimationObserver&) = delete;
-  SourceWindowAnimationObserver& operator=(
-      const SourceWindowAnimationObserver&) = delete;
-
-  ~SourceWindowAnimationObserver() override { StopObserving(); }
-
-  // ui::ImplicitAnimationObserver:
-  void OnLayerAnimationStarted(ui::LayerAnimationSequence* sequence) override {
-    DCHECK(dragged_window_ && source_window_);
-    dragged_window_->SetProperty(chromeos::kCanAttachToAnotherWindowKey, false);
-  }
-
-  void OnImplicitAnimationsCompleted() override {
-    DCHECK(dragged_window_ && source_window_);
-    // When arriving here, we know the source window bounds change animation
-    // just ended. Only clear the property
-    // chromeos::kCanAttachToAnotherWindowKey if the source window bounds
-    // restores to its maximized window size.
-    gfx::Rect work_area_bounds = display::Screen::GetScreen()
-                                     ->GetDisplayNearestWindow(source_window_)
-                                     .work_area();
-    ::wm::ConvertRectFromScreen(source_window_->parent(), &work_area_bounds);
-    if (source_window_->bounds() == work_area_bounds)
-      StopObserving();
-  }
-
-  // aura::WindowObserver:
-  void OnWindowDestroying(aura::Window* window) override {
-    DCHECK(window == source_window_ || window == dragged_window_);
-    StopObserving();
-  }
-
- private:
-  void StopObserving() {
-    StopObservingImplicitAnimations();
-    if (source_window_) {
-      source_window_->RemoveObserver(this);
-      source_window_ = nullptr;
-    }
-
-    if (dragged_window_) {
-      dragged_window_->RemoveObserver(this);
-      dragged_window_->ClearProperty(chromeos::kCanAttachToAnotherWindowKey);
-      dragged_window_ = nullptr;
-    }
-  }
-
-  aura::Window* source_window_;
-  aura::Window* dragged_window_;
-};
-
-}  // namespace
-
-TabletModeBrowserWindowDragDelegate::TabletModeBrowserWindowDragDelegate() =
-    default;
-
-TabletModeBrowserWindowDragDelegate::~TabletModeBrowserWindowDragDelegate() =
-    default;
-
-void TabletModeBrowserWindowDragDelegate::PrepareWindowDrag(
-    const gfx::PointF& location_in_screen) {
-  DCHECK(dragged_window_);
-
-  WindowState* window_state = WindowState::Get(dragged_window_);
-  window_state->OnDragStarted(window_state->drag_details()->window_component);
-}
-
-void TabletModeBrowserWindowDragDelegate::UpdateWindowDrag(
-    const gfx::PointF& location_in_screen) {
-  DCHECK(dragged_window_);
-
-  // Update the source window if necessary.
-  UpdateSourceWindow(location_in_screen);
-}
-
-void TabletModeBrowserWindowDragDelegate::EndingWindowDrag(
-    ToplevelWindowEventHandler::DragResult result,
-    const gfx::PointF& location_in_screen) {
-  if (result == ToplevelWindowEventHandler::DragResult::SUCCESS)
-    WindowState::Get(dragged_window_)->OnCompleteDrag(location_in_screen);
-  else
-    WindowState::Get(dragged_window_)->OnRevertDrag(location_in_screen);
-}
-
-void TabletModeBrowserWindowDragDelegate::EndedWindowDrag(
-    const gfx::PointF& location_in_screen) {
-  MergeBackToSourceWindowIfApplicable(location_in_screen);
-}
-
-void TabletModeBrowserWindowDragDelegate::StartFling(
-    const ui::GestureEvent* event) {
-  if (event->details().velocity_y() > kFlingToStayAsNewWindowThreshold)
-    can_merge_back_to_source_window_ = false;
-}
-
-bool TabletModeBrowserWindowDragDelegate::ShouldOpenOverviewWhenDragStarts() {
-  DCHECK(dragged_window_);
-  aura::Window* source_window =
-      dragged_window_->GetProperty(kTabDraggingSourceWindowKey);
-  return !source_window;
-}
-
-void TabletModeBrowserWindowDragDelegate::UpdateSourceWindow(
-    const gfx::PointF& location_in_screen) {
-  // Only do the scale if the source window is not the dragged window && the
-  // source window is not in splitscreen && the source window is not in
-  // overview.
-  aura::Window* source_window =
-      dragged_window_->GetProperty(kTabDraggingSourceWindowKey);
-  if (!source_window || source_window == dragged_window_ ||
-      split_view_controller_->IsWindowInSplitView(source_window) ||
-      source_window->GetProperty(chromeos::kIsShowingInOverviewKey)) {
-    return;
-  }
-
-  // Only create WindowHider if we need to scale up/down the source window.
-  if (!windows_hider_)
-    windows_hider_ =
-        std::make_unique<TabletModeBrowserWindowDragSessionWindowsHider>(
-            source_window, dragged_window_);
-
-  const gfx::Rect work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(dragged_window_)
-          .work_area();
-  gfx::Rect expected_bounds(work_area_bounds);
-  if (location_in_screen.y() >=
-      GetIndicatorsVerticalThreshold(work_area_bounds)) {
-    SplitViewController::SnapPosition snap_position =
-        GetSnapPosition(location_in_screen);
-
-    if (snap_position == SplitViewController::SnapPosition::kNone) {
-      // Scale down the source window if the event location passes the vertical
-      // |kIndicatorThresholdRatio| threshold.
-      expected_bounds.ClampToCenteredSize(
-          gfx::Size(work_area_bounds.width() * kSourceWindowScale,
-                    work_area_bounds.height() * kSourceWindowScale));
-    } else {
-      // Put the source window on the other side of the split screen.
-      expected_bounds = split_view_controller_->GetSnappedWindowBoundsInScreen(
-          snap_position == SplitViewController::SnapPosition::kPrimary
-              ? SplitViewController::SnapPosition::kSecondary
-              : SplitViewController::SnapPosition::kPrimary,
-          source_window);
-    }
-  }
-  ::wm::ConvertRectFromScreen(source_window->parent(), &expected_bounds);
-
-  if (expected_bounds != source_window->GetTargetBounds()) {
-    ui::ScopedLayerAnimationSettings settings(
-        source_window->layer()->GetAnimator());
-    settings.SetPreemptionStrategy(
-        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-    source_window_bounds_observer_ =
-        std::make_unique<SourceWindowAnimationObserver>(source_window,
-                                                        dragged_window_);
-    settings.AddObserver(source_window_bounds_observer_.get());
-    source_window->SetBounds(expected_bounds);
-  }
-}
-
-void TabletModeBrowserWindowDragDelegate::MergeBackToSourceWindowIfApplicable(
-    const gfx::PointF& location_in_screen) {
-  // No need to merge back if we're not in tab dragging process.
-  if (!window_util::IsDraggingTabs(dragged_window_))
-    return;
-
-  aura::Window* source_window =
-      dragged_window_->GetProperty(kTabDraggingSourceWindowKey);
-  // Do not merge back if there is no source window.
-  if (!source_window)
-    return;
-
-  // Do not merge back if the dragged window is not capable of merging back.
-  // This may happen if the drag ends because of a fling event and the fling
-  // velocity has exceeded kFlingToStayAsNewWindowThreshold.
-  if (!can_merge_back_to_source_window_)
-    return;
-
-  // Do not merge back if the window has dragged farther than half of the screen
-  // height.
-  const gfx::Rect work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(dragged_window_)
-          .work_area();
-  if (location_in_screen.y() >= work_area_bounds.CenterPoint().y())
-    return;
-
-  SplitViewController::SnapPosition desired_snap_position =
-      GetSnapPosition(location_in_screen);
-  // If splitscreen is not active, do not merge back if the dragged window is
-  // in the drag-to-snap preview area.
-  if (!split_view_controller_->InSplitViewMode() &&
-      desired_snap_position != SplitViewController::SnapPosition::kNone) {
-    return;
-  }
-
-  // In splitscreen, do not merge back if the drag point is on one side of the
-  // split view divider and the source window is snapped on the opposite side.
-  if (split_view_controller_->InSplitViewMode()) {
-    const int drag_position = IsCurrentScreenOrientationLandscape()
-                                  ? location_in_screen.x()
-                                  : location_in_screen.y();
-    const bool is_dragging_on_left =
-        IsCurrentScreenOrientationPrimary()
-            ? drag_position < split_view_controller_->divider_position()
-            : drag_position > split_view_controller_->divider_position();
-    aura::Window* window_on_opposite_side =
-        is_dragging_on_left ? split_view_controller_->secondary_window()
-                            : split_view_controller_->primary_window();
-    if (source_window == window_on_opposite_side)
-      return;
-  }
-
-  // Arriving here we know the dragged window should merge back into its source
-  // window.
-  source_window->SetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey,
-                             true);
-}
-
-}  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h
deleted file mode 100644
index 065b3861d..0000000
--- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
-#define ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
-
-#include "ash/ash_export.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
-
-namespace ash {
-
-class TabletModeBrowserWindowDragSessionWindowsHider;
-
-// The drag delegate for browser windows. It not only includes the logic in
-// TabletModeWindowDragDelegate, but also has special logic for browser windows,
-// e.g., scales the source window, shows/hides the other windows below the
-// source window.
-class ASH_EXPORT TabletModeBrowserWindowDragDelegate
-    : public TabletModeWindowDragDelegate {
- public:
-  TabletModeBrowserWindowDragDelegate();
-
-  TabletModeBrowserWindowDragDelegate(
-      const TabletModeBrowserWindowDragDelegate&) = delete;
-  TabletModeBrowserWindowDragDelegate& operator=(
-      const TabletModeBrowserWindowDragDelegate&) = delete;
-
-  ~TabletModeBrowserWindowDragDelegate() override;
-
- private:
-  // TabletModeWindowDragDelegate:
-  void PrepareWindowDrag(const gfx::PointF& location_in_screen) override;
-  void UpdateWindowDrag(const gfx::PointF& location_in_screen) override;
-  void EndingWindowDrag(ToplevelWindowEventHandler::DragResult result,
-                        const gfx::PointF& location_in_screen) override;
-  void EndedWindowDrag(const gfx::PointF& location_in_screen) override;
-  void StartFling(const ui::GestureEvent* event) override;
-  bool ShouldOpenOverviewWhenDragStarts() override;
-
-  // Scales down the source window if the dragged window is dragged past the
-  // |kIndicatorThresholdRatio| threshold and restores it if the dragged window
-  // is dragged back toward the top of the screen. |location_in_screen| is the
-  // current drag location for the dragged window.
-  void UpdateSourceWindow(const gfx::PointF& location_in_screen);
-
-  // After drag ends, the dragged window might need to merge back into the
-  // source window if 1) the dragged window or the source window is not added to
-  // overview and 2) the dragged window has dragged farther than half of the
-  // screen height and 3) the dragged window is not in snap preview area and 4)
-  // the dragged window is not dragged to the other side of the split screen.
-  void MergeBackToSourceWindowIfApplicable(
-      const gfx::PointF& location_in_screen);
-
-  // It's used to hide all visible windows if the source window needs to be
-  // scaled up/down during dragging a tab out of the source window. It also
-  // hides the home launcher if home launcher is enabled, blurs and darkens the
-  // background upon its creation. All of these will be restored upon its
-  // destruction.
-  std::unique_ptr<TabletModeBrowserWindowDragSessionWindowsHider>
-      windows_hider_;
-
-  // The observer to observe the source window's bounds change animation during
-  // dragging. It's used to prevent the dragged window to merge back into the
-  // source window during dragging. Only when the source window restores to its
-  // maximized window size, the dragged window can be merged back into the
-  // source window.
-  std::unique_ptr<ui::ImplicitAnimationObserver> source_window_bounds_observer_;
-
-  // True if the dragged window is capable of merging back to source window
-  // after drag ends. If it's false, it means the drag ends because of a fling
-  // event and the fling velocity has exceeded kFlingToStayAsNewWindowThreshold.
-  bool can_merge_back_to_source_window_ = true;
-};
-
-}  // namespace ash
-
-#endif  // ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h
index f6cc21f..0ee92539 100644
--- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h
+++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h
@@ -19,6 +19,9 @@
 // launcher if home launcher is enabled. Only need to do so if we need
 // to scale up and down the source window when dragging a tab window out
 // of it.
+// TODO(xdai): This class is now only used by `TabDragDropDelegate`, and
+// `dragged_window` parameter is no longer needed. Clean up this class and move
+// it to where it's used.
 class ASH_EXPORT TabletModeBrowserWindowDragSessionWindowsHider
     : public aura::WindowObserver {
  public:
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
deleted file mode 100644
index e558af8..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
-
-#include "ash/display/screen_orientation_controller.h"
-#include "ash/public/cpp/window_backdrop.h"
-#include "ash/root_window_controller.h"
-#include "ash/screen_util.h"
-#include "ash/shelf/shelf_layout_manager.h"
-#include "ash/shell.h"
-#include "ash/system/overview/overview_button_tray.h"
-#include "ash/system/status_area_widget.h"
-#include "ash/wm/mru_window_tracker.h"
-#include "ash/wm/overview/overview_controller.h"
-#include "ash/wm/overview/overview_grid.h"
-#include "ash/wm/overview/overview_item.h"
-#include "ash/wm/overview/overview_session.h"
-#include "ash/wm/overview/overview_utils.h"
-#include "ash/wm/splitview/split_view_constants.h"
-#include "ash/wm/splitview/split_view_controller.h"
-#include "ash/wm/splitview/split_view_drag_indicators.h"
-#include "ash/wm/splitview/split_view_utils.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h"
-#include "ash/wm/window_transient_descendant_iterator.h"
-#include "ash/wm/window_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/transform_util.h"
-#include "ui/wm/core/coordinate_conversion.h"
-
-namespace ash {
-
-namespace {
-
-// The threshold to compute the minimum vertical distance to start showing the
-// drag indicators and preview window when dragging a window into splitscreen in
-// tablet mode.
-constexpr float kIndicatorsThresholdRatio = 0.1;
-
-// Items dragged to within |kDistanceFromEdgeDp| of the screen will get snapped
-// even if they have not moved by |kMinimumDragToSnapDistanceDp|.
-constexpr float kDistanceFromEdgeDp = 16.f;
-// The minimum distance that an item must be moved before it is snapped. This
-// prevents accidental snaps.
-constexpr float kMinimumDragToSnapDistanceDp = 96.f;
-
-// Duration of a drag that it will be considered as an intended drag. Must be at
-// least the duration of the split view divider snap animation, or else issues
-// like crbug.com/946601, crbug.com/997764, and https://crbug.com/997765, which
-// all refer to dragging from overview, will apply to dragging from the top.
-constexpr base::TimeDelta kIsWindowMovedTimeoutMs = base::Milliseconds(300);
-
-constexpr char kSwipeDownDragWindowHistogram[] =
-    "Ash.SwipeDownDrag.Window.PresentationTime.TabletMode";
-constexpr char kSwipeDownDragWindowMaxLatencyHistogram[] =
-    "Ash.SwipeDownDrag.Window.PresentationTime.MaxLatency.TabletMode";
-constexpr char kSwipeDownDragTabHistogram[] =
-    "Ash.SwipeDownDrag.Tab.PresentationTime.TabletMode";
-constexpr char kSwipeDownDragTabMaxLatencyHistogram[] =
-    "Ash.SwipeDownDrag.Tab.PresentationTime.MaxLatency.TabletMode";
-
-// Returns the overview session if overview mode is active, otherwise returns
-// nullptr.
-OverviewSession* GetOverviewSession() {
-  return Shell::Get()->overview_controller()->InOverviewSession()
-             ? Shell::Get()->overview_controller()->overview_session()
-             : nullptr;
-}
-
-OverviewGrid* GetOverviewGrid(aura::Window* dragged_window) {
-  if (!GetOverviewSession())
-    return nullptr;
-
-  return GetOverviewSession()->GetGridWithRootWindow(
-      dragged_window->GetRootWindow());
-}
-
-// Returns the drop target in overview during drag.
-OverviewItem* GetDropTarget(aura::Window* dragged_window) {
-  OverviewGrid* overview_grid = GetOverviewGrid(dragged_window);
-  if (!overview_grid || overview_grid->empty())
-    return nullptr;
-
-  return overview_grid->GetDropTarget();
-}
-
-// Gets the bounds of selected drop target in overview grid that is displaying
-// in the same root window as |dragged_window|. Note that the returned bounds is
-// scaled-up.
-gfx::Rect GetBoundsOfSelectedDropTarget(aura::Window* dragged_window) {
-  OverviewItem* drop_target = GetDropTarget(dragged_window);
-  if (!drop_target)
-    return gfx::Rect();
-
-  return drop_target->GetBoundsOfSelectedItem();
-}
-
-}  // namespace
-
-TabletModeWindowDragDelegate::TabletModeWindowDragDelegate()
-    : split_view_controller_(
-          SplitViewController::Get(Shell::GetPrimaryRootWindow())),
-      split_view_drag_indicators_(std::make_unique<SplitViewDragIndicators>(
-          Shell::GetPrimaryRootWindow())) {}
-
-TabletModeWindowDragDelegate::~TabletModeWindowDragDelegate() {
-  if (dragged_window_) {
-    OverviewGrid* overview_grid = GetOverviewGrid(dragged_window_);
-    if (overview_grid) {
-      overview_grid->RemoveDropTarget();
-      const gfx::Rect grid_bounds = GetGridBoundsInScreen(dragged_window_);
-      overview_grid->SetBoundsAndUpdatePositions(
-          grid_bounds, /*ignored_items=*/{}, /*animate=*/true);
-    }
-  }
-
-  split_view_controller_->OnWindowDragCanceled();
-  Shelf::UpdateShelfVisibility();
-}
-
-void TabletModeWindowDragDelegate::StartWindowDrag(
-    aura::Window* dragged_window,
-    const gfx::PointF& location_in_screen) {
-  // TODO(oshima): Consider doing the same for normal window dragging as well
-  // crbug.com/904631.
-  DCHECK(!occlusion_excluder_);
-  occlusion_excluder_.emplace(dragged_window);
-
-  DCHECK(!presentation_time_recorder_);
-  presentation_time_recorder_.reset();
-  if (window_util::IsDraggingTabs(dragged_window)) {
-    presentation_time_recorder_ = CreatePresentationTimeHistogramRecorder(
-        dragged_window->layer()->GetCompositor(), kSwipeDownDragTabHistogram,
-        kSwipeDownDragTabMaxLatencyHistogram);
-  } else {
-    presentation_time_recorder_ = CreatePresentationTimeHistogramRecorder(
-        dragged_window->layer()->GetCompositor(), kSwipeDownDragWindowHistogram,
-        kSwipeDownDragWindowMaxLatencyHistogram);
-  }
-
-  dragged_window_ = dragged_window;
-  initial_location_in_screen_ = location_in_screen;
-  drag_start_deadline_ = base::Time::Now() + kIsWindowMovedTimeoutMs;
-
-  PrepareWindowDrag(location_in_screen);
-
-  // Update the shelf's visibility to keep shelf visible during drag.
-  RootWindowController::ForWindow(dragged_window_)
-      ->GetShelfLayoutManager()
-      ->UpdateVisibilityState();
-
-  // Disable the backdrop on the dragged window.
-  WindowBackdrop::Get(dragged_window_)->DisableBackdrop();
-
-  OverviewController* controller = Shell::Get()->overview_controller();
-  bool was_overview_open = controller->InOverviewSession();
-
-  const bool was_splitview_active = split_view_controller_->InSplitViewMode();
-  // If the dragged window is one of the snapped windows, SplitViewController
-  // might open overview in the dragged window side of the screen.
-  split_view_controller_->OnWindowDragStarted(dragged_window_);
-  if (ShouldOpenOverviewWhenDragStarts() && !controller->InOverviewSession()) {
-    OverviewButtonTray* overview_button_tray =
-        RootWindowController::ForWindow(dragged_window_)
-            ->GetStatusAreaWidget()
-            ->overview_button_tray();
-    DCHECK(overview_button_tray);
-    overview_button_tray->SnapRippleToActivated();
-    controller->StartOverview(OverviewStartAction::kSplitView,
-                              OverviewEnterExitType::kImmediateEnter);
-  }
-
-  if (controller->InOverviewSession()) {
-    // Only do animation if overview was open before the drag started. If the
-    // overview is opened because of the window drag, do not do animation.
-    GetOverviewSession()->OnWindowDragStarted(dragged_window_,
-                                              /*animate=*/was_overview_open);
-  }
-
-  split_view_drag_indicators_->SetDraggedWindow(dragged_window_);
-  bounds_of_selected_drop_target_ =
-      GetBoundsOfSelectedDropTarget(dragged_window_);
-
-  // Update the dragged window's shadow. It should have the active window
-  // shadow during dragging.
-  original_shadow_elevation_ =
-      ::wm::GetShadowElevationConvertDefault(dragged_window_);
-  ::wm::SetShadowElevation(dragged_window_, ::wm::kShadowElevationActiveWindow);
-
-  Shell* shell = Shell::Get();
-  TabletModeController* tablet_mode_controller =
-      shell->tablet_mode_controller();
-  if (window_util::IsDraggingTabs(dragged_window_)) {
-    tablet_mode_controller->increment_tab_drag_count();
-    if (was_splitview_active)
-      tablet_mode_controller->increment_tab_drag_in_splitview_count();
-
-    // For tab drag, we only open the overview behind if the dragged window is
-    // the source window.
-    if (ShouldOpenOverviewWhenDragStarts())
-      RecordTabDragTypeHistogram(TabDragType::kDragSourceWindow);
-    else
-      RecordTabDragTypeHistogram(TabDragType::kDragTabOutOfWindow);
-  } else {
-    tablet_mode_controller->increment_app_window_drag_count();
-    if (was_splitview_active)
-      tablet_mode_controller->increment_app_window_drag_in_splitview_count();
-  }
-  if (controller->InOverviewSession()) {
-    UMA_HISTOGRAM_COUNTS_100(
-        "Tablet.WindowDrag.OpenedWindowsNumber",
-        shell->mru_window_tracker()->BuildMruWindowList(kActiveDesk).size());
-    base::RecordAction(
-        base::UserMetricsAction("Tablet.WindowDrag.OpenedOverview"));
-  }
-}
-
-void TabletModeWindowDragDelegate::ContinueWindowDrag(
-    const gfx::PointF& location_in_screen,
-    UpdateDraggedWindowType type,
-    const gfx::Rect& target_bounds) {
-  UpdateIsWindowConsideredMoved(location_in_screen.y());
-
-  if (presentation_time_recorder_)
-    presentation_time_recorder_->RequestNext();
-
-  if (type == UpdateDraggedWindowType::UPDATE_BOUNDS) {
-    // UPDATE_BOUNDS is used when dragging tab(s) out of a browser window.
-    // Changing bounds might delete ourselves as the dragged (browser) window
-    // tab(s) might merge into another browser window.
-    base::WeakPtr<TabletModeWindowDragDelegate> delegate(
-        weak_ptr_factory_.GetWeakPtr());
-    if (target_bounds != dragged_window_->bounds()) {
-      dragged_window_->SetBounds(target_bounds);
-      if (!delegate)
-        return;
-    }
-  } else {  // type == UpdateDraggedWindowType::UPDATE_TRANSFORM
-    // UPDATE_TRANSFORM is used when dragging an entire window around, either
-    // it's a browser window or an app window.
-    UpdateDraggedWindowTransform(location_in_screen);
-  }
-
-  // For child classes to do their special handling if any.
-  UpdateWindowDrag(location_in_screen);
-
-  // Update drag indicators and preview window if necessary.
-  SplitViewDragIndicators::WindowDraggingState window_dragging_state =
-      SplitViewDragIndicators::ComputeWindowDraggingState(
-          is_window_considered_moved_,
-          SplitViewDragIndicators::WindowDraggingState::kFromTop,
-          GetSnapPosition(location_in_screen));
-  split_view_drag_indicators_->SetWindowDraggingState(window_dragging_state);
-
-  if (GetOverviewSession()) {
-    GetOverviewSession()->OnWindowDragContinued(
-        dragged_window_, location_in_screen, window_dragging_state);
-  }
-}
-
-void TabletModeWindowDragDelegate::EndWindowDrag(
-    ToplevelWindowEventHandler::DragResult result,
-    const gfx::PointF& location_in_screen) {
-  EndingWindowDrag(result, location_in_screen);
-
-  WindowBackdrop::Get(dragged_window_)->RestoreBackdrop();
-  SplitViewController::SnapPosition snap_position =
-      SplitViewController::SnapPosition::kNone;
-  if (result == ToplevelWindowEventHandler::DragResult::SUCCESS &&
-      split_view_controller_->CanSnapWindow(dragged_window_)) {
-    snap_position = GetSnapPosition(location_in_screen);
-  }
-
-  // The window might merge into an overview window or become a new window item
-  // in overview mode.
-  OverviewSession* overview_session = GetOverviewSession();
-  if (overview_session) {
-    GetOverviewSession()->OnWindowDragEnded(
-        dragged_window_, location_in_screen,
-        ShouldDropWindowIntoOverview(snap_position, location_in_screen),
-        snap_position != SplitViewController::SnapPosition::kNone);
-  }
-
-  WindowState::Get(dragged_window_)
-      ->set_snap_action_source(WindowSnapActionSource::kDragDownFromTopToSnap);
-  split_view_controller_->OnWindowDragEnded(
-      dragged_window_, snap_position, gfx::ToRoundedPoint(location_in_screen));
-  split_view_drag_indicators_->SetWindowDraggingState(
-      SplitViewDragIndicators::WindowDraggingState::kNoDrag);
-
-  // Reset the dragged window's window shadow elevation.
-  ::wm::SetShadowElevation(dragged_window_, original_shadow_elevation_);
-
-  // For child class to do its special handling if any.
-  EndedWindowDrag(location_in_screen);
-
-  if (!window_util::IsDraggingTabs(dragged_window_)) {
-    if (split_view_controller_->IsWindowInSplitView(dragged_window_)) {
-      RecordAppDragEndWindowStateHistogram(
-          AppWindowDragEndWindowState::kDraggedIntoSplitView);
-    } else if (overview_session &&
-               overview_session->IsWindowInOverview(dragged_window_)) {
-      RecordAppDragEndWindowStateHistogram(
-          AppWindowDragEndWindowState::kDraggedIntoOverview);
-    } else {
-      RecordAppDragEndWindowStateHistogram(
-          AppWindowDragEndWindowState::kBackToMaximizedOrFullscreen);
-    }
-  }
-
-  presentation_time_recorder_.reset();
-  occlusion_excluder_.reset();
-  dragged_window_ = nullptr;
-  is_window_considered_moved_ = false;
-}
-
-void TabletModeWindowDragDelegate::FlingOrSwipe(ui::GestureEvent* event) {
-  if (event->type() == ui::ET_SCROLL_FLING_START) {
-    if (ShouldFlingIntoOverview(event)) {
-      DCHECK(Shell::Get()->overview_controller()->InOverviewSession());
-      Shell::Get()
-          ->overview_controller()
-          ->overview_session()
-          ->AddItemInMruOrder(dragged_window_, /*reposition=*/true,
-                              /*animate=*/false, /*restack=*/true,
-                              /*use_spawn_animation=*/false);
-    }
-    StartFling(event);
-  }
-  EndWindowDrag(ToplevelWindowEventHandler::DragResult::SUCCESS,
-                GetEventLocationInScreen(event));
-}
-
-gfx::PointF TabletModeWindowDragDelegate::GetEventLocationInScreen(
-    const ui::GestureEvent* event) const {
-  gfx::PointF location_in_screen(event->location());
-  ::wm::ConvertPointToScreen(static_cast<aura::Window*>(event->target()),
-                             &location_in_screen);
-  return location_in_screen;
-}
-
-bool TabletModeWindowDragDelegate::ShouldOpenOverviewWhenDragStarts() {
-  DCHECK(dragged_window_);
-  return true;
-}
-
-int TabletModeWindowDragDelegate::GetIndicatorsVerticalThreshold(
-    const gfx::Rect& work_area_bounds) const {
-  return work_area_bounds.y() +
-         work_area_bounds.height() * kIndicatorsThresholdRatio;
-}
-
-SplitViewController::SnapPosition TabletModeWindowDragDelegate::GetSnapPosition(
-    const gfx::PointF& location_in_screen) const {
-  // Check that the window has been considered as moved and is compatible with
-  // split view. If the window has not been considered as moved, it shall not
-  // become snapped, although if it already was snapped, it can stay snapped.
-  if (!(is_window_considered_moved_ &&
-        split_view_controller_->CanSnapWindow(dragged_window_))) {
-    return SplitViewController::SnapPosition::kNone;
-  }
-
-  const gfx::Rect area =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          dragged_window_);
-  SplitViewController::SnapPosition snap_position = ::ash::GetSnapPosition(
-      Shell::GetPrimaryRootWindow(), dragged_window_,
-      gfx::ToRoundedPoint(location_in_screen),
-      gfx::ToRoundedPoint(initial_location_in_screen_),
-      /*snap_distance_from_edge=*/kDistanceFromEdgeDp,
-      /*minimum_drag_distance=*/kMinimumDragToSnapDistanceDp,
-      /*horizontal_edge_inset=*/area.width() *
-              kHighlightScreenPrimaryAxisRatio +
-          kHighlightScreenEdgePaddingDp,
-      /*vertical_edge_inset=*/area.height() * kHighlightScreenPrimaryAxisRatio +
-          kHighlightScreenEdgePaddingDp);
-
-  // For portrait mode, since the drag always starts from the top of the
-  // screen, we only allow the window to be dragged to snap to the bottom of
-  // the screen.
-  const bool is_landscape = IsCurrentScreenOrientationLandscape();
-  const bool is_primary = IsCurrentScreenOrientationPrimary();
-  if (!is_landscape &&
-      ((is_primary &&
-        snap_position == SplitViewController::SnapPosition::kPrimary) ||
-       (!is_primary &&
-        snap_position == SplitViewController::SnapPosition::kSecondary))) {
-    snap_position = SplitViewController::SnapPosition::kNone;
-  }
-
-  return snap_position;
-}
-
-void TabletModeWindowDragDelegate::UpdateDraggedWindowTransform(
-    const gfx::PointF& location_in_screen) {
-  DCHECK(Shell::Get()->overview_controller()->InOverviewSession());
-
-  // Calculate the desired scale along the y-axis. The scale of the window
-  // during drag is based on the distance from |y_location_in_screen| to the y
-  // position of |bounds_of_selected_drop_target_|. The dragged windowt will
-  // become smaller when it becomes nearer to the drop target. And then keep the
-  // minimum scale if it has been dragged further than the drop target.
-  float scale = static_cast<float>(bounds_of_selected_drop_target_.height()) /
-                static_cast<float>(dragged_window_->bounds().height());
-  float y_full = bounds_of_selected_drop_target_.y();
-  float y_diff = y_full - location_in_screen.y();
-  if (y_diff >= 0)
-    scale = (1.0f - scale) * y_diff / y_full + scale;
-
-  gfx::Transform transform;
-  gfx::Rect window_bounds = dragged_window_->bounds();
-  ::wm::ConvertRectToScreen(dragged_window_->parent(), &window_bounds);
-  transform.Translate(
-      (location_in_screen.x() - window_bounds.x()) -
-          (initial_location_in_screen_.x() - window_bounds.x()) * scale,
-      (location_in_screen.y() - window_bounds.y()) -
-          (initial_location_in_screen_.y() - window_bounds.y()) * scale);
-  transform.Scale(scale, scale);
-  SetTransform(dragged_window_, transform);
-}
-
-bool TabletModeWindowDragDelegate::ShouldDropWindowIntoOverview(
-    SplitViewController::SnapPosition snap_position,
-    const gfx::PointF& location_in_screen) {
-  // Do not drop the dragged window into overview if preview area is shown.
-  if (snap_position != SplitViewController::SnapPosition::kNone)
-    return false;
-
-  OverviewItem* drop_target = GetDropTarget(dragged_window_);
-  if (!drop_target)
-    return false;
-
-  OverviewGrid* overview_grid = GetOverviewGrid(dragged_window_);
-  aura::Window* target_window = overview_grid->GetTargetWindowOnLocation(
-      location_in_screen, /*ignored_item=*/nullptr);
-  const bool is_drop_target_selected =
-      target_window && overview_grid->IsDropTargetWindow(target_window);
-
-  const gfx::Rect work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(dragged_window_)
-          .work_area();
-  return is_drop_target_selected ||
-         (location_in_screen.y() - work_area_bounds.y()) >=
-             kDragPositionToOverviewRatio *
-                 (drop_target->GetTransformedBounds().y() -
-                  work_area_bounds.y());
-}
-
-bool TabletModeWindowDragDelegate::ShouldFlingIntoOverview(
-    const ui::GestureEvent* event) const {
-  // Only fling into overview if overview is currently open. In some case,
-  // overview is not opened when drag starts (if it's tab-dragging and the
-  // dragged window is not the same with the source window), we should not fling
-  // the dragged window into overview in this case.
-  if (!Shell::Get()->overview_controller()->InOverviewSession())
-    return false;
-
-  const gfx::PointF location_in_screen = GetEventLocationInScreen(event);
-  const SplitViewDragIndicators::WindowDraggingState window_dragging_state =
-      SplitViewDragIndicators::ComputeWindowDraggingState(
-          is_window_considered_moved_,
-          SplitViewDragIndicators::WindowDraggingState::kFromTop,
-          GetSnapPosition(location_in_screen));
-  const bool is_landscape = IsCurrentScreenOrientationLandscape();
-  const float velocity = is_landscape ? event->details().velocity_x()
-                                      : event->details().velocity_y();
-
-  // Drop the window into overview if fling with large enough velocity to the
-  // opposite snap position when preview area is shown.
-  if (IsCurrentScreenOrientationPrimary()) {
-    if (window_dragging_state ==
-        SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary) {
-      return velocity > kFlingToOverviewFromSnappingAreaThreshold;
-    } else if (window_dragging_state ==
-               SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary) {
-      return -velocity > kFlingToOverviewFromSnappingAreaThreshold;
-    }
-  } else {
-    if (window_dragging_state ==
-        SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary) {
-      return -velocity > kFlingToOverviewFromSnappingAreaThreshold;
-    } else if (window_dragging_state ==
-               SplitViewDragIndicators::WindowDraggingState::kToSnapSecondary) {
-      return velocity > kFlingToOverviewFromSnappingAreaThreshold;
-    }
-  }
-
-  // Consider only the velocity_y if no preview area is shown.
-  return event->details().velocity_y() > kFlingToOverviewThreshold;
-}
-
-void TabletModeWindowDragDelegate::UpdateIsWindowConsideredMoved(
-    int y_location_in_screen) {
-  if (is_window_considered_moved_)
-    return;
-
-  if (base::Time::Now() < drag_start_deadline_)
-    return;
-
-  DCHECK(dragged_window_);
-  const gfx::Rect work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestWindow(dragged_window_)
-          .work_area();
-  is_window_considered_moved_ =
-      y_location_in_screen >= GetIndicatorsVerticalThreshold(work_area_bounds);
-}
-
-}  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h
deleted file mode 100644
index 5125c66..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_DELEGATE_H_
-#define ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_DELEGATE_H_
-
-#include <memory>
-
-#include "ash/public/cpp/window_properties.h"
-#include "ash/wm/splitview/split_view_controller.h"
-#include "ash/wm/toplevel_window_event_handler.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/aura/window_occlusion_tracker.h"
-#include "ui/compositor/presentation_time_recorder.h"
-#include "ui/wm/core/shadow_types.h"
-
-namespace {
-class PresentationTimeRecorder;
-}
-
-namespace ash {
-
-class SplitViewDragIndicators;
-
-// This class includes the common logic when dragging a window around, either
-// it's a browser window, or an app window. It does almost everything needs to
-// be done, including updating the dragged window's bounds (if it's dragged by
-// tabs) or transform (if it's dragged by entire window). it also decides
-// when/where to show the drag indicators and preview windows, shows/hides the
-// backdrop, interacts with overview and splitview, etc.
-class TabletModeWindowDragDelegate {
- public:
-  // The threshold to compute the end position of the dragged window to drop it
-  // into overview.
-  static constexpr float kDragPositionToOverviewRatio = 0.5f;
-
-  // Threshold of the fling velocity to drop the dragged window into overview if
-  // fling from the top of the display or from the caption area of the window.
-  static constexpr float kFlingToOverviewThreshold = 2000.f;
-
-  // Threshold of the fling velocity to drop the dragged window into overview if
-  // fling inside preview area or when splitview is active.
-  static constexpr float kFlingToOverviewFromSnappingAreaThreshold = 1000.f;
-
-  enum class UpdateDraggedWindowType {
-    UPDATE_BOUNDS,
-    UPDATE_TRANSFORM,
-  };
-
-  TabletModeWindowDragDelegate();
-
-  TabletModeWindowDragDelegate(const TabletModeWindowDragDelegate&) = delete;
-  TabletModeWindowDragDelegate& operator=(const TabletModeWindowDragDelegate&) =
-      delete;
-
-  virtual ~TabletModeWindowDragDelegate();
-
-  // Called when a window starts being dragged.
-  void StartWindowDrag(aura::Window* window,
-                       const gfx::PointF& location_in_screen);
-
-  // Called when a window continues being dragged. |type| specifies how we want
-  // to update the dragged window during dragging, and |target_bounds| is the
-  // target window bounds for the dragged window if |type| is UPDATE_BOUNDS.
-  // Note |target_bounds| has no use if |type| is UPDATE_TRANSFROM.
-  void ContinueWindowDrag(const gfx::PointF& location_in_screen,
-                          UpdateDraggedWindowType type,
-                          const gfx::Rect& target_bounds = gfx::Rect());
-
-  // Calls when a window ends dragging with its drag result |result|.
-  void EndWindowDrag(ToplevelWindowEventHandler::DragResult result,
-                     const gfx::PointF& location_in_screen);
-
-  // Calls when a window ends dragging because of fling or swipe.
-  void FlingOrSwipe(ui::GestureEvent* event);
-
-  // Return the location of |event| in screen coordinates.
-  gfx::PointF GetEventLocationInScreen(const ui::GestureEvent* event) const;
-
-  aura::Window* dragged_window() { return dragged_window_; }
-
-  SplitViewDragIndicators* split_view_drag_indicators_for_testing() {
-    return split_view_drag_indicators_.get();
-  }
-
-  void set_drag_start_deadline_for_testing(base::Time time) {
-    drag_start_deadline_ = time;
-  }
-
- protected:
-  // These five methods are used by its child class to do its special handling
-  // before/during/after dragging.
-  virtual void PrepareWindowDrag(const gfx::PointF& location_in_screen) {}
-  virtual void UpdateWindowDrag(const gfx::PointF& location_in_screen) {}
-  virtual void EndingWindowDrag(ToplevelWindowEventHandler::DragResult result,
-                                const gfx::PointF& location_in_screen) {}
-  virtual void EndedWindowDrag(const gfx::PointF& location_in_screen) {}
-  // Calls when a fling event starts.
-  virtual void StartFling(const ui::GestureEvent* event) {}
-
-  // Returns true if we should open overview behind the dragged window when drag
-  // starts.
-  virtual bool ShouldOpenOverviewWhenDragStarts();
-
-  // When the dragged window is dragged past this value, the drag indicators
-  // will show up.
-  int GetIndicatorsVerticalThreshold(const gfx::Rect& work_area_bounds) const;
-
-  // Gets the desired snap position for |location_in_screen|.
-  SplitViewController::SnapPosition GetSnapPosition(
-      const gfx::PointF& location_in_screen) const;
-
-  // Updates the dragged window's transform during dragging.
-  void UpdateDraggedWindowTransform(const gfx::PointF& location_in_screen);
-
-  // Returns true if the dragged window should be dropped into overview on drag
-  // end.
-  bool ShouldDropWindowIntoOverview(
-      SplitViewController::SnapPosition snap_position,
-      const gfx::PointF& location_in_screen);
-
-  // Returns true if fling event should drop the window into overview grid.
-  bool ShouldFlingIntoOverview(const ui::GestureEvent* event) const;
-
-  // Updates |is_window_considered_moved_| on current time and
-  // |y_location_in_screen|.
-  void UpdateIsWindowConsideredMoved(int y_location_in_screen);
-
-  SplitViewController* const split_view_controller_;
-
-  // A widget to display the drag indicators and preview window.
-  std::unique_ptr<SplitViewDragIndicators> split_view_drag_indicators_;
-
-  aura::Window* dragged_window_ = nullptr;  // not owned.
-
-  // The dragged window should have the active window shadow elevation during
-  // dragging.
-  int original_shadow_elevation_ = ::wm::kShadowElevationDefault;
-
-  gfx::PointF initial_location_in_screen_;
-
-  // Overview mode will be triggered if a window is being dragged, and the drop
-  // target will be created in the overview grid. The variable stores the bounds
-  // of the selected drop target in overview and will be used to calculate the
-  // desired window transform during dragging.
-  gfx::Rect bounds_of_selected_drop_target_;
-
-  // True if the |dragged_window_| has been considered as moved. Only after it
-  // has been dragged longer than kIsWindowMovedTimeoutMs on time and further
-  // than GetIndicatorsVerticalThreshold on distance, it can be considered as
-  // moved. Only change its window state or show the drag indicators if it has
-  // been 'moved'. Once it has been 'moved', it will stay as 'moved'.
-  bool is_window_considered_moved_ = false;
-
-  // Drag need to last later than the deadline here to be considered as 'moved'.
-  base::Time drag_start_deadline_;
-
-  absl::optional<aura::WindowOcclusionTracker::ScopedExclude>
-      occlusion_excluder_;
-
-  // Records the presentation time for app/browser/tab window dragging
-  // in tablet mode.
-  std::unique_ptr<ui::PresentationTimeRecorder> presentation_time_recorder_;
-
-  base::WeakPtrFactory<TabletModeWindowDragDelegate> weak_ptr_factory_{this};
-};
-
-}  // namespace ash
-
-#endif  // ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_DELEGATE_H_
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.cc
deleted file mode 100644
index b36a84a..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h"
-
-#include "base/metrics/histogram_macros.h"
-
-namespace ash {
-
-constexpr char kWindowDragEndEventTypeHistogram[] =
-    "Tablet.WindowDrag.DragEndEventType";
-constexpr char kAppDragEndWindowStateHistogram[] =
-    "Tablet.AppDrag.EndWindowState";
-constexpr char kTabDragTypeHistogram[] = "Tablet.TabDrag.DragType";
-
-void RecordWindowDragEndTypeHistogram(WindowDragEndEventType type) {
-  UMA_HISTOGRAM_ENUMERATION(kWindowDragEndEventTypeHistogram, type);
-}
-
-void RecordAppDragEndWindowStateHistogram(AppWindowDragEndWindowState state) {
-  UMA_HISTOGRAM_ENUMERATION(kAppDragEndWindowStateHistogram, state);
-}
-
-void RecordTabDragTypeHistogram(TabDragType type) {
-  UMA_HISTOGRAM_ENUMERATION(kTabDragTypeHistogram, type);
-}
-
-}  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h b/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h
deleted file mode 100644
index 7920600..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_METRICS_H_
-#define ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_METRICS_H_
-
-namespace ash {
-
-// See WindowDragEndEventType at tools/metrics/histograms/enums.xml
-enum class WindowDragEndEventType {
-  kEndsWithNormalComplete = 0,
-  kEndsWithRevert = 1,
-  kEndsWithFling = 2,
-  kMaxValue = kEndsWithFling,
-};
-
-void RecordWindowDragEndTypeHistogram(WindowDragEndEventType type);
-
-// See AppWindowDragEndWindowState at tools/metrics/histograms/enums.xml
-enum class AppWindowDragEndWindowState {
-  kBackToMaximizedOrFullscreen = 0,
-  kDraggedIntoOverview = 1,
-  kDraggedIntoSplitView = 2,
-  kMaxValue = kDraggedIntoSplitView,
-};
-
-void RecordAppDragEndWindowStateHistogram(AppWindowDragEndWindowState state);
-
-// See TabDragType at tools/metrics/histograms/enums.xml
-enum class TabDragType {
-  kDragSourceWindow = 0,
-  kDragTabOutOfWindow = 1,
-  kMaxValue = kDragTabOutOfWindow,
-};
-
-void RecordTabDragTypeHistogram(TabDragType type);
-
-}  // namespace ash
-
-#endif  // ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_DRAG_METRICS_H_
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index d6a7533..77456b8 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1580,21 +1580,6 @@
   EXPECT_EQ(window->bounds(), rect);
 }
 
-// Test that if a window is currently in tab-dragging process, its window bounds
-// should not updated.
-TEST_F(TabletModeWindowManagerTest, DontChangeBoundsForTabDraggingWindow) {
-  gfx::Rect rect(0, 0, 200, 200);
-  std::unique_ptr<aura::Window> window(
-      CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect));
-  // Now put the window in tab-dragging process.
-  window->SetProperty(kIsDraggingTabsKey, true);
-
-  TabletModeWindowManager* manager = CreateTabletModeWindowManager();
-  ASSERT_TRUE(manager);
-  EXPECT_EQ(1, manager->GetNumberOfManagedWindows());
-  EXPECT_EQ(window->bounds(), rect);
-}
-
 // Make sure that transient children should not be maximized.
 TEST_F(TabletModeWindowManagerTest, DontMaximizeTransientChild) {
   gfx::Rect rect(0, 0, 200, 200);
diff --git a/ash/wm/tablet_mode/tablet_mode_window_resizer.cc b/ash/wm/tablet_mode/tablet_mode_window_resizer.cc
deleted file mode 100644
index 7abece4..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_resizer.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
-
-#include "ash/shell.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_metrics.h"
-#include "ash/wm/toplevel_window_event_handler.h"
-#include "ash/wm/window_util.h"
-#include "ui/wm/core/coordinate_conversion.h"
-#include "ui/wm/core/cursor_manager.h"
-
-namespace ash {
-
-TabletModeWindowResizer::TabletModeWindowResizer(
-    WindowState* window_state,
-    std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate)
-    : WindowResizer(window_state), drag_delegate_(std::move(drag_delegate)) {
-  if (details().source != ::wm::WINDOW_MOVE_SOURCE_TOUCH) {
-    Shell::Get()->cursor_manager()->LockCursor();
-    did_lock_cursor_ = true;
-  }
-
-  previous_location_in_screen_ = details().initial_location_in_parent;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(),
-                             &previous_location_in_screen_);
-
-  drag_delegate_->StartWindowDrag(GetTarget(), previous_location_in_screen_);
-}
-
-TabletModeWindowResizer::~TabletModeWindowResizer() {
-  if (did_lock_cursor_)
-    Shell::Get()->cursor_manager()->UnlockCursor();
-}
-
-void TabletModeWindowResizer::Drag(const gfx::PointF& location_in_parent,
-                                   int event_flags) {
-  gfx::PointF location_in_screen = location_in_parent;
-  ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
-  previous_location_in_screen_ = location_in_screen;
-
-  // Update the dragged window, the drag indicators, the preview window,
-  // source window position, blurred background, etc, if necessary.
-  if (window_util::IsDraggingTabs(GetTarget())) {
-    // Update the dragged window's bounds if it's tab-dragging.
-    base::WeakPtr<TabletModeWindowResizer> resizer(
-        weak_ptr_factory_.GetWeakPtr());
-    drag_delegate_->ContinueWindowDrag(
-        location_in_screen,
-        TabletModeWindowDragDelegate::UpdateDraggedWindowType::UPDATE_BOUNDS,
-        CalculateBoundsForDrag(location_in_parent));
-    // Note, this might have been deleted when reaching here.
-    if (!resizer)
-      return;
-  } else {
-    // Otherwise, update the dragged window's transform.
-    drag_delegate_->ContinueWindowDrag(
-        location_in_screen, TabletModeWindowDragDelegate::
-                                UpdateDraggedWindowType::UPDATE_TRANSFORM);
-  }
-}
-
-void TabletModeWindowResizer::CompleteDrag() {
-  drag_delegate_->EndWindowDrag(ToplevelWindowEventHandler::DragResult::SUCCESS,
-                                previous_location_in_screen_);
-  RecordWindowDragEndTypeHistogram(
-      WindowDragEndEventType::kEndsWithNormalComplete);
-}
-
-void TabletModeWindowResizer::RevertDrag() {
-  drag_delegate_->EndWindowDrag(ToplevelWindowEventHandler::DragResult::REVERT,
-                                previous_location_in_screen_);
-  RecordWindowDragEndTypeHistogram(WindowDragEndEventType::kEndsWithRevert);
-}
-
-void TabletModeWindowResizer::FlingOrSwipe(ui::GestureEvent* event) {
-  drag_delegate_->FlingOrSwipe(event);
-  RecordWindowDragEndTypeHistogram(WindowDragEndEventType::kEndsWithFling);
-}
-
-}  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_resizer.h b/ash/wm/tablet_mode/tablet_mode_window_resizer.h
deleted file mode 100644
index 11efa7339..0000000
--- a/ash/wm/tablet_mode/tablet_mode_window_resizer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_RESIZER_H_
-#define ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_RESIZER_H_
-
-#include <memory>
-
-#include "ash/ash_export.h"
-#include "ash/wm/window_resizer.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/gfx/geometry/point_f.h"
-
-namespace ash {
-
-class TabletModeWindowDragDelegate;
-class WindowState;
-
-// WindowResizer implementation for windows in tablet mode. Currently we
-// don't allow any resizing and any dragging happening on the area other than
-// the caption tabs area in tablet mode, or the top few client pixels for app
-// windows without caption areas. Depending on the event position, the dragged
-// window may be 1) maximized, or 2) snapped in splitscreen, or 3) merged to an
-// existing window (in the case of a browser window).
-class ASH_EXPORT TabletModeWindowResizer : public WindowResizer {
- public:
-  TabletModeWindowResizer(
-      WindowState* window_state,
-      std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate);
-
-  TabletModeWindowResizer(const TabletModeWindowResizer&) = delete;
-  TabletModeWindowResizer& operator=(const TabletModeWindowResizer&) = delete;
-
-  ~TabletModeWindowResizer() override;
-
-  // WindowResizer:
-  void Drag(const gfx::PointF& location_in_parent, int event_flags) override;
-  void CompleteDrag() override;
-  void RevertDrag() override;
-  void FlingOrSwipe(ui::GestureEvent* event) override;
-
-  TabletModeWindowDragDelegate* drag_delegate_for_testing() {
-    return drag_delegate_.get();
-  }
-
- private:
-  // The drag delegate that does the real work: shows/hides the drag indicators,
-  // preview windows, blurred background, etc, during dragging.
-  std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_;
-
-  gfx::PointF previous_location_in_screen_;
-
-  bool did_lock_cursor_ = false;
-
-  // Used to determine if this has been deleted during a drag such as when a tab
-  // gets dragged into another browser window.
-  base::WeakPtrFactory<TabletModeWindowResizer> weak_ptr_factory_{this};
-};
-
-}  // namespace ash
-
-#endif  // ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_RESIZER_H_
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc
index c394bae..5309d3cf 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_state.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -98,33 +98,6 @@
   return window_state->window()->GetBoundsInScreen();
 }
 
-// Returns true if |window| is the source window of the current tab-dragging
-// window.
-bool IsTabDraggingSourceWindow(aura::Window* window) {
-  if (!window)
-    return false;
-
-  MruWindowTracker::WindowList window_list =
-      Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
-  if (window_list.empty())
-    return false;
-
-  // Find the window that's currently in tab-dragging process. There is at most
-  // one such window.
-  aura::Window* dragged_window = nullptr;
-  for (auto* maybe_dragged_window : window_list) {
-    if (window_util::IsDraggingTabs(maybe_dragged_window)) {
-      dragged_window = maybe_dragged_window;
-      break;
-    }
-  }
-  if (!dragged_window)
-    return false;
-
-  return dragged_window->GetProperty(ash::kTabDraggingSourceWindowKey) ==
-         window;
-}
-
 // True if `window` is floated. If `window` is not floated, it is animated if:
 //   - It is the top window in the MRU list.
 //   - It the top window in the MRU list is a floated window, and `window` is
@@ -400,14 +373,12 @@
         // Floated windows in tablet mode are freeform, so they can placed
         // anywhere, not just centered.
         window_state->SetBoundsDirectCrossFade(bounds_in_parent, to_float);
-      } else if (window_util::IsDraggingTabs(window_state->window()) ||
-                 IsTabDraggingSourceWindow(window_state->window()) ||
-                 TabDragDropDelegate::IsSourceWindowForDrag(
+      } else if (TabDragDropDelegate::IsSourceWindowForDrag(
                      window_state->window()) ||
                  BoundsChangeIsFromVKAndAllowed(window_state->window())) {
-        // If the window is the current tab-dragged window or the current tab-
-        // dragged window's source window, we may need to update its bounds
-        // during dragging.
+        // If the window is the current tab-dragged window's source window or
+        // bounds change is allowed, we may need to update its bounds during
+        // dragging.
         window_state->SetBoundsDirect(bounds_in_parent);
       } else if (current_state_type_ == WindowStateType::kMaximized) {
         // Having a maximized window, it could have been created with an empty
@@ -569,11 +540,6 @@
 
 void TabletModeWindowState::UpdateBounds(WindowState* window_state,
                                          bool animated) {
-  // Do not update window's bounds if it's in tab-dragging process. The bounds
-  // will be updated later when the drag ends.
-  if (window_util::IsDraggingTabs(window_state->window()))
-    return;
-
   // Do not update minimized windows bounds until it was unminimized.
   if (current_state_type_ == WindowStateType::kMinimized)
     return;
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 6126d01..0f23ddce 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -1265,26 +1265,6 @@
 
 }  // namespace
 
-// In tablet mode, the window's resizability shouldn't be taken into account
-// when dragging from the top. Regression test for https://crbug.com/1444132
-TEST_F(ToplevelWindowEventHandlerDragTest,
-       NonResizableWindowsCanBeDraggedInTabletMode) {
-  TabletModeControllerTestApi().EnterTabletMode();
-
-  dragged_window_->SetProperty(aura::client::kResizeBehaviorKey,
-                               aura::client::kResizeBehaviorNone);
-
-  SendGestureEvent(gfx::Point(100, 0), 0, 5, ui::ET_GESTURE_SCROLL_BEGIN);
-  SendGestureEvent(gfx::Point(600, 500), 600, 500,
-                   ui::ET_GESTURE_SCROLL_UPDATE);
-  EXPECT_TRUE(WindowState::Get(dragged_window_.get())->is_dragged());
-
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_TRUE(overview_controller->overview_session()->IsWindowInOverview(
-      non_dragged_window_.get()));
-}
-
 // Contrary to tablet mode, in non-tablet mode, non resizable windows cannot be
 // dragged.
 TEST_F(ToplevelWindowEventHandlerDragTest,
@@ -1317,29 +1297,6 @@
   EXPECT_FALSE(event_handler->is_drag_in_progress());
 }
 
-// Test that if window destroyed during resize/dragging in tablet mode, no crash
-// should happen.
-TEST_F(ToplevelWindowEventHandlerDragTest,
-       WindowDestroyedDuringDraggingInTabletMode) {
-  TabletModeControllerTestApi().EnterTabletMode();
-
-  SendGestureEvent(gfx::Point(0, 0), 0, 5, ui::ET_GESTURE_SCROLL_BEGIN);
-  SendGestureEvent(gfx::Point(700, 500), 700, 500,
-                   ui::ET_GESTURE_SCROLL_UPDATE);
-  EXPECT_TRUE(WindowState::Get(dragged_window_.get())->is_dragged());
-  ToplevelWindowEventHandler* event_handler =
-      Shell::Get()->toplevel_window_event_handler();
-  EXPECT_TRUE(event_handler->is_drag_in_progress());
-  OverviewController* overview_controller = Shell::Get()->overview_controller();
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-  EXPECT_FALSE(overview_controller->overview_session()->IsWindowInOverview(
-      dragged_window_.get()));
-
-  dragged_window_.reset();
-  EXPECT_FALSE(event_handler->is_drag_in_progress());
-  EXPECT_TRUE(overview_controller->InOverviewSession());
-}
-
 // Showing the resize shadows when the mouse is over the window edges is
 // tested in resize_shadow_and_cursor_test.cc
 
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index 71e5b8c1..9ff4785 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -11,6 +11,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/metrics/pip_uma.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/root_window_controller.h"
 #include "ash/scoped_animation_disabler.h"
 #include "ash/screen_util.h"
@@ -23,10 +24,7 @@
 #include "ash/wm/float/tablet_mode_float_window_resizer.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/pip/pip_window_resizer.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
 #include "ash/wm/toplevel_window_event_handler.h"
 #include "ash/wm/window_animations.h"
 #include "ash/wm/window_positioning_utils.h"
@@ -312,64 +310,7 @@
     return std::make_unique<TabletModeFloatWindowResizer>(window_state);
   }
 
-  // Window dragging from top and tab dragging are disabled if "WebUITabStrip"
-  // feature is enabled. "WebUITabStrip" will be enabled on 81 for Krane and on
-  // 82 for all other boards.
-  if (features::IsWebUITabStripEnabled()) {
-    return nullptr;
-  }
-
-  // Only maximized/fullscreen/snapped window can be dragged from the top of
-  // the screen.
-  if (!window_state->IsMaximized() && !window_state->IsFullscreen() &&
-      !window_state->IsSnapped()) {
-    return nullptr;
-  }
-
-  AppType app_type =
-      static_cast<AppType>(window->GetProperty(aura::client::kAppType));
-  // App windows can be dragged from the client area (see
-  // ToplevelWindowEventHandler).
-  if (app_type != AppType::BROWSER && app_type != AppType::LACROS &&
-      window_component == HTCLIENT) {
-    DCHECK_EQ(source, ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-    window_state->CreateDragDetails(point_in_parent, HTCLIENT,
-                                    ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-    std::unique_ptr<WindowResizer> window_resizer =
-        std::make_unique<TabletModeWindowResizer>(
-            window_state, std::make_unique<TabletModeWindowDragDelegate>());
-    return std::make_unique<DragWindowResizer>(std::move(window_resizer),
-                                               window_state);
-  }
-
-  // Only allow drag that happens on caption or top area. Note: for a maximized
-  // or fullscreen window, the window component here is always HTCAPTION, but
-  // for a snapped window, the window component here can either be HTCAPTION or
-  // HTTOP.
-  if (window_component != HTCAPTION && window_component != HTTOP) {
-    return nullptr;
-  }
-
-  // Note: only browser windows and chrome app windows are included here.
-  // For browser windows, this piece of codes will be called no matter the
-  // drag happens on the tab(s) or on the non-tabstrip caption or top area.
-  // But for app window, this piece of codes will only be called if the chrome
-  // app window has its customized caption area and can't be hidden in tablet
-  // mode (and thus the drag for this type of chrome app window always happens
-  // on caption or top area). The case where the caption area of the chrome app
-  // window can be hidden is handled above.
-  if (app_type != AppType::BROWSER && app_type != AppType::CHROME_APP &&
-      app_type != AppType::LACROS) {
-    return nullptr;
-  }
-
-  window_state->CreateDragDetails(point_in_parent, window_component, source);
-  std::unique_ptr<WindowResizer> window_resizer =
-      std::make_unique<TabletModeWindowResizer>(
-          window_state,
-          std::make_unique<TabletModeBrowserWindowDragDelegate>());
-  return std::make_unique<DragWindowResizer>(std::move(window_resizer),
-                                             window_state);
+  return nullptr;
 }
 
 // When dragging, drags events have to moved pass this threshold before the
@@ -955,7 +896,7 @@
         NOTREACHED();
         type = WM_EVENT_MAXIMIZE;
         break;
-    };
+    }
 
     const WMEvent event(type);
     window_state()->OnWMEvent(&event);
@@ -1719,7 +1660,7 @@
       break;
     case SnapType::kNone:
       break;
-  };
+  }
   return snap_type;
 }
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8bc9f34..3b15044 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2026,7 +2026,6 @@
       "CoreFoundation.framework",
       "IOKit.framework",
       "OpenDirectory.framework",
-      "Security.framework",
     ]
   }
 
@@ -2071,6 +2070,7 @@
       "threading/platform_thread_mac.mm",
       "time/time_mac.mm",
     ]
+    frameworks += [ "Security.framework" ]
   }
 
   # Linux.
diff --git a/base/logging.cc b/base/logging.cc
index 496e68df..b1b0af07 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -20,6 +20,7 @@
 #include "base/debug/crash_logging.h"
 #include "base/immediate_crash.h"
 #include "base/pending_task.h"
+#include "base/process/process_handle.h"
 #include "base/strings/string_piece.h"
 #include "base/task/common/task_annotator.h"
 #include "base/trace_event/base_tracing.h"
@@ -72,7 +73,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
-#include "base/process/process_handle.h"
 #define MAX_PATH PATH_MAX
 typedef FILE* FileHandle;
 #endif
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
index 74d1351..d6f794e 100644
--- a/base/mac/foundation_util.mm
+++ b/base/mac/foundation_util.mm
@@ -369,6 +369,8 @@
 CF_CAST_DEFN(CTFontDescriptor)
 CF_CAST_DEFN(CTRun)
 
+CF_CAST_DEFN(SecCertificate)
+
 #if BUILDFLAG(IS_IOS)
 CF_CAST_DEFN(CTFont)
 #else
@@ -407,7 +409,6 @@
 
 #if !BUILDFLAG(IS_IOS)
 CF_CAST_DEFN(SecAccessControl)
-CF_CAST_DEFN(SecCertificate)
 CF_CAST_DEFN(SecKey)
 CF_CAST_DEFN(SecPolicy)
 #endif
diff --git a/buildtools/reclient_cfgs/rewrapper_chroot_compile.cfg b/buildtools/reclient_cfgs/rewrapper_chroot_compile.cfg
index d079abc..ea327f99 100644
--- a/buildtools/reclient_cfgs/rewrapper_chroot_compile.cfg
+++ b/buildtools/reclient_cfgs/rewrapper_chroot_compile.cfg
@@ -2,4 +2,5 @@
 server_address=unix:///tmp/reproxy.sock
 labels=type=compile,compiler=clang,lang=cpp
 exec_root=/
-env_var_allowlist=PATH
\ No newline at end of file
+env_var_allowlist=PATH
+exec_strategy=remote_local_fallback
diff --git a/buildtools/reclient_cfgs/rewrapper_chroot_python.cfg b/buildtools/reclient_cfgs/rewrapper_chroot_python.cfg
new file mode 100644
index 0000000..aae5b2f
--- /dev/null
+++ b/buildtools/reclient_cfgs/rewrapper_chroot_python.cfg
@@ -0,0 +1,6 @@
+platform=container-image=docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1,dockerChrootPath=.,dockerRuntime=runsc
+server_address=unix:///tmp/reproxy.sock
+labels=type=tool
+exec_root=/
+env_var_allowlist=PATH
+exec_strategy=remote_local_fallback
diff --git a/chrome/VERSION b/chrome/VERSION
index faa4e64..b43c0fe 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=113
 MINOR=0
-BUILD=5622
+BUILD=5623
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
index 79229f3..d118f862 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -78,6 +78,7 @@
     "+chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java",
     "+chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelector.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java",
+    "+chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java",
   ],
   'TabImpl\.java': [
     "+chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
index 023497a5..0db5e39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
@@ -4,6 +4,7 @@
 package org.chromium.chrome.browser.tab;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
 
@@ -17,6 +18,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.crash.ChromePureJavaExceptionReporter;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.metrics.UmaSessionStats;
@@ -47,6 +49,7 @@
 import org.chromium.components.profile_metrics.BrowserProfileType;
 import org.chromium.components.ukm.UkmRecorder;
 import org.chromium.content_public.browser.ContentFeatureList;
+import org.chromium.ui.display.DisplayAndroid;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
@@ -65,6 +68,7 @@
  * Utilities for requesting desktop sites support.
  */
 public class RequestDesktopUtils {
+    private static final double MAX_RECORDED_SCREEN_SIZE_INCHES = 15.2;
     private static final String SITE_WILDCARD = "*";
     // Global defaults experiment constants.
     private static final String ENABLED_GROUP_SUFFIX = "_Enabled";
@@ -391,6 +395,15 @@
         }
 
         SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
+        double screenSizeThreshold = ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(feature,
+                PARAM_GLOBAL_SETTING_DEFAULT_ON_DISPLAY_SIZE_THRESHOLD_INCHES,
+                DEFAULT_GLOBAL_SETTING_DEFAULT_ON_DISPLAY_SIZE_THRESHOLD_INCHES);
+        if (displaySizeInInches < screenSizeThreshold
+                && sharedPreferencesManager.contains(
+                        ChromePreferenceKeys.DEFAULT_ENABLE_DESKTOP_SITE_GLOBAL_SETTING_COHORT)) {
+            silentlyReportingCrashes(
+                    context, displaySizeInInches, "Display size falls below threshold");
+        }
 
         boolean previouslyDefaultEnabled = sharedPreferencesManager.readBoolean(
                 ChromePreferenceKeys.DEFAULT_ENABLED_DESKTOP_SITE_GLOBAL_SETTING, false);
@@ -398,10 +411,6 @@
                 SingleCategorySettingsConstants
                         .USER_ENABLED_DESKTOP_SITE_GLOBAL_SETTING_PREFERENCE_KEY);
 
-        double screenSizeThreshold = ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(feature,
-                PARAM_GLOBAL_SETTING_DEFAULT_ON_DISPLAY_SIZE_THRESHOLD_INCHES,
-                DEFAULT_GLOBAL_SETTING_DEFAULT_ON_DISPLAY_SIZE_THRESHOLD_INCHES);
-
         boolean inCohort = !previouslyUpdatedByUser && displaySizeInInches >= screenSizeThreshold;
         boolean wouldEnable = !previouslyDefaultEnabled && inCohort;
         if (wouldEnable) {
@@ -409,6 +418,12 @@
             // experiment for ongoing tracking in both enabled and control groups.
             sharedPreferencesManager.writeBoolean(
                     ChromePreferenceKeys.DEFAULT_ENABLE_DESKTOP_SITE_GLOBAL_SETTING_COHORT, true);
+            captureDisplaySpec(context, displaySizeInInches);
+        }
+
+        if (displaySizeInInches > MAX_RECORDED_SCREEN_SIZE_INCHES) {
+            silentlyReportingCrashes(
+                    context, displaySizeInInches, "Display size falls into overflow bucket");
         }
 
         if (inCohort
@@ -424,6 +439,49 @@
         return !isControlGroup && wouldEnable;
     }
 
+    private static void silentlyReportingCrashes(
+            Context context, double displaySizeInInches, String message) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS_LOGGING)) {
+            return;
+        }
+        DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(context);
+        Configuration config = context.getResources().getConfiguration();
+        String logMessage = String.format(Locale.US,
+                message + ", silently reporting crashes for debugging, displaySizeInInches: %.1f "
+                        + "displayWidth: %d displayHeight: %d xdpi: %.1f ydpi: %.1f "
+                        + "densityDpi: %d screenWidthDp: %d screenHeightDp: %d",
+                displaySizeInInches, display.getDisplayWidth(), display.getDisplayHeight(),
+                display.getXdpi(), display.getYdpi(), config.densityDpi, config.screenWidthDp,
+                config.screenHeightDp);
+        SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
+        String previousDisplaySpec = sharedPreferencesManager.readString(
+                ChromePreferenceKeys.DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC,
+                "");
+        if (!previousDisplaySpec.isEmpty()) {
+            logMessage += " " + previousDisplaySpec;
+        }
+        ChromePureJavaExceptionReporter.reportJavaException(new Throwable(logMessage));
+    }
+
+    private static void captureDisplaySpec(Context context, double displaySizeInInches) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS_LOGGING)) {
+            return;
+        }
+        SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
+        DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(context);
+        Configuration config = context.getResources().getConfiguration();
+        String displaySpec = String.format(Locale.US,
+                "lastDisplaySizeInInches: %.1f lastDisplayWidth: %d lastDisplayHeight: %d "
+                        + "lastXdpi: %.1f lastYdpi: %.1f lastDensityDpi: %d "
+                        + "lastScreenWidthDp: %d lastScreenHeightDp: %d",
+                displaySizeInInches, display.getDisplayWidth(), display.getDisplayHeight(),
+                display.getXdpi(), display.getYdpi(), config.densityDpi, config.screenWidthDp,
+                config.screenHeightDp);
+        sharedPreferencesManager.writeString(
+                ChromePreferenceKeys.DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC,
+                displaySpec);
+    }
+
     private static void updateNoLongerInCohort() {
         SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
         if (sharedPreferencesManager.contains(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
index 18d26a8c7..78047831 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -46,6 +46,7 @@
 import org.chromium.chrome.browser.omnibox.action.OmniboxActionType;
 import org.chromium.chrome.browser.omnibox.action.OmniboxPedalType;
 import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionView;
+import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalViewAdapter;
 import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
 import org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment;
 import org.chromium.chrome.browser.settings.MainSettings;
@@ -67,8 +68,8 @@
 import org.chromium.components.omnibox.action.HistoryClustersAction;
 import org.chromium.components.omnibox.action.OmniboxPedal;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.ui.test.util.DisableAnimationsTestRule;
 import org.chromium.url.GURL;
 
 import java.util.ArrayList;
@@ -88,9 +89,10 @@
             Arrays.asList(new ParameterSet().value(false).name("RegularTab"),
                     new ParameterSet().value(true).name("IncognitoTab"));
 
-    @ClassRule
-    public static ChromeTabbedActivityTestRule sActivityTestRule =
+    public static @ClassRule ChromeTabbedActivityTestRule sActivityTestRule =
             new ChromeTabbedActivityTestRule();
+    public static @ClassRule DisableAnimationsTestRule sDisableAnimationsRule =
+            new DisableAnimationsTestRule();
 
     @Rule
     public HistogramTestRule mHistogramTester = new HistogramTestRule();
@@ -178,8 +180,9 @@
         SuggestionInfo<PedalSuggestionView> info =
                 mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION);
         CriteriaHelper.pollUiThread(() -> {
-            TestTouchUtils.performClickOnMainSync(
-                    InstrumentationRegistry.getInstrumentation(), info.view.getPedalChipView());
+            var adapter = (PedalViewAdapter) info.view.getPedalView().getAdapter();
+            adapter.selectNextItem();
+            adapter.getSelectedView().performClick();
         }, DEFAULT_MAX_TIME_TO_POLL * 5, DEFAULT_POLLING_INTERVAL);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
index 39fd8fd7..80cb69a 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
@@ -17,6 +17,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.res.Resources;
 import android.os.Build;
 
@@ -51,6 +52,7 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.RequestDesktopUtilsUnitTest.ShadowDisplayAndroid;
 import org.chromium.chrome.browser.tab.RequestDesktopUtilsUnitTest.ShadowSysUtils;
 import org.chromium.chrome.browser.tab.RequestDesktopUtilsUnitTest.ShadowUmaSessionStats;
 import org.chromium.chrome.browser.tab.TabUtilsUnitTest.ShadowProfile;
@@ -73,6 +75,7 @@
 import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.display.DisplayAndroid;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
@@ -96,7 +99,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE,
         shadows = {ShadowGURL.class, ShadowSysUtils.class, ShadowProfile.class,
-                ShadowUmaSessionStats.class})
+                ShadowUmaSessionStats.class, ShadowDisplayAndroid.class})
 public class RequestDesktopUtilsUnitTest {
     @Rule
     public JniMocker mJniMocker = new JniMocker();
@@ -154,6 +157,20 @@
         }
     }
 
+    @Implements(DisplayAndroid.class)
+    static class ShadowDisplayAndroid {
+        private static DisplayAndroid sDisplayAndroid;
+
+        public static void setDisplayAndroid(DisplayAndroid displayAndroid) {
+            sDisplayAndroid = displayAndroid;
+        }
+
+        @Implementation
+        public static DisplayAndroid getNonMultiDisplay(Context context) {
+            return sDisplayAndroid;
+        }
+    }
+
     @Mock
     private WebsitePreferenceBridge.Natives mWebsitePreferenceBridgeJniMock;
     @Mock
@@ -176,6 +193,8 @@
     private TabModel mIncognitoTabModel;
     @Mock
     private ObservableSupplier<Tab> mCurrentTabSupplier;
+    @Mock
+    private DisplayAndroid mDisplayAndroid;
 
     private Tab mTab;
     private @ContentSettingValues int mRdsDefaultValue;
@@ -246,6 +265,13 @@
         disableGlobalDefaultsExperimentFeatures();
 
         ShadowSysUtils.setMemoryInMB(2048);
+        ShadowDisplayAndroid.setDisplayAndroid(mDisplayAndroid);
+        when(mDisplayAndroid.getDisplayWidth()).thenReturn(1600);
+        when(mDisplayAndroid.getDisplayHeight()).thenReturn(2560);
+        when(mDisplayAndroid.getXdpi()).thenReturn(275.5f);
+        when(mDisplayAndroid.getYdpi()).thenReturn(276.5f);
+        enableFeatureWithParams(
+                ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS_LOGGING, null, false);
     }
 
     @After
@@ -254,6 +280,7 @@
         ShadowSysUtils.setLowEndDevice(false);
         ShadowProfile.reset();
         ShadowUmaSessionStats.reset();
+        ShadowDisplayAndroid.setDisplayAndroid(null);
         if (mSharedPreferencesManager != null) {
             mSharedPreferencesManager.removeKey(
                     ChromePreferenceKeys.DEFAULT_ENABLED_DESKTOP_SITE_GLOBAL_SETTING);
@@ -427,6 +454,38 @@
     }
 
     @Test
+    public void testShouldDefaultEnableGlobalSetting_WithLogging() {
+        Map<String, String> params = new HashMap<>();
+        params.put(
+                RequestDesktopUtils.PARAM_GLOBAL_SETTING_DEFAULT_ON_DISPLAY_SIZE_THRESHOLD_INCHES,
+                "10.0");
+        enableFeatureWithParams(ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS, params, true);
+        enableFeatureWithParams(
+                ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS_LOGGING, null, true);
+        boolean shouldDefaultEnable =
+                RequestDesktopUtils.shouldDefaultEnableGlobalSetting(11.0, mActivity);
+        Assert.assertTrue("Desktop site global setting should be default-enabled on 10\"+ devices.",
+                shouldDefaultEnable);
+        Assert.assertTrue(
+                "SharedPreference DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC "
+                        + "should not be empty.",
+                mSharedPreferencesManager.contains(
+                        ChromePreferenceKeys
+                                .DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC)
+                        && !mSharedPreferencesManager
+                                    .readString(
+                                            ChromePreferenceKeys
+                                                    .DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC,
+                                            "")
+                                    .isEmpty());
+
+        shouldDefaultEnable = RequestDesktopUtils.shouldDefaultEnableGlobalSetting(9.0, mActivity);
+        Assert.assertFalse(
+                "Desktop site global setting should only be default-enabled on 10\"+ devices.",
+                shouldDefaultEnable);
+    }
+
+    @Test
     public void testShouldDefaultEnableGlobalSetting_UserPreviouslyUpdatedSetting() {
         enableFeatureWithParams(ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS, null, true);
         // This SharedPreference key will ideally be updated when the user explicitly requests for
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 0f2df09..e9e23e008 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5659,6 +5659,9 @@
   <message name="IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE" desc="Error message shown if Plugin VM installation fails because there is not enough free space on the device.">
       Your device is low on storage. At least <ph name="MINIMUM_SPACE">$1<ex>16GB</ex></ph> of free space is required to use <ph name="APP_NAME">$2<ex>Plugin VM</ex></ph>. To increase free space, delete files from device.
   </message>
+  <message name="IDS_PLUGIN_VM_INSTALLER_ERROR_INVALID_IMAGE_MESSAGE" desc="Error message shown if Plugin VM installation fails because there is already VM with given name, but wrong type.">
+      Virtual machine "<ph name="VM_NAME">$1<ex>Plugin VM</ex></ph>" exists, but does not appear to be a valid <ph name="APP_NAME">$2<ex>Parallels Desktop</ex></ph> virtual machine. Please contact your administrator.
+  </message>
   <message name="IDS_PLUGIN_VM_APP_NAME_WINDOWS_SUFFIX" desc="Application name with ' (Windows)' suffix. Do not translate 'Windows'">
     <ph name="APP_NAME">$1<ex>Notepad</ex></ph> (Windows)
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_ERROR_INVALID_IMAGE_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_ERROR_INVALID_IMAGE_MESSAGE.png.sha1
new file mode 100644
index 0000000..96d16ca
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_ERROR_INVALID_IMAGE_MESSAGE.png.sha1
@@ -0,0 +1 @@
+a614489dc1f40ccb0b188c8532307bee29f144cf
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a46f136c..d997145 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -239,6 +239,7 @@
 #include "chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/web_applications/preinstalled_app_install_features.h"
+#include "components/user_notes/user_notes_features.h"
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -4587,9 +4588,6 @@
     {"enable-tls13-early-data", flag_descriptions::kEnableTLS13EarlyDataName,
      flag_descriptions::kEnableTLS13EarlyDataDescription, kOsAll,
      FEATURE_VALUE_TYPE(net::features::kEnableTLS13EarlyData)},
-    {"post-quantum-cecpq2", flag_descriptions::kPostQuantumCECPQ2Name,
-     flag_descriptions::kPostQuantumCECPQ2Description, kOsAll,
-     FEATURE_VALUE_TYPE(net::features::kPostQuantumCECPQ2)},
 #if BUILDFLAG(IS_ANDROID)
     {"feed-bottom-sync-banner", flag_descriptions::kFeedBottomSyncBannerName,
      flag_descriptions::kFeedBottomSyncBannerDescription, kOsAndroid,
@@ -5754,6 +5752,10 @@
      FEATURE_VALUE_TYPE(ntp_features::kNtpDummyModules)},
 #endif
 
+    {"ntp-journeys-module", flag_descriptions::kNtpHistoryClustersModuleName,
+     flag_descriptions::kNtpHistoryClustersModuleDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(ntp_features::kNtpHistoryClustersModule)},
+
     {"ntp-middle-slot-promo-dismissal",
      flag_descriptions::kNtpMiddleSlotPromoDismissalName,
      flag_descriptions::kNtpMiddleSlotPromoDismissalDescription, kOsDesktop,
@@ -8859,6 +8861,14 @@
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_ANDROID)
+    {"request-desktop-site-defaults-logging",
+     flag_descriptions::kRequestDesktopSiteDefaultsLoggingName,
+     flag_descriptions::kRequestDesktopSiteDefaultsLoggingDescription,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kRequestDesktopSiteDefaultsLogging)},
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(IS_ANDROID)
     {"request-desktop-site-exceptions-downgrade",
      flag_descriptions::kRequestDesktopSiteExceptionsDowngradeName,
      flag_descriptions::kRequestDesktopSiteExceptionsDowngradeDescription,
@@ -9383,6 +9393,12 @@
      flag_descriptions::kPowerBookmarkBackendDescription, kOsAll,
      FEATURE_VALUE_TYPE(power_bookmarks::kPowerBookmarkBackend)},
 
+#if !BUILDFLAG(IS_ANDROID)
+    {"user-notes-side-panel", flag_descriptions::kUserNotesSidePanelName,
+     flag_descriptions::kUserNotesSidePanelDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(user_notes::kUserNotes)},
+#endif
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/apps/app_service/launch_utils.cc b/chrome/browser/apps/app_service/launch_utils.cc
index 06abc2d..9ecc229 100644
--- a/chrome/browser/apps/app_service/launch_utils.cc
+++ b/chrome/browser/apps/app_service/launch_utils.cc
@@ -24,11 +24,13 @@
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/webui_url_constants.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/sessions/core/session_id.h"
+#include "extensions/common/constants.h"
 #include "mojo/public/cpp/bindings/struct_ptr.h"
 #include "storage/browser/file_system/file_system_url.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -315,10 +317,13 @@
       return extensions::AppLaunchSource::kSourceProtocolHandler;
     case LaunchSource::kFromUrlHandler:
       return extensions::AppLaunchSource::kSourceUrlHandler;
-    case apps::LaunchSource::kFromLockScreen:
+    case LaunchSource::kFromLockScreen:
       return extensions::AppLaunchSource::kSourceUntracked;
-    case apps::LaunchSource::kFromAppHomePage:
+    case LaunchSource::kFromAppHomePage:
       return extensions::AppLaunchSource::kSourceAppHomePage;
+    // No equivalent extensions launch source or not needed in extensions:
+    case LaunchSource::kFromReparenting:
+      return extensions::AppLaunchSource::kSourceNone;
   }
 }
 
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
index f4abc78..684428f 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
@@ -421,15 +421,15 @@
   window_is_closed = true;
 }
 
-base::Value AppPlatformMetrics::UsageTime::ConvertToValue() const {
-  base::Value usage_time_dict(base::Value::Type::DICT);
-  usage_time_dict.SetStringKey(kUsageTimeAppIdKey, app_id);
-  usage_time_dict.SetStringKey(kUsageTimeAppTypeKey,
-                               GetAppTypeHistogramName(app_type_name));
-  usage_time_dict.SetPath(kUsageTimeDurationKey,
-                          base::TimeDeltaToValue(running_time));
-  usage_time_dict.SetPath(kReportingUsageTimeDurationKey,
-                          base::TimeDeltaToValue(reporting_usage_time));
+base::Value::Dict AppPlatformMetrics::UsageTime::ConvertToDict() const {
+  base::Value::Dict usage_time_dict;
+  usage_time_dict.Set(kUsageTimeAppIdKey, app_id);
+  usage_time_dict.Set(kUsageTimeAppTypeKey,
+                      GetAppTypeHistogramName(app_type_name));
+  usage_time_dict.Set(kUsageTimeDurationKey,
+                      base::TimeDeltaToValue(running_time));
+  usage_time_dict.Set(kReportingUsageTimeDurationKey,
+                      base::TimeDeltaToValue(reporting_usage_time));
   return usage_time_dict;
 }
 
@@ -1240,20 +1240,20 @@
   ScopedDictPrefUpdate usage_dict_pref(profile_->GetPrefs(), kAppUsageTime);
   for (auto it : usage_time_per_two_hours_) {
     const std::string& instance_id = it.first.ToString();
-    auto* const usage_info = usage_dict_pref->FindByDottedPath(instance_id);
+    auto* const usage_info = usage_dict_pref->FindDictByDottedPath(instance_id);
     if (!usage_info) {
       // No entry in the pref store for this instance, so we create a new one.
-      usage_dict_pref->SetByDottedPath(instance_id, it.second.ConvertToValue());
+      usage_dict_pref->SetByDottedPath(instance_id, it.second.ConvertToDict());
       continue;
     }
 
     // Only override the fields tracked by this component so we do not override
     // the reporting usage time.
-    usage_info->SetStringPath(kUsageTimeAppIdKey, it.second.app_id);
-    usage_info->SetStringPath(kUsageTimeAppTypeKey,
-                              GetAppTypeHistogramName(it.second.app_type_name));
-    usage_info->SetPath(kUsageTimeDurationKey,
-                        base::TimeDeltaToValue(it.second.running_time));
+    usage_info->Set(kUsageTimeAppIdKey, it.second.app_id);
+    usage_info->Set(kUsageTimeAppTypeKey,
+                    GetAppTypeHistogramName(it.second.app_type_name));
+    usage_info->Set(kUsageTimeDurationKey,
+                    base::TimeDeltaToValue(it.second.running_time));
   }
 }
 
@@ -1331,9 +1331,10 @@
     const base::StringPiece& instance_id) {
   ScopedDictPrefUpdate usage_time_pref_update(profile_->GetPrefs(),
                                               kAppUsageTime);
-  if (usage_time_pref_update->FindByDottedPath(instance_id)) {
-    usage_time_pref_update->FindByDottedPath(instance_id)
-        ->SetPath(kUsageTimeDurationKey, base::Int64ToValue(0));
+  auto* instance_dict =
+      usage_time_pref_update->FindDictByDottedPath(instance_id);
+  if (instance_dict) {
+    instance_dict->Set(kUsageTimeDurationKey, base::Int64ToValue(0));
   }
 }
 
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
index 75c9dfa..182b29f 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
@@ -131,14 +131,14 @@
     // reset, ideally after the corresponding snapshot has been reported.
     base::TimeDelta reporting_usage_time;
 
-    // Converts the struct UsageTime to base::Value, e.g.:
+    // Converts the struct UsageTime to base::Value::Dict, e.g.:
     // {
     //    "app_id": "hhsosodfjlsjdflkjsdlfksdf",
     //    "app_type": "SystemWebApp",
     //    "time": 3600,
     //    "reporting_usage_time": 1800,
     // }
-    base::Value ConvertToValue() const;
+    base::Value::Dict ConvertToDict() const;
   };
 
   explicit AppPlatformMetrics(Profile* profile,
diff --git a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc
index 5d2ed24..3d9d581 100644
--- a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "components/app_constants/constants.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "extensions/common/constants.h"
 
@@ -149,6 +150,7 @@
     case apps::LaunchSource::kFromCommandLine:
     case apps::LaunchSource::kFromBackgroundMode:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       NOTREACHED();
       break;
   }
@@ -199,6 +201,7 @@
     case apps::LaunchSource::kFromUrlHandler:
     case apps::LaunchSource::kFromLockScreen:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       break;
   }
 }
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index 43a31d3..c4b9fc82b 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -146,11 +146,11 @@
   promotable = promotable_value.value();
 }
 
-base::Value WebsiteMetrics::UrlInfo::ConvertToValue() const {
-  base::Value usage_time_dict(base::Value::Type::DICT);
-  usage_time_dict.SetPath(kRunningTimeKey,
-                          base::TimeDeltaToValue(running_time_in_two_hours));
-  usage_time_dict.SetBoolKey(kPromotableKey, promotable);
+base::Value::Dict WebsiteMetrics::UrlInfo::ConvertToDict() const {
+  base::Value::Dict usage_time_dict;
+  usage_time_dict.Set(kRunningTimeKey,
+                      base::TimeDeltaToValue(running_time_in_two_hours));
+  usage_time_dict.Set(kPromotableKey, promotable);
   return usage_time_dict;
 }
 
@@ -551,7 +551,7 @@
     }
     // Save all urls running time in the past two hours to the user pref.
     if (!it.second.running_time_in_two_hours.is_zero()) {
-      dict.Set(it.first.spec(), it.second.ConvertToValue());
+      dict.Set(it.first.spec(), it.second.ConvertToDict());
     }
   }
 
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.h b/chrome/browser/apps/app_service/metrics/website_metrics.h
index c601986..70aa87fc 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.h
@@ -12,6 +12,7 @@
 #include "base/scoped_multi_source_observation.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/browser_tab_strip_tracker.h"
@@ -135,13 +136,13 @@
     bool is_activated = false;
     bool promotable = false;
 
-    // Converts the struct UsageTime to base::Value, e.g.:
+    // Converts the struct UsageTime to base::Value::Dict, e.g.:
     // {
     //    "time": "3600",
     //    "url_content": "scope",
     //    "promotable": "false",
     // }
-    base::Value ConvertToValue() const;
+    base::Value::Dict ConvertToDict() const;
   };
 
   // Observes the root window's activation client for the OnWindowActivated
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc
index 26637f1..4edb009 100644
--- a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc
+++ b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc
@@ -37,6 +37,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_metrics.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "components/services/app_service/public/cpp/intent.h"
@@ -345,6 +346,7 @@
     case apps::LaunchSource::kFromUrlHandler:
     case apps::LaunchSource::kFromLockScreen:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       break;
   }
 
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
index 0515b4d..acef23b4 100644
--- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
+++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
@@ -158,6 +158,7 @@
     case apps::LaunchSource::kFromUrlHandler:
     case apps::LaunchSource::kFromLockScreen:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       return ash::LAUNCH_FROM_UNKNOWN;
   }
 }
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
index 60f0501..bec680a7 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
@@ -68,7 +68,7 @@
 // https://crbug.com/1274236
 BASE_FEATURE(kAppShimProfileMenuIcons,
              "AppShimProfileMenuIcons",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // A crash key that is used when dumping because of errors when building and
 // verifying the app shim requirement.
diff --git a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
index e09ceaa..7888c53 100644
--- a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
@@ -15,10 +15,15 @@
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
-#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/crosapi/cpp/gurl_os_handler_utils.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 #include "components/omnibox/browser/autocomplete_input.h"
+#include "components/omnibox/browser/autocomplete_match.h"
+#include "components/omnibox/browser/autocomplete_match_type.h"
+#include "components/omnibox/browser/autocomplete_provider.h"
+#include "components/omnibox/browser/search_suggestion_parser.h"
 #include "url/gurl.h"
 
 namespace app_list {
@@ -38,7 +43,9 @@
     Profile* profile,
     AppListControllerDelegate* list_controller,
     crosapi::CrosapiManager* crosapi_manager)
-    : profile_(profile), list_controller_(list_controller) {
+    : search_provider_(nullptr),
+      profile_(profile),
+      list_controller_(list_controller) {
   DCHECK(profile_);
   DCHECK(list_controller_);
 
@@ -51,8 +58,43 @@
 OmniboxLacrosProvider::~OmniboxLacrosProvider() = default;
 
 void OmniboxLacrosProvider::Start(const std::u16string& query) {
-  if (!search_provider_)
+  if (!search_provider_ || !search_provider_->IsSearchControllerConnected()) {
+    const GURL sanitized_url =
+        crosapi::gurl_os_handler_utils::SanitizeAshURL(GURL(query));
+    const bool is_system_url =
+        ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(
+            sanitized_url);
+
+    if (is_system_url) {
+      AutocompleteInput input;
+
+      SearchSuggestionParser::SuggestResult suggest_result(
+          query, AutocompleteMatchType::URL_WHAT_YOU_TYPED, /*subtypes=*/{},
+          /*from_keyword=*/false,
+          /*relevance=*/kMaxOmniboxScore, /*relevance_from_server=*/false,
+          /*input_text=*/query);
+      AutocompleteMatch match(/*provider=*/nullptr, suggest_result.relevance(),
+                              /*deletable=*/false, suggest_result.type());
+      match.destination_url = GURL(query);
+      match.allowed_to_be_default_match = true;
+      match.contents = suggest_result.match_contents();
+      match.contents_class = suggest_result.match_contents_class();
+      match.suggestion_group_id = suggest_result.suggestion_group_id();
+      match.answer = suggest_result.answer();
+      match.stripped_destination_url = GURL(query);
+
+      crosapi::mojom::SearchResultPtr result =
+          crosapi::CreateResult(match, /*controller=*/nullptr,
+                                /*favicon_cache=*/nullptr,
+                                /*bookmark_model=*/nullptr, input);
+
+      SearchProvider::Results new_results;
+      new_results.emplace_back(std::make_unique<OmniboxResult>(
+          profile_, list_controller_, std::move(result), query));
+      SwapResults(&new_results);
+    }
     return;
+  }
 
   last_query_ = query;
   last_tokenized_query_.emplace(query, TokenizedString::Mode::kCamelCase);
diff --git a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
index 333a040..834e42c 100644
--- a/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
@@ -8,9 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "ash/constants/ash_features.h"
 #include "base/run_loop.h"
-#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
@@ -332,4 +330,84 @@
             search_controller_->last_results()[1]->id());
 }
 
+// A secondary test fixture which does not have any search producer connected to
+// the crosapi manager.
+class OmniboxLacrosProviderNoCrosAPITest : public testing::Test {
+ public:
+  OmniboxLacrosProviderNoCrosAPITest() = default;
+  OmniboxLacrosProviderNoCrosAPITest(
+      const OmniboxLacrosProviderNoCrosAPITest&) = delete;
+  OmniboxLacrosProviderNoCrosAPITest& operator=(
+      const OmniboxLacrosProviderNoCrosAPITest&) = delete;
+  ~OmniboxLacrosProviderNoCrosAPITest() override = default;
+
+  void SetUp() override {
+    // Create the profile manager and an active profile.
+    profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    ASSERT_TRUE(profile_manager_->SetUp());
+    // The profile needs a template URL service for history Omnibox results.
+    profile_ = profile_manager_->CreateTestingProfile(
+        chrome::kInitialProfile,
+        {{TemplateURLServiceFactory::GetInstance(),
+          base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor)}});
+
+    // The idle service has dependencies we can't instantiate in unit tests.
+    crosapi::IdleServiceAsh::DisableForTesting();
+
+    // The crosapi manager reads the global login state.
+    ash::LoginState::Initialize();
+
+    crosapi_manager_ = crosapi::CreateCrosapiManagerWithTestRegistry();
+
+    // Create fake lacros-side logic.
+    crosapi_manager_->crosapi_ash()->search_provider_ash();
+
+    // Create client of our provider.
+    search_controller_ = std::make_unique<TestSearchController>();
+
+    // Create the object to actually test.
+    omnibox_provider_ = std::make_unique<OmniboxLacrosProvider>(
+        profile_, &list_controller_, crosapi_manager_.get());
+    omnibox_provider_->set_controller(search_controller_.get());
+  }
+
+  void TearDown() override {
+    omnibox_provider_.reset();
+    search_controller_.reset();
+    crosapi_manager_.reset();
+    ash::LoginState::Shutdown();
+    profile_ = nullptr;
+    profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
+  }
+
+  // Starts a search and waits for the query to be sent to "lacros" over a Mojo
+  // pipe.
+  void StartSearch(const std::u16string& query) {
+    omnibox_provider_->Start(query);
+    base::RunLoop().RunUntilIdle();
+  }
+
+ protected:
+  std::unique_ptr<TestSearchController> search_controller_;
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  TestAppListControllerDelegate list_controller_;
+  std::unique_ptr<crosapi::CrosapiManager> crosapi_manager_;
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+  TestingProfile* profile_;
+  std::unique_ptr<OmniboxLacrosProvider> omnibox_provider_;
+};
+
+TEST_F(OmniboxLacrosProviderNoCrosAPITest, SystemURLsWorkWithNoSearchProvider) {
+  StartSearch(u"os://flags");
+
+  ASSERT_EQ(1u, search_controller_->last_results().size());
+  EXPECT_EQ("os://flags", search_controller_->last_results()[0]->id());
+  EXPECT_EQ(1.0, search_controller_->last_results()[0]->relevance());
+  EXPECT_EQ(u"os://flags", search_controller_->last_results()[0]->title());
+  EXPECT_EQ(u"", search_controller_->last_results()[0]->details());
+}
+
 }  // namespace app_list::test
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
index 1659a8b8..a0df887 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
@@ -68,10 +68,6 @@
           {} /* notification_key */};
 }
 
-bool ShouldTrackWindow(aura::Window* window) {
-  return IsArcOrGhostWindow(window);
-}
-
 void SetChildAxTreeIDForWindow(aura::Window* window,
                                const ui::AXTreeID& treeID) {
   DCHECK(window);
@@ -155,6 +151,7 @@
   // because exo::WMHelper can be destroyed earlier than this class.
 };
 
+// Observes windows corresponds to each task.
 class ArcAccessibilityTreeTracker::WindowsObserver
     : public aura::WindowObserver {
  public:
@@ -173,11 +170,17 @@
   void OnWindowPropertyChanged(aura::Window* window,
                                const void* key,
                                intptr_t old) override {
+    // TODO(b/270904414): remove kClientAccessibilityIdKey once sending a11y id
+    // is fully migrated to per-window level.
     if (key != exo::kApplicationIdKey &&
         key != ash::kClientAccessibilityIdKey) {
       return;
     }
-    owner_->UpdateWindowIdMapping(window);
+    owner_->UpdateTopWindowIds(window);
+  }
+
+  void OnWindowAdded(aura::Window* new_window) override {
+    owner_->TrackChildWindow(new_window);
   }
 
   void OnWindowDestroying(aura::Window* window) override {
@@ -196,6 +199,53 @@
       window_observations_{this};
 };
 
+// Observes child windows of toplevel ARC++ window, in order to get a value for
+// |ash::kClientAccessibilityIdKey|, which is set on window level.
+class ArcAccessibilityTreeTracker::ChildWindowsObserver
+    : public aura::WindowObserver {
+ public:
+  explicit ChildWindowsObserver(ArcAccessibilityTreeTracker* owner)
+      : owner_(owner) {}
+
+  void Observe(aura::Window* window) {
+    if (window_observations_.IsObservingSource(window)) {
+      return;
+    }
+
+    window_observations_.AddObservation(window);
+  }
+
+  void Reset() { window_observations_.RemoveAllObservations(); }
+
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override {
+    if (key != ash::kClientAccessibilityIdKey) {
+      return;
+    }
+    owner_->UpdateChildWindowIds(window);
+  }
+
+  void OnWindowAdded(aura::Window* new_window) override {
+    owner_->TrackChildWindow(new_window);
+  }
+
+  void OnWindowDestroying(aura::Window* window) override {
+    if (window_observations_.IsObservingSource(window)) {
+      window_observations_.RemoveObservation(window);
+    }
+  }
+
+  int GetTrackingWindowCount() const {
+    return window_observations_.GetSourcesCount();
+  }
+
+ private:
+  ArcAccessibilityTreeTracker* owner_;
+  base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
+      window_observations_{this};
+};
+
 class ArcAccessibilityTreeTracker::ArcInputMethodManagerServiceObserver
     : public ArcInputMethodManagerService::Observer {
  public:
@@ -418,6 +468,7 @@
       tree_source_delegate_(tree_source_delegate),
       accessibility_helper_instance_(accessibility_helper_instance),
       windows_observer_(std::make_unique<WindowsObserver>(this)),
+      child_windows_observer_(std::make_unique<ChildWindowsObserver>(this)),
       input_manager_service_observer_(
           std::make_unique<ArcInputMethodManagerServiceObserver>(this,
                                                                  profile)),
@@ -428,8 +479,9 @@
 ArcAccessibilityTreeTracker::~ArcAccessibilityTreeTracker() = default;
 
 void ArcAccessibilityTreeTracker::OnWindowInitialized(aura::Window* window) {
-  if (ShouldTrackWindow(window))
+  if (IsArcOrGhostWindow(window)) {
     TrackWindow(window);
+  }
 }
 
 void ArcAccessibilityTreeTracker::OnWindowFocused(aura::Window* gained_focus,
@@ -440,8 +492,8 @@
   // ToggleNativeChromeVoxArcSupport event.
   //  - When non-ChromeVox ARC window becomes inactive, dispatch |true|.
   //  - When non-ChromeVox ARC window becomes active, dispatch |false|.
-  bool lost_arc = ShouldTrackWindow(lost_focus);
-  bool gained_arc = ShouldTrackWindow(gained_focus);
+  bool lost_arc = IsArcOrGhostWindow(lost_focus);
+  bool gained_arc = IsArcOrGhostWindow(gained_focus);
   bool talkback_enabled = !native_chromevox_enabled_;
   if (talkback_enabled && lost_arc != gained_arc)
     DispatchCustomSpokenFeedbackToggled(gained_arc);
@@ -489,6 +541,7 @@
     DCHECK(aura::Env::HasInstance());
     env_observation_.Reset();
     windows_observer_->Reset();
+    child_windows_observer_->Reset();
   }
 }
 
@@ -748,40 +801,77 @@
 }
 
 bool ArcAccessibilityTreeTracker::IsArcFocused() const {
-  aura::Window* focused_window = GetFocusedArcWindow();
-  return focused_window && ShouldTrackWindow(focused_window);
+  return GetFocusedArcWindow();
 }
 
 void ArcAccessibilityTreeTracker::TrackWindow(aura::Window* window) {
   windows_observer_->Observe(window);
-  UpdateWindowIdMapping(window);
+  UpdateTopWindowIds(window);
   UpdateWindowProperties(window);
   uma_recorder_->OnWindowCreated();
 }
 
-void ArcAccessibilityTreeTracker::UpdateWindowIdMapping(aura::Window* window) {
+void ArcAccessibilityTreeTracker::TrackChildWindow(aura::Window* window) {
+  child_windows_observer_->Observe(window);
+  UpdateChildWindowIds(window);
+
+  for (aura::Window* child : window->children()) {
+    TrackChildWindow(child);
+  }
+}
+
+void ArcAccessibilityTreeTracker::UpdateTopWindowIds(aura::Window* window) {
   auto task_id = GetWindowTaskId(window);
   if (!task_id.has_value())
     return;
 
-  if (task_id_to_window_.count(task_id.value()) == 0)
+  if (task_id_to_window_.count(task_id.value()) == 0) {
     task_id_to_window_.emplace(task_id.value(), window);
 
-  const auto window_id = exo::GetShellClientAccessibilityId(window);
-  if (!window_id.has_value())
-    return;
+    // Force re-evaluate children so that window_id and task_id are correctly
+    // mapped.
+    for (aura::Window* child : window->children()) {
+      TrackChildWindow(child);
+    }
+  }
 
-  if (window_id_to_task_id_.find(window_id.value()) !=
-      window_id_to_task_id_.end()) {
+  // TODO(b/270904414): remove a11y window id check on top window once sending
+  // a11y id is fully migrated to per-window level.
+  const auto window_id = exo::GetShellClientAccessibilityId(window);
+  if (!window_id.has_value()) {
+    return;
+  }
+
+  UpdateWindowIdAndTaskId(window_id.value(), task_id.value());
+}
+
+void ArcAccessibilityTreeTracker::UpdateChildWindowIds(aura::Window* window) {
+  const auto window_id = exo::GetShellClientAccessibilityId(window);
+  if (!window_id.has_value()) {
+    return;
+  }
+
+  aura::Window* parent = FindArcWindow(window);
+  auto task_id = GetWindowTaskId(parent);
+  if (!task_id.has_value()) {
+    return;
+  }
+
+  UpdateWindowIdAndTaskId(window_id.value(), task_id.value());
+}
+
+void ArcAccessibilityTreeTracker::UpdateWindowIdAndTaskId(int32_t window_id,
+                                                          int32_t task_id) {
+  if (window_id_to_task_id_.find(window_id) != window_id_to_task_id_.end()) {
     // We already know this window ID.
     return;
   }
 
-  window_id_to_task_id_[window_id.value()] = *task_id;
+  window_id_to_task_id_[window_id] = task_id;
 
   // The window ID is new to us. Request the entire tree.
   arc::mojom::AccessibilityWindowKeyPtr window_key =
-      arc::mojom::AccessibilityWindowKey::NewWindowId(window_id.value());
+      arc::mojom::AccessibilityWindowKey::NewWindowId(window_id);
   accessibility_helper_instance_.RequestSendAccessibilityTree(
       std::move(window_key));
 }
@@ -823,7 +913,7 @@
 }
 
 void ArcAccessibilityTreeTracker::StartTrackingWindows(aura::Window* window) {
-  if (ShouldTrackWindow(window)) {
+  if (IsArcOrGhostWindow(window)) {
     TrackWindow(window);
     return;
   }
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h
index e147e007..48408d1 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h
@@ -122,9 +122,13 @@
   // Start observing the given window.
   void TrackWindow(aura::Window* window);
 
+  // Start observing the given window as a children of the toplevel ARC window.
+  void TrackChildWindow(aura::Window* window);
+
  private:
   class FocusChangeObserver;
   class WindowsObserver;
+  class ChildWindowsObserver;
   class ArcInputMethodManagerServiceObserver;
   class MojoConnectionObserver;
   class ArcNotificationSurfaceManagerObserver;
@@ -133,9 +137,20 @@
   AXTreeSourceArc* GetFromKey(const TreeKey&);
   AXTreeSourceArc* CreateFromKey(TreeKey, aura::Window* window);
 
-  // Update |window_id_to_task_id_| with a given window if necessary.
-  void UpdateWindowIdMapping(aura::Window* window);
+  // Updates task_id and window_id properties when properties of the toplevel
+  // ARC++ window change.
+  // As a side-effect, when a new task id is assigned to the window, it may
+  // also trigger updating child window ids.
+  void UpdateTopWindowIds(aura::Window* window);
 
+  // Updates task_id and window_id propertied when properties of child ARC++
+  // window change.
+  void UpdateChildWindowIds(aura::Window* window);
+
+  // Should be notified for mapping from |window_id| to |task_id|.
+  void UpdateWindowIdAndTaskId(int32_t window_id, int32_t task_id);
+
+  // Updates properties set to the given aura::Window.
   void UpdateWindowProperties(aura::Window* window);
 
   void StartTrackingWindows();
@@ -154,6 +169,7 @@
 
   std::unique_ptr<FocusChangeObserver> focus_change_observer_;
   std::unique_ptr<WindowsObserver> windows_observer_;
+  std::unique_ptr<ChildWindowsObserver> child_windows_observer_;
   std::unique_ptr<ArcInputMethodManagerServiceObserver>
       input_manager_service_observer_;
   std::unique_ptr<MojoConnectionObserver> connection_observer_;
@@ -164,7 +180,9 @@
 
   base::ScopedObservation<aura::Env, aura::EnvObserver> env_observation_{this};
 
+  // a11y window id (obtained from exo, put for each window) to task id.
   std::map<int32_t, int32_t> window_id_to_task_id_;
+  // task id to top aura::window.
   std::map<int32_t, aura::Window*> task_id_to_window_;
 
   arc::mojom::AccessibilityFilterType filter_type_ =
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
index 17abc041..265c4ab6 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
@@ -157,18 +157,26 @@
   ASSERT_EQ(0U, key_to_tree.size());
 
   // Set task ID 1 to the window.
-  // Also, set a11y window id to the window.
+  // Also, set a11y window id to a child window.
   tree_tracker.TrackWindow(test_window.get());
   exo::SetShellApplicationId(test_window.get(), "org.chromium.arc.1");
-  exo::SetShellClientAccessibilityId(test_window.get(), 10);
+
+  std::unique_ptr<aura::Window> child_window1 =
+      CreateWindow(ash::AppType::NON_APP);
+  exo::SetShellClientAccessibilityId(child_window1.get(), 10);
+  test_window->AddChild(child_window1.get());
 
   AXTreeSourceArc* tree1 =
       tree_tracker.OnAccessibilityEvent(event.Clone().get());
   ASSERT_NE(nullptr, tree1);
   ASSERT_EQ(1U, key_to_tree.size());
 
-  // In the same task, update window id.
-  exo::SetShellClientAccessibilityId(test_window.get(), 11);
+  // Add another child window with different id. (and call AddChild first.)
+  std::unique_ptr<aura::Window> child_window2 =
+      CreateWindow(ash::AppType::NON_APP);
+  test_window->AddChild(child_window2.get());
+  exo::SetShellClientAccessibilityId(child_window2.get(), 11);
+
   event->window_id = 11;
 
   AXTreeSourceArc* tree2 =
@@ -195,7 +203,10 @@
 
   std::unique_ptr<aura::Window> another_window = CreateWindow();
   exo::SetShellApplicationId(another_window.get(), "org.chromium.arc.2");
-  exo::SetShellClientAccessibilityId(another_window.get(), 20);
+  std::unique_ptr<aura::Window> another_child_window =
+      CreateWindow(ash::AppType::NON_APP);
+  exo::SetShellClientAccessibilityId(another_child_window.get(), 20);
+  another_window->AddChild(another_child_window.get());
 
   tree_tracker.TrackWindow(another_window.get());
 
diff --git a/chrome/browser/ash/borealis/borealis_util.cc b/chrome/browser/ash/borealis/borealis_util.cc
index 210b43c3..c698f84 100644
--- a/chrome/browser/ash/borealis/borealis_util.cc
+++ b/chrome/browser/ash/borealis/borealis_util.cc
@@ -29,7 +29,7 @@
 const char kInstallerAppId[] = "dkecggknbdokeipkgnhifhiokailichf";
 const char kClientAppId[] = "epfhbkiklgmlkhfpbcdleadnhcfdjfmo";
 const char kLauncherSearchAppId[] = "ceoplblcdaffnnflkkcagjpomjgedmdl";
-const char kIgnoredAppIdPrefix[] = "org.chromium.borealis.xid.";
+const char kIgnoredAppIdPrefix[] = "org.chromium.guest_os.borealis.xid.";
 const char kBorealisDlcName[] = "borealis-dlc";
 const char kAllowedScheme[] = "steam";
 const base::StringPiece kURLAllowlist[] = {"//store/", "//run/"};
@@ -67,10 +67,17 @@
     "org.chromium.guest_os.borealis.xprop.");
 
 // Windows with these app IDs are not games. Don't prompt for feedback for them.
-// Hashed by crx_file::id_util::GenerateId().
-static constexpr char kNonGameIdHash1[] = "hnfpbccfbbbjkmcalgjofgokpgjjppon";
-static constexpr char kNonGameIdHash2[] = "kooplpnkalpdpoohnhmlmfebokjkgnlb";
-static constexpr char kNonGameIdHash3[] = "bmhgcnboebpgmobfgfjcfplecleopefa";
+//
+// Some Steam updater windows use Zenity to show dialog boxes, and use its
+// default WMClass.
+static constexpr char kZenityId[] =
+    "borealis_anon:org.chromium.guest_os.borealis.wmclass.Zenity";
+// The Steam client is not a game.
+static constexpr char kSteamClientId[] =
+    "borealis_anon:org.chromium.guest_os.borealis.wmclass.steam";
+// 769 is the Steam App ID assigned to the Steam Big Picture client as of 2023.
+static constexpr char kSteamBigPictureId[] =
+    "borealis_anon:org.chromium.guest_os.borealis.xprop.769";
 
 GURL AssembleUrlAsync(std::string owner_id,
                       absl::optional<int> game_id,
@@ -173,9 +180,8 @@
     return;
   }
 
-  std::string hash = crx_file::id_util::GenerateId(app_id);
-  if (hash == kNonGameIdHash1 || hash == kNonGameIdHash2 ||
-      hash == kNonGameIdHash3) {
+  if (app_id == kZenityId || app_id == kSteamClientId ||
+      app_id == kSteamBigPictureId) {
     std::move(url_callback).Run(GURL());
     return;
   }
diff --git a/chrome/browser/ash/borealis/borealis_util_unittest.cc b/chrome/browser/ash/borealis/borealis_util_unittest.cc
index d986b62..1a7e8bab 100644
--- a/chrome/browser/ash/borealis/borealis_util_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_util_unittest.cc
@@ -80,17 +80,19 @@
 TEST_F(BorealisUtilTest, FeedbackFormUrlExcludesNonGames) {
   TestingProfile profile;
 
-  EXPECT_FALSE(GetFeedbackFormUrl(&profile,
-                                  "borealisanon:org.chromium.borealis.xid.100",
-                                  "CoolApp")
-                   .is_valid());
+  EXPECT_FALSE(
+      GetFeedbackFormUrl(&profile,
+                         "borealis_anon:org.chromium.guest_os.borealis.xid.100",
+                         "CoolApp")
+          .is_valid());
 }
 
 TEST_F(BorealisUtilTest, FeedbackFormUrlPrefillsWindowTitle) {
   TestingProfile profile;
 
   EXPECT_THAT(GetFeedbackFormUrl(
-                  &profile, "borealisanon:org.chromium.borealis.app", "CoolApp")
+                  &profile, "borealis_anon:org.chromium.guest_os.borealis.app",
+                  "CoolApp")
                   .spec(),
               testing::HasSubstr("=CoolApp"));
 }
@@ -99,7 +101,7 @@
   TestingProfile profile;
 
   GURL url = GetFeedbackFormUrl(
-      &profile, "borealisanon:org.chromium.borealis.app", "CoolApp");
+      &profile, "borealis_anon:org.chromium.guest_os.borealis.app", "CoolApp");
 
   // Count the number of query parameters beginning with "entry"; these are
   // form fields that we're prefilling.
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
index 4c228b9..17cfb2e 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
@@ -198,6 +198,10 @@
       net::MutableNetworkTrafficAnnotationTag(kBruschettaTrafficAnnotation);
 
   params.request_params.url = std::move(url);
+  // Disable Safe Browsing/checks because the download is system-initiated,
+  // the target is specified via enterprise policy, and contents will be
+  // validated by comparing hashes.
+  params.request_params.require_safety_checks = false;
 
   download_service->StartDownload(std::move(params));
 }
diff --git a/chrome/browser/ash/child_accounts/family_user_app_metrics.cc b/chrome/browser/ash/child_accounts/family_user_app_metrics.cc
index 91bc83ba..6b67245b 100644
--- a/chrome/browser/ash/child_accounts/family_user_app_metrics.cc
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics.cc
@@ -192,9 +192,9 @@
 
 void FamilyUserAppMetrics::RecordInstalledExtensionsCount() {
   int extensions_count = 0;
-  std::unique_ptr<extensions::ExtensionSet> all_installed_extensions =
+  const extensions::ExtensionSet all_installed_extensions =
       extension_registry_->GenerateInstalledExtensionsSet();
-  for (const auto& extension : *all_installed_extensions) {
+  for (const auto& extension : all_installed_extensions) {
     if (extensions::Manifest::IsComponentLocation(extension->location()))
       continue;
     if (extension->is_extension() || extension->is_theme())
diff --git a/chrome/browser/ash/crosapi/search_provider_ash.cc b/chrome/browser/ash/crosapi/search_provider_ash.cc
index 4184971..64c2b74 100644
--- a/chrome/browser/ash/crosapi/search_provider_ash.cc
+++ b/chrome/browser/ash/crosapi/search_provider_ash.cc
@@ -63,6 +63,10 @@
   }
 }
 
+bool SearchProviderAsh::IsSearchControllerConnected() const {
+  return search_controller_.is_bound() && search_controller_.is_connected();
+}
+
 void SearchProviderAsh::BindPublisher(
     SearchResultsReceivedCallback callback,
     mojo::PendingAssociatedReceiver<mojom::SearchResultsPublisher> publisher) {
diff --git a/chrome/browser/ash/crosapi/search_provider_ash.h b/chrome/browser/ash/crosapi/search_provider_ash.h
index ff202be..b8a4387 100644
--- a/chrome/browser/ash/crosapi/search_provider_ash.h
+++ b/chrome/browser/ash/crosapi/search_provider_ash.h
@@ -71,6 +71,8 @@
       mojom::SearchStatus status,
       absl::optional<std::vector<mojom::SearchResultPtr>> results) override;
 
+  bool IsSearchControllerConnected() const;
+
  private:
   void BindPublisher(
       SearchResultsReceivedCallback callback,
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
index bfa792e..db53b56e 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_offset_string_conversions.h"
 #include "base/strings/utf_string_conversion_utils.h"
@@ -26,6 +27,7 @@
 #include "chrome/browser/ash/input_method/ui/input_method_menu_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#include "chrome/browser/ui/webui/settings/ash/search/search_tag_registry.h"
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/ash/services/ime/public/mojom/input_method.mojom.h"
@@ -137,6 +139,13 @@
   return engine_id;
 }
 
+std::string SettingToQueryString(std::string subpagePath,
+                                 chromeos::settings::mojom::Setting setting) {
+  const std::string settingString =
+      base::NumberToString(static_cast<int>(setting));
+  return base::StrCat({subpagePath, "?settingId=", settingString});
+}
+
 mojom::ModifierStatePtr ModifierStateFromEvent(const ui::KeyEvent& event) {
   auto modifier_state = mojom::ModifierState::New();
   modifier_state->alt = event.flags() & ui::EF_ALT_DOWN;
@@ -1067,9 +1076,14 @@
         autocorrect_manager_->HideUndoWindow();
         base::RecordAction(base::UserMetricsAction(
             "ChromeOS.Settings.InputMethod.Autocorrect.Open"));
+        chromeos::settings::mojom::Setting setting =
+            ChromeKeyboardControllerClient::Get()->is_keyboard_visible()
+                ? chromeos::settings::mojom::Setting::kShowVKAutoCorrection
+                : chromeos::settings::mojom::Setting::kShowPKAutoCorrection;
+        std::string path = SettingToQueryString(
+            chromeos::settings::mojom::kInputMethodOptionsSubpagePath, setting);
         chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-            ProfileManager::GetActiveUserProfile(),
-            chromeos::settings::mojom::kInputMethodOptionsSubpagePath);
+            ProfileManager::GetActiveUserProfile(), path);
       }
       break;
     case ui::ime::ButtonId::kSuggestion:
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor.cc b/chrome/browser/ash/input_method/screen_projection_change_monitor.cc
index 1553262..21a604dd 100644
--- a/chrome/browser/ash/input_method/screen_projection_change_monitor.cc
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor.cc
@@ -19,7 +19,7 @@
   // Shell::Get() and CastConfigController::Get() might be null in tests.
   if (Shell::HasInstance()) {
     Shell::Get()->display_manager()->AddObserver(this);
-    Shell::Get()->system_tray_notifier()->AddScreenCaptureObserver(this);
+    Shell::Get()->system_tray_notifier()->AddScreenSecurityObserver(this);
   }
 
   if (CastConfigController::Get()) {
@@ -33,7 +33,7 @@
   }
 
   if (Shell::HasInstance()) {
-    Shell::Get()->system_tray_notifier()->RemoveScreenCaptureObserver(this);
+    Shell::Get()->system_tray_notifier()->RemoveScreenSecurityObserver(this);
     Shell::Get()->display_manager()->RemoveObserver(this);
   }
 }
@@ -63,14 +63,14 @@
   UpdateCastingAndMirroringState(casting_desktop, is_mirroring_);
 }
 
-void ScreenProjectionChangeMonitor::OnScreenCaptureStart(
+void ScreenProjectionChangeMonitor::OnScreenAccessStart(
     base::OnceClosure stop_callback,
     const base::RepeatingClosure& source_callback,
-    const std::u16string& screen_capture_status) {
+    const std::u16string& access_app_name) {
   UpdateCastingAndMirroringState(true, is_mirroring_);
 }
 
-void ScreenProjectionChangeMonitor::OnScreenCaptureStop() {
+void ScreenProjectionChangeMonitor::OnScreenAccessStop() {
   UpdateCastingAndMirroringState(false, is_mirroring_);
 }
 
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor.h b/chrome/browser/ash/input_method/screen_projection_change_monitor.h
index bd1692c..350eebf 100644
--- a/chrome/browser/ash/input_method/screen_projection_change_monitor.h
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor.h
@@ -7,7 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/public/cpp/cast_config_controller.h"
-#include "ash/system/privacy/screen_capture_observer.h"
+#include "ash/system/privacy/screen_security_observer.h"
 #include "ui/display/display_observer.h"
 
 namespace ash::input_method {
@@ -17,7 +17,7 @@
 class ASH_EXPORT ScreenProjectionChangeMonitor
     : public display::DisplayObserver,
       public CastConfigController::Observer,
-      public ScreenCaptureObserver {
+      public ScreenSecurityObserver {
  public:
   using OnScreenProjectionChangedCallback =
       base::RepeatingCallback<void(bool is_projected)>;
@@ -36,12 +36,11 @@
   // CastConfigController::Observer:
   void OnDevicesUpdated(const std::vector<SinkAndRoute>& devices) override;
 
-  // ScreenCaptureObserver:
-  void OnScreenCaptureStart(
-      base::OnceClosure stop_callback,
-      const base::RepeatingClosure& source_callback,
-      const std::u16string& screen_capture_status) override;
-  void OnScreenCaptureStop() override;
+  // ScreenSecurityObserver:
+  void OnScreenAccessStart(base::OnceClosure stop_callback,
+                           const base::RepeatingClosure& source_callback,
+                           const std::u16string& access_app_name) override;
+  void OnScreenAccessStop() override;
 
   bool IsProjecting() const;
 
diff --git a/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc b/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc
index 274ca4a..626a49a8 100644
--- a/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc
+++ b/chrome/browser/ash/input_method/screen_projection_change_monitor_unittest.cc
@@ -40,9 +40,9 @@
   RepeatingTestFuture<bool> monitor_future;
   ScreenProjectionChangeMonitor monitor(monitor_future.GetCallback());
 
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::DoNothing(), base::DoNothing(), u"");
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
 
   EXPECT_TRUE(monitor_future.Take());
   EXPECT_FALSE(monitor_future.Take());
@@ -59,7 +59,7 @@
   display_manager->UpdateDisplays();
   // Turning on screen capture will not change the screen projection state
   // because we are already mirroring.
-  Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::DoNothing(), base::DoNothing(), u"");
 
   EXPECT_TRUE(monitor_future.Take());
diff --git a/chrome/browser/ash/notifications/screen_capture_notification_ui_ash.cc b/chrome/browser/ash/notifications/screen_capture_notification_ui_ash.cc
index ad85e44..33ed9abd 100644
--- a/chrome/browser/ash/notifications/screen_capture_notification_ui_ash.cc
+++ b/chrome/browser/ash/notifications/screen_capture_notification_ui_ash.cc
@@ -19,7 +19,7 @@
   // MediaStreamCaptureIndicator will delete ScreenCaptureNotificationUI object
   // after it stops screen capture.
   stop_callback_.Reset();
-  ash::Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStop();
+  ash::Shell::Get()->system_tray_notifier()->NotifyScreenAccessStop();
 }
 
 gfx::NativeViewId ScreenCaptureNotificationUIAsh::OnStarted(
@@ -27,7 +27,7 @@
     content::MediaStreamUI::SourceCallback source_callback,
     const std::vector<content::DesktopMediaID>& media_ids) {
   stop_callback_ = std::move(stop_callback);
-  ash::Shell::Get()->system_tray_notifier()->NotifyScreenCaptureStart(
+  ash::Shell::Get()->system_tray_notifier()->NotifyScreenAccessStart(
       base::BindRepeating(
           &ScreenCaptureNotificationUIAsh::ProcessStopRequestFromUI,
           base::Unretained(this)),
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer.cc b/chrome/browser/ash/plugin_vm/plugin_vm_installer.cc
index 3d2af79..dfeb02d6 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_installer.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer.cc
@@ -401,8 +401,7 @@
   vm_tools::concierge::ListVmDisksRequest request;
   request.set_cryptohome_id(
       ash::ProfileHelper::GetUserIdHashFromProfile(profile_));
-  request.set_storage_location(
-      vm_tools::concierge::STORAGE_CRYPTOHOME_PLUGINVM);
+  request.set_all_locations(true);
   request.set_vm_name(kPluginVmName);
 
   GetConciergeClient()->ListVmDisks(
@@ -424,12 +423,20 @@
     return;
   }
 
-  if (response->images_size() == 1) {
-    RecordPluginVmSetupResultHistogram(PluginVmSetupResult::kVmAlreadyExists);
-    if (observer_)
-      observer_->OnVmExists();
-    profile_->GetPrefs()->SetBoolean(prefs::kPluginVmImageExists, true);
-    InstallFinished();
+  if (response->images_size() > 0) {
+    auto& image = response->images(0);
+    if (image.storage_location() ==
+        vm_tools::concierge::STORAGE_CRYPTOHOME_PLUGINVM) {
+      RecordPluginVmSetupResultHistogram(PluginVmSetupResult::kVmAlreadyExists);
+      if (observer_) {
+        observer_->OnVmExists();
+      }
+      profile_->GetPrefs()->SetBoolean(prefs::kPluginVmImageExists, true);
+      InstallFinished();
+    } else {
+      LOG(ERROR) << "VM " << image.name() << " exists, but in wrong location";
+      InstallFailed(FailureReason::EXISTING_IMAGE_INVALID);
+    }
     return;
   }
 
@@ -967,6 +974,10 @@
   // RequestParams
   params.request_params.url = url;
   params.request_params.method = "GET";
+  // Disable Safe Browsing/checks because the download is system-initiated,
+  // the target is specified via enterprise policy, and contents will be
+  // validated by comparing hashes.
+  params.request_params.require_safety_checks = false;
 
   // SchedulingParams
   // User initiates download by clicking on PluginVm icon so priorities should
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer.h b/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
index 3f3bb76..8d9c99983 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer.h
@@ -80,8 +80,10 @@
     DOWNLOAD_FAILED_404 = 30,
     // Download appeared to succeed but downloaded image size was unexpected
     DOWNLOAD_SIZE_MISMATCH = 31,
+    // Image with the right name exists, but in a wrong location.
+    EXISTING_IMAGE_INVALID = 32,
 
-    kMaxValue = DOWNLOAD_SIZE_MISMATCH,
+    kMaxValue = EXISTING_IMAGE_INVALID,
   };
 
   enum class InstallingState {
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
index 9666b30..a80c893f 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ash/plugin_vm/plugin_vm_metrics_util.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_test_helper.h"
+#include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/test/base/testing_profile.h"
@@ -459,7 +460,9 @@
 
   vm_tools::concierge::ListVmDisksResponse list_vm_disks_response;
   list_vm_disks_response.set_success(true);
-  list_vm_disks_response.add_images();
+  auto* image = list_vm_disks_response.add_images();
+  image->set_name(kPluginVmName);
+  image->set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_PLUGINVM);
   fake_concierge_client_->set_list_vm_disks_response(list_vm_disks_response);
 
   ExpectObserverEventsUntil(InstallingState::kCheckingForExistingVm);
@@ -470,6 +473,26 @@
       kPluginVmSetupResultHistogram, PluginVmSetupResult::kVmAlreadyExists, 1);
 }
 
+TEST_F(PluginVmInstallerDownloadServiceTest, InvalidVmExists) {
+  // This flow works even if the image url is not set.
+  SetPluginVmImagePref("", kHash);
+
+  vm_tools::concierge::ListVmDisksResponse list_vm_disks_response;
+  list_vm_disks_response.set_success(true);
+  auto* image = list_vm_disks_response.add_images();
+  // Pretend we have a VM with the right name in a wrong location.
+  image->set_name(kPluginVmName);
+  image->set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT);
+  fake_concierge_client_->set_list_vm_disks_response(list_vm_disks_response);
+
+  ExpectObserverEventsUntil(InstallingState::kCheckingForExistingVm);
+  EXPECT_CALL(*observer_, OnError(FailureReason::EXISTING_IMAGE_INVALID));
+  StartAndRunToCompletion();
+
+  histogram_tester_->ExpectUniqueSample(
+      kFailureReasonHistogram, FailureReason::EXISTING_IMAGE_INVALID, 1);
+}
+
 TEST_F(PluginVmInstallerDownloadServiceTest, CancelOnVmExistsCheck) {
   base::RunLoop run_loop;
   ExpectObserverEventsUntil(InstallingState::kCheckingForExistingVm);
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
index 9cdf76d..216c381 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
@@ -6,11 +6,8 @@
 
 #include <memory>
 
-#include "base/memory/ptr_util.h"
 #include "base/observer_list_types.h"
 #include "base/sequence_checker.h"
-#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
-#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "components/reporting/metrics/metric_event_observer.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
@@ -20,51 +17,17 @@
 
 namespace reporting {
 
-bool AppEventsObserver::Delegate::IsAppServiceAvailableForProfile(
-    Profile* profile) {
-  return ::apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
-      profile);
-}
-
-::apps::AppPlatformMetrics*
-AppEventsObserver::Delegate::GetAppPlatformMetricsForProfile(Profile* profile) {
-  return ::apps::AppServiceProxyFactory::GetForProfile(profile)
-      ->AppPlatformMetrics();
-}
-
-// static
-std::unique_ptr<AppEventsObserver> AppEventsObserver::CreateForProfile(
-    Profile* profile) {
-  auto delegate = std::make_unique<AppEventsObserver::Delegate>();
-  return base::WrapUnique(new AppEventsObserver(profile, std::move(delegate)));
-}
-
-// static
-std::unique_ptr<AppEventsObserver> AppEventsObserver::CreateForTest(
-    Profile* profile,
-    std::unique_ptr<AppEventsObserver::Delegate> delegate) {
-  return base::WrapUnique(new AppEventsObserver(profile, std::move(delegate)));
-}
-
 AppEventsObserver::AppEventsObserver(
-    Profile* profile,
-    std::unique_ptr<AppEventsObserver::Delegate> delegate)
-    : profile_(profile), delegate_(std::move(delegate)) {
-  if (!delegate_->IsAppServiceAvailableForProfile(profile)) {
-    // Profile cannot run apps, so we just return.
-    return;
-  }
-
-  // Register instance so we can start observing app events.
-  auto* const app_platform_metrics =
-      delegate_->GetAppPlatformMetricsForProfile(profile);
+    ::apps::AppPlatformMetrics* app_platform_metrics)
+    : app_platform_metrics_(app_platform_metrics) {
+  DCHECK(app_platform_metrics_);
   app_platform_metrics->AddObserver(this);
 }
 
 AppEventsObserver::~AppEventsObserver() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (IsInObserverList()) {
-    delegate_->GetAppPlatformMetricsForProfile(profile_)->RemoveObserver(this);
+    app_platform_metrics_->RemoveObserver(this);
   }
 }
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h
index 579b39e..448790fa 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h
@@ -11,7 +11,6 @@
 #include "base/sequence_checker.h"
 #include "base/thread_annotations.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
-#include "chrome/browser/profiles/profile.h"
 #include "components/reporting/metrics/metric_event_observer.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
@@ -23,36 +22,7 @@
 class AppEventsObserver : public MetricEventObserver,
                           public ::apps::AppPlatformMetrics::Observer {
  public:
-  // Delegate that manages interactions with the `AppServiceProxyFactory` before
-  // registering the `AppPlatformMetrics` component as an observer. Can be
-  // stubbed for testing purposes.
-  class Delegate {
-   public:
-    Delegate() = default;
-    Delegate(const Delegate& other) = delete;
-    Delegate& operator=(const Delegate& other) = delete;
-    virtual ~Delegate() = default;
-
-    // Returns app service availability for the given profile. Not all profiles
-    // can run apps (for example, non-guest incognito profiles).
-    virtual bool IsAppServiceAvailableForProfile(Profile* profile);
-
-    // Retrieves the `AppPlatformMetrics` component so the `AppEventsObserver`
-    // can register itself as an observer.
-    virtual ::apps::AppPlatformMetrics* GetAppPlatformMetricsForProfile(
-        Profile* profile);
-  };
-
-  // Static helper that instantiates the `AppEventsObserver` for the given
-  // profile.
-  static std::unique_ptr<AppEventsObserver> CreateForProfile(Profile* profile);
-
-  // Static test helper that instantiates the `AppEventsObserver` for the given
-  // profile using a test delegate.
-  static std::unique_ptr<AppEventsObserver> CreateForTest(
-      Profile* profile,
-      std::unique_ptr<Delegate> delegate);
-
+  explicit AppEventsObserver(::apps::AppPlatformMetrics* app_platform_metrics);
   AppEventsObserver(const AppEventsObserver& other) = delete;
   AppEventsObserver& operator=(const AppEventsObserver& other) = delete;
   ~AppEventsObserver() override;
@@ -64,8 +34,6 @@
   void SetReportingEnabled(bool is_enabled) override;
 
  private:
-  AppEventsObserver(Profile* profile, std::unique_ptr<Delegate> delegate);
-
   // ::apps::AppPlatformMetrics::Observer:
   void OnAppInstalled(const std::string& app_id,
                       ::apps::AppType app_type,
@@ -84,9 +52,7 @@
                         ::apps::UninstallSource app_uninstall_source) override;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  const raw_ptr<Profile> profile_;
-  const std::unique_ptr<Delegate> delegate_;
+  const raw_ptr<::apps::AppPlatformMetrics> app_platform_metrics_;
 
   // Boolean that controls app metric collection and reporting.
   bool is_enabled_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
index d4517e07..2288871 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
@@ -30,34 +30,6 @@
 
 constexpr char kTestAppId[] = "TestApp";
 
-// Test delegate that stubs out `AppEventsObserver` interactions with the
-// `AppServiceProxyFactory`.
-class TestDelegate : public AppEventsObserver::Delegate {
- public:
-  TestDelegate(bool is_app_service_available,
-               ::apps::AppPlatformMetrics* app_platform_metrics)
-      : is_app_service_available_(is_app_service_available),
-        app_platform_metrics_(app_platform_metrics) {}
-  TestDelegate(const TestDelegate& other) = delete;
-  TestDelegate& operator=(const TestDelegate& other) = delete;
-  ~TestDelegate() override = default;
-
-  // AppEventsObserver::Delegate:
-  bool IsAppServiceAvailableForProfile(Profile* profile) override {
-    return is_app_service_available_;
-  }
-
-  // AppEventsObserver::Delegate:
-  ::apps::AppPlatformMetrics* GetAppPlatformMetricsForProfile(
-      Profile* profile) override {
-    return app_platform_metrics_.get();
-  }
-
- private:
-  const bool is_app_service_available_;
-  const raw_ptr<::apps::AppPlatformMetrics> app_platform_metrics_;
-};
-
 // Fake `AppPublisher` used by the test to simulate app launches.
 class FakePublisher : public ::apps::AppPublisher {
  public:
@@ -88,9 +60,8 @@
                ::apps::LoadIconCallback callback));
 };
 
-class AppEventsObserverTest
-    : public ::apps::AppPlatformMetricsServiceTestBase,
-      public ::testing::WithParamInterface<std::tuple<bool, bool>> {
+class AppEventsObserverTest : public ::apps::AppPlatformMetricsServiceTestBase,
+                              public ::testing::WithParamInterface<bool> {
  protected:
   void SetUp() override {
     ::apps::AppPlatformMetricsServiceTestBase::SetUp();
@@ -100,11 +71,8 @@
                   ::apps::Readiness::kReady, ::apps::InstallSource::kPlayStore);
 
     // Set up `AppEventsObserver` with relevant test params.
-    auto delegate = std::make_unique<TestDelegate>(
-        IsAppServiceAvailableForProfile(),
+    app_events_observer_ = std::make_unique<AppEventsObserver>(
         app_platform_metrics_service()->AppPlatformMetrics());
-    app_events_observer_ =
-        AppEventsObserver::CreateForTest(profile(), std::move(delegate));
     app_events_observer_->SetReportingEnabled(IsReportingEnabled());
   }
 
@@ -113,11 +81,7 @@
     ::apps::AppPlatformMetricsServiceTestBase::TearDown();
   }
 
-  bool IsAppServiceAvailableForProfile() const {
-    return ::testing::get<0>(GetParam());
-  }
-
-  bool IsReportingEnabled() const { return ::testing::get<1>(GetParam()); }
+  bool IsReportingEnabled() const { return GetParam(); }
 
   std::unique_ptr<AppEventsObserver> app_events_observer_;
 };
@@ -132,7 +96,7 @@
                 /*publisher_id=*/"", ::apps::Readiness::kReady,
                 ::apps::InstallSource::kBrowser);
 
-  if (IsAppServiceAvailableForProfile() && IsReportingEnabled()) {
+  if (IsReportingEnabled()) {
     // Verify data being reported.
     const MetricData& result = test_event.result();
     ASSERT_TRUE(result.has_event_data());
@@ -157,8 +121,7 @@
         app_install_data.app_install_time(),
         Eq(::apps::ApplicationInstallTime::APPLICATION_INSTALL_TIME_INIT));
   } else {
-    // Should not report any data if app service unavailable or reporting is
-    // disabled for profile.
+    // Should not report any data if reporting is disabled.
     ASSERT_TRUE(test_event.no_result());
   }
 }
@@ -174,7 +137,7 @@
   proxy->Launch(kTestAppId, ui::EF_NONE, apps::LaunchSource::kFromCommandLine,
                 nullptr);
 
-  if (IsAppServiceAvailableForProfile() && IsReportingEnabled()) {
+  if (IsReportingEnabled()) {
     // Verify data being reported.
     const MetricData& result = test_event.result();
     ASSERT_TRUE(result.has_event_data());
@@ -192,8 +155,7 @@
                 Eq(::apps::ApplicationLaunchSource::
                        APPLICATION_LAUNCH_SOURCE_COMMAND_LINE));
   } else {
-    // Should not report any data if app service unavailable or reporting is
-    // disabled for profile.
+    // Should not report any data if reporting is disabled.
     ASSERT_TRUE(test_event.no_result());
   }
 }
@@ -208,7 +170,7 @@
   FakePublisher fake_publisher(proxy, ::apps::AppType::kArc);
   proxy->UninstallSilently(kTestAppId, ::apps::UninstallSource::kAppList);
 
-  if (IsAppServiceAvailableForProfile() && IsReportingEnabled()) {
+  if (IsReportingEnabled()) {
     // Verify data being reported.
     const MetricData& result = test_event.result();
     ASSERT_TRUE(result.has_event_data());
@@ -228,18 +190,14 @@
                 Eq(::apps::ApplicationUninstallSource::
                        APPLICATION_UNINSTALL_SOURCE_APP_LIST));
   } else {
-    // Should not report any data if app service unavailable or reporting is
-    // disabled for profile.
+    // Should not report any data if reporting is disabled.
     ASSERT_TRUE(test_event.no_result());
   }
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    AppEventsObserverTests,
-    AppEventsObserverTest,
-    ::testing::Combine(
-        ::testing::Bool() /* true - app service available for profile*/,
-        ::testing::Bool()) /* true - reporting enabled*/);
+INSTANTIATE_TEST_SUITE_P(AppEventsObserverTests,
+                         AppEventsObserverTest,
+                         ::testing::Bool() /* true - reporting enabled*/);
 
 }  // namespace
 }  // namespace reporting
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
index ce1f04e..7ffe0ad 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.cc
@@ -18,6 +18,9 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h"
@@ -40,6 +43,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/reporting/metric_default_utils.h"
 #include "chrome/browser/chromeos/reporting/network/network_bandwidth_sampler.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
 #include "components/reporting/client/report_queue_configuration.h"
 #include "components/reporting/metrics/collector_base.h"
@@ -96,6 +100,19 @@
   return std::make_unique<NetworkTelemetrySampler>();
 }
 
+bool MetricReportingManager::Delegate::IsAppServiceAvailableForProfile(
+    Profile* profile) const {
+  return ::apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
+      profile);
+}
+
+::apps::AppPlatformMetrics*
+MetricReportingManager::Delegate::GetAppPlatformMetricsForProfile(
+    Profile* profile) {
+  return ::apps::AppServiceProxyFactory::GetForProfile(profile)
+      ->AppPlatformMetrics();
+}
+
 // static
 std::unique_ptr<MetricReportingManager> MetricReportingManager::Create(
     policy::ManagedSessionService* managed_session_service) {
@@ -285,9 +302,12 @@
       /*init_delay=*/base::TimeDelta());
   InitPeripheralsCollectors();
 
-  // Start observing app events only if the feature flag is set.
-  if (base::FeatureList::IsEnabled(kEnableAppMetricsReporting)) {
-    auto app_events_observer = AppEventsObserver::CreateForProfile(profile);
+  // Start observing app events only if the feature flag is set and app service
+  // is available for the given profile.
+  if (base::FeatureList::IsEnabled(kEnableAppMetricsReporting) &&
+      delegate_->IsAppServiceAvailableForProfile(profile)) {
+    auto app_events_observer = std::make_unique<AppEventsObserver>(
+        delegate_->GetAppPlatformMetricsForProfile(profile));
     InitEventObserverManager(
         std::move(app_events_observer), user_event_report_queue_.get(),
         /*enable_setting_path=*/::ash::kReportDeviceAppInfo,
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
index d80f41a..fcaa87e 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
@@ -15,6 +15,7 @@
 #include "base/strings/string_piece_forward.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_sampler_handlers/cros_healthd_sampler_handler.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_reporting_settings.h"
 #include "chrome/browser/ash/policy/status_collector/managed_session_service.h"
@@ -61,6 +62,14 @@
     virtual std::unique_ptr<Sampler> GetHttpsLatencySampler() const;
 
     virtual std::unique_ptr<Sampler> GetNetworkTelemetrySampler() const;
+
+    // Returns app service availability for the given profile. Not all profiles
+    // can run apps (for example, non-guest incognito profiles).
+    virtual bool IsAppServiceAvailableForProfile(Profile* profile) const;
+
+    // Retrieves the `AppPlatformMetrics` component for the given profile.
+    virtual ::apps::AppPlatformMetrics* GetAppPlatformMetricsForProfile(
+        Profile* profile);
   };
 
   static std::unique_ptr<MetricReportingManager> Create(
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
index 6e5a18a..17a14b4d 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager_unittest.cc
@@ -14,9 +14,12 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
+#include "chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h"
 #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
 #include "chrome/browser/chromeos/reporting/metric_default_utils.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
 #include "components/reporting/client/report_queue_configuration.h"
 #include "components/reporting/metrics/collector_base.h"
@@ -184,6 +187,16 @@
               GetNetworkTelemetrySampler,
               (),
               (const, override));
+
+  MOCK_METHOD(bool,
+              IsAppServiceAvailableForProfile,
+              (Profile * profile),
+              (const, override));
+
+  MOCK_METHOD(::apps::AppPlatformMetrics*,
+              GetAppPlatformMetricsForProfile,
+              (Profile * profile),
+              (override));
 };
 
 struct MetricReportingSettingData {
@@ -251,10 +264,15 @@
   return metric_report_queue_ptr;
 }
 
+// Base class used to test scenarios for the `MetricReportingManager`. We extend
+// `AppPlatformMetricsServiceTestBase` for relevant setup of the
+// `AppPlatformMetrics` component.
 class MetricReportingManagerTest
-    : public ::testing::TestWithParam<MetricReportingManagerTestCase> {
+    : public ::apps::AppPlatformMetricsServiceTestBase,
+      public ::testing::WithParamInterface<MetricReportingManagerTestCase> {
  protected:
   void SetUp() override {
+    apps::AppPlatformMetricsServiceTestBase::SetUp();
     mock_delegate_ = std::make_unique<::testing::NiceMock<MockDelegate>>();
     info_queue_ptr_ = CreateMockMetricReportQueueHelper(
         mock_delegate_.get(), EventType::kDevice, Destination::INFO_METRIC,
@@ -277,10 +295,14 @@
     // Only one periodic upload report queue should be created.
     ON_CALL(*mock_delegate_, CreatePeriodicUploadReportQueue)
         .WillByDefault(Return(ByMove(std::move(telemetry_queue))));
-  }
 
-  base::test::SingleThreadTaskEnvironment task_environment_{
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+    // App platform metrics instance is only requested when app service is
+    // available for the given profile, so it is safe to return the instance by
+    // default here.
+    ON_CALL(*mock_delegate_, GetAppPlatformMetricsForProfile)
+        .WillByDefault(
+            Return(app_platform_metrics_service()->AppPlatformMetrics()));
+  }
 
   test::FakeMetricReportQueue* info_queue_ptr_;
   test::FakeMetricReportQueue* telemetry_queue_ptr_;
@@ -302,6 +324,8 @@
 
   ON_CALL(*mock_delegate_, IsDeprovisioned).WillByDefault(Return(true));
   ON_CALL(*mock_delegate_, IsAffiliated).WillByDefault(Return(true));
+  ON_CALL(*mock_delegate_, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
 
   ON_CALL(*mock_delegate_, CreateOneShotCollector).WillByDefault([&]() {
     return std::make_unique<FakeCollector>(&one_shot_collector_count);
@@ -352,13 +376,15 @@
               test_case.setting_data.setting_enabled_default_value, init_delay))
       .WillByDefault(
           [&]() { return std::make_unique<FakeCollector>(&collector_count); });
+  ON_CALL(*mock_delegate_ptr, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
 
   auto metric_reporting_manager = MetricReportingManager::CreateForTesting(
       std::move(mock_delegate_), nullptr);
 
   EXPECT_EQ(collector_count, test_case.expected_count_before_login);
 
-  metric_reporting_manager->OnLogin(nullptr);
+  metric_reporting_manager->OnLogin(profile());
 
   EXPECT_EQ(collector_count, test_case.expected_count_after_login);
 
@@ -426,6 +452,8 @@
   int observer_manager_count = 0;
   ON_CALL(*mock_delegate_ptr, IsAffiliated)
       .WillByDefault(Return(test_case.is_affiliated));
+  ON_CALL(*mock_delegate_ptr, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
   ON_CALL(
       *mock_delegate_ptr,
       CreateEventObserverManager(
@@ -451,7 +479,7 @@
 
   EXPECT_EQ(observer_manager_count, test_case.expected_count_before_login);
 
-  metric_reporting_manager->OnLogin(nullptr);
+  metric_reporting_manager->OnLogin(profile());
 
   EXPECT_EQ(observer_manager_count, test_case.expected_count_after_login);
 
@@ -461,6 +489,51 @@
   EXPECT_EQ(observer_manager_count, 0);
 }
 
+TEST_F(MetricReportingManagerEventTest,
+       ShouldNotCreateAppEventObserverWhenAppServiceUnavailable) {
+  // Enable app metrics reporting feature flag.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(kEnableAppMetricsReporting);
+
+  // Setup appropriate mocks and stubs.
+  auto fake_reporting_settings =
+      std::make_unique<test::FakeReportingSettings>();
+  auto* const mock_delegate_ptr = mock_delegate_.get();
+  int observer_manager_count = 0;
+  ON_CALL(*mock_delegate_ptr, IsAffiliated).WillByDefault(Return(true));
+  ON_CALL(*mock_delegate_ptr, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_delegate_ptr,
+          CreateEventObserverManager(
+              _, event_queue_ptr_, _, app_event_settings.enable_setting_path,
+              app_event_settings.setting_enabled_default_value, _, _))
+      .WillByDefault([&]() {
+        return std::make_unique<FakeMetricEventObserverManager>(
+            fake_reporting_settings.get(), &observer_manager_count);
+      });
+  ON_CALL(
+      *mock_delegate_ptr,
+      CreateEventObserverManager(
+          _, user_event_queue_ptr_, _, app_event_settings.enable_setting_path,
+          app_event_settings.setting_enabled_default_value, _, _))
+      .WillByDefault([&]() {
+        return std::make_unique<FakeMetricEventObserverManager>(
+            fake_reporting_settings.get(), &observer_manager_count);
+      });
+
+  // Create a metric reporting manager and ensure observer manager count is 0
+  // before and after login.
+  auto metric_reporting_manager = MetricReportingManager::CreateForTesting(
+      std::move(mock_delegate_), nullptr);
+  EXPECT_EQ(observer_manager_count, 0);
+  metric_reporting_manager->OnLogin(profile());
+  EXPECT_EQ(observer_manager_count, 0);
+
+  ON_CALL(*mock_delegate_ptr, IsDeprovisioned).WillByDefault(Return(true));
+  metric_reporting_manager->DeviceSettingsUpdated();
+  EXPECT_EQ(observer_manager_count, 0);
+}
+
 INSTANTIATE_TEST_SUITE_P(
     MetricReportingManagerEventTests,
     MetricReportingManagerEventTest,
@@ -548,6 +621,8 @@
   int observer_manager_count = 0;
   ON_CALL(*mock_delegate_ptr, IsAffiliated)
       .WillByDefault(Return(test_case.is_affiliated));
+  ON_CALL(*mock_delegate_ptr, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
   ON_CALL(
       *mock_delegate_ptr,
       CreateEventObserverManager(
@@ -564,7 +639,7 @@
 
   EXPECT_EQ(observer_manager_count, test_case.expected_count_before_login);
 
-  metric_reporting_manager->OnLogin(nullptr);
+  metric_reporting_manager->OnLogin(profile());
 
   EXPECT_EQ(observer_manager_count, test_case.expected_count_after_login);
 
@@ -641,6 +716,8 @@
   int collector_count = 0;
   ON_CALL(*mock_delegate_ptr, IsAffiliated)
       .WillByDefault(Return(test_case.is_affiliated));
+  ON_CALL(*mock_delegate_ptr, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
   ON_CALL(*mock_delegate_ptr,
           CreatePeriodicCollector(
               _, telemetry_queue_ptr_, _,
@@ -670,7 +747,7 @@
 
   EXPECT_EQ(telemetry_queue_ptr_->GetNumFlush(), 1);
 
-  metric_reporting_manager->OnLogin(nullptr);
+  metric_reporting_manager->OnLogin(profile());
 
   EXPECT_EQ(collector_count, test_case.expected_count_after_login);
 
@@ -832,6 +909,8 @@
 
   ON_CALL(*mock_delegate_, IsDeprovisioned).WillByDefault(Return(false));
   ON_CALL(*mock_delegate_, IsAffiliated).WillByDefault(Return(true));
+  ON_CALL(*mock_delegate_, IsAppServiceAvailableForProfile)
+      .WillByDefault(Return(true));
 
   auto metric_reporting_manager = MetricReportingManager::CreateForTesting(
       std::move(mock_delegate_), nullptr);
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc
index ebbe41b..49f9acc5 100644
--- a/chrome/browser/ash/preferences.cc
+++ b/chrome/browser/ash/preferences.cc
@@ -212,7 +212,7 @@
       prefs::kPrimaryMouseButtonRight, false,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterBooleanPref(
-      ::prefs::kPrimaryPointingStickButtonRight, false,
+      prefs::kPrimaryPointingStickButtonRight, false,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterBooleanPref(
       prefs::kMouseAcceleration, true,
@@ -221,7 +221,7 @@
       prefs::kMouseScrollAcceleration, true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterBooleanPref(
-      ::prefs::kPointingStickAcceleration, true,
+      prefs::kPointingStickAcceleration, true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterBooleanPref(
       prefs::kTouchpadAcceleration, true,
@@ -244,7 +244,7 @@
       prefs::kMouseScrollSensitivity, 3,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterIntegerPref(
-      ::prefs::kPointingStickSensitivity, 3,
+      prefs::kPointingStickSensitivity, 3,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
   registry->RegisterIntegerPref(
       prefs::kTouchpadSensitivity, 3,
@@ -589,16 +589,16 @@
   touchpad_sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, callback);
   touchpad_scroll_sensitivity_.Init(prefs::kTouchpadScrollSensitivity, prefs,
                                     callback);
-  pointing_stick_sensitivity_.Init(::prefs::kPointingStickSensitivity, prefs,
+  pointing_stick_sensitivity_.Init(prefs::kPointingStickSensitivity, prefs,
                                    callback);
   primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, prefs,
                                    callback);
   primary_pointing_stick_button_right_.Init(
-      ::prefs::kPrimaryPointingStickButtonRight, prefs, callback);
+      prefs::kPrimaryPointingStickButtonRight, prefs, callback);
   mouse_acceleration_.Init(prefs::kMouseAcceleration, prefs, callback);
   mouse_scroll_acceleration_.Init(prefs::kMouseScrollAcceleration, prefs,
                                   callback);
-  pointing_stick_acceleration_.Init(::prefs::kPointingStickAcceleration, prefs,
+  pointing_stick_acceleration_.Init(prefs::kPointingStickAcceleration, prefs,
                                     callback);
   touchpad_acceleration_.Init(prefs::kTouchpadAcceleration, prefs, callback);
   touchpad_scroll_acceleration_.Init(prefs::kTouchpadScrollAcceleration, prefs,
@@ -874,7 +874,7 @@
                                      sensitivity_int);
   }
   if (reason != REASON_PREF_CHANGED ||
-      pref_name == ::prefs::kPointingStickSensitivity) {
+      pref_name == prefs::kPointingStickSensitivity) {
     const int sensitivity_int = pointing_stick_sensitivity_.GetValue();
     if (user_is_active) {
       pointing_stick_settings.SetSensitivity(sensitivity_int);
@@ -923,7 +923,7 @@
     }
   }
   if (reason != REASON_PREF_CHANGED ||
-      pref_name == ::prefs::kPrimaryPointingStickButtonRight) {
+      pref_name == prefs::kPrimaryPointingStickButtonRight) {
     const bool right = primary_pointing_stick_button_right_.GetValue();
     if (user_is_active)
       pointing_stick_settings.SetPrimaryButtonRight(right);
@@ -951,7 +951,7 @@
                                  "Mouse.ScrollAcceleration.Started", enabled);
   }
   if (reason != REASON_PREF_CHANGED ||
-      pref_name == ::prefs::kPointingStickAcceleration) {
+      pref_name == prefs::kPointingStickAcceleration) {
     const bool enabled = pointing_stick_acceleration_.GetValue();
     if (user_is_active)
       pointing_stick_settings.SetAcceleration(enabled);
diff --git a/chrome/browser/ash/preferences_browsertest.cc b/chrome/browser/ash/preferences_browsertest.cc
index 7f52188f..e5384d8 100644
--- a/chrome/browser/ash/preferences_browsertest.cc
+++ b/chrome/browser/ash/preferences_browsertest.cc
@@ -63,17 +63,17 @@
     prefs->SetBoolean(prefs::kNaturalScroll, variant);
     prefs->SetBoolean(prefs::kTapToClickEnabled, variant);
     prefs->SetBoolean(prefs::kPrimaryMouseButtonRight, !variant);
-    prefs->SetBoolean(::prefs::kPrimaryPointingStickButtonRight, !variant);
+    prefs->SetBoolean(prefs::kPrimaryPointingStickButtonRight, !variant);
     prefs->SetBoolean(prefs::kMouseAcceleration, variant);
     prefs->SetBoolean(prefs::kMouseScrollAcceleration, variant);
-    prefs->SetBoolean(::prefs::kPointingStickAcceleration, variant);
+    prefs->SetBoolean(prefs::kPointingStickAcceleration, variant);
     prefs->SetBoolean(prefs::kTouchpadAcceleration, variant);
     prefs->SetBoolean(prefs::kTouchpadScrollAcceleration, variant);
     prefs->SetBoolean(prefs::kTouchpadHapticFeedback, variant);
     prefs->SetBoolean(prefs::kEnableTouchpadThreeFingerClick, !variant);
     prefs->SetInteger(prefs::kMouseSensitivity, !variant);
     prefs->SetInteger(prefs::kMouseScrollSensitivity, variant ? 1 : 4);
-    prefs->SetInteger(::prefs::kPointingStickSensitivity, !variant);
+    prefs->SetInteger(prefs::kPointingStickSensitivity, !variant);
     prefs->SetInteger(prefs::kTouchpadSensitivity, variant);
     prefs->SetInteger(prefs::kTouchpadHapticClickSensitivity, variant ? 1 : 3);
     prefs->SetInteger(prefs::kTouchpadScrollSensitivity, variant ? 1 : 4);
@@ -91,7 +91,7 @@
     EXPECT_EQ(
         prefs->GetBoolean(prefs::kPrimaryMouseButtonRight),
         input_settings_->current_mouse_settings().GetPrimaryButtonRight());
-    EXPECT_EQ(prefs->GetBoolean(::prefs::kPrimaryPointingStickButtonRight),
+    EXPECT_EQ(prefs->GetBoolean(prefs::kPrimaryPointingStickButtonRight),
               input_settings_->current_pointing_stick_settings()
                   .GetPrimaryButtonRight());
     EXPECT_EQ(prefs->GetBoolean(prefs::kMouseReverseScroll),
@@ -102,7 +102,7 @@
         prefs->GetBoolean(prefs::kMouseScrollAcceleration),
         input_settings_->current_mouse_settings().GetScrollAcceleration());
     EXPECT_EQ(
-        prefs->GetBoolean(::prefs::kPointingStickAcceleration),
+        prefs->GetBoolean(prefs::kPointingStickAcceleration),
         input_settings_->current_pointing_stick_settings().GetAcceleration());
     EXPECT_EQ(prefs->GetBoolean(prefs::kTouchpadAcceleration),
               input_settings_->current_touchpad_settings().GetAcceleration());
@@ -119,7 +119,7 @@
     EXPECT_EQ(prefs->GetInteger(prefs::kMouseScrollSensitivity),
               input_settings_->current_mouse_settings().GetScrollSensitivity());
     EXPECT_EQ(
-        prefs->GetInteger(::prefs::kPointingStickSensitivity),
+        prefs->GetInteger(prefs::kPointingStickSensitivity),
         input_settings_->current_pointing_stick_settings().GetSensitivity());
     EXPECT_EQ(prefs->GetInteger(prefs::kTouchpadSensitivity),
               input_settings_->current_touchpad_settings().GetSensitivity());
@@ -151,7 +151,7 @@
               prefs->GetBoolean(prefs::kPrimaryMouseButtonRight));
     EXPECT_EQ(
         local_state->GetBoolean(::prefs::kOwnerPrimaryPointingStickButtonRight),
-        prefs->GetBoolean(::prefs::kPrimaryPointingStickButtonRight));
+        prefs->GetBoolean(prefs::kPrimaryPointingStickButtonRight));
   }
 
   LoginManagerMixin login_mixin_{&mixin_host_};
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc
index e1efee3..84d2d8c 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc
@@ -46,9 +46,13 @@
 
 namespace {
 
-// Width and height of the preview image for personal album.
-constexpr int kBannerWidthPx = 160;
-constexpr int kBannerHeightPx = 160;
+// Width and height of the preview images.
+// When Jelly is enabled, the max possible preview image container is 360x130.
+// Double the fetched image W/H to stay sharp when scaled down.
+const int kBannerWidthPx =
+    (features::IsPersonalizationJellyEnabled() ? 720 : 160);
+const int kBannerHeightPx =
+    (features::IsPersonalizationJellyEnabled() ? 260 : 160);
 
 constexpr int kMaxRetries = 3;
 
@@ -534,6 +538,7 @@
   needs_update_previews_ = false;
   previews_weak_factory_.InvalidateWeakPtrs();
   ash::AmbientBackendController::Get()->FetchPreviewImages(
+      gfx::Size(kBannerWidthPx, kBannerHeightPx),
       base::BindOnce(&PersonalizationAppAmbientProviderImpl::OnPreviewsFetched,
                      previews_weak_factory_.GetWeakPtr()));
 }
@@ -542,14 +547,10 @@
 void PersonalizationAppAmbientProviderImpl::FetchGooglePhotosAlbumsPreviews(
     const std::vector<std::string>& album_ids) {
   const int num_previews = features::IsPersonalizationJellyEnabled() ? 3 : 4;
-  const int preview_width =
-      features::IsPersonalizationJellyEnabled() ? 360 : kBannerWidthPx;
-  const int preview_height =
-      features::IsPersonalizationJellyEnabled() ? 130 : kBannerHeightPx;
   DCHECK(!album_ids.empty());
   previews_weak_factory_.InvalidateWeakPtrs();
   ash::AmbientBackendController::Get()->GetGooglePhotosAlbumsPreview(
-      album_ids, preview_width, preview_height, num_previews,
+      album_ids, kBannerWidthPx, kBannerHeightPx, num_previews,
       base::BindOnce(&PersonalizationAppAmbientProviderImpl::OnPreviewsFetched,
                      previews_weak_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc
index f58088ed..d926f4d 100644
--- a/chrome/browser/background/background_application_list_model_unittest.cc
+++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -158,7 +158,7 @@
   ASSERT_TRUE(ExtensionSystem::Get(profile())->is_ready());
   ASSERT_TRUE(model()->startup_done());
 
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
+  ASSERT_TRUE(registry()->enabled_extensions().empty());
   ASSERT_EQ(0U, model()->size());
 
   scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
@@ -224,7 +224,7 @@
   service()->Init();
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(ExtensionSystem::Get(profile())->is_ready());
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
+  ASSERT_TRUE(registry()->enabled_extensions().empty());
   ASSERT_EQ(0U, model()->size());
 
   scoped_refptr<Extension> ext = CreateExtension("extension", false);
@@ -277,7 +277,7 @@
       CreateExtension("background_application", true);
   ASSERT_TRUE(bgapp->permissions_data()->HasAPIPermission(
       APIPermissionID::kBackground));
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
+  ASSERT_TRUE(registry()->enabled_extensions().empty());
   ASSERT_EQ(0U, model()->size());
 
   extensions::TestExtensionRegistryObserver load_observer(registry());
@@ -290,7 +290,7 @@
   service()->UnloadExtension(bgapp->id(),
                              extensions::UnloadedExtensionReason::UNINSTALL);
   unload_observer.WaitForExtensionUnloaded();
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
+  ASSERT_TRUE(registry()->enabled_extensions().empty());
   EXPECT_EQ(0U, model()->size());
 }
 
@@ -306,7 +306,7 @@
       CreateExtension("background_application", true);
   EXPECT_TRUE(bgapp->permissions_data()->HasAPIPermission(
       APIPermissionID::kBackground));
-  EXPECT_TRUE(registry()->enabled_extensions().is_empty());
+  EXPECT_TRUE(registry()->enabled_extensions().empty());
   EXPECT_EQ(0U, model()->size());
 
   extensions::TestExtensionRegistryObserver load_observer(registry());
@@ -433,7 +433,7 @@
   service()->Init();
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(ExtensionSystem::Get(profile())->is_ready());
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
+  ASSERT_TRUE(registry()->enabled_extensions().empty());
   ASSERT_EQ(0U, model()->size());
 
   static const int kIterations = 20;
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index f5df391..ab39c257 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -67,12 +67,6 @@
 // ui/webui/resources/js/browser_command/browser_command.mojom
 const char kBrowserCommandIdParam[] = "BrowserCommandIdParam";
 
-// Enables using policy::ManagementService to get the browser's and platform
-// management state everywhere.
-BASE_FEATURE(kUseManagementService,
-             "UseManagementService",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 #if BUILDFLAG(IS_MAC)
 // Enables integration with the macOS feature Universal Links.
 BASE_FEATURE(kEnableUniveralLinks,
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h
index 131e64d2..d43ecb71 100644
--- a/chrome/browser/browser_features.h
+++ b/chrome/browser/browser_features.h
@@ -32,8 +32,6 @@
 BASE_DECLARE_FEATURE(kPromoBrowserCommands);
 extern const char kBrowserCommandIdParam[];
 
-BASE_DECLARE_FEATURE(kUseManagementService);
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 BASE_DECLARE_FEATURE(kQuickSettingsPWANotifications);
 #endif
diff --git a/chrome/browser/browsing_data/counters/hosted_apps_counter.cc b/chrome/browser/browsing_data/counters/hosted_apps_counter.cc
index 15315e3d..d337dcc1b 100644
--- a/chrome/browser/browsing_data/counters/hosted_apps_counter.cc
+++ b/chrome/browser/browsing_data/counters/hosted_apps_counter.cc
@@ -26,12 +26,12 @@
 void HostedAppsCounter::Count() {
   std::vector<std::string> names;
 
-  std::unique_ptr<extensions::ExtensionSet> extensions =
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile_)
           ->GenerateInstalledExtensionsSet();
   auto* special_storage_policy = profile_->GetExtensionSpecialStoragePolicy();
 
-  for (const auto& extension : *extensions) {
+  for (const auto& extension : extensions) {
     // Exclude kChromeAppId because this is not a proper hosted app. It is just
     // a shortcut to launch Chrome on Chrome OS.
     if (special_storage_policy->NeedsProtection(extension.get()) &&
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index b6a072f9..2d3ef8d 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -1050,7 +1050,9 @@
                                            NewTabPageUI>(map);
   }
 
-  if (base::FeatureList::IsEnabled(ntp_features::kNtpHistoryClustersModule)) {
+  if (base::FeatureList::IsEnabled(ntp_features::kNtpHistoryClustersModule) ||
+      base::FeatureList::IsEnabled(
+          ntp_features::kNtpHistoryClustersModuleLoad)) {
     RegisterWebUIControllerInterfaceBinder<
         ntp::history_clusters::mojom::PageHandler, NewTabPageUI>(map);
   }
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
index d574de5..5bf0e26 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler.cc
@@ -57,10 +57,10 @@
       GetCleanupExemptExtensions();
 
   auto* extension_registry = extensions::ExtensionRegistry::Get(profile_);
-  std::unique_ptr<extensions::ExtensionSet> all_installed_extensions =
+  const extensions::ExtensionSet all_installed_extensions =
       extension_registry->GenerateInstalledExtensionsSet();
 
-  for (const auto& extension : *all_installed_extensions) {
+  for (const auto& extension : all_installed_extensions) {
     std::string extension_id = extension->id();
     // Skip the apps/extensions not meant to be uninstalled and reinstalled. The
     // browsing history will be removed by BrowsingDataCleanupHandler and open
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
index 98c561a..378fbde 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_browsertest.cc
@@ -162,7 +162,7 @@
   int GetNumberOfInstalledExtensions() {
     return extensions::ExtensionRegistry::Get(GetActiveUserProfile())
         ->GenerateInstalledExtensionsSet()
-        ->size();
+        .size();
   }
 
   void WaitForSessionStart() {
@@ -236,11 +236,11 @@
   EXPECT_EQ(GetNumberOfInstalledExtensions(), num_default_extensions + 3);
 
   // Create observers for all extensions and apps that will be cleaned up.
-  std::unique_ptr<extensions::ExtensionSet> all_installed_extensions =
+  const extensions::ExtensionSet all_installed_extensions =
       extension_registry->GenerateInstalledExtensionsSet();
   std::unordered_set<std::unique_ptr<extensions::TestExtensionRegistryObserver>>
       extension_observers;
-  for (auto& extension : *all_installed_extensions) {
+  for (const auto& extension : all_installed_extensions) {
     // Don't observe exempt and user installed extensions.
     if (base::Contains(kExemptExtensions, extension->id()))
       continue;
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
index 0c3f364..3addd4d 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
@@ -164,9 +164,9 @@
       ->AddExtension(MakeExtensionNamed("baz", kExtensionId2).get());
 
   SetupExemptList();
-  std::unique_ptr<extensions::ExtensionSet> all_installed_extensions =
+  extensions::ExtensionSet all_installed_extensions =
       extension_registry_->GenerateInstalledExtensionsSet();
-  EXPECT_EQ(all_installed_extensions->size(), 3u);
+  EXPECT_EQ(all_installed_extensions.size(), 3u);
 
   base::RunLoop run_loop;
   extension_cleanup_handler_->Cleanup(
@@ -178,8 +178,8 @@
 
   all_installed_extensions =
       extension_registry_->GenerateInstalledExtensionsSet();
-  EXPECT_EQ(all_installed_extensions->size(), 1u);
-  EXPECT_TRUE(all_installed_extensions->Contains(kExemptExtensionId));
+  EXPECT_EQ(all_installed_extensions.size(), 1u);
+  EXPECT_TRUE(all_installed_extensions.Contains(kExemptExtensionId));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_android.cc b/chrome/browser/crash_upload_list/crash_upload_list_android.cc
index e355c2b..4b779cd 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_android.cc
+++ b/chrome/browser/crash_upload_list/crash_upload_list_android.cc
@@ -57,14 +57,14 @@
   return Java_MinidumpUploadServiceImpl_didBrowserCrashRecently(env);
 }
 
-std::vector<UploadList::UploadInfo> CrashUploadListAndroid::LoadUploadList() {
-  std::vector<UploadInfo> uploads;
+std::vector<std::unique_ptr<UploadList::UploadInfo>>
+CrashUploadListAndroid::LoadUploadList() {
+  std::vector<std::unique_ptr<UploadInfo>> uploads;
   LoadUnsuccessfulUploadList(&uploads);
 
-  std::vector<UploadInfo> complete_uploads =
-      TextLogUploadList::LoadUploadList();
-  for (auto info : complete_uploads) {
-    uploads.push_back(info);
+  auto complete_uploads = TextLogUploadList::LoadUploadList();
+  for (auto& info : complete_uploads) {
+    uploads.push_back(std::move(info));
   }
   return uploads;
 }
@@ -77,7 +77,7 @@
 }
 
 void CrashUploadListAndroid::LoadUnsuccessfulUploadList(
-    std::vector<UploadInfo>* uploads) {
+    std::vector<std::unique_ptr<UploadInfo>>* uploads) {
   const char pending_uploads[] = ".dmp";
   const char skipped_uploads[] = ".skipped";
   const char manually_forced_uploads[] = ".forced";
@@ -136,8 +136,7 @@
     RecordUnsuccessfulUploadListState(
         UnsuccessfulUploadListState::ADDING_AN_UPLOAD_ENTRY);
     id = id.substr(pos + 1);
-    UploadList::UploadInfo upload(id, info.creation_time, upload_state,
-                                  ui::FormatBytes(file_size));
-    uploads->push_back(upload);
+    uploads->push_back(std::make_unique<UploadList::UploadInfo>(
+        id, info.creation_time, upload_state, ui::FormatBytes(file_size)));
   }
 }
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_android.h b/chrome/browser/crash_upload_list/crash_upload_list_android.h
index 36e92cdc..d95f96cb 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_android.h
+++ b/chrome/browser/crash_upload_list/crash_upload_list_android.h
@@ -32,11 +32,13 @@
  protected:
   ~CrashUploadListAndroid() override;
 
-  std::vector<UploadInfo> LoadUploadList() override;
+  std::vector<std::unique_ptr<UploadList::UploadInfo>> LoadUploadList()
+      override;
   void RequestSingleUpload(const std::string& local_id) override;
 
  private:
-  void LoadUnsuccessfulUploadList(std::vector<UploadInfo>* uploads);
+  void LoadUnsuccessfulUploadList(
+      std::vector<std::unique_ptr<UploadInfo>>* uploads);
 };
 
 #endif  // CHROME_BROWSER_CRASH_UPLOAD_LIST_CRASH_UPLOAD_LIST_ANDROID_H_
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.cc b/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.cc
index 09e4649..8ee7374 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.cc
+++ b/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.cc
@@ -11,7 +11,8 @@
 
 CrashUploadListFuchsia::~CrashUploadListFuchsia() = default;
 
-std::vector<UploadList::UploadInfo> CrashUploadListFuchsia::LoadUploadList() {
+std::vector<std::unique_ptr<UploadList::UploadInfo>>
+CrashUploadListFuchsia::LoadUploadList() {
   // TODO(crbug.com/1234373): Implement using the crash system component.
   NOTIMPLEMENTED_LOG_ONCE();
   return {};
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.h b/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.h
index 6dd065e..0b7c425 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.h
+++ b/chrome/browser/crash_upload_list/crash_upload_list_fuchsia.h
@@ -20,7 +20,8 @@
  protected:
   ~CrashUploadListFuchsia() override;
 
-  std::vector<UploadInfo> LoadUploadList() override;
+  std::vector<std::unique_ptr<UploadList::UploadInfo>> LoadUploadList()
+      override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
   void RequestSingleUpload(const std::string& local_id) override;
 
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index b4684bf0..9068a8e 100644
--- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -205,11 +205,13 @@
   const extensions::Extension* extension = nullptr;
   if (web_contents) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+    // Disable devtools for ash webui for dev, beta, stable channels unless
+    // device is in devmode, or running with `--force-devtools-available'.
     GURL url = web_contents->GetLastCommittedURL();
     if ((url.SchemeIs("chrome") && url.host() != "inspect") ||
         url.SchemeIs("os")) {
       base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-      if (chrome::GetChannel() != version_info::Channel::CANARY &&
+      if (chrome::GetChannel() >= version_info::Channel::DEV &&
           !command_line->HasSwitch(chromeos::switches::kSystemInDevMode) &&
           !command_line->HasSwitch(ash::switches::kForceDevToolsAvailable)) {
         return false;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 70b9db17..6c452b7 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -1593,6 +1593,11 @@
 bool ChromeDownloadManagerDelegate::ShouldBlockFile(
     download::DownloadItem* item,
     download::DownloadDangerType danger_type) const {
+  // Chrome-initiated background downloads should not be blocked.
+  if (!item->RequireSafetyChecks()) {
+    return false;
+  }
+
   DownloadPrefs::DownloadRestriction download_restriction =
       download_prefs_->download_restriction();
 
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 39c66645..bfb8b16 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -757,6 +757,8 @@
   EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(kUrl));
   EXPECT_CALL(*download_item, GetContentDisposition())
       .WillRepeatedly(Return(kTargetDisposition));
+  EXPECT_CALL(*download_item, RequireSafetyChecks())
+      .WillRepeatedly(Return(true));
 
   base::FilePath kExpectedPath = GetPathInDownloadDir("bar.txt");
 
@@ -782,6 +784,41 @@
   VerifyAndClearExpectations();
 }
 
+TEST_F(ChromeDownloadManagerDelegateTest, NoSafetyChecksNotBlockedByPolicy) {
+  const GURL kUrl("http://example.com/foo");
+  const std::string kTargetDisposition("attachment; filename=\"foo.txt\"");
+
+  std::unique_ptr<download::MockDownloadItem> download_item =
+      CreateActiveDownloadItem(0);
+  EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(kUrl));
+  EXPECT_CALL(*download_item, GetContentDisposition())
+      .WillRepeatedly(Return(kTargetDisposition));
+  EXPECT_CALL(*download_item, RequireSafetyChecks())
+      .WillRepeatedly(Return(false));
+
+  base::FilePath kExpectedPath = GetPathInDownloadDir("bar.txt");
+
+  DetermineDownloadTargetResult result;
+
+  EXPECT_CALL(*delegate(), MockReserveVirtualPath(_, _, _, _, _))
+      .WillOnce(DoAll(SetArgPointee<4>(PathValidationResult::CONFLICT),
+                      ReturnArg<1>()));
+  EXPECT_CALL(*delegate(),
+              RequestConfirmation_(
+                  _, _, DownloadConfirmationReason::TARGET_CONFLICT, _))
+      .WillOnce(WithArg<3>(ScheduleCallback2(
+          DownloadConfirmationResult::CONFIRMED, kExpectedPath)));
+
+  pref_service()->SetInteger(
+      prefs::kDownloadRestrictions,
+      static_cast<int>(DownloadPrefs::DownloadRestriction::ALL_FILES));
+
+  DetermineDownloadTarget(download_item.get(), &result);
+  EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_NONE, result.interrupt_reason);
+
+  VerifyAndClearExpectations();
+}
+
 #if BUILDFLAG(IS_ANDROID)
 TEST_F(ChromeDownloadManagerDelegateTest, InterceptDownloadByOfflinePages) {
   const GURL kUrl("http://example.com/foo");
diff --git a/chrome/browser/enterprise/util/managed_browser_utils.cc b/chrome/browser/enterprise/util/managed_browser_utils.cc
index a9368c9..53829f9f 100644
--- a/chrome/browser/enterprise/util/managed_browser_utils.cc
+++ b/chrome/browser/enterprise/util/managed_browser_utils.cc
@@ -17,8 +17,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
-#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -44,13 +42,6 @@
 #include "chrome/browser/ui/managed_ui.h"
 #endif  // BUILDFLAG(IS_ANDROID)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
-#include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/browser_process_platform_part.h"
-#include "components/user_manager/user_manager.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 namespace chrome {
 namespace enterprise_util {
 
@@ -116,42 +107,7 @@
 
 bool IsBrowserManaged(Profile* profile) {
   DCHECK(profile);
-
-  if (base::FeatureList::IsEnabled(features::kUseManagementService)) {
-    return policy::ManagementServiceFactory::GetForProfile(profile)
-        ->IsManaged();
-  }
-
-  // This profile may have policies configured.
-  auto* profile_connector = profile->GetProfilePolicyConnector();
-  if (profile_connector && profile_connector->IsManaged())
-    return true;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // This session's primary user may also have policies, and those policies may
-  // not have per-profile support.
-  auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser();
-  if (primary_user) {
-    auto* primary_profile =
-        ash::ProfileHelper::Get()->GetProfileByUser(primary_user);
-    if (primary_profile) {
-      auto* primary_profile_connector =
-          primary_profile->GetProfilePolicyConnector();
-      if (primary_profile_connector->IsManaged())
-        return true;
-    }
-  }
-
-  // The machine may be enrolled, via Google Cloud or Active Directory.
-  auto* browser_connector =
-      g_browser_process->platform_part()->browser_policy_connector_ash();
-  return browser_connector && browser_connector->IsDeviceEnterpriseManaged();
-#else
-  // There may be policies set in a platform-specific way (e.g. Windows
-  // Registry), or with machine level user cloud policies.
-  auto* browser_connector = g_browser_process->browser_policy_connector();
-  return browser_connector && browser_connector->HasMachineLevelPolicies();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+  return policy::ManagementServiceFactory::GetForProfile(profile)->IsManaged();
 }
 
 std::string GetDomainFromEmail(const std::string& email) {
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
index d82d29c..7a177b1 100644
--- a/chrome/browser/extensions/active_tab_permission_granter.cc
+++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -225,8 +225,9 @@
 }
 
 void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() {
-  if (granted_extensions_.is_empty())
+  if (granted_extensions_.empty()) {
     return;
+  }
 
   std::set<content::RenderFrameHost*> frame_hosts;
   std::vector<std::string> extension_ids;
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc
index eeddf88..f57c3d1 100644
--- a/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -211,10 +211,10 @@
     RemoveKeybindingPrefs(extension_id, command_name);
 
   // Set the keybinding pref.
-  base::Value keybinding(base::Value::Type::DICT);
-  keybinding.SetStringKey(kExtension, extension_id);
-  keybinding.SetStringKey(kCommandName, command_name);
-  keybinding.SetBoolKey(kGlobal, global);
+  base::Value::Dict keybinding;
+  keybinding.Set(kExtension, extension_id);
+  keybinding.Set(kCommandName, command_name);
+  keybinding.Set(kGlobal, global);
 
   bindings.Set(key, std::move(keybinding));
 
diff --git a/chrome/browser/extensions/api/commands/command_service_browsertest.cc b/chrome/browser/extensions/api/commands/command_service_browsertest.cc
index d4aaa866..f7ad0e9c 100644
--- a/chrome/browser/extensions/api/commands/command_service_browsertest.cc
+++ b/chrome/browser/extensions/api/commands/command_service_browsertest.cc
@@ -469,10 +469,10 @@
   // another platform.
   std::string anotherPlatformKey = GetAnotherCommandPlatform() + ":Alt+G";
   const char kNamedCommandName[] = "toggle-feature";
-  base::Value keybinding(base::Value::Type::DICT);
-  keybinding.SetStringKey("extension", extension->id());
-  keybinding.SetStringKey("command_name", kNamedCommandName);
-  keybinding.SetBoolKey("global", false);
+  base::Value::Dict keybinding;
+  keybinding.Set("extension", extension->id());
+  keybinding.Set("command_name", kNamedCommandName);
+  keybinding.Set("global", false);
   bindings.Set(anotherPlatformKey, std::move(keybinding));
 
   CommandService* command_service = CommandService::Get(browser()->profile());
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index efd7d324..e146db1 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -215,13 +215,13 @@
 // Runs the install verifier for all extensions that are enabled, disabled, or
 // terminated.
 void PerformVerificationCheck(content::BrowserContext* context) {
-  std::unique_ptr<ExtensionSet> extensions =
+  const ExtensionSet extensions =
       ExtensionRegistry::Get(context)->GenerateInstalledExtensionsSet(
           ExtensionRegistry::ENABLED | ExtensionRegistry::DISABLED |
           ExtensionRegistry::TERMINATED);
   ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
   bool should_do_verification_check = false;
-  for (const scoped_refptr<const Extension>& extension : *extensions) {
+  for (const scoped_refptr<const Extension>& extension : extensions) {
     if (ui_util::ShouldDisplayInExtensionSettings(*extension) &&
         prefs->HasDisableReason(extension->id(),
                                 disable_reason::DISABLE_NOT_VERIFIED)) {
@@ -2508,12 +2508,12 @@
 
   std::vector<developer::MatchingExtensionInfo> matching_extensions;
   URLPatternSet site_pattern({parsed_site});
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       ExtensionRegistry::Get(browser_context())
           ->GenerateInstalledExtensionsSet(
               ExtensionRegistry::ENABLED | ExtensionRegistry::DISABLED |
               ExtensionRegistry::TERMINATED | ExtensionRegistry::BLOCKLISTED);
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     const URLPatternSet& extension_withheld_sites =
         extension->permissions_data()->withheld_permissions().effective_hosts();
     const URLPatternSet granted_intersection =
diff --git a/chrome/browser/extensions/api/management/management_api_unittest.cc b/chrome/browser/extensions/api/management/management_api_unittest.cc
index 5914fcf..f08555b 100644
--- a/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -384,8 +384,8 @@
         extensions::UNINSTALL_SOURCE_CHROME_EXTENSIONS_PAGE, 2);
 
     // Try again, using showConfirmDialog: false.
-    base::Value options(base::Value::Type::DICT);
-    options.SetBoolPath("showConfirmDialog", false);
+    base::Value::Dict options;
+    options.Set("showConfirmDialog", false);
     uninstall_args.Append(std::move(options));
     function = base::MakeRefCounted<ManagementUninstallFunction>();
     function->set_source_context_type(Feature::WEBUI_CONTEXT);
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index 6894a211..85800b50 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -361,7 +361,7 @@
   ExtensionService* service = extension_service();
   ExtensionRegistry* registry = extension_registry();
   const size_t size_before = registry->enabled_extensions().size();
-  ASSERT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
   const Extension* extension = InstallExtension(crx_v1_path, 1);
   ASSERT_TRUE(extension);
   EXPECT_TRUE(listener1.WaitUntilSatisfied());
@@ -523,7 +523,7 @@
 
   ExtensionRegistry* registry = extension_registry();
   const size_t size_before = registry->enabled_extensions().size();
-  ASSERT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
 
   extensions::PendingExtensionManager* pending_extension_manager =
       service->pending_extension_manager();
@@ -610,7 +610,7 @@
 
   ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
   const size_t size_before = registry->enabled_extensions().size();
-  ASSERT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
 
   ASSERT_TRUE(extensions::ExtensionManagementFactory::GetForBrowserContext(
                   browser()->profile())
@@ -679,7 +679,7 @@
   ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
   const char kExtensionId[] = "ogjcoiohnmldgjemafoockdghcjciccf";
   const size_t size_before = registry->enabled_extensions().size();
-  ASSERT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
 
   base::ScopedAllowBlockingForTesting allow_blocking;
   base::ScopedTempDir temp_dir;
@@ -746,7 +746,7 @@
   ASSERT_TRUE(extension);
   EXPECT_EQ(ManifestLocation::kInternal, extension->location());
   EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
-  EXPECT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
 
   DisableExtension(kExtensionId);
   EXPECT_EQ(1u, registry->disabled_extensions().size());
@@ -769,5 +769,5 @@
   ASSERT_TRUE(extension);
   EXPECT_EQ(ManifestLocation::kExternalPolicyDownload, extension->location());
   EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
-  EXPECT_TRUE(registry->disabled_extensions().is_empty());
+  EXPECT_TRUE(registry->disabled_extensions().empty());
 }
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index be75706f..2b0c9b4 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -223,7 +223,7 @@
   Respond(Error(error));
 }
 
-void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int64_t file_size) {
+void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int file_size) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   WebContents* web_contents = GetWebContents();
@@ -235,10 +235,10 @@
   ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(source_process_id(),
                                                            mhtml_path_);
 
-  base::Value response(base::Value::Type::DICT);
-  response.SetStringKey("mhtmlFilePath", mhtml_path_.AsUTF8Unsafe());
-  response.SetIntKey("mhtmlFileLength", file_size);
-  response.SetIntKey("requestId", request_id());
+  base::Value::Dict response;
+  response.Set("mhtmlFilePath", mhtml_path_.AsUTF8Unsafe());
+  response.Set("mhtmlFileLength", file_size);
+  response.Set("requestId", request_id());
 
   // Add a reference, extending the lifespan of this extension function until
   // the response has been received by the renderer. This function generates a
@@ -251,7 +251,7 @@
   if (is_from_service_worker())
     AddWorkerResponseTarget();
 
-  Respond(OneArgument(std::move(response)));
+  Respond(OneArgument(base::Value(std::move(response))));
 }
 
 WebContents* PageCaptureSaveAsMHTMLFunction::GetWebContents() {
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.h b/chrome/browser/extensions/api/page_capture/page_capture_api.h
index be5891b..42fba0e 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_api.h
+++ b/chrome/browser/extensions/api/page_capture/page_capture_api.h
@@ -59,7 +59,7 @@
 
   // Called on the UI thread.
   void ReturnFailure(const std::string& error);
-  void ReturnSuccess(int64_t file_size);
+  void ReturnSuccess(int file_size);
 
   // Callback called once the MHTML generation is done.
   void MHTMLGenerated(int64_t mhtml_file_size);
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
index 45281cd..0141beb 100644
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -111,17 +111,16 @@
 
     // Set up the test policy that gives |extension_| the permission to access
     // corporate keys.
-    base::Value key_permissions_policy(base::Value::Type::DICT);
+    base::Value::Dict key_permissions_policy;
     {
-      base::Value cert1_key_permission(base::Value::Type::DICT);
-      cert1_key_permission.SetKey("allowCorporateKeyUsage", base::Value(true));
-      key_permissions_policy.SetKey(kExtensionId,
-                                    std::move(cert1_key_permission));
+      base::Value::Dict cert1_key_permission;
+      cert1_key_permission.Set("allowCorporateKeyUsage", true);
+      key_permissions_policy.Set(kExtensionId, std::move(cert1_key_permission));
     }
 
     policy.Set(policy::key::kKeyPermissions, policy::POLICY_LEVEL_MANDATORY,
                policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
-               std::move(key_permissions_policy), nullptr);
+               base::Value(std::move(key_permissions_policy)), nullptr);
 
     mock_policy_provider()->UpdateChromePolicy(policy);
   }
diff --git a/chrome/browser/extensions/api/preference/preference_helpers.cc b/chrome/browser/extensions/api/preference/preference_helpers.cc
index 306ae55..a968916 100644
--- a/chrome/browser/extensions/api/preference/preference_helpers.cc
+++ b/chrome/browser/extensions/api/preference/preference_helpers.cc
@@ -104,7 +104,7 @@
       std::string level_of_control =
           level_getter.Run(profile, extension->id(), browser_pref, incognito);
 
-      args[0].SetStringKey(kLevelOfControlKey, level_of_control);
+      args[0].GetDict().Set(kLevelOfControlKey, level_of_control);
 
       // If the extension is in incognito split mode,
       // a) incognito pref changes are visible only to the incognito tabs
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 43498e7c..07d5073 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -853,7 +853,7 @@
       settings_api::PrefType::PREF_TYPE_NUMBER;
   (*s_allowlist)[ash::prefs::kPrimaryMouseButtonRight] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
-  (*s_allowlist)[::prefs::kPrimaryPointingStickButtonRight] =
+  (*s_allowlist)[ash::prefs::kPrimaryPointingStickButtonRight] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_allowlist)[ash::prefs::kMouseReverseScroll] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
@@ -861,7 +861,7 @@
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_allowlist)[ash::prefs::kMouseScrollAcceleration] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
-  (*s_allowlist)[::prefs::kPointingStickAcceleration] =
+  (*s_allowlist)[ash::prefs::kPointingStickAcceleration] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_allowlist)[ash::prefs::kTouchpadAcceleration] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
@@ -871,7 +871,7 @@
       settings_api::PrefType::PREF_TYPE_NUMBER;
   (*s_allowlist)[ash::prefs::kMouseScrollSensitivity] =
       settings_api::PrefType::PREF_TYPE_NUMBER;
-  (*s_allowlist)[::prefs::kPointingStickSensitivity] =
+  (*s_allowlist)[ash::prefs::kPointingStickSensitivity] =
       settings_api::PrefType::PREF_TYPE_NUMBER;
   (*s_allowlist)[::prefs::kLanguageRemapSearchKeyTo] =
       settings_api::PrefType::PREF_TYPE_NUMBER;
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index 24f835ed..3c2390a8 100644
--- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -86,15 +86,14 @@
   void OnExtensionsReady();
 
   // Starts a schema load for all extensions that use managed storage.
-  void LoadSchemas(std::unique_ptr<ExtensionSet> added);
+  void LoadSchemas(ExtensionSet added);
 
   bool UsesManagedStorage(const Extension* extension) const;
 
   // Loads the schemas of the |extensions| and passes a ComponentMap to
   // Register().
-  static void LoadSchemasOnFileTaskRunner(
-      std::unique_ptr<ExtensionSet> extensions,
-      base::WeakPtr<ExtensionTracker> self);
+  static void LoadSchemasOnFileTaskRunner(ExtensionSet extensions,
+                                          base::WeakPtr<ExtensionTracker> self);
   void Register(const policy::ComponentMap* components);
 
   raw_ptr<Profile> profile_;
@@ -129,8 +128,8 @@
   // most once.
   if (!ExtensionSystem::Get(profile_)->ready().is_signaled())
     return;
-  auto added = std::make_unique<ExtensionSet>();
-  added->Insert(extension);
+  ExtensionSet added;
+  added.Insert(extension);
   LoadSchemas(std::move(added));
 }
 
@@ -152,17 +151,16 @@
       ExtensionRegistry::Get(profile_)->GenerateInstalledExtensionsSet());
 }
 
-void ManagedValueStoreCache::ExtensionTracker::LoadSchemas(
-    std::unique_ptr<ExtensionSet> added) {
+void ManagedValueStoreCache::ExtensionTracker::LoadSchemas(ExtensionSet added) {
   // Filter out extensions that don't use managed storage.
-  ExtensionSet::const_iterator it = added->begin();
-  while (it != added->end()) {
+  ExtensionSet::const_iterator it = added.begin();
+  while (it != added.end()) {
     std::string to_remove;
     if (!UsesManagedStorage(it->get()))
       to_remove = (*it)->id();
     ++it;
     if (!to_remove.empty())
-      added->Remove(to_remove);
+      added.Remove(to_remove);
   }
 
   GetExtensionFileTaskRunner()->PostTask(
@@ -177,28 +175,27 @@
 
 // static
 void ManagedValueStoreCache::ExtensionTracker::LoadSchemasOnFileTaskRunner(
-    std::unique_ptr<ExtensionSet> extensions,
+    ExtensionSet extensions,
     base::WeakPtr<ExtensionTracker> self) {
   auto components = std::make_unique<policy::ComponentMap>();
 
-  for (const auto& it : *extensions) {
-    const Extension& extension = *it;
-    if (!extension.manifest()->FindStringPath(
+  for (const auto& extension : extensions) {
+    if (!extension->manifest()->FindStringPath(
             manifest_keys::kStorageManagedSchema)) {
       // TODO(joaodasilva): Remove this. http://crbug.com/325349
-      (*components)[extension.id()] = policy::Schema();
+      (*components)[extension->id()] = policy::Schema();
       continue;
     }
     // The extension should have been validated, so assume the schema exists
     // and is valid.
     std::string error;
     policy::Schema schema =
-        StorageSchemaManifestHandler::GetSchema(&extension, &error);
+        StorageSchemaManifestHandler::GetSchema(extension.get(), &error);
     // If the schema is invalid then proceed with an empty schema. The extension
     // will be listed in chrome://policy but won't be able to load any policies.
     if (!schema.valid())
       schema = policy::Schema();
-    (*components)[extension.id()] = schema;
+    (*components)[extension->id()] = schema;
   }
 
   content::GetUIThreadTaskRunner({})->PostTask(
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index fe9c7e60..613fb70 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -755,7 +755,7 @@
   EXTENSION_FUNCTION_VALIDATE(params.get());
   PrefService* service =
       Profile::FromBrowserContext(browser_context())->GetPrefs();
-  base::Value result(base::Value::Type::DICT);
+  base::Value::Dict result;
 
   for (const auto& path : params->paths) {
     // Ignore non-allowed paths.
@@ -767,9 +767,9 @@
       guest_os::RecordTerminalSettingsChangesUMAs(
           Profile::FromBrowserContext(browser_context()));
     }
-    result.SetKey(path, service->GetValue(path).Clone());
+    result.Set(path, service->GetValue(path).Clone());
   }
-  return RespondNow(OneArgument(std::move(result)));
+  return RespondNow(OneArgument(base::Value(std::move(result))));
 }
 
 TerminalPrivateSetPrefsFunction::~TerminalPrivateSetPrefsFunction() = default;
diff --git a/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc b/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
index 8647c66..57344e20 100644
--- a/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
+++ b/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
@@ -79,15 +79,14 @@
   }
 
   void SetPendingList(const std::vector<ExtensionId>& ids) {
-    std::unique_ptr<base::Value> id_values =
-        std::make_unique<base::Value>(base::Value::Type::DICT);
+    base::Value::Dict id_values;
     for (const auto& id : ids) {
-      base::Value request_data(base::Value::Type::DICT);
-      request_data.SetKey(extension_misc::kExtensionRequestTimestamp,
-                          ::base::TimeToValue(base::Time::Now()));
-      id_values->SetKey(id, std::move(request_data));
+      base::Value::Dict request_data;
+      request_data.Set(extension_misc::kExtensionRequestTimestamp,
+                       ::base::TimeToValue(base::Time::Now()));
+      id_values.Set(id, std::move(request_data));
     }
-    profile()->GetTestingPrefService()->SetUserPref(
+    profile()->GetTestingPrefService()->SetDict(
         prefs::kCloudExtensionRequestIds, std::move(id_values));
   }
 };
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index 4526c3a3..3235106 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -345,12 +345,12 @@
   ScopedDictPrefUpdate pending_requests_update(
       profile->GetPrefs(), prefs::kCloudExtensionRequestIds);
   DCHECK(!pending_requests_update->Find(id));
-  base::Value request_data(base::Value::Type::DICT);
-  request_data.SetKey(extension_misc::kExtensionRequestTimestamp,
-                      ::base::TimeToValue(base::Time::Now()));
+  base::Value::Dict request_data;
+  request_data.Set(extension_misc::kExtensionRequestTimestamp,
+                   ::base::TimeToValue(base::Time::Now()));
   if (!justification.empty()) {
-    request_data.SetKey(extension_misc::kExtensionWorkflowJustification,
-                        base::Value(justification));
+    request_data.Set(extension_misc::kExtensionWorkflowJustification,
+                     justification);
   }
   pending_requests_update->Set(id, std::move(request_data));
   // Query the new extension install status again. It should be changed from
diff --git a/chrome/browser/extensions/ash_extension_keeplist_manager.cc b/chrome/browser/extensions/ash_extension_keeplist_manager.cc
index 8dd41f1..b075e88 100644
--- a/chrome/browser/extensions/ash_extension_keeplist_manager.cc
+++ b/chrome/browser/extensions/ash_extension_keeplist_manager.cc
@@ -44,10 +44,10 @@
 void AshExtensionKeeplistManager::ActivateKeeplistEnforcement() {
   DCHECK(should_enforce_keeplist_);
 
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       registry_->GenerateInstalledExtensionsSet();
 
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     if (ShouldDisable(extension.get()))
       Disable(extension->id());
   }
@@ -92,12 +92,12 @@
 void AshExtensionKeeplistManager::DeactivateKeeplistEnforcement() {
   DCHECK(!should_enforce_keeplist_);
 
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       registry_->GenerateInstalledExtensionsSet();
 
   // Find all extensions disabled by keeplist enforcement, remove the disable
   // reason.
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     if (extension_prefs_->HasDisableReason(
             extension->id(), disable_reason::DISABLE_NOT_ASH_KEEPLISTED)) {
       extension_service_->RemoveDisableReasonAndMaybeEnable(
diff --git a/chrome/browser/extensions/extension_allowlist.cc b/chrome/browser/extensions/extension_allowlist.cc
index d6c5e98..81b13b04 100644
--- a/chrome/browser/extensions/extension_allowlist.cc
+++ b/chrome/browser/extensions/extension_allowlist.cc
@@ -294,9 +294,9 @@
 void ExtensionAllowlist::ActivateAllowlistEnforcement() {
   DCHECK(should_auto_disable_extensions_);
 
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       registry_->GenerateInstalledExtensionsSet();
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     if (GetExtensionAllowlistState(extension->id()) ==
         ALLOWLIST_NOT_ALLOWLISTED) {
       ApplyEnforcement(extension->id());
@@ -307,12 +307,12 @@
 void ExtensionAllowlist::DeactivateAllowlistEnforcement() {
   DCHECK(!should_auto_disable_extensions_);
 
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       registry_->GenerateInstalledExtensionsSet();
 
   // Find all extensions disabled by allowlist enforcement, remove the disable
   // reason and reset the acknowledge state.
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     if (extension_prefs_->HasDisableReason(
             extension->id(), disable_reason::DISABLE_NOT_ALLOWLISTED)) {
       extension_service_->RemoveDisableReasonAndMaybeEnable(
@@ -340,10 +340,10 @@
   }
 
   if (previous_warnings_enabled != warnings_enabled_) {
-    std::unique_ptr<ExtensionSet> all_extensions =
+    const ExtensionSet all_extensions =
         registry_->GenerateInstalledExtensionsSet();
 
-    for (const auto& extension : *all_extensions) {
+    for (const auto& extension : all_extensions) {
       if (GetExtensionAllowlistState(extension->id()) ==
           ALLOWLIST_NOT_ALLOWLISTED) {
         NotifyExtensionAllowlistWarningStateChanged(
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 6d1d42a..aaf2d26 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -79,7 +79,6 @@
 #include "extensions/browser/updater/extension_cache_fake.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_set.h"
-#include "extensions/common/file_test_util.h"
 #include "extensions/common/file_util.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/background_info.h"
@@ -277,8 +276,7 @@
   }
   std::string generated_sw_script_content = base::StringPrintf(
       "importScripts(%s);", base::JoinString(script_filenames, ",").c_str());
-  if (!file_test_util::WriteFile(combined_script_filepath,
-                                 generated_sw_script_content)) {
+  if (!base::WriteFile(combined_script_filepath, generated_sw_script_content)) {
     ADD_FAILURE() << "Could not write combined Service Worker script to: "
                   << combined_script_filepath.value();
     return false;
diff --git a/chrome/browser/extensions/extension_error_controller.cc b/chrome/browser/extensions/extension_error_controller.cc
index aa089f0..968c7ec 100644
--- a/chrome/browser/extensions/extension_error_controller.cc
+++ b/chrome/browser/extensions/extension_error_controller.cc
@@ -38,7 +38,7 @@
 
   // Make sure there's something to show, and that there isn't currently a
   // bubble displaying.
-  if (!blocklisted_extensions_.is_empty() && !error_ui_.get()) {
+  if (!blocklisted_extensions_.empty() && !error_ui_.get()) {
     if (!is_first_run_) {
       error_ui_.reset(g_create_ui(this));
       if (!error_ui_->ShowErrorInBubbleView())  // Couldn't find a browser.
diff --git a/chrome/browser/extensions/extension_garbage_collector.cc b/chrome/browser/extensions/extension_garbage_collector.cc
index 3820b8d0..8052263 100644
--- a/chrome/browser/extensions/extension_garbage_collector.cc
+++ b/chrome/browser/extensions/extension_garbage_collector.cc
@@ -220,9 +220,9 @@
   extension_prefs->SetNeedsStorageGarbageCollection(false);
 
   std::unordered_set<base::FilePath> active_paths;
-  std::unique_ptr<ExtensionSet> extensions =
+  const ExtensionSet extensions =
       ExtensionRegistry::Get(context_)->GenerateInstalledExtensionsSet();
-  for (const auto& ext : *extensions) {
+  for (const auto& ext : extensions) {
     if (AppIsolationInfo::HasIsolatedStorage(ext.get())) {
       active_paths.insert(
           util::GetStoragePartitionForExtensionId(ext->id(), context_)
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.cc b/chrome/browser/extensions/extension_message_bubble_controller.cc
index 7b83c32..f1ed262 100644
--- a/chrome/browser/extensions/extension_message_bubble_controller.cc
+++ b/chrome/browser/extensions/extension_message_bubble_controller.cc
@@ -312,13 +312,12 @@
 ExtensionIdList* ExtensionMessageBubbleController::GetOrCreateExtensionList() {
   if (!initialized_) {
     ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
-    std::unique_ptr<const ExtensionSet> all_extensions;
+    absl::optional<ExtensionSet> all_extensions;
     if (!delegate_->ShouldLimitToEnabledExtensions())
       all_extensions = registry->GenerateInstalledExtensionsSet();
     const ExtensionSet& extensions_to_check =
         all_extensions ? *all_extensions : registry->enabled_extensions();
-    for (const scoped_refptr<const Extension>& extension :
-         extensions_to_check) {
+    for (const auto& extension : extensions_to_check) {
       if (delegate_->ShouldIncludeExtension(extension.get()))
         extension_list_.push_back(extension->id());
     }
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 034a426..ea7a9bfa 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1033,12 +1033,11 @@
   block_extensions_ = true;
 
   // Blocklisted extensions are already unloaded, need not be blocked.
-  std::unique_ptr<ExtensionSet> extensions =
-      registry_->GenerateInstalledExtensionsSet(ExtensionRegistry::ENABLED |
-                                                ExtensionRegistry::DISABLED |
-                                                ExtensionRegistry::TERMINATED);
+  const ExtensionSet extensions = registry_->GenerateInstalledExtensionsSet(
+      ExtensionRegistry::ENABLED | ExtensionRegistry::DISABLED |
+      ExtensionRegistry::TERMINATED);
 
-  for (const auto& extension : *extensions) {
+  for (const auto& extension : extensions) {
     const std::string& id = extension->id();
 
     if (!CanBlockExtension(extension.get()))
@@ -1053,10 +1052,10 @@
 // as appropriate.
 void ExtensionService::UnblockAllExtensions() {
   block_extensions_ = false;
-  std::unique_ptr<ExtensionSet> to_unblock =
+  const ExtensionSet to_unblock =
       registry_->GenerateInstalledExtensionsSet(ExtensionRegistry::BLOCKED);
 
-  for (const auto& extension : *to_unblock) {
+  for (const auto& extension : to_unblock) {
     registry_->RemoveBlocked(extension->id());
     AddExtension(extension.get());
   }
@@ -1775,9 +1774,9 @@
   ExtensionManagement* settings =
       ExtensionManagementFactory::GetForBrowserContext(profile());
   CHECK(settings);
-  std::unique_ptr<ExtensionSet> all_extensions(
-      registry_->GenerateInstalledExtensionsSet());
-  for (const auto& extension : *all_extensions) {
+  const ExtensionSet all_extensions =
+      registry_->GenerateInstalledExtensionsSet();
+  for (const auto& extension : all_extensions) {
     if (!settings->IsPermissionSetAllowed(
             extension.get(),
             extension->permissions_data()->active_permissions()) &&
@@ -2160,7 +2159,7 @@
 
 void ExtensionService::OnBlocklistUpdated() {
   blocklist_->GetBlocklistedIDs(
-      registry_->GenerateInstalledExtensionsSet()->GetIDs(),
+      registry_->GenerateInstalledExtensionsSet().GetIDs(),
       base::BindOnce(&ExtensionService::ManageBlocklist,
                      AsExtensionServiceWeakPtr()));
 }
@@ -2320,10 +2319,10 @@
 }
 
 void ExtensionService::UninstallMigratedExtensions() {
-  std::unique_ptr<ExtensionSet> installed_extensions =
+  const ExtensionSet installed_extensions =
       registry_->GenerateInstalledExtensionsSet();
   for (const std::string& extension_id : kObsoleteComponentExtensionIds) {
-    auto* extension = installed_extensions->GetByID(extension_id);
+    auto* extension = installed_extensions.GetByID(extension_id);
     if (extension) {
       UninstallExtension(extension_id, UNINSTALL_REASON_COMPONENT_REMOVED,
                          nullptr);
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index ed52a2e7..639982c 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -703,13 +703,15 @@
   }
 
   testing::AssertionResult IsBlocked(const std::string& id) {
-    std::unique_ptr<ExtensionSet> all_unblocked_extensions =
+    const ExtensionSet all_unblocked_extensions =
         registry()->GenerateInstalledExtensionsSet(
             ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::BLOCKED);
-    if (all_unblocked_extensions->Contains(id))
+    if (all_unblocked_extensions.Contains(id)) {
       return testing::AssertionFailure() << id << " is still unblocked!";
-    if (!registry()->blocked_extensions().Contains(id))
+    }
+    if (!registry()->blocked_extensions().Contains(id)) {
       return testing::AssertionFailure() << id << " is not blocked!";
+    }
     return testing::AssertionSuccess();
   }
 
@@ -2835,7 +2837,7 @@
 
 TEST_F(ExtensionServiceTest, InstallAppsWithUnlimitedStorage) {
   InitializeEmptyExtensionService();
-  EXPECT_TRUE(registry()->enabled_extensions().is_empty());
+  EXPECT_TRUE(registry()->enabled_extensions().empty());
 
   int pref_count = 0;
 
@@ -2886,7 +2888,7 @@
 
 TEST_F(ExtensionServiceTest, InstallAppsAndCheckStorageProtection) {
   InitializeEmptyExtensionService();
-  EXPECT_TRUE(registry()->enabled_extensions().is_empty());
+  EXPECT_TRUE(registry()->enabled_extensions().empty());
 
   int pref_count = 0;
 
@@ -2917,7 +2919,7 @@
 
   UninstallExtension(id2);
 
-  EXPECT_TRUE(registry()->enabled_extensions().is_empty());
+  EXPECT_TRUE(registry()->enabled_extensions().empty());
   EXPECT_FALSE(
       profile()->GetExtensionSpecialStoragePolicy()->IsStorageProtected(
           origin1));
@@ -4926,7 +4928,7 @@
       ::switches::kDisableExtensions);
   InitializeGoodInstalledExtensionService();
   service()->Init();
-  EXPECT_TRUE(registry()->GenerateInstalledExtensionsSet()->is_empty());
+  EXPECT_TRUE(registry()->GenerateInstalledExtensionsSet().empty());
 }
 
 // ... But, if we remove the switch, they are.
@@ -4935,8 +4937,8 @@
       ::switches::kDisableExtensions));
   InitializeGoodInstalledExtensionService();
   service()->Init();
-  EXPECT_FALSE(registry()->GenerateInstalledExtensionsSet()->is_empty());
-  EXPECT_FALSE(registry()->enabled_extensions().is_empty());
+  EXPECT_FALSE(registry()->GenerateInstalledExtensionsSet().empty());
+  EXPECT_FALSE(registry()->enabled_extensions().empty());
 }
 
 // Tests reloading extensions.
@@ -5558,7 +5560,7 @@
 
   EXPECT_EQ(1u, GetErrors().size());
   EXPECT_EQ(1u, registry()->enabled_extensions().size());
-  EXPECT_EQ(1u, registry()->GenerateInstalledExtensionsSet()->size());
+  EXPECT_EQ(1u, registry()->GenerateInstalledExtensionsSet().size());
   EXPECT_TRUE(
       get_extension_by_name(registry()->enabled_extensions(), kGoodExtension));
 
@@ -5568,7 +5570,7 @@
           ->id();
   service()->UninstallExtension(good_id, UNINSTALL_REASON_FOR_TESTING, nullptr);
   task_environment()->RunUntilIdle();
-  EXPECT_TRUE(registry()->GenerateInstalledExtensionsSet()->is_empty());
+  EXPECT_TRUE(registry()->GenerateInstalledExtensionsSet().empty());
 }
 
 // Tests that we generate IDs when they are not specified in the manifest for
@@ -7605,7 +7607,7 @@
 TEST_F(ExtensionServiceTest, CannotEnableBlocklistedExtension) {
   InitializeGoodInstalledExtensionService();
   service()->Init();
-  ASSERT_FALSE(registry()->enabled_extensions().is_empty());
+  ASSERT_FALSE(registry()->enabled_extensions().empty());
 
   // Blocklist the first extension; then try enabling it.
   std::string id = (*(registry()->enabled_extensions().begin()))->id();
@@ -7652,7 +7654,7 @@
 TEST_F(ExtensionServiceTest, UninstallBlocklistedExtension) {
   InitializeGoodInstalledExtensionService();
   service()->Init();
-  ASSERT_FALSE(registry()->enabled_extensions().is_empty());
+  ASSERT_FALSE(registry()->enabled_extensions().empty());
 
   // Blocklist the first extension; then try uninstalling it.
   std::string id = (*(registry()->enabled_extensions().begin()))->id();
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc
index 8bef558..4244b31 100644
--- a/chrome/browser/extensions/extension_special_storage_policy.cc
+++ b/chrome/browser/extensions/extension_special_storage_policy.cc
@@ -365,7 +365,7 @@
 
 bool ExtensionSpecialStoragePolicy::SpecialCollection::Contains(
     const GURL& origin) {
-  return !ExtensionsContaining(origin)->is_empty();
+  return !ExtensionsContaining(origin)->empty();
 }
 
 bool ExtensionSpecialStoragePolicy::SpecialCollection::GrantsCapabilitiesTo(
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index 89ff0ff..266158b 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -513,12 +513,12 @@
 
 // static
 void ExtensionWebUI::ValidateChromeURLOverrides(Profile* profile) {
-  std::unique_ptr<extensions::ExtensionSet> all_extensions =
+  extensions::ExtensionSet all_extensions =
       extensions::ExtensionRegistry::Get(profile)
           ->GenerateInstalledExtensionsSet();
 
-  ForEachOverrideList(profile, base::BindRepeating(&ValidateOverridesList,
-                                                   all_extensions.get()));
+  ForEachOverrideList(
+      profile, base::BindRepeating(&ValidateOverridesList, &all_extensions));
 }
 
 // static
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc b/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
index 55061f5..eba85e63 100644
--- a/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
+++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics.cc
@@ -459,12 +459,13 @@
   auto installed_extensions = registry_->GenerateInstalledExtensionsSet();
   auto blocklisted_extensions = registry_->GenerateInstalledExtensionsSet(
       ExtensionRegistry::IncludeFlag::BLOCKLISTED);
-  for (const auto& entry : *installed_extensions) {
+  for (const auto& entry : installed_extensions) {
     if (missing_forced_extensions.count(entry->id())) {
       missing_forced_extensions.erase(entry->id());
       ReportDisableReason(entry->id());
-      if (blocklisted_extensions->Contains(entry->id()))
+      if (blocklisted_extensions.Contains(entry->id())) {
         blocklisted_count++;
+      }
     }
   }
   size_t misconfigured_extensions = 0;
diff --git a/chrome/browser/extensions/install_verifier.cc b/chrome/browser/extensions/install_verifier.cc
index 56a48e48..47af320 100644
--- a/chrome/browser/extensions/install_verifier.cc
+++ b/chrome/browser/extensions/install_verifier.cc
@@ -320,12 +320,12 @@
 
 ExtensionIdSet InstallVerifier::GetExtensionsToVerify() const {
   ExtensionIdSet result;
-  std::unique_ptr<ExtensionSet> extensions =
+  const ExtensionSet extensions =
       ExtensionRegistry::Get(context_)->GenerateInstalledExtensionsSet();
-  for (ExtensionSet::const_iterator iter = extensions->begin();
-       iter != extensions->end(); ++iter) {
-    if (NeedsVerification(**iter, context_))
-      result.insert((*iter)->id());
+  for (const auto& extension : extensions) {
+    if (NeedsVerification(*extension, context_)) {
+      result.insert(extension->id());
+    }
   }
   return result;
 }
diff --git a/chrome/browser/extensions/safe_browsing_verdict_handler.cc b/chrome/browser/extensions/safe_browsing_verdict_handler.cc
index 97c31c7..c4724d5 100644
--- a/chrome/browser/extensions/safe_browsing_verdict_handler.cc
+++ b/chrome/browser/extensions/safe_browsing_verdict_handler.cc
@@ -47,10 +47,10 @@
 void SafeBrowsingVerdictHandler::Init() {
   TRACE_EVENT0("browser,startup", "SafeBrowsingVerdictHandler::Init");
 
-  std::unique_ptr<ExtensionSet> all_extensions =
+  const ExtensionSet all_extensions =
       registry_->GenerateInstalledExtensionsSet();
 
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     const BitMapBlocklistState state =
         blocklist_prefs::GetSafeBrowsingExtensionBlocklistState(
             extension->id(), extension_prefs_);
@@ -76,7 +76,7 @@
   ExtensionIdSet unchanged;
 
   ExtensionIdSet installed_ids =
-      registry_->GenerateInstalledExtensionsSet()->GetIDs();
+      registry_->GenerateInstalledExtensionsSet().GetIDs();
   for (const auto& it : state_map) {
     // It is possible that an extension is uninstalled when the blocklist is
     // fetching asynchronously. In this case, we should ignore this extension.
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc
index 50e4166d..5f6aac7 100644
--- a/chrome/browser/extensions/user_script_listener_unittest.cc
+++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -147,7 +147,7 @@
   void UnloadTestExtension() {
     const extensions::ExtensionSet& extensions =
         ExtensionRegistry::Get(profile_)->enabled_extensions();
-    ASSERT_FALSE(extensions.is_empty());
+    ASSERT_FALSE(extensions.empty());
     service_->UnloadExtension((*extensions.begin())->id(),
                               UnloadedExtensionReason::DISABLE);
   }
diff --git a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
index 3f43722..4490848e 100644
--- a/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/crash_ids_source_unittest.cc
@@ -24,7 +24,9 @@
 
  protected:
   ~StubUploadList() override = default;
-  std::vector<UploadInfo> LoadUploadList() override { return {}; }
+  std::vector<std::unique_ptr<UploadInfo>> LoadUploadList() override {
+    return {};
+  }
 
   void ClearUploadList(const base::Time& begin,
                        const base::Time& end) override {}
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 1308ffc..83e656e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -5016,6 +5016,11 @@
     "expiry_milestone": 108
   },
   {
+    "name": "ntp-journeys-module",
+    "owners": [ "romanarora", "mfacey", "tiborg" ],
+    "expiry_milestone": 118
+  },
+  {
     "name": "ntp-middle-slot-promo-dismissal",
     "owners": [ "pauladedeji", "tiborg" ],
     "expiry_milestone": 111
@@ -5118,11 +5123,6 @@
     "expiry_milestone": 120
   },
   {
-    "name": "omnibox-active-search-engines",
-    "owners": [ "yoangela", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 105
-  },
-  {
     "name": "omnibox-adaptive-suggestions-count",
     "owners": [ "stkhapugin", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 120
@@ -5751,6 +5751,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "policy-logs-page-ios",
+    "owners": [ "esalma", "ftirelo" ],
+    "expiry_milestone": 122
+  },
+  {
     "name": "policy-merge-multi-source",
     "owners": [ "igorruvinov", "ydago", "pastarmovj" ],
     "expiry_milestone": 116
@@ -5766,11 +5771,6 @@
     "expiry_milestone": 120
   },
   {
-    "name": "post-quantum-cecpq2",
-    "owners": [ "agl" ],
-    "expiry_milestone": 116
-  },
-  {
     "name": "power-bookmark-backend",
     "owners": [ "wylieb", "skym" ],
     "expiry_milestone": 118
@@ -6127,6 +6127,11 @@
     "expiry_milestone": 114
   },
   {
+    "name": "request-desktop-site-defaults-logging",
+    "owners": [ "shuyng@google.com", "clank-app-team@google.com" ],
+    "expiry_milestone": 116
+  },
+  {
     "name": "request-desktop-site-exceptions",
     "owners": [ "shuyng@google.com", "twellington", "clank-app-team@google.com" ],
     "expiry_milestone": 114
@@ -6277,7 +6282,7 @@
   {
     "name" : "search-web-in-side-panel",
     "owners": [ "chrome-cros@google.com", "pengchaocai" ],
-    "expiry_milestone" : 113
+    "expiry_milestone" : 115
   },
   {
     "name": "send-tab-to-self-signin-promo",
@@ -7135,6 +7140,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "user-notes-side-panel",
+    "owners": [ "corising", "chrome-desktop-ui-sea" ],
+    "expiry_milestone": 118
+  },
+  {
     "name": "username-first-flow-fallback-crowdsourcing",
     "owners": [ "kolos", "shaikhitdin@google.com" ],
     "expiry_milestone": 116
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 47b9abb..5ed0941 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1033,11 +1033,6 @@
     "This option enables improvements in the text shown when hovering over the "
     "Select-to-Speak feature icon in the system tray.";
 
-const char kPostQuantumCECPQ2Name[] = "TLS Post-Quantum Confidentiality";
-const char kPostQuantumCECPQ2Description[] =
-    "This option enables a post-quantum (i.e. resistent to quantum computers) "
-    "key exchange algorithm in TLS (CECPQ2).";
-
 const char kMacCoreLocationBackendName[] = "Core Location Backend";
 const char kMacCoreLocationBackendDescription[] =
     "Enables usage of the Core Location APIs as the backend for Geolocation "
@@ -3138,6 +3133,11 @@
     "Enables IPv4 to IPv6 address translation for IPv4 literals when chrome is "
     "on an IPv6 only network";
 
+const char kUserNotesSidePanelName[] = "User notes side panel";
+const char kUserNotesSidePanelDescription[] =
+    "Enables the user notes feature in the side panel. "
+    "Only works if Power bookmark backend is also enabled.";
+
 const char kUsernameFirstFlowFallbackCrowdsourcingName[] =
     "Username first flow fallback crowdsourcing";
 const char kUsernameFirstFlowFallbackCrowdsourcingDescription[] =
@@ -3922,6 +3922,12 @@
     "Disable the request desktop site global setting if it was enabled by "
     "default based on device conditions.";
 
+const char kRequestDesktopSiteDefaultsLoggingName[] =
+    "Silently report crashes for debugging request desktop site on Android.";
+const char kRequestDesktopSiteDefaultsLoggingDescription[] =
+    "Silently report crashes with display spec when ineligible device shows "
+    "up in cohort or device screen size exceeds threshold.";
+
 const char kRequestDesktopSiteExceptionsDowngradeName[] =
     "Downgrade request desktop site exceptions on Android.";
 const char kRequestDesktopSiteExceptionsDowngradeDescription[] =
@@ -4284,6 +4290,10 @@
     "enabled.";
 #endif
 
+const char kNtpHistoryClustersModuleName[] = "NTP Journeys Module";
+const char kNtpHistoryClustersModuleDescription[] =
+    "Shows the Journeys module on the New Tab Page.";
+
 const char kNtpMiddleSlotPromoDismissalName[] =
     "NTP Middle Slot Promo Dismissal";
 const char kNtpMiddleSlotPromoDismissalDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 380cd4b3..9479002 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -590,9 +590,6 @@
 extern const char kAccessibilitySelectToSpeakHoverTextImprovementsName[];
 extern const char kAccessibilitySelectToSpeakHoverTextImprovementsDescription[];
 
-extern const char kPostQuantumCECPQ2Name[];
-extern const char kPostQuantumCECPQ2Description[];
-
 extern const char kMacCoreLocationBackendName[];
 extern const char kMacCoreLocationBackendDescription[];
 
@@ -1788,6 +1785,9 @@
 extern const char kUseNAT64ForIPv4LiteralName[];
 extern const char kUseNAT64ForIPv4LiteralDescription[];
 
+extern const char kUserNotesSidePanelName[];
+extern const char kUserNotesSidePanelDescription[];
+
 extern const char kUseSearchClickForRightClickName[];
 extern const char kUseSearchClickForRightClickDescription[];
 
@@ -2248,6 +2248,9 @@
 extern const char kRequestDesktopSiteDefaultsDowngradeName[];
 extern const char kRequestDesktopSiteDefaultsDowngradeDescription[];
 
+extern const char kRequestDesktopSiteDefaultsLoggingName[];
+extern const char kRequestDesktopSiteDefaultsLoggingDescription[];
+
 extern const char kRequestDesktopSiteExceptionsName[];
 extern const char kRequestDesktopSiteExceptionsDescription[];
 
@@ -2456,6 +2459,9 @@
 extern const char kNtpDummyModulesDescription[];
 #endif
 
+extern const char kNtpHistoryClustersModuleName[];
+extern const char kNtpHistoryClustersModuleDescription[];
+
 extern const char kNtpMiddleSlotPromoDismissalName[];
 extern const char kNtpMiddleSlotPromoDismissalDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 8a9a5bb..aa6a2639 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -274,6 +274,7 @@
     &kRequestDesktopSiteOptInControlSynthetic,
     &kRequestDesktopSiteOptInSynthetic,
     &kRequestDesktopSiteDefaultsDowngrade,
+    &kRequestDesktopSiteDefaultsLogging,
     &kRequestDesktopSitePerSiteIph,
     &kSafeModeForCachedFlags,
     &kShowScrollableMVTOnNTPAndroid,
@@ -897,6 +898,10 @@
              "RequestDesktopSiteDefaultsDowngrade",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kRequestDesktopSiteDefaultsLogging,
+             "RequestDesktopSiteDefaultsLogging",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kRequestDesktopSitePerSiteIph,
              "RequestDesktopSitePerSiteIph",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 92e01a54..a0e1f87 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -138,6 +138,7 @@
 BASE_DECLARE_FEATURE(kRequestDesktopSiteOptInControlSynthetic);
 BASE_DECLARE_FEATURE(kRequestDesktopSiteOptInSynthetic);
 BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsDowngrade);
+BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsLogging);
 BASE_DECLARE_FEATURE(kRequestDesktopSitePerSiteIph);
 BASE_DECLARE_FEATURE(kSharingHubLinkToggle);
 BASE_DECLARE_FEATURE(kShowScrollableMVTOnNTPAndroid);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index be2470d..d950d322 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -452,6 +452,8 @@
             "RequestDesktopSiteDefaultsControlSynthetic";
     public static final String REQUEST_DESKTOP_SITE_DEFAULTS_DOWNGRADE =
             "RequestDesktopSiteDefaultsDowngrade";
+    public static final String REQUEST_DESKTOP_SITE_DEFAULTS_LOGGING =
+            "RequestDesktopSiteDefaultsLogging";
     public static final String REQUEST_DESKTOP_SITE_DEFAULTS_SYNTHETIC =
             "RequestDesktopSiteDefaultsSynthetic";
     public static final String REQUEST_DESKTOP_SITE_OPT_IN_CONTROL_SYNTHETIC =
diff --git a/chrome/browser/installable/installed_webapp_geolocation_bridge.cc b/chrome/browser/installable/installed_webapp_geolocation_bridge.cc
index 20e7124..729d175d 100644
--- a/chrome/browser/installable/installed_webapp_geolocation_bridge.cc
+++ b/chrome/browser/installable/installed_webapp_geolocation_bridge.cc
@@ -105,7 +105,6 @@
   DCHECK(context_);
 
   current_position_ = position;
-  current_position_.valid = device::ValidateGeoposition(position);
   has_position_to_report_ = true;
 
   if (!position_callback_.is_null())
diff --git a/chrome/browser/metrics/extensions_metrics_provider.cc b/chrome/browser/metrics/extensions_metrics_provider.cc
index e240eed..383412b 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.cc
+++ b/chrome/browser/metrics/extensions_metrics_provider.cc
@@ -33,6 +33,7 @@
 #include "extensions/common/manifest.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/background_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
 
 using extensions::Extension;
@@ -344,14 +345,14 @@
     Profile* profile,
     base::Time last_sample_time) {
   extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile);
-  std::unique_ptr<extensions::ExtensionSet> extensions =
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile)
           ->GenerateInstalledExtensionsSet();
   std::vector<ExtensionInstallProto> installs;
-  installs.reserve(extensions->size());
+  installs.reserve(extensions.size());
   extensions::ExtensionManagement* extension_management =
       extensions::ExtensionManagementFactory::GetForBrowserContext(profile);
-  for (const auto& extension : *extensions) {
+  for (const auto& extension : extensions) {
     installs.push_back(ConstructInstallProto(
         *extension, prefs, last_sample_time, extension_management));
   }
@@ -380,12 +381,12 @@
   return output % kExtensionListBuckets;
 }
 
-std::unique_ptr<extensions::ExtensionSet>
+absl::optional<extensions::ExtensionSet>
 ExtensionsMetricsProvider::GetInstalledExtensions(Profile* profile) {
   // Some profiles cannot have extensions, such as the System Profile.
   if (!profile || extensions::ChromeContentBrowserClientExtensionsPart::
                       AreExtensionsDisabledForProfile(profile)) {
-    return nullptr;
+    return absl::nullopt;
   }
 
   extensions::ExtensionRegistry* registry =
@@ -441,8 +442,8 @@
   // time when this metric is generated.
   std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
   for (size_t i = 0u; i < profiles.size() && state < OFF_STORE; ++i) {
-    std::unique_ptr<extensions::ExtensionSet> extensions(
-        GetInstalledExtensions(profiles[i]));
+    absl::optional<extensions::ExtensionSet> extensions =
+        GetInstalledExtensions(profiles[i]);
     if (!extensions)
       continue;
 
@@ -452,8 +453,8 @@
 
     // Combine the state from each profile, always favoring the higher state as
     // defined by the order of ExtensionState.
-    state = std::max(
-        state, CheckForOffStore(*extensions.get(), *verifier, profiles[i]));
+    state =
+        std::max(state, CheckForOffStore(*extensions, *verifier, profiles[i]));
   }
 
   system_profile->set_offstore_extensions_state(ExtensionStateAsProto(state));
@@ -467,8 +468,8 @@
   // profiles.
   Profile* profile = cached_profile_.GetMetricsProfile();
 
-  std::unique_ptr<extensions::ExtensionSet> extensions(
-      GetInstalledExtensions(profile));
+  absl::optional<extensions::ExtensionSet> extensions =
+      GetInstalledExtensions(profile);
   if (!extensions)
     return;
 
diff --git a/chrome/browser/metrics/extensions_metrics_provider.h b/chrome/browser/metrics/extensions_metrics_provider.h
index 04fea0e..c18c8bcf 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.h
+++ b/chrome/browser/metrics/extensions_metrics_provider.h
@@ -15,6 +15,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/metrics/cached_metrics_profile.h"
 #include "components/metrics/metrics_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/metrics_proto/extension_install.pb.h"
 
 class Profile;
@@ -61,7 +62,7 @@
   // Exposed for the sake of mocking in test code.
 
   // Retrieves the set of extensions installed in the given |profile|.
-  virtual std::unique_ptr<extensions::ExtensionSet> GetInstalledExtensions(
+  virtual absl::optional<extensions::ExtensionSet> GetInstalledExtensions(
       Profile* profile);
 
   // Retrieves the client ID.
diff --git a/chrome/browser/metrics/extensions_metrics_provider_unittest.cc b/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
index 77628a4..d6bd3c7 100644
--- a/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/extensions_metrics_provider_unittest.cc
@@ -34,6 +34,7 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/metrics_proto/extension_install.pb.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
 
@@ -58,10 +59,9 @@
  protected:
   // Override the GetInstalledExtensions method to return a set of extensions
   // for tests.
-  std::unique_ptr<extensions::ExtensionSet> GetInstalledExtensions(
+  absl::optional<extensions::ExtensionSet> GetInstalledExtensions(
       Profile* profile) override {
-    std::unique_ptr<extensions::ExtensionSet> extensions(
-        new extensions::ExtensionSet());
+    extensions::ExtensionSet extensions;
     scoped_refptr<const extensions::Extension> extension;
     extension = extensions::ExtensionBuilder()
                     .SetManifest(extensions::DictionaryBuilder()
@@ -71,7 +71,7 @@
                                      .Build())
                     .SetID("ahfgeienlihckogmohjhadlkjgocpleb")
                     .Build();
-    extensions->Insert(extension);
+    extensions.Insert(extension);
     extension = extensions::ExtensionBuilder()
                     .SetManifest(extensions::DictionaryBuilder()
                                      .Set("name", "Test extension 2")
@@ -80,7 +80,7 @@
                                      .Build())
                     .SetID("pknkgggnfecklokoggaggchhaebkajji")
                     .Build();
-    extensions->Insert(extension);
+    extensions.Insert(extension);
     extension = extensions::ExtensionBuilder()
                     .SetManifest(extensions::DictionaryBuilder()
                                      .Set("name", "Colliding Extension")
@@ -89,7 +89,7 @@
                                      .Build())
                     .SetID("mdhofdjgenpkhlmddfaegdjddcecipmo")
                     .Build();
-    extensions->Insert(extension);
+    extensions.Insert(extension);
     return extensions;
   }
 
diff --git a/chrome/browser/net/net_export_helper.cc b/chrome/browser/net/net_export_helper.cc
index 664ce3a..5c943a2 100644
--- a/chrome/browser/net/net_export_helper.cc
+++ b/chrome/browser/net/net_export_helper.cc
@@ -52,10 +52,10 @@
     extensions::ExtensionService* extension_service =
         extension_system->extension_service();
     if (extension_service) {
-      std::unique_ptr<const extensions::ExtensionSet> extensions(
+      const extensions::ExtensionSet extensions =
           extensions::ExtensionRegistry::Get(profile)
-              ->GenerateInstalledExtensionsSet());
-      for (const auto& extension : *extensions) {
+              ->GenerateInstalledExtensionsSet();
+      for (const auto& extension : extensions) {
         base::Value::Dict extension_info;
         bool enabled = extension_service->IsExtensionEnabled(extension->id());
         extensions::GetExtensionBasicInfo(extension.get(), enabled,
diff --git a/chrome/browser/performance_manager/decorators/page_aggregator.cc b/chrome/browser/performance_manager/decorators/page_aggregator.cc
index d9774e4b..adae9983 100644
--- a/chrome/browser/performance_manager/decorators/page_aggregator.cc
+++ b/chrome/browser/performance_manager/decorators/page_aggregator.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/performance_manager/decorators/page_aggregator.h"
 
-#include <stdint.h>
+#include <cstdint>
 
 #include "components/performance_manager/graph/node_attached_data_impl.h"
 #include "components/performance_manager/graph/page_node_impl.h"
@@ -46,6 +46,10 @@
     page_node->SetHadFormInteraction(base::PassKey<PageAggregatorAccess>(),
                                      value);
   }
+
+  static void SetPageHadUserEdits(PageNodeImpl* page_node, bool value) {
+    page_node->SetHadUserEdits(base::PassKey<PageAggregatorAccess>(), value);
+  }
 };
 
 // Specify the packing alignment for this class as it's expected to have a
@@ -90,6 +94,14 @@
       PageNodeImpl* page_node,
       const FrameNode* frame_node_being_removed);
 
+  // Updates the counter of frames with user-initiated edits and sets the
+  // corresponding page-level property.  |frame_node_being_removed| indicates
+  // if this function is called while removing a frame node.
+  void UpdateCurrentFrameCountForUserEdits(
+      bool frame_had_user_edits,
+      PageNodeImpl* page_node,
+      const FrameNode* frame_node_being_removed);
+
  private:
   friend class PageAggregator;
 
@@ -100,6 +112,9 @@
 
   // The number of current frames which have received some form interaction.
   uint32_t num_current_frames_with_form_interaction_ = 0;
+
+  // The number of current frames which have some user-initiated edits.
+  uint32_t num_current_frames_with_user_edits_ = 0;
 };
 #pragma pack(pop)
 
@@ -160,6 +175,36 @@
       page_node, num_current_frames_with_form_interaction_ > 0);
 }
 
+void PageAggregator::Data::UpdateCurrentFrameCountForUserEdits(
+    bool frame_had_user_edits,
+    PageNodeImpl* page_node,
+    const FrameNode* frame_node_being_removed) {
+  if (frame_had_user_edits) {
+    ++num_current_frames_with_user_edits_;
+  } else {
+    DCHECK_GT(num_current_frames_with_user_edits_, 0U);
+    --num_current_frames_with_user_edits_;
+  }
+  // DCHECK that the |num_current_frames_with_user_edits_| accounting is
+  // correct.
+  DCHECK_EQ(
+      [&]() {
+        const auto frame_nodes = GraphOperations::GetFrameNodes(page_node);
+        size_t num_current_frames_with_user_edits = 0;
+        for (const auto* node : frame_nodes) {
+          if (node != frame_node_being_removed && node->IsCurrent() &&
+              node->HadUserEdits()) {
+            ++num_current_frames_with_user_edits;
+          }
+        }
+        return num_current_frames_with_user_edits;
+      }(),
+      num_current_frames_with_user_edits_);
+
+  PageAggregatorAccess::SetPageHadUserEdits(
+      page_node, num_current_frames_with_user_edits_ > 0);
+}
+
 PageAggregator::PageAggregator() = default;
 PageAggregator::~PageAggregator() = default;
 
@@ -173,11 +218,15 @@
   if (frame_node->IsCurrent()) {
     // Data should have been created when the frame became current.
     DCHECK(data);
+    // Decrement the form interaction and user edits counters for this page if
+    // needed.
     if (frame_node->HadFormInteraction()) {
-      // Decrement the form interaction counter for this page.
       data->UpdateCurrentFrameCountForFormInteraction(false, page_node,
                                                       frame_node);
     }
+    if (frame_node->HadUserEdits()) {
+      data->UpdateCurrentFrameCountForUserEdits(false, page_node, frame_node);
+    }
   }
 
   // It is not guaranteed that the graph will be notified that the frame has
@@ -192,8 +241,8 @@
   auto* page_node = PageNodeImpl::FromNode(frame_node->GetPageNode());
   Data* data = Data::GetOrCreate(page_node);
 
-  // Check if the frame node had some form interaction, in this case there's two
-  // possibilities:
+  // Check if the frame node had some form interaction or user edit, in this
+  // case there's two possibilities:
   //   - The frame became current: The counter of current frames with form
   //     interactions should be increased.
   //   - The frame became non current: The counter of current frames with form
@@ -202,6 +251,10 @@
     data->UpdateCurrentFrameCountForFormInteraction(frame_node->IsCurrent(),
                                                     page_node, nullptr);
   }
+  if (frame_node->HadUserEdits()) {
+    data->UpdateCurrentFrameCountForUserEdits(frame_node->IsCurrent(),
+                                              page_node, nullptr);
+  }
 }
 
 void PageAggregator::OnFrameIsHoldingWebLockChanged(
@@ -229,6 +282,15 @@
   }
 }
 
+void PageAggregator::OnHadUserEditsChanged(const FrameNode* frame_node) {
+  if (frame_node->IsCurrent()) {
+    auto* page_node = PageNodeImpl::FromNode(frame_node->GetPageNode());
+    Data* data = Data::GetOrCreate(page_node);
+    data->UpdateCurrentFrameCountForUserEdits(frame_node->HadUserEdits(),
+                                              page_node, nullptr);
+  }
+}
+
 void PageAggregator::OnPassedToGraph(Graph* graph) {
   // This observer presumes that it's been added before any frame nodes exist in
   // the graph.
diff --git a/chrome/browser/performance_manager/decorators/page_aggregator.h b/chrome/browser/performance_manager/decorators/page_aggregator.h
index 0c6092f8..042bd76 100644
--- a/chrome/browser/performance_manager/decorators/page_aggregator.h
+++ b/chrome/browser/performance_manager/decorators/page_aggregator.h
@@ -39,6 +39,7 @@
   void OnFrameIsHoldingIndexedDBLockChanged(
       const FrameNode* frame_node) override;
   void OnHadFormInteractionChanged(const FrameNode* frame_node) override;
+  void OnHadUserEditsChanged(const FrameNode* frame_node) override;
 
   // GraphOwned implementation:
   void OnPassedToGraph(Graph* graph) override;
diff --git a/chrome/browser/policy/chrome_policy_conversions_client.cc b/chrome/browser/policy/chrome_policy_conversions_client.cc
index a6ed93c1..985f246 100644
--- a/chrome/browser/policy/chrome_policy_conversions_client.cc
+++ b/chrome/browser/policy/chrome_policy_conversions_client.cc
@@ -148,10 +148,9 @@
   }
   const scoped_refptr<SchemaMap> schema_map =
       schema_registry_service->registry()->schema_map();
-  std::unique_ptr<extensions::ExtensionSet> extension_set =
+  const extensions::ExtensionSet extension_set =
       registry->GenerateInstalledExtensionsSet();
-  for (const scoped_refptr<const extensions::Extension>& extension :
-       *extension_set) {
+  for (const auto& extension : extension_set) {
     // Skip this extension if it's not an enterprise extension.
     if (!extension->manifest()->FindPath(
             extensions::manifest_keys::kStorageManagedSchema)) {
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.h b/chrome/browser/policy/messaging_layer/public/report_client.h
index 00cbc4a..069e232 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client.h
+++ b/chrome/browser/policy/messaging_layer/public/report_client.h
@@ -40,6 +40,7 @@
   class Uploader;
 
   friend class ReportQueueProvider;
+  friend class RecordHandlerImpl;
   friend struct base::DefaultSingletonTraits<ReportingClient>;
 
   // Constructor to be used by singleton only.
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_test_util.cc b/chrome/browser/policy/messaging_layer/public/report_client_test_util.cc
index 3d49bd6..8b2c5f9 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client_test_util.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client_test_util.cc
@@ -4,16 +4,23 @@
 
 #include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
 
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/singleton.h"
+#include "base/strings/string_piece.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client.h"
+#include "components/reporting/storage/storage_module_interface.h"
+#include "components/reporting/storage/test_storage_module.h"
 
 namespace reporting {
 
-ReportingClient::TestEnvironment::TestEnvironment(
+// static
+std::unique_ptr<ReportingClient::TestEnvironment>
+ReportingClient::TestEnvironment::CreateWithLocalStorage(
     const base::FilePath& reporting_path,
-    base::StringPiece verification_key)
-    : saved_storage_create_cb_(
-          std::move(ReportingClient::GetInstance()->storage_create_cb_)) {
-  ReportingClient::GetInstance()->storage_create_cb_ = base::BindRepeating(
+    base::StringPiece verification_key) {
+  return base::WrapUnique(new TestEnvironment(base::BindRepeating(
       [](const base::FilePath& reporting_path,
          base::StringPiece verification_key,
          base::OnceCallback<void(
@@ -25,7 +32,28 @@
             base::BindRepeating(&ReportingClient::AsyncStartUploader),
             std::move(storage_created_cb));
       },
-      reporting_path, verification_key);
+      reporting_path, verification_key)));
+}
+
+// static
+std::unique_ptr<ReportingClient::TestEnvironment>
+ReportingClient::TestEnvironment::CreateWithStorageModule(
+    scoped_refptr<StorageModuleInterface> storage) {
+  return base::WrapUnique(new TestEnvironment(base::BindRepeating(
+      [](scoped_refptr<StorageModuleInterface> storage,
+         base::OnceCallback<void(
+             StatusOr<scoped_refptr<StorageModuleInterface>>)>
+             storage_created_cb) {
+        std::move(storage_created_cb).Run(storage);
+      },
+      storage)));
+}
+
+ReportingClient::TestEnvironment::TestEnvironment(
+    ReportingClient::StorageModuleCreateCallback storage_create_cb)
+    : saved_storage_create_cb_(
+          std::move(ReportingClient::GetInstance()->storage_create_cb_)) {
+  ReportingClient::GetInstance()->storage_create_cb_ = storage_create_cb;
 }
 
 ReportingClient::TestEnvironment::~TestEnvironment() {
@@ -33,5 +61,4 @@
       std::move(saved_storage_create_cb_);
   base::Singleton<ReportingClient>::OnExit(nullptr);
 }
-
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_test_util.h b/chrome/browser/policy/messaging_layer/public/report_client_test_util.h
index 97500de6..de4f41a2d 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client_test_util.h
+++ b/chrome/browser/policy/messaging_layer/public/report_client_test_util.h
@@ -8,18 +8,32 @@
 #include "base/files/file_path.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/policy/messaging_layer/public/report_client.h"
+#include "components/reporting/storage/storage_module_interface.h"
 
 namespace reporting {
 
 class ReportingClient::TestEnvironment {
  public:
+  // Factory method creates an environment with actual local storage at
+  // `reporting_path` location and with encryption support included.
+  static std::unique_ptr<TestEnvironment> CreateWithLocalStorage(
+      const base::FilePath& reporting_path,
+      base::StringPiece verification_key);
+
+  // Factory method creates an environment with a given storage module
+  // (usually it is `test::TestStorageModule`).
+  static std::unique_ptr<TestEnvironment> CreateWithStorageModule(
+      scoped_refptr<StorageModuleInterface> storage);
+
   TestEnvironment(const TestEnvironment& other) = delete;
   TestEnvironment& operator=(const TestEnvironment& other) = delete;
-  TestEnvironment(const base::FilePath& reporting_path,
-                  base::StringPiece verification_key);
   ~TestEnvironment();
 
  private:
+  // Constructor is only called by factory methods above.
+  explicit TestEnvironment(
+      ReportingClient::StorageModuleCreateCallback storage_create_cb);
+
   ReportingClient::StorageModuleCreateCallback saved_storage_create_cb_;
 };
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
index fdb4c04..ef3e899 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
@@ -88,7 +88,9 @@
 
     // Provide a mock cloud policy client.
     test_env_.client()->SetDMToken(kDMToken);
-    test_reporting_ = std::make_unique<ReportingClient::TestEnvironment>(
+
+    // Provide client test environment with local storage.
+    test_reporting_ = ReportingClient::TestEnvironment::CreateWithLocalStorage(
         base::FilePath(location_.GetPath()),
         base::StringPiece(
             reinterpret_cast<const char*>(signature_verification_public_key_),
diff --git a/chrome/browser/policy/messaging_layer/upload/file_upload_job.cc b/chrome/browser/policy/messaging_layer/upload/file_upload_job.cc
index 251e8f2c..9943f25 100644
--- a/chrome/browser/policy/messaging_layer/upload/file_upload_job.cc
+++ b/chrome/browser/policy/messaging_layer/upload/file_upload_job.cc
@@ -318,6 +318,11 @@
                                  access_parameters.size());
 }
 
+bool FileUploadJob::in_action() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(job_sequence_checker_);
+  return in_action_;
+}
+
 const UploadSettings& FileUploadJob::settings() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(job_sequence_checker_);
   return settings_;
diff --git a/chrome/browser/policy/messaging_layer/upload/file_upload_job.h b/chrome/browser/policy/messaging_layer/upload/file_upload_job.h
index f03ece03..f9b931c 100644
--- a/chrome/browser/policy/messaging_layer/upload/file_upload_job.h
+++ b/chrome/browser/policy/messaging_layer/upload/file_upload_job.h
@@ -154,6 +154,7 @@
   void Finalize(base::OnceClosure done_cb = base::DoNothing());
 
   // Accessors.
+  bool in_action() const;
   const UploadSettings& settings() const;
   const UploadTracker& tracker() const;
   base::WeakPtr<FileUploadJob> GetWeakPtr();
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
index 57835fa3..e8dd384 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
@@ -77,10 +77,13 @@
   return priority;
 }
 
-// Reposts updated copy of LOG_UPLOAD event. Called back once the FileUploadJob
-// is located/created.
+// Called once the FileUploadJob is located/created and processed by RunJob.
+// Calling `done_cb` with OK will allow the uploader to include the current
+// event, so before that if we intend to proceed with the job, the new event
+// needs to be posted.
+// Calling `done_cb` with any other status stops the upload before the current
+// event, so no new event should be posted in this case.
 void RepostLogUploadEvent(base::WeakPtr<FileUploadJob> job,
-                          scoped_refptr<StorageModuleInterface> storage,
                           Priority priority,
                           Record record_copy,
                           ::ash::reporting::LogUploadEvent log_upload_event,
@@ -92,7 +95,7 @@
         Status(error::DATA_LOSS, "Upload Job has been removed"));
     return;
   }
-  // Job is still around.
+  // Job is still around. Update the new event with its status.
   if (job->tracker().access_parameters().empty() &&
       !job->tracker().has_status()) {
     // The job is in progress (not succeeded and not failed),
@@ -113,7 +116,8 @@
   }
   // Repost the copy event, and if succeeded, `done_cb` will allow the current
   // event to be uploaded.
-  storage->AddRecord(priority, std::move(record_copy), std::move(done_cb));
+  RecordHandlerImpl::AddRecordToStorage(priority, std::move(record_copy),
+                                        std::move(done_cb));
 }
 
 // FileUploadJob progresses based on the last recorded state.
@@ -167,13 +171,14 @@
 
 // Processes LOG_UPLOAD event.
 void ProcessFileUpload(FileUploadJob::Delegate* delegate,
-                       scoped_refptr<StorageModuleInterface> storage,
                        Priority priority,
                        Record record_copy,
                        base::OnceCallback<void(Status)> done_cb) {
   // Here we need to determine which events we got. It would be better to
   // use protobuf reflection and detect upload_settings presence in the event,
   // but protobuf_lite library included in Chrome does not expose reflection.
+  // `done_cb` called with OK causes the event to upload and then uploader picks
+  // up the next event. Any other status stops the upload before the event.
   switch (record_copy.destination()) {
     case LOG_UPLOAD: {
       // Parse `record_copy.data()` string into the event.
@@ -186,6 +191,14 @@
         std::move(done_cb).Run(Status::StatusOK());
         return;
       }
+      if (log_upload_event.has_upload_tracker() &&
+          (!log_upload_event.upload_tracker().access_parameters().empty() ||
+           log_upload_event.upload_tracker().has_status())) {
+        // The event already reports job as completed (succeeded or failed),
+        // upload it with no further processing.
+        std::move(done_cb).Run(Status::StatusOK());
+        return;
+      }
       // Check whether this upload is already being processed, based on the
       // whole `upload_settings` (including retry count).
       const auto settings = log_upload_event.upload_settings();
@@ -195,7 +208,6 @@
           base::BindOnce(
               [](Priority priority, Record record,
                  ::ash::reporting::LogUploadEvent log_upload_event,
-                 scoped_refptr<StorageModuleInterface> storage,
                  base::OnceCallback<void(Status)> done_cb,
                  StatusOr<FileUploadJob*> job_or_error) {
                 if (!job_or_error.ok()) {
@@ -207,12 +219,38 @@
                 }
                 // Job has been located or created.
                 auto* const job = job_or_error.ValueOrDie();
-                // Prepare a callback that will repost event with updates based
-                // on the job status, if it is still available. It will be
-                // invoked on the sequenced_task_runner of the job manager,
-                // so we can use weak pointer there.
+                if (job->in_action()) {
+                  // The job already executes, the event we are dealing with
+                  // is likely the one that caused this, do not upload it
+                  // (otherwise we would lose track of the job if the device
+                  // restarts).
+                  std::move(done_cb).Run(
+                      Status(error::ALREADY_EXISTS, "Duplicate event"));
+                  return;
+                }
+                if (job->tracker().has_status()) {
+                  // The job already failed before.
+                  // Upload the event as is.
+                  std::move(done_cb).Run(Status::StatusOK());
+                  return;
+                }
+                if (!job->tracker().access_parameters().empty()) {
+                  // Job complete, nothing left to do.
+                  // Upload the event as is.
+                  std::move(done_cb).Run(Status::StatusOK());
+                  return;
+                }
+
+                // Prepare a callback that will either
+                // 1) repost event with updates based on the job status,
+                //    if the job is still available, and allow the current event
+                //    to proceed,
+                // or
+                // 2) stop uploading before the current event.
+                // The callback will be invoked on the sequenced_task_runner of
+                // the job manager, so we can use weak pointer there.
                 auto processed_cb = base::BindOnce(
-                    &RepostLogUploadEvent, job->GetWeakPtr(), storage, priority,
+                    &RepostLogUploadEvent, job->GetWeakPtr(), priority,
                     std::move(record), log_upload_event,  // Copy, not move!
                     std::move(done_cb));
                 // Run the next step.
@@ -220,7 +258,7 @@
                        std::move(processed_cb));
               },
               priority, std::move(record_copy), std::move(log_upload_event),
-              storage, std::move(done_cb)));
+              std::move(done_cb)));
       break;
     }
     default:
@@ -238,7 +276,6 @@
  public:
   ReportUploader(
       FileUploadJob::Delegate* delegate,
-      scoped_refptr<StorageModuleInterface> storage,
       bool need_encryption_key,
       std::vector<EncryptedRecord> records,
       ScopedReservation scoped_reservation,
@@ -278,8 +315,6 @@
 
   const raw_ptr<FileUploadJob::Delegate> delegate_;
 
-  const scoped_refptr<StorageModuleInterface> storage_;
-
   bool need_encryption_key_ GUARDED_BY_CONTEXT(sequence_checker_);
   std::vector<EncryptedRecord> records_ GUARDED_BY_CONTEXT(sequence_checker_);
   ScopedReservation scoped_reservation_ GUARDED_BY_CONTEXT(sequence_checker_);
@@ -303,7 +338,6 @@
 
 RecordHandlerImpl::ReportUploader::ReportUploader(
     FileUploadJob::Delegate* delegate,
-    scoped_refptr<StorageModuleInterface> storage,
     bool need_encryption_key,
     std::vector<EncryptedRecord> records,
     ScopedReservation scoped_reservation,
@@ -313,7 +347,6 @@
     : TaskRunnerContext<CompletionResponse>(std::move(completion_cb),
                                             sequenced_task_runner),
       delegate_(delegate),
-      storage_(storage),
       need_encryption_key_(need_encryption_key),
       records_(std::move(records)),
       scoped_reservation_(std::move(scoped_reservation)),
@@ -359,11 +392,12 @@
   while (next_record < records_.size()) {
     auto& record = records_.at(next_record++);
     if (!record.has_record_copy()) {
-      // Regular event, add it and proceed.
+      // Regular event, add it for upload and proceed.
       request_builder_->AddRecord(std::move(record), scoped_reservation_);
       continue;
     }
-    // Upload event, attempt to asynchronously process it.
+    // Asynchronously process event, add it for upload and proceed if
+    // successful.
     const auto priority = record.sequence_information().priority();
     auto record_copy = std::move(*record.mutable_record_copy());
     record.clear_record_copy();
@@ -389,8 +423,7 @@
     base::ThreadPool::PostTask(
         FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
         base::BindOnce(&ProcessFileUpload, base::Unretained(delegate_.get()),
-                       storage_, priority, std::move(record_copy),
-                       std::move(resume_cb)));
+                       priority, std::move(record_copy), std::move(resume_cb)));
     return;  // We will resume on `resume_cb`
   }
 
@@ -662,11 +695,9 @@
 
 RecordHandlerImpl::RecordHandlerImpl(
     scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner,
-    std::unique_ptr<FileUploadJob::Delegate> delegate,
-    scoped_refptr<StorageModuleInterface> storage)
+    std::unique_ptr<FileUploadJob::Delegate> delegate)
     : sequenced_task_runner_(sequenced_task_runner),
-      delegate_(std::move(delegate)),
-      storage_(storage) {}
+      delegate_(std::move(delegate)) {}
 
 RecordHandlerImpl::~RecordHandlerImpl() = default;
 
@@ -677,9 +708,28 @@
     CompletionCallback upload_complete_cb,
     EncryptionKeyAttachedCallback encryption_key_attached_cb) {
   Start<RecordHandlerImpl::ReportUploader>(
-      delegate_.get(), storage_, need_encryption_key, std::move(records),
+      delegate_.get(), need_encryption_key, std::move(records),
       std::move(scoped_reservation), std::move(upload_complete_cb),
       std::move(encryption_key_attached_cb), sequenced_task_runner_);
 }
 
+// static
+void RecordHandlerImpl::AddRecordToStorage(
+    Priority priority,
+    Record record_copy,
+    base::OnceCallback<void(Status)> done_cb) {
+  ReportingClient::GetInstance()->sequenced_task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(
+                     [](Priority priority, Record record_copy,
+                        base::OnceCallback<void(Status)> done_cb) {
+                       // We can only get to here from upload, which originates
+                       // from Storage Module, so `storage()` below cannot be
+                       // null.
+                       DCHECK(ReportingClient::GetInstance()->storage());
+                       ReportingClient::GetInstance()->storage()->AddRecord(
+                           priority, std::move(record_copy),
+                           std::move(done_cb));
+                     },
+                     priority, std::move(record_copy), std::move(done_cb)));
+}
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h
index 7d3e174..169ed3e 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.h
@@ -18,7 +18,6 @@
 #include "chrome/browser/policy/messaging_layer/upload/file_upload_job.h"
 #include "components/reporting/proto/synced/record.pb.h"
 #include "components/reporting/resources/resource_manager.h"
-#include "components/reporting/storage/storage_module_interface.h"
 #include "components/reporting/util/status.h"
 #include "components/reporting/util/statusor.h"
 
@@ -32,8 +31,7 @@
  public:
   RecordHandlerImpl(
       scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner,
-      std::unique_ptr<FileUploadJob::Delegate> delegate,
-      scoped_refptr<StorageModuleInterface> storage);
+      std::unique_ptr<FileUploadJob::Delegate> delegate);
   ~RecordHandlerImpl() override;
 
   // Base class RecordHandler method implementation.
@@ -44,6 +42,12 @@
       CompletionCallback upload_complete,
       EncryptionKeyAttachedCallback encryption_key_attached_cb) override;
 
+  // Helper method adds a record to the default storage on ReportClient task
+  // runner and calls `done_cb` with the result..
+  static void AddRecordToStorage(Priority priority,
+                                 Record record_copy,
+                                 base::OnceCallback<void(Status)> done_cb);
+
  private:
   // Helper `ReportUploader` class handles events being uploaded.
   class ReportUploader;
@@ -52,7 +56,6 @@
 
   // The next two fields are only used for LOG_UPLOAD events.
   const std::unique_ptr<FileUploadJob::Delegate> delegate_;
-  scoped_refptr<StorageModuleInterface> storage_;
 };
 
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
index 8e0d4c4c..07c95f48 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
@@ -17,6 +17,8 @@
 #include "base/task/thread_pool.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
 #include "chrome/browser/policy/messaging_layer/upload/dm_server_uploader.h"
 #include "chrome/browser/policy/messaging_layer/upload/file_upload_job.h"
 #include "chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h"
@@ -107,8 +109,10 @@
  protected:
   void SetUp() override {
     handler_ = std::make_unique<RecordHandlerImpl>(
-        sequenced_task_runner_, std::make_unique<MockFileUploadDelegate>(),
-        base::MakeRefCounted<test::TestStorageModule>());
+        sequenced_task_runner_, std::make_unique<MockFileUploadDelegate>());
+    test_storage_ = base::MakeRefCounted<test::TestStorageModule>();
+    test_reporting_ = ReportingClient::TestEnvironment::CreateWithStorageModule(
+        test_storage_);
 
     memory_resource_ =
         base::MakeRefCounted<ResourceManager>(4u * 1024LLu * 1024LLu);  // 4 MiB
@@ -116,6 +120,8 @@
 
   void TearDown() override {
     handler_.reset();
+    test_reporting_.reset();
+    test_storage_.reset();
     EXPECT_THAT(memory_resource_->GetUsed(), Eq(0uL));
   }
 
@@ -129,6 +135,9 @@
 
   ReportingServerConnector::TestEnvironment test_env_;
 
+  scoped_refptr<test::TestStorageModule> test_storage_;
+  std::unique_ptr<ReportingClient::TestEnvironment> test_reporting_;
+
   std::unique_ptr<RecordHandlerImpl> handler_;
 
   scoped_refptr<ResourceManager> memory_resource_;
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_upload_unittest.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_upload_unittest.cc
index b03cf86..2232902 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_upload_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_upload_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chrome/browser/policy/messaging_layer/proto/synced/log_upload_event.pb.h"
+#include "chrome/browser/policy/messaging_layer/public/report_client_test_util.h"
 #include "chrome/browser/policy/messaging_layer/upload/dm_server_uploader.h"
 #include "chrome/browser/policy/messaging_layer/upload/file_upload_job.h"
 #include "chrome/browser/policy/messaging_layer/upload/file_upload_job_test_util.h"
@@ -117,11 +118,46 @@
 class RecordHandlerUploadTest : public ::testing::Test {
  protected:
   void SetUp() override {
+    test_storage_ = base::MakeRefCounted<test::TestStorageModule>();
+    test_reporting_ = ReportingClient::TestEnvironment::CreateWithStorageModule(
+        test_storage_);
+    auto delegate = std::make_unique<MockFileUploadDelegate>();
+    delegate_ = delegate.get();
+    handler_ = std::make_unique<RecordHandlerImpl>(sequenced_task_runner_,
+                                                   std::move(delegate));
+
     memory_resource_ =
         base::MakeRefCounted<ResourceManager>(4u * 1024LLu * 1024LLu);  // 4 MiB
+
+    // Create a queue and post event, in order to let ReportClient set storage.
+    auto config_result = ReportQueueConfiguration::Create(
+        EventType::kDevice, LOG_UPLOAD,
+        /*policy_check_callback=*/base::BindRepeating([]() {
+          return Status::StatusOK();
+        }));
+    EXPECT_OK(config_result) << config_result.status();
+    test::TestEvent<StatusOr<std::unique_ptr<ReportQueue>>> create_queue_event;
+    ReportQueueProvider::CreateQueue(std::move(config_result.ValueOrDie()),
+                                     create_queue_event.cb());
+    auto report_queue_result = create_queue_event.result();
+    // Let everything ongoing to finish.
+    task_environment_.RunUntilIdle();
+    ASSERT_OK(report_queue_result) << report_queue_result.status();
+
+    // Enqueue event.
+    test::TestEvent<Status> enqueue_record_event;
+    std::move(report_queue_result.ValueOrDie())
+        ->Enqueue("Record", FAST_BATCH, enqueue_record_event.cb());
+    const auto enqueue_record_result = enqueue_record_event.result();
+    EXPECT_OK(enqueue_record_result) << enqueue_record_result;
   }
 
   void TearDown() override {
+    delegate_ = nullptr;
+    handler_.reset();
+    test_storage_.reset();
+    test_reporting_.reset();
+
     EXPECT_THAT(memory_resource_->GetUsed(), Eq(0uL));
   }
 
@@ -133,6 +169,13 @@
   FileUploadJob::TestEnvironment manager_test_env_;
   ReportingServerConnector::TestEnvironment test_env_;
 
+  scoped_refptr<test::TestStorageModule> test_storage_;
+  std::unique_ptr<ReportingClient::TestEnvironment> test_reporting_;
+
+  raw_ptr<MockFileUploadDelegate> delegate_;
+
+  std::unique_ptr<RecordHandlerImpl> handler_;
+
   scoped_refptr<ResourceManager> memory_resource_;
 };
 
@@ -243,8 +286,7 @@
   test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
   test::TestEvent<CompletionResponse> responder_event;
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate(StrEq("/tmp/file"), Not(IsEmpty()), _))
+  EXPECT_CALL(*delegate_, DoInitiate(StrEq("/tmp/file"), Not(IsEmpty()), _))
       .WillOnce(Invoke(
           [](base::StringPiece origin_path, base::StringPiece upload_parameters,
              base::OnceCallback<void(
@@ -252,11 +294,10 @@
                                     std::string /*session_token*/>>)> cb) {
             std::move(cb).Run(std::make_pair(300L, "ABC"));
           }));
-  EXPECT_CALL(*delegate, DoNextStep).Times(0);
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .WillOnce(Invoke([](Priority priority, Record record,
                           StorageModuleInterface::EnqueueCallback callback) {
         EXPECT_TRUE(record.needs_local_unencrypted_copy());
@@ -270,12 +311,10 @@
         std::move(callback).Run(Status::StatusOK());
       }));
 
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
-  handler.HandleRecords(/*need_encryption_key=*/false,
-                        std::vector(1, std::move(init_encrypted_record)),
-                        std::move(record_reservation), responder_event.cb(),
-                        encryption_key_attached_event.repeating_cb());
+  handler_->HandleRecords(/*need_encryption_key=*/false,
+                          std::vector(1, std::move(init_encrypted_record)),
+                          std::move(record_reservation), responder_event.cb(),
+                          encryption_key_attached_event.repeating_cb());
   auto response = responder_event.result();
   EXPECT_THAT(response, ResponseEquals(expected_response));
 }
@@ -298,9 +337,8 @@
   test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
   test::TestEvent<CompletionResponse> responder_event;
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
       .WillOnce(
           [](int64_t total, int64_t uploaded, base::StringPiece session_token,
              base::OnceCallback<void(
@@ -309,10 +347,9 @@
             std::move(cb).Run(
                 std::make_pair(uploaded + 100L, std::string(session_token)));
           });
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .WillOnce(Invoke([](Priority priority, Record record,
                           StorageModuleInterface::EnqueueCallback callback) {
         EXPECT_TRUE(record.needs_local_unencrypted_copy());
@@ -325,12 +362,10 @@
         EXPECT_FALSE(log_upload_event.upload_tracker().has_status());
         std::move(callback).Run(Status::StatusOK());
       }));
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
-  handler.HandleRecords(/*need_encryption_key=*/false,
-                        std::vector(1, std::move(next_step_encrypted_record)),
-                        std::move(record_reservation), responder_event.cb(),
-                        encryption_key_attached_event.repeating_cb());
+  handler_->HandleRecords(/*need_encryption_key=*/false,
+                          std::vector(1, std::move(next_step_encrypted_record)),
+                          std::move(record_reservation), responder_event.cb(),
+                          encryption_key_attached_event.repeating_cb());
   auto response = responder_event.result();
   EXPECT_THAT(response, ResponseEquals(expected_response));
 }
@@ -353,10 +388,9 @@
   test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
   test::TestEvent<CompletionResponse> responder_event;
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep).Times(0);
-  EXPECT_CALL(*delegate, DoFinalize(StrEq("ABC"), _))
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize(StrEq("ABC"), _))
       .WillOnce(
           Invoke([](base::StringPiece session_token,
                     base::OnceCallback<void(
@@ -364,8 +398,7 @@
             std::move(cb).Run("http://destination");
           }));
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .WillOnce(Invoke([](Priority priority, Record record,
                           StorageModuleInterface::EnqueueCallback callback) {
         EXPECT_FALSE(record.needs_local_unencrypted_copy());
@@ -378,12 +411,10 @@
         EXPECT_FALSE(log_upload_event.upload_tracker().has_status());
         std::move(callback).Run(Status::StatusOK());
       }));
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
-  handler.HandleRecords(/*need_encryption_key=*/false,
-                        std::vector(1, std::move(fin_encrypted_record)),
-                        std::move(record_reservation), responder_event.cb(),
-                        encryption_key_attached_event.repeating_cb());
+  handler_->HandleRecords(/*need_encryption_key=*/false,
+                          std::vector(1, std::move(fin_encrypted_record)),
+                          std::move(record_reservation), responder_event.cb(),
+                          encryption_key_attached_event.repeating_cb());
   auto response = responder_event.result();
   EXPECT_THAT(response, ResponseEquals(expected_response));
 }
@@ -406,32 +437,16 @@
   test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
   test::TestEvent<CompletionResponse> responder_event;
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep).Times(0);
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
-      .WillOnce(Invoke([](Priority priority, Record record,
-                          StorageModuleInterface::EnqueueCallback callback) {
-        EXPECT_FALSE(record.needs_local_unencrypted_copy());
-        LogUploadEvent log_upload_event;
-        EXPECT_TRUE(log_upload_event.ParseFromArray(record.data().data(),
-                                                    record.data().size()));
-        EXPECT_THAT(log_upload_event,
-                    AllOf(MatchSettings(),
-                          MatchTrackerFinished(300L, "http://destination")));
-        EXPECT_FALSE(log_upload_event.upload_tracker().has_status());
-        std::move(callback).Run(Status::StatusOK());
-      }));
+  EXPECT_CALL(*test_storage_, AddRecord).Times(0);
 
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
-  handler.HandleRecords(/*need_encryption_key=*/false,
-                        std::vector(1, std::move(fin_encrypted_record)),
-                        std::move(record_reservation), responder_event.cb(),
-                        encryption_key_attached_event.repeating_cb());
+  handler_->HandleRecords(/*need_encryption_key=*/false,
+                          std::vector(1, std::move(fin_encrypted_record)),
+                          std::move(record_reservation), responder_event.cb(),
+                          encryption_key_attached_event.repeating_cb());
   auto response = responder_event.result();
   EXPECT_THAT(response, ResponseEquals(expected_response));
 }
@@ -454,9 +469,8 @@
   test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
   test::TestEvent<CompletionResponse> responder_event;
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
       .WillOnce(
           [](int64_t total, int64_t uploaded, base::StringPiece session_token,
              base::OnceCallback<void(
@@ -464,10 +478,9 @@
                                     std::string /*session_token*/>>)> cb) {
             std::move(cb).Run(Status(error::CANCELLED, "Failure by test"));
           });
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .WillOnce(Invoke([](Priority priority, Record record,
                           StorageModuleInterface::EnqueueCallback callback) {
         EXPECT_FALSE(record.needs_local_unencrypted_copy());
@@ -480,12 +493,10 @@
                   MatchError(Status(error::CANCELLED, "Failure by test"))));
         std::move(callback).Run(Status::StatusOK());
       }));
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
-  handler.HandleRecords(/*need_encryption_key=*/false,
-                        std::vector(1, std::move(next_step_encrypted_record)),
-                        std::move(record_reservation), responder_event.cb(),
-                        encryption_key_attached_event.repeating_cb());
+  handler_->HandleRecords(/*need_encryption_key=*/false,
+                          std::vector(1, std::move(next_step_encrypted_record)),
+                          std::move(record_reservation), responder_event.cb(),
+                          encryption_key_attached_event.repeating_cb());
   auto response = responder_event.result();
   EXPECT_THAT(response, ResponseEquals(expected_response));
 }
@@ -505,8 +516,7 @@
       .WillRepeatedly(MakeUploadEncryptedReportAction(
           std::move(ResponseBuilder().SetSuccess(true))));
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate(StrEq("/tmp/file"), Not(IsEmpty()), _))
+  EXPECT_CALL(*delegate_, DoInitiate(StrEq("/tmp/file"), Not(IsEmpty()), _))
       .WillOnce(Invoke(
           [](base::StringPiece origin_path, base::StringPiece upload_parameters,
              base::OnceCallback<void(
@@ -514,11 +524,10 @@
                                     std::string /*session_token*/>>)> cb) {
             std::move(cb).Run(std::make_pair(300L, "ABC"));
           }));
-  EXPECT_CALL(*delegate, DoNextStep).Times(0);
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .Times(kNumTestRecords)
       .WillRepeatedly(
           Invoke([](Priority priority, Record record,
@@ -534,17 +543,15 @@
             std::move(callback).Run(Status::StatusOK());
           }));
 
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
   for (size_t i = 0; i < kNumTestRecords; ++i) {
     ScopedReservation record_reservation(init_encrypted_record.ByteSizeLong(),
                                          memory_resource_);
     test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
     test::TestEvent<CompletionResponse> responder_event;
-    handler.HandleRecords(/*need_encryption_key=*/false,
-                          std::vector(1, init_encrypted_record),
-                          std::move(record_reservation), responder_event.cb(),
-                          encryption_key_attached_event.repeating_cb());
+    handler_->HandleRecords(/*need_encryption_key=*/false,
+                            std::vector(1, init_encrypted_record),
+                            std::move(record_reservation), responder_event.cb(),
+                            encryption_key_attached_event.repeating_cb());
     auto response = responder_event.result();
     EXPECT_THAT(response, ResponseEquals(expected_response));
     init_encrypted_record.mutable_sequence_information()->set_sequencing_id(
@@ -570,9 +577,8 @@
       .WillRepeatedly(MakeUploadEncryptedReportAction(
           std::move(ResponseBuilder().SetSuccess(true))));
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep(Eq(300L), Eq(100L), StrEq("ABC"), _))
       .WillOnce(
           [](int64_t total, int64_t uploaded, base::StringPiece session_token,
              base::OnceCallback<void(
@@ -581,10 +587,9 @@
             std::move(cb).Run(
                 std::make_pair(uploaded + 100L, std::string(session_token)));
           });
-  EXPECT_CALL(*delegate, DoFinalize).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize).Times(0);
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
       .Times(kNumTestRecords)
       .WillRepeatedly(
           Invoke([](Priority priority, Record record,
@@ -600,17 +605,15 @@
             std::move(callback).Run(Status::StatusOK());
           }));
 
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
   for (size_t i = 0; i < kNumTestRecords; ++i) {
     ScopedReservation record_reservation(
         next_step_encrypted_record.ByteSizeLong(), memory_resource_);
     test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
     test::TestEvent<CompletionResponse> responder_event;
-    handler.HandleRecords(/*need_encryption_key=*/false,
-                          std::vector(1, next_step_encrypted_record),
-                          std::move(record_reservation), responder_event.cb(),
-                          encryption_key_attached_event.repeating_cb());
+    handler_->HandleRecords(/*need_encryption_key=*/false,
+                            std::vector(1, next_step_encrypted_record),
+                            std::move(record_reservation), responder_event.cb(),
+                            encryption_key_attached_event.repeating_cb());
     auto response = responder_event.result();
     EXPECT_THAT(response, ResponseEquals(expected_response));
     next_step_encrypted_record.mutable_sequence_information()
@@ -638,10 +641,9 @@
       .WillRepeatedly(MakeUploadEncryptedReportAction(
           std::move(ResponseBuilder().SetSuccess(true))));
 
-  auto delegate = std::make_unique<MockFileUploadDelegate>();
-  EXPECT_CALL(*delegate, DoInitiate).Times(0);
-  EXPECT_CALL(*delegate, DoNextStep).Times(0);
-  EXPECT_CALL(*delegate, DoFinalize(StrEq("ABC"), _))
+  EXPECT_CALL(*delegate_, DoInitiate).Times(0);
+  EXPECT_CALL(*delegate_, DoNextStep).Times(0);
+  EXPECT_CALL(*delegate_, DoFinalize(StrEq("ABC"), _))
       .WillOnce(
           Invoke([](base::StringPiece session_token,
                     base::OnceCallback<void(
@@ -649,35 +651,30 @@
             std::move(cb).Run("http://destination");
           }));
 
-  auto storage = base::MakeRefCounted<test::TestStorageModule>();
-  EXPECT_CALL(*storage, AddRecord(Eq(Priority::IMMEDIATE), _, _))
-      .Times(kNumTestRecords)
-      .WillRepeatedly(
-          Invoke([](Priority priority, Record record,
-                    StorageModuleInterface::EnqueueCallback callback) {
-            EXPECT_FALSE(record.needs_local_unencrypted_copy());
-            LogUploadEvent log_upload_event;
-            EXPECT_TRUE(log_upload_event.ParseFromArray(record.data().data(),
-                                                        record.data().size()));
-            EXPECT_THAT(
-                log_upload_event,
-                AllOf(MatchSettings(),
-                      MatchTrackerFinished(300L, "http://destination")));
-            EXPECT_FALSE(log_upload_event.upload_tracker().has_status());
-            std::move(callback).Run(Status::StatusOK());
-          }));
+  // Record added only once!
+  EXPECT_CALL(*test_storage_, AddRecord(Eq(Priority::IMMEDIATE), _, _))
+      .WillOnce(Invoke([](Priority priority, Record record,
+                          StorageModuleInterface::EnqueueCallback callback) {
+        EXPECT_FALSE(record.needs_local_unencrypted_copy());
+        LogUploadEvent log_upload_event;
+        EXPECT_TRUE(log_upload_event.ParseFromArray(record.data().data(),
+                                                    record.data().size()));
+        EXPECT_THAT(log_upload_event,
+                    AllOf(MatchSettings(),
+                          MatchTrackerFinished(300L, "http://destination")));
+        EXPECT_FALSE(log_upload_event.upload_tracker().has_status());
+        std::move(callback).Run(Status::StatusOK());
+      }));
 
-  RecordHandlerImpl handler(sequenced_task_runner_, std::move(delegate),
-                            storage);
   for (size_t i = 0; i < kNumTestRecords; ++i) {
     ScopedReservation record_reservation(fin_encrypted_record.ByteSizeLong(),
                                          memory_resource_);
     test::TestEvent<SignedEncryptionInfo> encryption_key_attached_event;
     test::TestEvent<CompletionResponse> responder_event;
-    handler.HandleRecords(/*need_encryption_key=*/false,
-                          std::vector(1, fin_encrypted_record),
-                          std::move(record_reservation), responder_event.cb(),
-                          encryption_key_attached_event.repeating_cb());
+    handler_->HandleRecords(/*need_encryption_key=*/false,
+                            std::vector(1, fin_encrypted_record),
+                            std::move(record_reservation), responder_event.cb(),
+                            encryption_key_attached_event.repeating_cb());
     auto response = responder_event.result();
     EXPECT_THAT(response, ResponseEquals(expected_response));
     fin_encrypted_record.mutable_sequence_information()->set_sequencing_id(
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client.cc b/chrome/browser/policy/messaging_layer/upload/upload_client.cc
index 7b6659f..ca839624 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_client.cc
+++ b/chrome/browser/policy/messaging_layer/upload/upload_client.cc
@@ -50,8 +50,7 @@
     : sequenced_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()),
       handler_(std::make_unique<RecordHandlerImpl>(
           sequenced_task_runner_,
-          std::make_unique<FileUploadDelegate>(),
-          ReportQueueProvider::GetInstance()->storage())) {}
+          std::make_unique<FileUploadDelegate>())) {}
 
 UploadClient::~UploadClient() = default;
 
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client.h b/chrome/browser/policy/messaging_layer/upload/upload_client.h
index dc90550..6b560f1 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_client.h
+++ b/chrome/browser/policy/messaging_layer/upload/upload_client.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <vector>
 
-#include "base/task/task_runner.h"
+#include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/policy/messaging_layer/upload/dm_server_uploader.h"
 #include "components/reporting/proto/synced/record.pb.h"
 #include "components/reporting/resources/resource_manager.h"
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_provider.cc b/chrome/browser/policy/messaging_layer/upload/upload_provider.cc
index f23143b..0d7b6d7 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_provider.cc
+++ b/chrome/browser/policy/messaging_layer/upload/upload_provider.cc
@@ -104,7 +104,8 @@
 
   // Upload client (protected by sequenced task runner). Once set, is used
   // repeatedly.
-  std::unique_ptr<UploadClient> upload_client_;
+  std::unique_ptr<UploadClient> upload_client_
+      GUARDED_BY_CONTEXT(sequenced_task_checker_);
 
   // Keep this last so that all weak pointers will be invalidated at the
   // beginning of destruction.
diff --git a/chrome/browser/policy/value_provider/extension_policies_value_provider.cc b/chrome/browser/policy/value_provider/extension_policies_value_provider.cc
index e847384e..23c86f46 100644
--- a/chrome/browser/policy/value_provider/extension_policies_value_provider.cc
+++ b/chrome/browser/policy/value_provider/extension_policies_value_provider.cc
@@ -120,11 +120,10 @@
 
   const extensions::ExtensionRegistry* registry =
       extensions::ExtensionRegistry::Get(extension_profile);
-  std::unique_ptr<extensions::ExtensionSet> extension_set =
+  const extensions::ExtensionSet extension_set =
       registry->GenerateInstalledExtensionsSet();
 
-  for (const scoped_refptr<const extensions::Extension>& extension :
-       *extension_set) {
+  for (const auto& extension : extension_set) {
     // Skip this extension if it's not an enterprise extension.
     if (!ContainsStorageManagedSchema(extension.get())) {
       continue;
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index 038e363..7e18844f 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -259,6 +259,12 @@
      */
     public static final String DESKTOP_SITE_EXCEPTIONS_DOWNGRADE_TAB_SETTING_SET =
             "Chrome.RequestDesktopSiteExceptionsDowngrade.TabSettingSet";
+    /**
+     * Indicates display spec when the device is added to the default-on cohort for the desktop site
+     * global setting experiment.
+     */
+    public static final String DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC =
+            "Chrome.RequestDesktopSiteGlobalSetting.DefaultOnCohortDisplaySpec";
 
     public static final String DOWNLOAD_AUTO_RESUMPTION_ATTEMPT_LEFT = "ResumptionAttemptLeft";
     public static final String DOWNLOAD_FOREGROUND_SERVICE_OBSERVERS = "ForegroundServiceObservers";
@@ -1034,6 +1040,7 @@
                 DEFAULT_ENABLE_DESKTOP_SITE_GLOBAL_SETTING_COHORT,
                 DESKTOP_SITE_EXCEPTIONS_DOWNGRADE_GLOBAL_SETTING_ENABLED,
                 DESKTOP_SITE_EXCEPTIONS_DOWNGRADE_TAB_SETTING_SET,
+                DESKTOP_SITE_GLOBAL_SETTING_DEFAULT_ON_COHORT_DISPLAY_SPEC,
                 DESKTOP_SITE_GLOBAL_SETTING_OPT_IN_MESSAGE_COHORT,
                 DOWNLOAD_INTERSTITIAL_DOWNLOAD_PENDING_REMOVAL,
                 EXPLORE_OFFLINE_CONTENT_AVAILABILITY_STATUS,
diff --git a/chrome/browser/profiles/pref_service_builder_utils.cc b/chrome/browser/profiles/pref_service_builder_utils.cc
index be62f35..41978a9 100644
--- a/chrome/browser/profiles/pref_service_builder_utils.cc
+++ b/chrome/browser/profiles/pref_service_builder_utils.cc
@@ -62,8 +62,7 @@
   std::string product_name = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
   std::string readme_text = base::StringPrintf(
       kReadmeText, product_name.c_str(), product_name.c_str());
-  if (base::WriteFile(readme_path, readme_text.data(), readme_text.size()) ==
-      -1) {
+  if (!base::WriteFile(readme_path, readme_text)) {
     LOG(ERROR) << "Could not create README file.";
   }
 }
diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc
index 838fee18..51b9338 100644
--- a/chrome/browser/profiles/profile_attributes_storage.cc
+++ b/chrome/browser/profiles/profile_attributes_storage.cc
@@ -128,8 +128,7 @@
     return false;
   }
 
-  if (base::WriteFile(image_path, reinterpret_cast<char*>(&(*data)[0]),
-                      data->size()) == -1) {
+  if (!base::WriteFile(image_path, *data)) {
     LOG(ERROR) << "Failed to save image to file.";
     return false;
   }
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
index 0d5add7..137bb0c 100644
--- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc
+++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -1487,7 +1487,7 @@
       "\x24\x00\x00\x00\x0A\x49\x44\x41\x54\x08\x1D\x63\x60\x00\x00\x00"
       "\x02\x00\x01\xCF\xC8\x35\xE5\x00\x00\x00\x00\x49\x45\x4E\x44\xAE"
       "\x42\x60\x82";
-  base::WriteFile(icon_path, bitmap, sizeof(bitmap));
+  base::WriteFile(icon_path, base::StringPiece(bitmap, sizeof(bitmap)));
   ASSERT_TRUE(base::PathExists(icon_path));
 
   // Add a new profile.
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
index 5c80de02..6908446 100644
--- a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
@@ -7,7 +7,7 @@
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {Cluster} from '../../history_cluster_types.mojom-webui.js';
+import {Cluster, URLVisit} from '../../history_cluster_types.mojom-webui.js';
 import {I18nMixin} from '../../i18n_setup.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
@@ -65,16 +65,15 @@
   const element = new HistoryClustersModuleElement();
   element.cluster = data.cluster!;
 
+  // History cluster visits include a visit entry for the SRP, which is intended
+  // to be used for the module header's title and for opening the cluster in a
+  // tab group.
   const visits = element.cluster.visits;
   // Count number of visits with images.
-  const imageCount = visits
-                         .filter((visit) => {
-                           return !!visit.imageUrl;
-                         })
-                         .length;
-  // Subtract the SRP from the visit count.
-  // The SRP is a visit that is included to be used in the module header
-  // and for opening the cluster in tab group.
+  const imageCount =
+      visits.filter((visit: URLVisit) => visit.hasUrlKeyedImage).length;
+  // We subtract the SRP from the  visit count to get the actual number of
+  // visits that are eligible for layout selection.
   const visitCount = visits.length - 1;
 
   // Calculate which layout to use.
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.html b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.html
index d857bbc2e..2191c086 100644
--- a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.html
+++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.html
@@ -1,19 +1,12 @@
 <style include="history-clusters-shared-style">
+  /* TODO(crbug.com/1414484): Add comprehensive theming colors. */
+
   #content {
     background: var(--google-grey-100);
     border-radius: 25px;
     color: var(--google-grey-900);
   }
 
-  /* TODO(crbug.com/1414484): Add comprehensive theming to the hover states */
-  /*:host(:hover) #content {*/
-  /*  background-color: var(--cr-hover-background-color);*/
-  /*}*/
-
-  /*:host(:active) #content {*/
-  /*  background-color: var(--cr-active-background-color);*/
-  /*}*/
-
   :host([large-format]) #content {
     display: flex;
     flex-direction: column;
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts
index 1daf624..8f182c9 100644
--- a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts
+++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts
@@ -26,11 +26,9 @@
       /* The visit to display. */
       visit: Object,
 
+      // TODO(crbug.com/1419917): Image service integration.
       /* The icon to display. */
-      iconStyle_: {
-        type: String,
-        computed: `computeIconStyle_(visit.imageUrl)`,
-      },
+      iconStyle_: String,
 
       /* The label to display. */
       label_: {
@@ -55,12 +53,7 @@
     super.disconnectedCallback();
   }
 
-  private computeIconStyle_(): string {
-    return `-webkit-mask-image: url(${this.visit.imageUrl})`;
-  }
-
   private computeLabel_(): string {
-    // TODO: Figure out better way to strip host name
     return this.visit.urlForDisplay;
   }
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts b/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
index cfb2343..9686651 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
+++ b/chrome/browser/resources/new_tab_page/modules/module_descriptors.ts
@@ -17,6 +17,7 @@
 import {dummyV2Descriptor, dummyV2Descriptor02, dummyV2Descriptor03, dummyV2Descriptor04, dummyV2Descriptor05, dummyV2Descriptor06, dummyV2Descriptor07, dummyV2Descriptor08, dummyV2Descriptor09, dummyV2Descriptor10, dummyV2Descriptor11, dummyV2Descriptor12} from './dummy_v2/module.js';
 // </if>
 import {feedDescriptor, feedV2Descriptor} from './feed/module.js';
+import {HistoryClustersProxyImpl} from './history_clusters/history_clusters_proxy.js';
 import {historyClustersDescriptor} from './history_clusters/module.js';
 import {ModuleDescriptor} from './module_descriptor.js';
 import {ModuleRegistry} from './module_registry.js';
@@ -66,5 +67,12 @@
           modules.map(module => module.descriptor.id));
     }
   }
+  // Instantiate history clusters module if |historyClustersModuleEnabled| is
+  // false to counterfactually log metrics about the coverage of the history
+  // clusters module without rendering it.
+  if (!loadTimeData.getBoolean('historyClustersModuleEnabled') &&
+      loadTimeData.getBoolean('historyClustersModuleLoadEnabled')) {
+    HistoryClustersProxyImpl.getInstance().handler.getCluster();
+  }
 }
 counterfactualLoad();
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 3f0ea72..65a510d 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -130,9 +130,9 @@
 group("generate_mojom_webui") {
   public_deps = [
     ":copy_mojom_ts",
-    ":generate_ash_search_mojo_webui",
     ":generate_input_device_settings_mojom",
     ":generate_personalization_search_mojom",
+    ":generate_search_mojom",
     ":generate_settings_mojo_webui",
   ]
 }
@@ -185,13 +185,14 @@
   ]
 }
 
-copy("generate_ash_search_mojo_webui") {
-  deps =
-      [ "//chrome/browser/ui/webui/settings/ash/search:mojo_bindings_webui_js" ]
+copy("generate_search_mojom") {
+  deps = [
+    "//chrome/browser/ui/webui/settings/ash/search:mojo_bindings_ts__generator",
+  ]
   sources = [
-    "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/settings/ash/search/search.mojom-webui.js",
-    "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/settings/ash/search/search_result_icon.mojom-webui.js",
-    "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/settings/ash/search/user_action_recorder.mojom-webui.js",
+    "$root_gen_dir/chrome/browser/ui/webui/settings/ash/search/search.mojom-webui.ts",
+    "$root_gen_dir/chrome/browser/ui/webui/settings/ash/search/search_result_icon.mojom-webui.ts",
+    "$root_gen_dir/chrome/browser/ui/webui/settings/ash/search/user_action_recorder.mojom-webui.ts",
   ]
   outputs = [ "$tsc_input_dir/mojom-webui/search/{{source_file_part}}" ]
 }
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.html b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.html
new file mode 100644
index 0000000..3c7a447a
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.html
@@ -0,0 +1,47 @@
+<style include="settings-shared">
+  #header {
+    display: flex;
+  }
+
+  .key-container {
+    align-items: center;
+    border-radius: 5px;
+    box-sizing: border-box;
+    color: var(--cros-text-color-secondary);
+    display: flex;
+    font-weight: 500;
+    height: 28px;
+    justify-content: center;
+    margin-inline-end: 8px;
+    min-width: 28px;
+    padding-inline: 8px;
+  }
+
+  :host([key-state='default-remapping']) .key-container {
+    background-color: var(--cros-button-icon-color-secondary-disabled);
+    border: none;
+    box-shadow: 0 1px 1px var(--cros-button-icon-color-secondary-disabled);
+  }
+
+  :host([key-state='modifier-remapped']) .key-container {
+    background-color: var(--cros-highlight-color);
+    border: none;
+    box-shadow: 0 1px 1px var(--cros-highlight-color);
+  }
+
+  .settings-box {
+    justify-content: space-between;
+  }
+</style>
+<div class="settings-box">
+  <div>
+    <div id="keyLabel"
+        class="start key-container"
+        aria-hidden="true">[[keyLabel]]</div>
+  </div>
+  <settings-dropdown-menu id="keyDropdown"
+      label="[[keyLabel]]"
+      pref="{{pref}}"
+      menu-options="[[menuOptions]]">
+  </settings-dropdown-menu>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts
new file mode 100644
index 0000000..1695725f
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard_remap_modifier_key_row.ts
@@ -0,0 +1,123 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'keyboard-remap-key-row' contains a key with icon label and dropdown menu to
+ * allow users to customize the remapped key.
+ */
+
+import '../../settings_shared.css.js';
+import '../../controls/settings_dropdown_menu.js';
+import '../../prefs/prefs.js';
+
+import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
+
+import {MetaKey, ModifierKey} from './input_device_settings_types.js';
+import {getTemplate} from './keyboard_remap_modifier_key_row.html.js';
+
+/**
+ * Refers to the state of an 'remap-key' icon.
+ */
+enum KeyState {
+  DEFAULT_REMAPPING = 'default-remapping',
+  MODIFIER_REMAPPED = 'modifier-remapped',
+}
+
+/**
+ * Mapping for each modifier key to its default remapping key.
+ */
+let defaultRemappings: {[key: number]: ModifierKey} = {
+  [ModifierKey.META]: ModifierKey.META,
+  [ModifierKey.CONTROL]: ModifierKey.CONTROL,
+  [ModifierKey.ALT]: ModifierKey.ALT,
+  [ModifierKey.ESC]: ModifierKey.ESC,
+  [ModifierKey.BACKSPACE]: ModifierKey.BACKSPACE,
+  [ModifierKey.ASSISTANT]: ModifierKey.ASSISTANT,
+  [ModifierKey.CAPS_LOCK]: ModifierKey.CAPS_LOCK,
+};
+
+export class KeyboardRemapModifierKeyRowElement extends PolymerElement {
+  static get is(): string {
+    return 'keyboard-remap-modifier-key-row';
+  }
+
+  static get properties(): PolymerElementProperties {
+    return {
+      keyLabel: {
+        type: String,
+        value: '',
+      },
+
+      keyState: {
+        type: String,
+        value: KeyState.DEFAULT_REMAPPING,
+        reflectToAttribute: true,
+        computed: 'computeKeyState(pref.value)',
+      },
+
+      menuOptions: {
+        type: Array,
+      },
+
+      pref: {
+        type: Object,
+      },
+
+      metaKey: {
+        type: Number,
+        observer: 'updateDefaultRemapping',
+      },
+
+      key: {
+        type: Number,
+      },
+    };
+  }
+
+  keyLabel: string;
+  keyState: KeyState;
+  menuOptions: DropdownMenuOptionList;
+  pref: chrome.settingsPrivate.PrefObject;
+  metaKey: MetaKey;
+  key: ModifierKey;
+
+  static get template(): HTMLTemplateElement {
+    return getTemplate();
+  }
+
+  /**
+   * Whenever the key remapping is changed, update the keyState to change
+   * the icon color between default and highlighted.
+   */
+  private computeKeyState(): KeyState {
+    return defaultRemappings[this.key] === this.pref.value ?
+        KeyState.DEFAULT_REMAPPING :
+        KeyState.MODIFIER_REMAPPED;
+  }
+
+  private updateDefaultRemapping(): void {
+    defaultRemappings = {
+      ...defaultRemappings,
+      [ModifierKey.META]:
+          this.metaKey === MetaKey.COMMAND ? ModifierKey.CONTROL :
+                                             ModifierKey.META,
+      [ModifierKey.CONTROL]:
+          this.metaKey === MetaKey.COMMAND ? ModifierKey.META :
+                                             ModifierKey.CONTROL,
+    };
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'keyboard-remap-modifier-key-row': KeyboardRemapModifierKeyRowElement;
+  }
+}
+
+customElements.define(
+    KeyboardRemapModifierKeyRowElement.is, KeyboardRemapModifierKeyRowElement);
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html
index 3b6a446..19c7cc7 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html
@@ -11,70 +11,50 @@
 <div id="header">
   <div id="description">$i18n{remapKeyboardKeysDescription}</div>
   <cr-button id="restoreDefaultsButton"
-      on-click="restoreDefaults">
+      on-click="defaultInitializePrefs">
     $i18n{keyboardRemapRestoreDefaultsLabel}
   </cr-button>
 </div>
 <div id="container">
-  <div class="settings-box">
-    <div id="metaKeyLabel" class="start"
-        aria-hidden="true">[[metaKeyLabel]]</div>
-    <settings-dropdown-menu id="metaKey"
-        label="$i18n{keyboardKeySearch}"
-        pref="{{fakeMetaPref}}"
-        menu-options="[[keyMapTargets]]">
-    </settings-dropdown-menu>
-  </div>
-  <div class="settings-box">
-    <div class="start" aria-hidden="true">$i18n{keyboardKeyCtrl}</div>
-    <settings-dropdown-menu id="ctrlKey"
-        label="$i18n{keyboardKeyCtrl}"
-        pref="{{fakeCtrlPref}}"
-        menu-options="[[keyMapTargets]]">
-    </settings-dropdown-menu>
-  </div>
-  <div class="settings-box">
-    <div class="start" aria-hidden="true">$i18n{keyboardKeyAlt}</div>
-    <settings-dropdown-menu id="altKey"
-        label="$i18n{keyboardKeyAlt}"
-        pref="{{fakeAltPref}}"
-        menu-options="[[keyMapTargets]]">
-    </settings-dropdown-menu>
-  </div>
-  <div class="settings-box">
-    <div class="start" aria-hidden="true">$i18n{keyboardKeyEscape}</div>
-    <settings-dropdown-menu id="escKey"
-        label="$i18n{keyboardKeyEscape}"
-        pref="{{fakeEscPref}}"
-        menu-options="[[keyMapTargets]]">
-    </settings-dropdown-menu>
-  </div>
-  <div class="settings-box">
-    <div class="start" aria-hidden="true">$i18n{keyboardKeyBackspace}</div>
-    <settings-dropdown-menu id="backspaceKey"
-        label="$i18n{keyboardKeyBackspace}"
-        pref="{{fakeBackspacePref}}"
-        menu-options="[[keyMapTargets]]">
-    </settings-dropdown-menu>
-  </div>
+  <keyboard-remap-modifier-key-row key-label="[[metaKeyLabel]]"
+      key="[[modifierKey.META]]" id="metaKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeMetaPref}}"></keyboard-remap-modifier-key-row>
+  <keyboard-remap-modifier-key-row key-label="[[i18n('keyboardKeyCtrl')]]"
+      key="[[modifierKey.CONTROL]]" id="ctrlKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeCtrlPref}}"></keyboard-remap-modifier-key-row>
+  <keyboard-remap-modifier-key-row key-label="[[i18n('keyboardKeyAlt')]]"
+      key="[[modifierKey.ALT]]" id="altKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeAltPref}}"></keyboard-remap-modifier-key-row>
+  <keyboard-remap-modifier-key-row key-label="[[i18n('keyboardKeyEscape')]]"
+      key="[[modifierKey.ESC]]" id="escapeKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeEscPref}}"></keyboard-remap-modifier-key-row>
+  <keyboard-remap-modifier-key-row key-label="[[i18n('keyboardKeyBackspace')]]"
+      key="[[modifierKey.BACKSPACE]]" id="backspaceKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeBackspacePref}}"></keyboard-remap-modifier-key-row>
   <template is="dom-if" if="[[hasAssistantKey_]]">
-    <div class="settings-box">
-      <div class="start" aria-hidden="true">$i18n{keyboardKeyAssistant}</div>
-      <settings-dropdown-menu id="assistantKey"
-          label="$i18n{keyboardKeyAssistant}"
-          pref="{{fakeAssistantPref}}"
-          menu-options="[[keyMapTargets]]">
-      </settings-dropdown-menu>
-    </div>
+    <keyboard-remap-modifier-key-row
+    key-label="[[i18n('keyboardKeyAssistant')]]"
+      key="[[modifierKey.ASSISTANT]]" id="assistantKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeAssistantPref}}"></keyboard-remap-modifier-key-row>
   </template>
   <template is="dom-if" if="[[hasCapsLockKey]]">
-    <div class="settings-box">
-      <div class="start" aria-hidden="true">$i18n{keyboardKeyCapsLock}</div>
-      <settings-dropdown-menu id="capsLockKey"
-          label="$i18n{keyboardKeyCapsLock}"
-          pref="{{fakeCapsLockPref}}"
-          menu-options="[[keyMapTargets]]">
-      </settings-dropdown-menu>
-    </div>
+    <keyboard-remap-modifier-key-row
+    key-label="[[i18n('keyboardKeyCapsLock')]]"
+      key="[[modifierKey.CAPS_LOCK]]" id="capsLockKey"
+      menu-options="[[keyMapTargets]]"
+      meta-key="[[keyboard.metaKey]]"
+      pref="{{fakeCapsLockPref}}"></keyboard-remap-modifier-key-row>
   </template>
 </div>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
index daad04a..d934fc5 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
@@ -11,6 +11,7 @@
 import '../../icons.html.js';
 import '../../settings_shared.css.js';
 import '../../controls/settings_dropdown_menu.js';
+import './keyboard_remap_modifier_key_row.js';
 import '../../prefs/prefs.js';
 
 import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
@@ -48,7 +49,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeMetaKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.META,
           };
@@ -59,7 +60,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeCtrlKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.CONTROL,
           };
@@ -81,7 +82,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeEscKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.ESC,
           };
@@ -92,7 +93,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeBackspaceKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.BACKSPACE,
           };
@@ -103,7 +104,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeAssistantKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.ASSISTANT,
           };
@@ -114,7 +115,7 @@
         type: Object,
         value() {
           return {
-            key: 'fakeAltKeyRemapPref',
+            key: 'fakeCapsLockKeyRemapPref',
             type: chrome.settingsPrivate.PrefType.NUMBER,
             value: ModifierKey.CAPS_LOCK,
           };
@@ -156,6 +157,10 @@
     ];
   }
 
+  protected get modifierKey(): typeof ModifierKey {
+    return ModifierKey;
+  }
+
   protected keyboard: Keyboard;
   private inputDeviceSettingsProvider: InputDeviceSettingsProviderInterface =
       getInputDeviceSettingsProvider();
@@ -273,18 +278,16 @@
     this.set('fakeAltPref.value', ModifierKey.ALT);
     this.set('fakeAssitantPref.value', ModifierKey.ASSISTANT);
     this.set('fakeBackspacePref.value', ModifierKey.BACKSPACE);
-    this.set('fakeCtrlPref.value', ModifierKey.CONTROL);
+    this.set(
+        'fakeCtrlPref.value',
+        this.keyboard.metaKey === MetaKey.COMMAND ? ModifierKey.META :
+                                                    ModifierKey.CONTROL);
     this.set('fakeCapsLockPref.value', ModifierKey.CAPS_LOCK);
     this.set('fakeEscPref.value', ModifierKey.ESC);
-    this.set('fakeMetaPref.value', ModifierKey.META);
-  }
-
-  private restoreDefaults(): void {
-    this.defaultInitializePrefs();
-    if (this.keyboard.metaKey === MetaKey.COMMAND) {
-      this.set('fakeMetaPref.value', ModifierKey.CONTROL);
-      this.set('fakeCtrlPref.value', ModifierKey.META);
-    }
+    this.set(
+        'fakeMetaPref.value',
+        this.keyboard.metaKey === MetaKey.COMMAND ? ModifierKey.CONTROL :
+                                                    ModifierKey.META);
   }
 
   private setRemappedKey(originalKey: ModifierKey): void {
@@ -322,7 +325,7 @@
     }
   }
 
-  private onSettingsChanged() {
+  private onSettingsChanged(): void {
     // TODO(yyhyyh@): Call update keyboard settings API when user changes
     // settings value.
   }
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.ts b/chrome/browser/resources/settings/chromeos/lazy_load.ts
index ad77a3c3..f1f7982 100644
--- a/chrome/browser/resources/settings/chromeos/lazy_load.ts
+++ b/chrome/browser/resources/settings/chromeos/lazy_load.ts
@@ -37,7 +37,7 @@
 import './os_a11y_page/display_and_magnification_page.js';
 import './os_a11y_page/keyboard_and_text_input_page.js';
 import './os_a11y_page/cursor_and_touchpad_page.js';
-import './os_a11y_page/audio_and_captions_page.js';
+import './os_a11y_page/chromevox_subpage.js';
 import './os_a11y_page/select_to_speak_subpage.js';
 import './os_a11y_page/switch_access_action_assignment_dialog.js';
 import './os_a11y_page/switch_access_action_assignment_pane.js';
@@ -86,6 +86,7 @@
 export {TimeZoneAutoDetectMethod} from './date_time_page/date_time_types.js';
 export {TimeZoneBrowserProxyImpl} from './date_time_page/timezone_browser_proxy.js';
 export {CROSTINI_TYPE, GuestOsBrowserProxy, GuestOsBrowserProxyImpl, GuestOsSharedUsbDevice, PLUGIN_VM_TYPE} from './guest_os/guest_os_browser_proxy.js';
+export {SettingsAudioAndCaptionsPageElement} from './os_a11y_page/audio_and_captions_page.js';
 export {LanguagesBrowserProxyImpl} from './os_languages_page/languages_browser_proxy.js';
 export {InputsShortcutReminderState, LanguagesMetricsProxyImpl, LanguagesPageInteraction} from './os_languages_page/languages_metrics_proxy.js';
 export {PrinterType} from './os_printing_page/cups_printer_types.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.ts
index bce57b20..223fae4 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.ts
@@ -34,7 +34,7 @@
 import {getTemplate} from './audio_and_captions_page.html.js';
 import {AudioAndCaptionsPageBrowserProxy, AudioAndCaptionsPageBrowserProxyImpl} from './audio_and_captions_page_browser_proxy.js';
 
-interface SettingsAudioAndCaptionsPageElement {
+export interface SettingsAudioAndCaptionsPageElement {
   $: {
     startupSoundEnabled: CrToggleElement,
   };
@@ -43,7 +43,7 @@
 const SettingsAudioAndCaptionsPageElementBase = DeepLinkingMixin(
     RouteOriginMixin(WebUiListenerMixin(I18nMixin(PolymerElement))));
 
-class SettingsAudioAndCaptionsPageElement extends
+export class SettingsAudioAndCaptionsPageElement extends
     SettingsAudioAndCaptionsPageElementBase {
   static get is() {
     return 'settings-audio-and-captions-page';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.html
new file mode 100644
index 0000000..8185fed
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.html
@@ -0,0 +1,13 @@
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<style include="settings-shared">
+  h2 {
+    padding-inline-start: var(--cr-section-padding);
+  }
+</style>
+
+<h2>$i18n{chromeVoxLabel}</h2>
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts
new file mode 100644
index 0000000..99310266
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/chromevox_subpage.ts
@@ -0,0 +1,79 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'settings-chromevox-subpage' is the accessibility settings subpage for
+ * ChromeVox settings.
+ */
+
+import '../../settings_shared.css.js';
+import 'chrome://resources/cr_components/localized_link/localized_link.js';
+import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
+
+import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
+import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
+import {DeepLinkingMixin} from '../deep_linking_mixin.js';
+import {routes} from '../os_settings_routes.js';
+import {RouteOriginMixin} from '../route_origin_mixin.js';
+import {Route} from '../router.js';
+
+import {getTemplate} from './chromevox_subpage.html.js';
+
+const SettingsChromeVoxSubpageElementBase = DeepLinkingMixin(RouteOriginMixin(
+    PrefsMixin(WebUiListenerMixin(I18nMixin(PolymerElement)))));
+
+class SettingsChromeVoxSubpageElement extends
+    SettingsChromeVoxSubpageElementBase {
+  static get is() {
+    return 'settings-chromevox-subpage' as const;
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {};
+  }
+
+  static get observers() {
+    return [];
+  }
+
+  private route_: Route;
+
+  constructor() {
+    super();
+
+    /** RouteOriginMixin override */
+    this.route_ = routes.A11Y_CHROMEVOX;
+  }
+
+  /**
+   * Note: Overrides RouteOriginMixin implementation.
+   */
+  override currentRouteChanged(newRoute: Route, prevRoute?: Route): void {
+    super.currentRouteChanged(newRoute, prevRoute);
+
+    // Does not apply to this page.
+    if (newRoute !== this.route_) {
+      return;
+    }
+
+    this.attemptDeepLink();
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    [SettingsChromeVoxSubpageElement.is]: SettingsChromeVoxSubpageElement;
+  }
+}
+
+customElements.define(
+    SettingsChromeVoxSubpageElement.is, SettingsChromeVoxSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
index b324e76..24708620 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
@@ -50,11 +50,24 @@
     deep-link-focus-id$="[[Setting.kChromeVox]]">
 </settings-toggle-button>
 <iron-collapse opened="[[prefs.settings.accessibility.value]]">
+  <!-- TODO(b/270557583): Update link to point to new ChromeVox Settings Page
+  (when AccessibilityChromeVoxPageMigration flag enabled)-->
   <div class="sub-item">
-    <cr-link-row id="chromeVoxSubpageButton"
-        class="settings-box" on-click="onChromeVoxSettingsTap_"
-        label="$i18n{chromeVoxOptionsLabel}" external>
-    </cr-link-row>
+    <template is="dom-if"
+        if="[[isAccessibilityChromeVoxPageMigrationEnabled_]]">
+      <cr-link-row id="chromevoxSubpageTrigger"
+          class="settings-box" on-click="onChromeVoxNewSettingsTap_"
+          label="$i18n{chromeVoxOptionsLabel}"
+          role-description="$i18n{subpageArrowRoleDescription}">
+      </cr-link-row>
+    </template>
+    <template is="dom-if"
+        if="[[!isAccessibilityChromeVoxPageMigrationEnabled_]]">
+      <cr-link-row id="chromeVoxSubpageButton"
+          class="settings-box" on-click="onChromeVoxSettingsTap_"
+          label="$i18n{chromeVoxOptionsLabel}" external>
+      </cr-link-row>
+    </template>
   </div>
   <div class="sub-item">
     <cr-link-row id="chromeVoxTutorialButton"
@@ -73,10 +86,21 @@
 </settings-toggle-button>
 <iron-collapse opened="[[prefs.settings.a11y.select_to_speak.value]]">
   <div class="sub-item">
-    <cr-link-row id="selectToSpeakSubpageButton"
-        class="settings-box" on-click="onSelectToSpeakSettingsTap_"
-        label="$i18n{selectToSpeakOptionsLabel}" external>
+    <template is="dom-if"
+        if="[[isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
+      <cr-link-row id="selectToSpeakSubpageTrigger"
+          class="settings-box" on-click="onSelectToSpeakNewSettingsTap_"
+          label="$i18n{selectToSpeakLinkTitle}"
+          role-description="$i18n{subpageArrowRoleDescription}">
       </cr-link-row>
+    </template>
+    <template is="dom-if"
+        if="[[!isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
+      <cr-link-row id="selectToSpeakSubpageButton"
+          class="settings-box" on-click="onSelectToSpeakSettingsTap_"
+          label="$i18n{selectToSpeakOptionsLabel}" external>
+      </cr-link-row>
+    </template>
   </div>
 </iron-collapse>
 
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.ts
index 9d9d972..671f27f8 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.ts
@@ -304,6 +304,22 @@
 
       hasTouchpad_: Boolean,
 
+      isAccessibilityChromeVoxPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilityChromeVoxPageMigrationEnabled');
+        },
+      },
+
+      isAccessibilitySelectToSpeakPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilitySelectToSpeakPageMigrationEnabled');
+        },
+      },
+
       /**
        * Boolean indicating whether shelf navigation buttons should implicitly
        * be enabled in tablet mode - the navigation buttons are implicitly
@@ -381,6 +397,8 @@
   private hasMouse_: boolean;
   private hasPointingStick_: boolean;
   private hasTouchpad_: boolean;
+  private isAccessibilityChromeVoxPageMigrationEnabled_: boolean;
+  private isAccessibilitySelectToSpeakPageMigrationEnabled_: boolean;
   private isGuest_: boolean;
   private isKioskModeActive_: boolean;
   private manageBrowserProxy_: ManageA11yPageBrowserProxy;
@@ -523,6 +541,10 @@
     this.manageBrowserProxy_.showChromeVoxSettings();
   }
 
+  private onChromeVoxNewSettingsTap_(): void {
+    Router.getInstance().navigateTo(routes.A11Y_CHROMEVOX);
+  }
+
   private onChromeVoxTutorialTap_(): void {
     this.manageBrowserProxy_.showChromeVoxTutorial();
   }
@@ -531,6 +553,10 @@
     this.manageBrowserProxy_.showSelectToSpeakSettings();
   }
 
+  private onSelectToSpeakNewSettingsTap_(): void {
+    Router.getInstance().navigateTo(routes.A11Y_SELECT_TO_SPEAK);
+  }
+
   private onSwitchAccessSettingsTap_(): void {
     Router.getInstance().navigateTo(routes.MANAGE_SWITCH_ACCESS_SETTINGS);
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
index 865d7c10..8e0f963 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.html
@@ -78,6 +78,15 @@
     </os-settings-subpage>
   </template>
   <template is="dom-if"
+      if="[[isAccessibilityChromeVoxPageMigrationEnabled_]]">
+    <template is="dom-if" route-path="/textToSpeech/chromeVox">
+      <os-settings-subpage page-title="$i18n{chromeVoxLabel}">
+        <settings-chromevox-subpage prefs="{{prefs}}">
+        </settings-chromevox-subpage>
+      </os-settings-subpage>
+    </template>
+  </template>
+  <template is="dom-if"
       if="[[isAccessibilitySelectToSpeakPageMigrationEnabled_]]">
     <template is="dom-if" route-path="/textToSpeech/selectToSpeak">
       <os-settings-subpage page-title="$i18n{selectToSpeakLinkTitle}">
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
index 98a6bc6..d6def8c 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.ts
@@ -18,6 +18,7 @@
 import './keyboard_and_text_input_page.js';
 import './cursor_and_touchpad_page.js';
 import './audio_and_captions_page.js';
+import './chromevox_subpage.js';
 import './select_to_speak_subpage.js';
 import './switch_access_subpage.js';
 import './tts_subpage.js';
@@ -74,6 +75,17 @@
       },
 
       /**
+       * Whether ChromeVox page migration is enabled.
+       */
+      isAccessibilityChromeVoxPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilityChromeVoxPageMigrationEnabled');
+        },
+      },
+
+      /**
        * Whether Select-to-speak page migration is enabled.
        */
       isAccessibilitySelectToSpeakPageMigrationEnabled_: {
@@ -125,6 +137,8 @@
   private isKioskModeActive_: boolean;
   private route_: Route;
   private showAccessibilityLabelsSetting_: boolean;
+  private isAccessibilityChromeVoxPageMigrationEnabled_: boolean;
+  private isAccessibilitySelectToSpeakPageMigrationEnabled_: boolean;
 
   constructor() {
     super();
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
index 98f6663..98997ea 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
@@ -26,10 +26,21 @@
 </settings-toggle-button>
 <iron-collapse opened="[[prefs.settings.accessibility.value]]">
   <div class="sub-item">
-    <cr-link-row id="chromeVoxSubpageButton"
-        class="settings-box" on-click="onChromeVoxSettingsTap_"
-        label="$i18n{chromeVoxOptionsLabel}" external>
-    </cr-link-row>
+    <template is="dom-if"
+        if="[[isAccessibilityChromeVoxPageMigrationEnabled_]]">
+      <cr-link-row id="chromevoxSubpageTrigger"
+          class="settings-box" on-click="onChromeVoxNewSettingsTap_"
+          label="$i18n{chromeVoxOptionsLabel}"
+          role-description="$i18n{subpageArrowRoleDescription}">
+      </cr-link-row>
+    </template>
+    <template is="dom-if"
+        if="[[!isAccessibilityChromeVoxPageMigrationEnabled_]]">
+      <cr-link-row id="chromeVoxSubpageButton"
+          class="settings-box" on-click="onChromeVoxSettingsTap_"
+          label="$i18n{chromeVoxOptionsLabel}" external>
+      </cr-link-row>
+    </template>
   </div>
   <div class="sub-item">
     <cr-link-row id="chromeVoxTutorialButton"
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
index 26b4571c..963ee37 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
@@ -59,6 +59,14 @@
        */
       hasKeyboard_: Boolean,
 
+      isAccessibilityChromeVoxPageMigrationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean(
+              'isAccessibilityChromeVoxPageMigrationEnabled');
+        },
+      },
+
       isAccessibilitySelectToSpeakPageMigrationEnabled_: {
         type: Boolean,
         value() {
@@ -82,6 +90,8 @@
 
   private deviceBrowserProxy_: DevicePageBrowserProxy;
   private hasKeyboard_: boolean;
+  private isAccessibilityChromeVoxPageMigrationEnabled_: boolean;
+  private isAccessibilitySelectToSpeakPageMigrationEnabled_: boolean;
   private route_: Route;
   private textToSpeechBrowserProxy_: TextToSpeechPageBrowserProxy;
   private showPdfOcrSetting_: boolean;
@@ -161,6 +171,10 @@
     this.textToSpeechBrowserProxy_.showChromeVoxSettings();
   }
 
+  private onChromeVoxNewSettingsTap_(): void {
+    Router.getInstance().navigateTo(routes.A11Y_CHROMEVOX);
+  }
+
   private onChromeVoxTutorialTap_(): void {
     this.textToSpeechBrowserProxy_.showChromeVoxTutorial();
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
index 8cb22c5..31a9cf3 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.ts
@@ -144,6 +144,9 @@
   /** Opens the diagnostics page. */
   openDiagnostics(): void;
 
+  /** Opens the "other open source software" license page. */
+  openProductLicenseOther(): void;
+
   /** Opens the OS help page. */
   openOsHelpPage(): void;
 
@@ -245,6 +248,10 @@
     chrome.send('openDiagnostics');
   }
 
+  openProductLicenseOther() {
+    chrome.send('openProductLicenseOther');
+  }
+
   openOsHelpPage() {
     chrome.send('openOsHelpPage');
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
index 404ad75..02a6a64 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -240,7 +240,13 @@
     </div>
 
     <div class="info-section">
-      <div class="secondary">$i18nRaw{aboutProductLicense}</div>
+      <div class="secondary">
+        <span>$i18nRaw{aboutProductLicenseChromium}</span>
+        <localized-link
+            localized-string="$i18nRaw{aboutProductLicenseOther}"
+            on-link-clicked="onProductLicenseOtherClicked_">
+        </localized-link>
+      </div>
       <div class="secondary"
           inner-h-t-m-l="[[getAboutProductOsLicense_(
               showCrostiniLicense_)]]">
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
index 67951726..4b87848 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
@@ -367,6 +367,14 @@
     event.stopPropagation();
   }
 
+  private onProductLicenseOtherClicked_(event: CustomEvent<{event: Event}>) {
+    // Prevent the default link click behavior
+    event.detail.event.preventDefault();
+
+    // Programmatically open license.
+    this.aboutBrowserProxy_.openProductLicenseOther();
+  }
+
   private onReleaseNotesTap_() {
     this.aboutBrowserProxy_.launchReleaseNotes();
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.html
index 9bb680a..05d3253 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.html
@@ -37,8 +37,9 @@
           </template>
           <template is="dom-if" if="[[isToggleButton_(option.uiType)]]">
             <cr-toggle checked="{{option.value}}"
-                on-click="onToggleButtonOrDropdownChange_"
-                aria-label="[[option.label]]">
+                on-change="onToggleButtonOrDropdownChange_"
+                aria-label="[[option.label]]"
+                deep-link-focus-id$="[[option.deepLink]]">
             </cr-toggle>
           </template>
           <template is="dom-if" if="[[isDropdown_(option.uiType)]]">
@@ -47,7 +48,8 @@
                  <dom-repeat> events instead. -->
             <select class="md-select" value="{{option.value::change}}"
                 on-change="onToggleButtonOrDropdownChange_"
-                aria-label="[[option.label]]">
+                aria-label="[[option.label]]"
+                deep-link-focus-id$="[[option.deepLink]]">
               <template is="dom-repeat" items="[[option.menuItems]]">
                 <option selected="[[item.selected]]" value="[[item.value]]">
                   [[item.label]]
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.ts b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.ts
index 755be3e9..6c6554a 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.ts
@@ -18,8 +18,10 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {afterNextRender, DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {assertExhaustive} from '../assert_extras.js';
+import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {OsSettingsSubpageElement} from '../os_settings_page/os_settings_subpage.js';
 import {routes} from '../os_settings_routes.js';
 import {RouteObserverMixin} from '../route_observer_mixin.js';
@@ -57,6 +59,7 @@
   value: OptionValue;
   label: string;
   subtitle: string;
+  deepLink: number;
   menuItems: Array<{name?: string, value: unknown}>;
   url: Route|undefined;
   dependentOptions: Option[];
@@ -85,7 +88,7 @@
 type AutocorrectOptionMapKey = keyof typeof AUTOCORRECT_OPTION_MAP_OVERRIDE;
 
 const SettingsInputMethodOptionsPageElementBase =
-    I18nMixin(PrefsMixin(RouteObserverMixin(PolymerElement)));
+    RouteObserverMixin(PrefsMixin(I18nMixin(DeepLinkingMixin(PolymerElement))));
 
 class SettingsInputMethodOptionsPageElement extends
     SettingsInputMethodOptionsPageElementBase {
@@ -144,6 +147,13 @@
   // Public API: Downwards data flow.
   languageHelper: LanguageHelper;
 
+  // Internal properties for mixins.
+  // From DeepLinkingMixin.
+  override supportedSettingIds = new Set<Setting>([
+    Setting.kShowPKAutoCorrection,
+    Setting.kShowVKAutoCorrection,
+  ]);
+
   // Internal state.
   // This property does not have a default value in `static get properties()`,
   // but is set in `currentRouteChanged()`.
@@ -193,6 +203,7 @@
     assert(displayName !== '', `Input method ID '${this.id_}' is invalid`);
     this.engineId_ = getFirstPartyInputMethodEngineId(this.id_);
     this.populateOptionSections_();
+    this.attemptDeepLink();
   }
 
   private onSubmenuButtonClick_(e: DomRepeatEvent<Option, MouseEvent>): void {
@@ -309,12 +320,21 @@
       const subtitleStringName = getOptionSubtitleName(name);
       const subtitle = subtitleStringName && this.i18n(subtitleStringName);
 
+      let link = -1;
+      if (name === OptionType.PHYSICAL_KEYBOARD_AUTO_CORRECTION_LEVEL) {
+        link = Setting.kShowPKAutoCorrection;
+      }
+      if (name === OptionType.VIRTUAL_KEYBOARD_AUTO_CORRECTION_LEVEL) {
+        link = Setting.kShowVKAutoCorrection;
+      }
+
       return {
         name: name,
         uiType: uiType,
         value: value,
         label: label,
         subtitle: subtitle,
+        deepLink: link,
         menuItems: this.getMenuItems(name, value),
         url: getOptionUrl(name),
         dependentOptions: option.dependentOptions ?
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
index e5e8f192..f803308 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
@@ -107,11 +107,13 @@
 
 <div route-path="default">
   <template is="dom-if" if="[[shouldShowLanguagePacksNotice_]]">
-    <localized-link id="languagePacksNotice"
-        class="cr-row first bottom-margin cr-secondary-text"
-        localized-string="$i18n{languagePacksNotice}"
-        on-link-clicked="onLanguagePackNoticeLinkClick_">
-    </localized-link>
+    <div class="cr-row first bottom-margin">
+      <localized-link id="languagePacksNotice"
+          class="cr-secondary-text"
+          localized-string="$i18n{languagePacksNotice}"
+          on-link-clicked="onLanguagePackNoticeLinkClick_">
+      </localized-link>
+    </div>
   </template>
   <settings-toggle-button
       class="first" id="showImeMenu"
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.html
index 39c844ab..8a38ae7 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.html
@@ -90,12 +90,13 @@
     <h2 aria-hidden="true">
       [[getLanguagePreferenceTitle_(languageSettingsV2Update2Enabled_)]]
     </h2>
-    <localized-link id="webLanguagesDescription"
-        class="cr-row first bottom-margin"
-        localized-string="[[getLanguagePreferenceDescription_(
-            languageSettingsV2Update2Enabled_)]]"
-        on-link-clicked="onLanguagePreferenceDescriptionLinkClick_">
-    </localized-link>
+    <div class="cr-row first bottom-margin">
+      <localized-link id="webLanguagesDescription"
+          localized-string="[[getLanguagePreferenceDescription_(
+              languageSettingsV2Update2Enabled_)]]"
+          on-link-clicked="onLanguagePreferenceDescriptionLinkClick_">
+      </localized-link>
+    </div>
     <div class="list-frame vertical-list" id="languagesList">
       <template is="dom-repeat" items="[[languages.enabled]]">
         <div class$="list-item [[getTranslationTargetClass_(
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 310d898..3f9c5dd 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -56,6 +56,7 @@
   "chromeos/device_page/per_device_touchpad_subsection.ts",
   "chromeos/device_page/pointers.ts",
   "chromeos/device_page/power.ts",
+  "chromeos/device_page/keyboard_remap_modifier_key_row.ts",
   "chromeos/device_page/storage.ts",
   "chromeos/device_page/storage_external.ts",
   "chromeos/device_page/storage_external_entry.ts",
@@ -115,6 +116,7 @@
   "chromeos/nearby_share_page/nearby_share_subpage.ts",
   "chromeos/os_a11y_page/audio_and_captions_page.ts",
   "chromeos/os_a11y_page/change_dictation_locale_dialog.ts",
+  "chromeos/os_a11y_page/chromevox_subpage.ts",
   "chromeos/os_a11y_page/cursor_and_touchpad_page.ts",
   "chromeos/os_a11y_page/display_and_magnification_page.ts",
   "chromeos/os_a11y_page/keyboard_and_text_input_page.ts",
@@ -424,11 +426,12 @@
   "mojom-webui/input_device_settings.mojom-webui.js",
   "mojom-webui/modifier_key.mojom-webui.js",
   "mojom-webui/routes.mojom-webui.js",
-  "mojom-webui/search/personalization_search.mojom-webui.ts",
-  "mojom-webui/search/search.mojom-webui.js",
-  "mojom-webui/search/search_result_icon.mojom-webui.js",
-  "mojom-webui/search/user_action_recorder.mojom-webui.js",
   "mojom-webui/setting.mojom-webui.js",
+
+  "mojom-webui/search/personalization_search.mojom-webui.ts",
+  "mojom-webui/search/search.mojom-webui.ts",
+  "mojom-webui/search/search_result_icon.mojom-webui.ts",
+  "mojom-webui/search/user_action_recorder.mojom-webui.ts",
 ]
 
 # Files sourced from their checked-in version under src
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts
index 8328fc8..17544375 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -31,6 +31,7 @@
 import './device_page/per_device_touchpad_subsection.js';
 import './device_page/pointers.js';
 import './device_page/power.js';
+import './device_page/keyboard_remap_modifier_key_row.js';
 import './device_page/storage.js';
 import './device_page/storage_external.js';
 import './device_page/storage_external_entry.js';
@@ -161,6 +162,7 @@
 export {FakeInputDeviceSettingsProvider} from './device_page/fake_input_device_settings_provider.js';
 export {getInputDeviceSettingsProvider, setInputDeviceSettingsProviderForTesting, setupFakeInputDeviceSettingsProvider} from './device_page/input_device_mojo_interface_provider.js';
 export {MetaKey, ModifierKey} from './device_page/input_device_settings_types.js';
+export {KeyboardRemapModifierKeyRowElement} from './device_page/keyboard_remap_modifier_key_row.js';
 export {SettingsPerDeviceKeyboardElement} from './device_page/per_device_keyboard.js';
 export {SettingsPerDeviceKeyboardRemapKeysElement} from './device_page/per_device_keyboard_remap_keys.js';
 export {SettingsPerDeviceKeyboardSubsectionElement} from './device_page/per_device_keyboard_subsection.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.ts b/chrome/browser/resources/settings/chromeos/os_settings_routes.ts
index 8c0e87d..351d822 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_routes.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.ts
@@ -104,6 +104,7 @@
   A11Y_DISPLAY_AND_MAGNIFICATION: Route;
   A11Y_KEYBOARD_AND_TEXT_INPUT: Route;
   A11Y_TEXT_TO_SPEECH: Route;
+  A11Y_CHROMEVOX: Route;
   A11Y_SELECT_TO_SPEAK: Route;
   ABOUT: Route;
   ABOUT_ABOUT: Route;
@@ -419,6 +420,13 @@
       r.OS_ACCESSIBILITY, routesMojomWebui.AUDIO_AND_CAPTIONS_SUBPAGE_PATH,
       Subpage.kAudioAndCaptions);
   if (loadTimeData.valueExists(
+          'isAccessibilityChromeVoxPageMigrationEnabled') &&
+      loadTimeData.getBoolean('isAccessibilityChromeVoxPageMigrationEnabled')) {
+    r.A11Y_CHROMEVOX = createSubpage(
+        r.A11Y_TEXT_TO_SPEECH, routesMojomWebui.CHROME_VOX_SUBPAGE_PATH,
+        Subpage.kChromeVox);
+  }
+  if (loadTimeData.valueExists(
           'isAccessibilitySelectToSpeakPageMigrationEnabled') &&
       loadTimeData.getBoolean(
           'isAccessibilitySelectToSpeakPageMigrationEnabled')) {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts b/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts
index 1a47fb5..4270ed5e 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts
@@ -54,7 +54,6 @@
 
       /**
        * The number of engines visible when the list is collapsed.
-       * This is currently gated behind the #omnibox-active-search-engines-flag.
        */
       visibleEnginesSize: {
         type: Number,
@@ -64,8 +63,7 @@
       /**
        * An array of the first 'visibleEnginesSize' engines in the `engines`
        * array.  These engines are visible even when 'collapsedEngines' is
-       * collapsed. This is currently gated behind the
-       * #omnibox-active-search-engines flag.
+       * collapsed.
        */
       visibleEngines:
           {type: Array, computed: 'computeVisibleEngines_(engines)'},
@@ -73,8 +71,7 @@
       /**
        * An array of all remaining engines not in the `visibleEngines` array.
        * These engines' visibility can be toggled by expanding or collapsing the
-       * engines list. This is currently gated behind the
-       * #omnibox-active-search-engines flag.
+       * engines list.
        */
       collapsedEngines:
           {type: Array, computed: 'computeCollapsedEngines_(engines)'},
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html
index 051bc4a22..3623323 100644
--- a/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html
+++ b/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html>
+<html $i18n{chromeRefresh2023Attribute}>
   <head>
     <meta charset="utf-8">
     <title>cr-radio demo</title>
@@ -16,9 +16,16 @@
             <cr-radio-button name="option3" label="Option 3">
               <div>With slotted content</div>
             </cr-radio-button>
+            <cr-radio-button name="option4" label="Option 4" disabled>
+              <div>Disabled</div>
+            </cr-radio-button>
           </cr-radio-group>
 
           Selected option: [[selectedOption_]]
+          <cr-radio-group selected="option5">
+            <cr-radio-button name="option5" label="Disabled selected"
+                disabled></cr-radio-button>
+          </cr-radio-group>
         </div>
       </template>
     </dom-bind>
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
index fe0d0da..408187e9 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
@@ -268,6 +268,7 @@
         .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
     EXPECT_CALL(item_, GetReceivedBytes()).WillRepeatedly(Return(0));
     EXPECT_CALL(item_, HasUserGesture()).WillRepeatedly(Return(false));
+    EXPECT_CALL(item_, RequireSafetyChecks()).WillRepeatedly(Return(true));
     content::DownloadItemUtils::AttachInfoForTesting(&item_, profile_, nullptr);
 
     SetDMTokenForTesting(
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_util.cc b/chrome/browser/safe_browsing/download_protection/download_protection_util.cc
index 7c07ede6..6596160 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_util.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_util.cc
@@ -7,6 +7,7 @@
 #include "base/hash/sha1.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
+#include "components/safe_browsing/content/common/file_type_policies.h"
 #include "net/cert/x509_util.h"
 #include "url/gurl.h"
 
@@ -97,4 +98,23 @@
               "file-system-access-write");
 }
 
+google::protobuf::RepeatedPtrField<ClientDownloadRequest::ArchivedBinary>
+SelectArchiveEntries(const google::protobuf::RepeatedPtrField<
+                     ClientDownloadRequest::ArchivedBinary>& src_binaries) {
+  google::protobuf::RepeatedPtrField<ClientDownloadRequest::ArchivedBinary>
+      selected;
+
+  // Limit the number of entries so we don't clog the backend.
+  // We can expand this limit by pushing a new download_file_types update.
+  int limit = FileTypePolicies::GetInstance()->GetMaxArchivedBinariesToReport();
+
+  for (int i = 0; selected.size() < limit && i < src_binaries.size(); i++) {
+    if (src_binaries[i].is_executable() || src_binaries[i].is_archive()) {
+      *selected.Add() = src_binaries[i];
+    }
+  }
+
+  return selected;
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_util.h b/chrome/browser/safe_browsing/download_protection/download_protection_util.h
index e916d7db4..72a41242 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_util.h
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_util.h
@@ -125,6 +125,12 @@
 
 GURL GetFileSystemAccessDownloadUrl(const GURL& frame_url);
 
+// Determine which entries from `src_binaries` should be sent in the download
+// ping.
+google::protobuf::RepeatedPtrField<ClientDownloadRequest::ArchivedBinary>
+SelectArchiveEntries(const google::protobuf::RepeatedPtrField<
+                     ClientDownloadRequest::ArchivedBinary>& src_binaries);
+
 }  // namespace safe_browsing
 
 #endif  // CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_PROTECTION_UTIL_H_
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
index 3f8f99725..98ef987 100644
--- a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
+++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
@@ -12,6 +12,7 @@
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
 #include "chrome/browser/file_util_service.h"
+#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
 #include "chrome/common/safe_browsing/archive_analyzer_results.h"
 #include "chrome/common/safe_browsing/document_analyzer_results.h"
 #include "chrome/common/safe_browsing/download_type_util.h"
@@ -30,24 +31,6 @@
 
 using content::BrowserThread;
 
-void CopyArchivedBinaries(
-    const google::protobuf::RepeatedPtrField<
-        ClientDownloadRequest::ArchivedBinary>& src_binaries,
-    google::protobuf::RepeatedPtrField<ClientDownloadRequest::ArchivedBinary>*
-        dest_binaries) {
-  // Limit the number of entries so we don't clog the backend.
-  // We can expand this limit by pushing a new download_file_types update.
-  int limit = FileTypePolicies::GetInstance()->GetMaxArchivedBinariesToReport();
-
-  dest_binaries->Clear();
-  for (int i = 0; dest_binaries->size() < limit && i < src_binaries.size();
-       i++) {
-    if (src_binaries[i].is_executable() || src_binaries[i].is_archive()) {
-      *dest_binaries->Add() = src_binaries[i];
-    }
-  }
-}
-
 FileAnalyzer::Results ExtractFileFeatures(
     scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor,
     base::FilePath file_path) {
@@ -178,8 +161,8 @@
   }
   results_.archived_executable = archive_results.has_executable;
   results_.archived_archive = archive_results.has_archive;
-  CopyArchivedBinaries(archive_results.archived_binary,
-                       &results_.archived_binaries);
+  results_.archived_binaries =
+      SelectArchiveEntries(archive_results.archived_binary);
 
   if (archive_results.has_executable) {
     results_.type = ClientDownloadRequest::ZIPPED_EXECUTABLE;
@@ -233,8 +216,8 @@
   }
   results_.archived_executable = archive_results.has_executable;
   results_.archived_archive = archive_results.has_archive;
-  CopyArchivedBinaries(archive_results.archived_binary,
-                       &results_.archived_binaries);
+  results_.archived_binaries =
+      SelectArchiveEntries(archive_results.archived_binary);
 
   if (archive_results.has_executable) {
     results_.type = ClientDownloadRequest::RAR_COMPRESSED_EXECUTABLE;
@@ -299,8 +282,8 @@
   // Even if !results.success, some of the DMG may have been parsed.
   results_.archived_executable = archive_results.has_executable;
   results_.archived_archive = archive_results.has_archive;
-  CopyArchivedBinaries(archive_results.archived_binary,
-                       &results_.archived_binaries);
+  results_.archived_binaries =
+      SelectArchiveEntries(archive_results.archived_binary);
 
   if (archive_results.success) {
     results_.type = ClientDownloadRequest::MAC_EXECUTABLE;
@@ -405,8 +388,8 @@
   }
   results_.archived_executable = archive_results.has_executable;
   results_.archived_archive = archive_results.has_archive;
-  CopyArchivedBinaries(archive_results.archived_binary,
-                       &results_.archived_binaries);
+  results_.archived_binaries =
+      SelectArchiveEntries(archive_results.archived_binary);
 
   if (archive_results.has_executable) {
     results_.type = ClientDownloadRequest::SEVEN_ZIP_COMPRESSED_EXECUTABLE;
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
index cc0bdc7..1c8f7951 100644
--- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
+++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
@@ -543,9 +543,9 @@
 ExtensionTelemetryService::CreateReport() {
   // Don't create a telemetry report if there were no signals generated (i.e.,
   // extension store is empty) AND there are no installed extensions currently.
-  std::unique_ptr<extensions::ExtensionSet> installed_extensions =
+  extensions::ExtensionSet installed_extensions =
       extension_registry_->GenerateInstalledExtensionsSet();
-  if (extension_store_.empty() && installed_extensions->is_empty()) {
+  if (extension_store_.empty() && installed_extensions.empty()) {
     return nullptr;
   }
 
@@ -583,11 +583,11 @@
   // them. Note that these installed extension reports will only contain
   // extension information (and no signal data).
   for (const auto& entry : extension_store_) {
-    installed_extensions->Remove(entry.first /* extension_id */);
+    installed_extensions.Remove(entry.first /* extension_id */);
   }
 
-  for (const scoped_refptr<const extensions::Extension> installed_entry :
-       *installed_extensions) {
+  for (const scoped_refptr<const extensions::Extension>& installed_entry :
+       installed_extensions) {
     auto report_entry_pb =
         std::make_unique<ExtensionTelemetryReportRequest_Report>();
 
@@ -827,10 +827,10 @@
 }
 
 void ExtensionTelemetryService::GetOffstoreExtensionDirs() {
-  std::unique_ptr<extensions::ExtensionSet> installed_extensions =
+  const extensions::ExtensionSet installed_extensions =
       extension_registry_->GenerateInstalledExtensionsSet();
 
-  for (const auto& extension : *installed_extensions) {
+  for (const auto& extension : installed_extensions) {
     if (!extension->from_webstore() &&
         !extensions::Manifest::IsComponentLocation(extension->location())) {
       offstore_extension_dirs_[extension->id()] = extension->path();
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc
index 294655c..06458ae 100644
--- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc
@@ -114,12 +114,12 @@
       continue;
     }
 
-    std::unique_ptr<const extensions::ExtensionSet> extensions(
+    const extensions::ExtensionSet extensions =
         extensions::ExtensionRegistryFactory::GetForBrowserContext(profile)
-            ->GenerateInstalledExtensionsSet());
+            ->GenerateInstalledExtensionsSet();
     extensions::ExtensionPrefs* extension_prefs =
         extensions::ExtensionPrefsFactory::GetForBrowserContext(profile);
-    for (const auto& extension : *extensions) {
+    for (const auto& extension : extensions) {
       base::Time install_time =
           extension_prefs->GetLastUpdateTime(extension->id());
       if (install_time > last_install_time) {
diff --git a/chrome/browser/sync/test/integration/sync_app_helper.cc b/chrome/browser/sync/test/integration/sync_app_helper.cc
index 05663d94..b0104b1 100644
--- a/chrome/browser/sync/test/integration/sync_app_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_app_helper.cc
@@ -90,10 +90,10 @@
 AppStateMap GetAppStates(Profile* profile) {
   AppStateMap app_state_map;
 
-  std::unique_ptr<const extensions::ExtensionSet> extensions(
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile)
-          ->GenerateInstalledExtensionsSet());
-  for (scoped_refptr<const extensions::Extension> extension : *extensions) {
+          ->GenerateInstalledExtensionsSet();
+  for (const auto& extension : extensions) {
     if (extension->is_app() &&
         extensions::util::ShouldSync(extension.get(), profile)) {
       const std::string& id = extension->id();
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.cc b/chrome/browser/sync/test/integration/sync_extension_helper.cc
index 016297e23a..606e46d 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.cc
@@ -110,12 +110,11 @@
     Profile* profile) const {
   std::vector<std::string> names;
 
-  std::unique_ptr<const extensions::ExtensionSet> extensions(
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile)
-          ->GenerateInstalledExtensionsSet());
-  for (extensions::ExtensionSet::const_iterator it = extensions->begin();
-       it != extensions->end(); ++it) {
-    names.push_back((*it)->name());
+          ->GenerateInstalledExtensionsSet();
+  for (const auto& extension : extensions) {
+    names.push_back(extension->name());
   }
 
   return names;
@@ -219,13 +218,13 @@
 
   ExtensionStateMap extension_state_map;
 
-  std::unique_ptr<const extensions::ExtensionSet> extensions(
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile)
-          ->GenerateInstalledExtensionsSet());
+          ->GenerateInstalledExtensionsSet();
 
   extensions::ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
-  for (const scoped_refptr<const Extension>& extension : *extensions) {
+  for (const scoped_refptr<const Extension>& extension : extensions) {
     const std::string& id = extension->id();
     ExtensionState& extension_state = extension_state_map[id];
     extension_state.enabled_state = extension_service->IsExtensionEnabled(id)
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 851cacf..c9a644a 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -411,13 +411,11 @@
 
   std::string current_theme = GetThemeID();
   std::vector<std::string> remove_list;
-  std::unique_ptr<const extensions::ExtensionSet> extensions(
+  const extensions::ExtensionSet extensions =
       extensions::ExtensionRegistry::Get(profile_)
-          ->GenerateInstalledExtensionsSet());
+          ->GenerateInstalledExtensionsSet();
   extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
-  for (extensions::ExtensionSet::const_iterator it = extensions->begin();
-       it != extensions->end(); ++it) {
-    const extensions::Extension* extension = it->get();
+  for (const auto& extension : extensions) {
     if (extension->is_theme() && extension->id() != current_theme) {
       // Only uninstall themes which are not disabled or are disabled with
       // reason DISABLE_USER_ACTION. We cannot blanket uninstall all disabled
@@ -425,7 +423,7 @@
       int disable_reason = prefs->GetDisableReasons(extension->id());
       if (!prefs->IsExtensionDisabled(extension->id()) ||
           disable_reason == extensions::disable_reason::DISABLE_USER_ACTION) {
-        remove_list.push_back((*it)->id());
+        remove_list.push_back(extension->id());
       }
     }
   }
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn
index abea7b2b9..59c235eb 100644
--- a/chrome/browser/ui/android/omnibox/BUILD.gn
+++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -124,6 +124,7 @@
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapter.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java",
@@ -435,6 +436,7 @@
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapterUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinderUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantActionsHandlerUnitTest.java",
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml b/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml
index d39cfd6..d424c2a 100644
--- a/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml
+++ b/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml
@@ -72,7 +72,8 @@
     <dimen name="omnibox_carousel_suggestion_padding">12dp</dimen>
     <dimen name="omnibox_carousel_suggestion_small_bottom_padding">4dp</dimen>
     <dimen name="omnibox_carousel_icon_rounding_radius">4dp</dimen>
-    <dimen name="omnibox_pedal_suggestion_pedal_height">48dp</dimen>
+    <dimen name="omnibox_action_chips_container_height">48dp</dimen>
+    <dimen name="omnibox_action_chip_spacing">8dp</dimen>
     <dimen name="omnibox_pedal_suggestion_icon_size">18dp</dimen>
     <dimen name="omnibox_pedal_suggestion_text_vertical_padding">6dp</dimen>
 
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/styles.xml b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
index 73c7f06..c2d672b 100644
--- a/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
+++ b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
@@ -31,11 +31,11 @@
         <item name="android:layout_height">match_parent</item>
     </style>
 
-    <style name="OmniboxPedalChipThemeOverlay">
-        <item name="chipStyle">@style/OmniboxPedalChip</item>
+    <style name="OmniboxActionChipThemeOverlay">
+        <item name="chipStyle">@style/OmniboxActionChip</item>
     </style>
 
-    <style name="OmniboxPedalChip" parent="SuggestionChip">
+    <style name="OmniboxActionChip" parent="SuggestionChip">
         <item name="iconWidth">@dimen/omnibox_pedal_suggestion_icon_size</item>
         <item name="iconHeight">@dimen/omnibox_pedal_suggestion_icon_size</item>
         <item name="allowMultipleLines">true</item>
@@ -43,4 +43,12 @@
         <item name="textAlignStart">true</item>
     </style>
 
+    <style name="OmniboxIncognitoActionChipThemeOverlay">
+        <item name="chipStyle">@style/OmniboxIncognitoActionChip</item>
+    </style>
+
+    <style name="OmniboxIncognitoActionChip" parent="OmniboxActionChip">
+        <item name="chipColor">@color/default_bg_color_dark</item>
+        <item name="primaryTextAppearance">@style/TextAppearance.TextSmall.Primary.Baseline.Light</item>
+    </style>
 </resources>
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
index a09cbbe..abc8f44 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
@@ -25,9 +25,9 @@
 import org.chromium.components.omnibox.AutocompleteMatch;
 import org.chromium.components.omnibox.action.OmniboxPedal;
 import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyModel;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
@@ -101,8 +101,13 @@
      */
     protected void setPedalList(
             PropertyModel model, @NonNull List<OmniboxPedal> omniboxPedalList, int position) {
-        final int pedalsCount = omniboxPedalList.size();
-        final List<ListItem> modelList = new ArrayList<>(pedalsCount);
+        var modelList = new ModelList();
+
+        // The header item increases lead-in padding before the first actual chip is shown.
+        // In default state, the chips will align with the suggestion text, but when scrolled
+        // the chips may show up under the decoration.
+        modelList.add(
+                new ListItem(PedalSuggestionViewProperties.ViewType.HEADER, new PropertyModel()));
 
         for (OmniboxPedal chip : omniboxPedalList) {
             final var chipIcon = mOmniboxPedalDelegate.getIcon(chip);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java
index c922f05..b38bddb 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java
@@ -10,26 +10,20 @@
 
 import androidx.annotation.LayoutRes;
 import androidx.annotation.NonNull;
-import androidx.annotation.Px;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
 import org.chromium.chrome.browser.omnibox.suggestions.base.SimpleVerticalLayoutView;
-import org.chromium.components.browser_ui.widget.chips.ChipView;
-
-import java.util.ArrayList;
-import java.util.List;
 
 /**
- * Base layout for pedals suggestion types. This is a {@link BaseSuggestionView} with a pedal under
- * it.
+ * Base layout for pedals suggestion types. This is a {@link BaseSuggestionView} with a list of
+ * Action chips.
  *
  * @param <T> The type of View being wrapped by BaseSuggestionView.
  */
 public class PedalSuggestionView<T extends View> extends SimpleVerticalLayoutView {
     private final @NonNull BaseSuggestionView<T> mBaseSuggestionView;
-    private final @NonNull List<PedalView> mPedalList;
+    private final @NonNull PedalView mPedalView;
 
     /**
      * Constructs a new suggestion view and inflates supplied layout as the contents view.
@@ -39,28 +33,16 @@
      */
     public PedalSuggestionView(Context context, @LayoutRes int layoutId) {
         super(context);
+        setFocusable(true);
         mBaseSuggestionView = new BaseSuggestionView<T>(context, layoutId);
+        mPedalView = new PedalView(context);
         addView(mBaseSuggestionView);
-
-        mPedalList = new ArrayList<>();
-        PedalView pedal = new PedalView(getContext());
-        final @Px int pedalSuggestionSizePx = context.getResources().getDimensionPixelSize(
-                R.dimen.omnibox_pedal_suggestion_pedal_height);
-        final @Px int pedalStartPaddingPx =
-                getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_icon_area_size);
-        pedal.setPaddingRelative(pedalStartPaddingPx, 0, 0, 0);
-        pedal.getChipView().setMinimumHeight(pedalSuggestionSizePx);
-        addView(pedal);
-        mPedalList.add(pedal);
+        addView(mPedalView);
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        // TODO(crbug/1411871): implement proper keyboard navigation for actions.
-        if (mPedalList.size() > 0) {
-            return mPedalList.get(0).onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
-        }
-        return false;
+        return mPedalView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
     }
 
     /** @return base suggestion view. */
@@ -69,14 +51,14 @@
         return mBaseSuggestionView;
     }
 
-    /** @return The {@link ChipView} in this view. */
+    /** @return The {@link PedalView} in this view. */
     @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
-    public ChipView getPedalChipView() {
-        return mPedalList.get(0).getChipView();
+    public PedalView getPedalView() {
+        return mPedalView;
     }
 
-    /** @return The {@link PedalView} in this view. */
-    PedalView getPedalView() {
-        return mPedalList.get(0);
+    @Override
+    public boolean isFocused() {
+        return super.isFocused() || (isSelected() && !isInTouchMode());
     }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java
index 7e5ea1ac..3da0f20 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java
@@ -5,27 +5,30 @@
 package org.chromium.chrome.browser.omnibox.suggestions.pedal;
 
 import android.view.View;
+import android.view.ViewGroup;
 
+import androidx.annotation.NonNull;
 import androidx.core.view.ViewCompat;
 
-import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
+import org.chromium.chrome.browser.omnibox.OmniboxFeatures;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.DropdownCommonProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewBinder;
+import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
+import org.chromium.components.browser_ui.widget.chips.ChipView;
 import org.chromium.components.browser_ui.widget.chips.ChipViewBinder;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder;
 
-import java.util.List;
-
 /**
  * Binds chip suggestion view properties.
  * @param <T> The inner content view type being updated.
  */
 public final class PedalSuggestionViewBinder<T extends View>
         implements ViewBinder<PropertyModel, PedalSuggestionView<T>, PropertyKey> {
+    private static final ViewBinder<PropertyModel, View, PropertyKey> NOOP_BINDER = (m, v, p) -> {};
     private final BaseSuggestionViewBinder<T> mBaseViewBinder;
 
     /**
@@ -42,27 +45,17 @@
         mBaseViewBinder.bind(model, view.getBaseSuggestionView(), propertyKey);
 
         if (PedalSuggestionViewProperties.PEDAL_LIST == propertyKey) {
-            List<ListItem> chipList = model.get(PedalSuggestionViewProperties.PEDAL_LIST);
-            // TODO(crbug/1418077): Turn this into a proper MVC.
-            // We're introducing support for multiple chips (not landed yet) and migrating from
-            // FrameView to RecyclerView.
-            PropertyModel chipModel = chipList.get(0).model;
-            for (var property : chipModel.getAllSetProperties()) {
-                ChipViewBinder.bind(chipModel, view.getPedalChipView(), property);
-            }
+            var isIncognito = model.get(SuggestionCommonProperties.COLOR_SCHEME)
+                    == BrandedColorScheme.INCOGNITO;
+            var chipList = model.get(PedalSuggestionViewProperties.PEDAL_LIST);
+            var adapter = new PedalViewAdapter(chipList);
+            adapter.registerType(PedalSuggestionViewProperties.ViewType.HEADER,
+                    PedalSuggestionViewBinder::createHeaderView, NOOP_BINDER);
+            adapter.registerType(PedalSuggestionViewProperties.ViewType.PEDAL_VIEW,
+                    parent -> createChipView(parent, isIncognito), ChipViewBinder::bind);
+            view.getPedalView().setAdapter(adapter);
         } else if (SuggestionCommonProperties.COLOR_SCHEME == propertyKey) {
-            BaseSuggestionViewBinder.applySelectableBackground(model, view.getPedalView());
-            // Apply changes to Chips as well.
-            // Currently chips work well in light and dark themes, but poorly in an Incognito mode.
-            // Need to research how to plumb styling properly so that Incognito mode is properly
-            // reflected.
-            List<ListItem> chipList = model.get(PedalSuggestionViewProperties.PEDAL_LIST);
-            var brandedColorScheme = model.get(SuggestionCommonProperties.COLOR_SCHEME);
-            var chip = view.getPedalChipView();
-            chip.setBackgroundColor(BaseSuggestionViewBinder.getSuggestionBackgroundColor(
-                    model, view.getContext()));
-            chip.setTextColor(OmniboxResourceProvider.getSuggestionPrimaryTextColor(
-                    view.getContext(), brandedColorScheme));
+            BaseSuggestionViewBinder.applySelectableBackground(model, view);
         } else if (SuggestionCommonProperties.LAYOUT_DIRECTION == propertyKey) {
             ViewCompat.setLayoutDirection(
                     view.getPedalView(), model.get(SuggestionCommonProperties.LAYOUT_DIRECTION));
@@ -70,4 +63,34 @@
             BaseSuggestionViewBinder.updateMargin(model, view);
         }
     }
+
+    /**
+     * Create a view element that provides horizontal alignment.
+     */
+    private static View createHeaderView(@NonNull ViewGroup parent) {
+        var res = parent.getResources();
+
+        boolean showModernizedSuggestionsList =
+                OmniboxFeatures.shouldShowModernizeVisualUpdate(parent.getContext());
+
+        int actionChipHeaderWidth =
+                res.getDimensionPixelSize(showModernizedSuggestionsList
+                                ? R.dimen.omnibox_suggestion_icon_area_size_modern
+                                : R.dimen.omnibox_suggestion_icon_area_size)
+                -
+                // We apply spacing to every element, 1/2 on the left and 1/2 on the right.
+                // Lead-in header receives both left and right spacing, but we also need to erase
+                // the space before the first chip.
+                res.getDimensionPixelSize(R.dimen.omnibox_action_chip_spacing) * 3 / 2;
+
+        var view = new View(parent.getContext());
+        view.setMinimumWidth(actionChipHeaderWidth);
+        return view;
+    }
+
+    public static ChipView createChipView(@NonNull ViewGroup parent, boolean isIncognito) {
+        return new ChipView(parent.getContext(),
+                isIncognito ? R.style.OmniboxIncognitoActionChipThemeOverlay
+                            : R.style.OmniboxActionChipThemeOverlay);
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java
index 75f6237..9ef9a408 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java
@@ -7,14 +7,13 @@
 import androidx.annotation.IntDef;
 
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.List;
 
 /**
  * The properties associated with rendering the pedal suggestion view.
@@ -25,19 +24,21 @@
      * Views below can be used by any instance of the carousel, guaranteeing that each instance
      * will look like every other.
      */
-    @IntDef({ViewType.PEDAL_VIEW})
+    @IntDef({ViewType.HEADER, ViewType.PEDAL_VIEW})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ViewType {
+        /** Header element, used to provide leading space. */
+        public int HEADER = 0;
         /** Carousel item is a PedalView instance. */
-        public int PEDAL_VIEW = 0;
+        public int PEDAL_VIEW = 1;
     }
 
     /** Omnibox Pedal list descriptions. */
-    public static final WritableObjectPropertyKey<List<ListItem>> PEDAL_LIST =
+    public static final WritableObjectPropertyKey<ModelList> PEDAL_LIST =
             new WritableObjectPropertyKey<>();
 
     public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] {PEDAL_LIST};
 
     public static final PropertyKey[] ALL_KEYS =
             PropertyModel.concatKeys(ALL_UNIQUE_KEYS, SuggestionViewProperties.ALL_KEYS);
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java
index 5513e54ec..8b31739 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java
@@ -5,10 +5,15 @@
 package org.chromium.chrome.browser.omnibox.suggestions.pedal;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.view.KeyEvent;
-import android.widget.FrameLayout;
+import android.view.View;
 
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.Px;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
 
 import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
@@ -19,9 +24,8 @@
  * Chips should be initially horizontally aligned with the Content view and stretch to the end of
  * the encompassing BaseSuggestionView
  */
-public class PedalView extends FrameLayout {
-    private static final String TAG = "PedalView";
-    private final @NonNull ChipView mPedal;
+public class PedalView extends RecyclerView {
+    private @Nullable PedalViewAdapter mAdapter;
 
     /**
      * Constructs a new pedal view.
@@ -31,43 +35,53 @@
     public PedalView(Context context) {
         super(context);
 
-        setFocusable(true);
-        mPedal = new ChipView(context, R.style.OmniboxPedalChipThemeOverlay);
+        setItemAnimator(null);
+        setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
+        setMinimumHeight(getResources().getDimensionPixelSize(
+                R.dimen.omnibox_action_chips_container_height));
 
-        var layoutParams =
-                new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-        layoutParams.setMargins(0, 0, 0,
+        final @Px int actionChipSpacing =
+                getResources().getDimensionPixelSize(R.dimen.omnibox_action_chip_spacing);
+        addItemDecoration(new ItemDecoration() {
+            @Override
+            public void getItemOffsets(
+                    Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+                outRect.right = actionChipSpacing / 2;
+                outRect.left = actionChipSpacing / 2;
+            }
+        });
+
+        setPaddingRelative(0, 0, 0,
                 getResources().getDimensionPixelSize(
                         R.dimen.omnibox_suggestion_semicompact_padding));
-
-        addView(mPedal, layoutParams);
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
+        assert mAdapter != null;
+
         if (event.getKeyCode() == KeyEvent.KEYCODE_TAB) {
-            mPedal.setSelected(!mPedal.isSelected());
+            if (event.isShiftPressed()) {
+                mAdapter.selectPreviousItem();
+            } else {
+                mAdapter.selectNextItem();
+            }
             return true;
-        } else if (KeyNavigationUtil.isEnter(event) && mPedal.isSelected()) {
-            return mPedal.performClick();
+        } else if (KeyNavigationUtil.isEnter(event)) {
+            var chip = mAdapter.getSelectedView();
+            if (chip != null) return chip.performClick();
         }
 
         return super.onKeyDown(keyCode, event);
     }
 
+    public void setAdapter(@Nullable PedalViewAdapter adapter) {
+        super.setAdapter(adapter);
+        mAdapter = adapter;
+    }
+
     @Override
     public void setSelected(boolean isSelected) {
-        super.setSelected(isSelected);
-        mPedal.setSelected(false);
-    }
-
-    /** @return The {@link ChipView} in this view. */
-    ChipView getChipView() {
-        return mPedal;
-    }
-
-    @Override
-    public boolean isFocused() {
-        return super.isFocused() || (isSelected() && !isInTouchMode());
+        mAdapter.resetSelection();
     }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapter.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapter.java
new file mode 100644
index 0000000..1883e446
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapter.java
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// 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.omnibox.suggestions.pedal;
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.LayoutManager;
+
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
+import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
+
+/** ModelListAdapter for Omnibox Suggestion Action Chips. */
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+public class PedalViewAdapter extends SimpleRecyclerViewAdapter {
+    // The 0th element is always the lead-in header.
+    private static final int FIRST_CHIP_INDEX = 1;
+    private int mSelectedItem = RecyclerView.NO_POSITION;
+    private LayoutManager mLayoutManager;
+
+    PedalViewAdapter(ModelList data) {
+        super(data);
+    }
+
+    @Override
+    public void onAttachedToRecyclerView(@NonNull RecyclerView view) {
+        super.onAttachedToRecyclerView(view);
+        mLayoutManager = view.getLayoutManager();
+        mSelectedItem = RecyclerView.NO_POSITION;
+    }
+
+    /**
+     * Ensures selection is reset, with no views being highlighted.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public void resetSelection() {
+        setSelectedItem(RecyclerView.NO_POSITION);
+    }
+
+    /**
+     * Retrieve currently selected element.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public @Nullable View getSelectedView() {
+        return mLayoutManager.findViewByPosition(mSelectedItem);
+    }
+
+    /**
+     * Move focus to the next view, if possible, otherwise clear all selections.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public void selectNextItem() {
+        // Rotate: Nothing -> First chip -> ... -> Last chip -> Nothing.
+        var nextItem = FIRST_CHIP_INDEX;
+        if (mSelectedItem != RecyclerView.NO_POSITION) nextItem = mSelectedItem + 1;
+        if (nextItem >= getItemCount()) nextItem = RecyclerView.NO_POSITION;
+        setSelectedItem(nextItem);
+    }
+
+    /**
+     * Move focus to the previous view, if possible, otherwise clear all selections.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public void selectPreviousItem() {
+        // Rotate: Nothing -> Last chip -> ... -> First chip -> Nothing.
+        var prevItem = RecyclerView.NO_POSITION;
+        if (mSelectedItem > FIRST_CHIP_INDEX) prevItem = mSelectedItem - 1;
+        if (mSelectedItem == RecyclerView.NO_POSITION) prevItem = getItemCount() - 1;
+        setSelectedItem(prevItem);
+    }
+
+    /**
+     * Move focus to another view, ensuring that the view is fully visible.
+     *
+     * @param index The index of a view to select, or RecyclerView.NO_POSITION to clear selection.
+     */
+    @VisibleForTesting
+    public void setSelectedItem(int index) {
+        assert index == RecyclerView.NO_POSITION
+                || (index >= FIRST_CHIP_INDEX && index < getItemCount());
+        assert mLayoutManager != null;
+
+        View previousSelectedView = getSelectedView();
+        if (previousSelectedView != null) previousSelectedView.setSelected(false);
+
+        mSelectedItem = index;
+        mLayoutManager.scrollToPosition(index);
+
+        View currentSelectedView = getSelectedView();
+        if (currentSelectedView != null) currentSelectedView.setSelected(true);
+    }
+
+    @VisibleForTesting
+    public int getSelectedItemForTesting() {
+        return mSelectedItem;
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapterUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapterUnitTest.java
new file mode 100644
index 0000000..caa2078e
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalViewAdapterUnitTest.java
@@ -0,0 +1,200 @@
+// Copyright 2023 The Chromium Authors
+// 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.omnibox.suggestions.pedal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.LayoutManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.components.browser_ui.widget.chips.ChipProperties;
+import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
+import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * Tests for {@link PedalViewAdapter}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class PedalViewAdapterUnitTest {
+    private static final int HEADER_INDEX = 0;
+    private static final int CHIP_1_INDEX = 1;
+    private static final int CHIP_2_INDEX = 2;
+    private static final int CHIP_3_WITH_NO_VIEW_INDEX = 3;
+    public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule();
+    private @Mock View mHeader;
+    private @Mock View mChip1;
+    private @Mock View mChip2;
+    private @Mock LayoutManager mLayoutManager;
+
+    private ModelList mModel = new ModelList();
+    private RecyclerView mRecyclerView;
+    private PedalViewAdapter mAdapter = new PedalViewAdapter(mModel);
+
+    @Before
+    public void setUp() {
+        // Header
+        mModel.add(new ListItem(PedalSuggestionViewProperties.ViewType.HEADER,
+                new PropertyModel(ChipProperties.ALL_KEYS)));
+        doReturn(mHeader).when(mLayoutManager).findViewByPosition(HEADER_INDEX);
+
+        // Chip with View, 1
+        mModel.add(new ListItem(PedalSuggestionViewProperties.ViewType.PEDAL_VIEW,
+                new PropertyModel(ChipProperties.ALL_KEYS)));
+        doReturn(mChip1).when(mLayoutManager).findViewByPosition(CHIP_1_INDEX);
+
+        // Chip with View, 2
+        mModel.add(new ListItem(PedalSuggestionViewProperties.ViewType.PEDAL_VIEW,
+                new PropertyModel(ChipProperties.ALL_KEYS)));
+        doReturn(mChip2).when(mLayoutManager).findViewByPosition(CHIP_2_INDEX);
+
+        // Chip with no View, 3
+        mModel.add(new ListItem(PedalSuggestionViewProperties.ViewType.PEDAL_VIEW,
+                new PropertyModel(ChipProperties.ALL_KEYS)));
+
+        mRecyclerView = new RecyclerView(ContextUtils.getApplicationContext());
+        mRecyclerView.setLayoutManager(mLayoutManager);
+        mRecyclerView.setAdapter(mAdapter);
+    }
+
+    @Test
+    public void setSelectedItem_fromNoSelection() {
+        mAdapter.setSelectedItem(CHIP_1_INDEX);
+        verify(mChip1).setSelected(true);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void setSelectedItem_intoNewSelection() {
+        mAdapter.setSelectedItem(CHIP_1_INDEX);
+        verify(mChip1).setSelected(true);
+
+        mAdapter.setSelectedItem(CHIP_2_INDEX);
+        verify(mChip1).setSelected(false);
+        verify(mChip2).setSelected(true);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void setSelectedItem_intoNoView() {
+        mAdapter.setSelectedItem(CHIP_3_WITH_NO_VIEW_INDEX);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void setSelectedItem_fromNoView() {
+        mAdapter.setSelectedItem(CHIP_3_WITH_NO_VIEW_INDEX);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+
+        mAdapter.setSelectedItem(CHIP_2_INDEX);
+        verify(mChip2).setSelected(true);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void setSelectedItem_intoNoSelection() {
+        mAdapter.setSelectedItem(CHIP_1_INDEX);
+        verify(mChip1).setSelected(true);
+
+        mAdapter.setSelectedItem(RecyclerView.NO_POSITION);
+        verify(mChip1).setSelected(false);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test(expected = AssertionError.class)
+    public void setSelectedItem_rejectPositionOutOfRange() {
+        mAdapter.setSelectedItem(mAdapter.getItemCount());
+    }
+
+    @Test(expected = AssertionError.class)
+    public void setSelectedItem_rejectHeaderView() {
+        mAdapter.setSelectedItem(0);
+    }
+
+    // The following tests build on top of the setSelectedItem tests.
+    // The method setSelectedItem stays at the heart of all of the functionality below
+    // and is tested thoroughly by dedicated tests.
+    @Test
+    public void selectNextItem_loopsAround() {
+        assertEquals(RecyclerView.NO_POSITION, mAdapter.getSelectedItemForTesting());
+
+        mAdapter.selectNextItem();
+        assertEquals(CHIP_1_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mChip1).setSelected(true);
+        verify(mLayoutManager).scrollToPosition(CHIP_1_INDEX);
+
+        mAdapter.selectNextItem();
+        assertEquals(CHIP_2_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mChip1).setSelected(false);
+        verify(mChip2).setSelected(true);
+        verify(mLayoutManager).scrollToPosition(CHIP_2_INDEX);
+
+        mAdapter.selectNextItem();
+        assertEquals(CHIP_3_WITH_NO_VIEW_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mChip2).setSelected(false);
+        verify(mLayoutManager).scrollToPosition(CHIP_3_WITH_NO_VIEW_INDEX);
+
+        mAdapter.selectNextItem();
+        assertEquals(RecyclerView.NO_POSITION, mAdapter.getSelectedItemForTesting());
+
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void selectPreviousItem_loopsAround() {
+        assertEquals(RecyclerView.NO_POSITION, mAdapter.getSelectedItemForTesting());
+
+        mAdapter.selectPreviousItem();
+        assertEquals(CHIP_3_WITH_NO_VIEW_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mLayoutManager).scrollToPosition(CHIP_3_WITH_NO_VIEW_INDEX);
+
+        mAdapter.selectPreviousItem();
+        assertEquals(CHIP_2_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mChip2).setSelected(true);
+        verify(mLayoutManager).scrollToPosition(CHIP_2_INDEX);
+
+        mAdapter.selectPreviousItem();
+        assertEquals(CHIP_1_INDEX, mAdapter.getSelectedItemForTesting());
+        verify(mChip2).setSelected(false);
+        verify(mChip1).setSelected(true);
+        verify(mLayoutManager).scrollToPosition(CHIP_1_INDEX);
+
+        mAdapter.selectPreviousItem();
+        assertEquals(RecyclerView.NO_POSITION, mAdapter.getSelectedItemForTesting());
+        verify(mChip1).setSelected(false);
+
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+
+    @Test
+    public void resetSelection_fromNoSelection() {
+        mAdapter.setSelectedItem(CHIP_1_INDEX);
+        verify(mChip1).setSelected(true);
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+
+        mAdapter.resetSelection();
+        verify(mChip1).setSelected(false);
+
+        assertEquals(RecyclerView.NO_POSITION, mAdapter.getSelectedItemForTesting());
+        verifyNoMoreInteractions(mHeader, mChip1, mChip2);
+    }
+}
diff --git a/chrome/browser/ui/ash/ash_shell_init.cc b/chrome/browser/ui/ash/ash_shell_init.cc
index 40b72b63..18f7cb3 100644
--- a/chrome/browser/ui/ash/ash_shell_init.cc
+++ b/chrome/browser/ui/ash/ash_shell_init.cc
@@ -36,10 +36,6 @@
 AshShellInit::AshShellInit() {
   CreateShell();
   ash::Shell::GetPrimaryRootWindow()->GetHost()->Show();
-
-  // Push browser feature flags to ash.
-  ash::features::SetWebUITabStripEnabled(
-      base::FeatureList::IsEnabled(features::kWebUITabStrip));
 }
 
 AshShellInit::~AshShellInit() {
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index 7e8dc65..26b7ebe2 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -205,6 +205,8 @@
   /* Omnibox colors. */ \
   E_CPONLY(kColorOmniboxAnswerIconBackground) \
   E_CPONLY(kColorOmniboxAnswerIconForeground) \
+  E_CPONLY(kColorOmniboxAnswerIconGM3Background) \
+  E_CPONLY(kColorOmniboxAnswerIconGM3Foreground) \
   E_CPONLY(kColorOmniboxBubbleOutline) \
   E_CPONLY(kColorOmniboxBubbleOutlineExperimentalKeywordMode) \
   E_CPONLY(kColorOmniboxChipBackground) \
@@ -219,6 +221,7 @@
   E_CPONLY(kColorOmniboxResultsButtonInkDropSelected) \
   E_CPONLY(kColorOmniboxResultsFocusIndicator) \
   E_CPONLY(kColorOmniboxResultsIcon) \
+  E_CPONLY(kColorOmniboxResultsIconGM3Background) \
   E_CPONLY(kColorOmniboxResultsIconSelected) \
   E_CPONLY(kColorOmniboxResultsStarterPackIcon) \
   E_CPONLY(kColorOmniboxResultsTextDimmed) \
diff --git a/chrome/browser/ui/color/omnibox_color_mixer.cc b/chrome/browser/ui/color/omnibox_color_mixer.cc
index eac1063..8b23acf 100644
--- a/chrome/browser/ui/color/omnibox_color_mixer.cc
+++ b/chrome/browser/ui/color/omnibox_color_mixer.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/color/chrome_color_provider_utils.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_mixer.h"
 #include "ui/color/color_provider.h"
@@ -205,4 +206,15 @@
         security_chip_color(gfx::kGoogleGrey500, gfx::kGoogleGrey700);
     mixer[kColorOmniboxSecurityChipDefault] = {kColorOmniboxSecurityChipSecure};
   }
+
+  // TODO(manukh): Figure out if we can use the blending defined above and in
+  //   `ui::` instead of hard coding these colors. That'll probably be safer for
+  //   e.g. when users use high contrast mode. But this is (hopefully) fine for
+  //   non-launch experiments.
+  mixer[kColorOmniboxResultsIconGM3Background] = ui::SelectBasedOnDarkInput(
+      kColorToolbar, SkColorSetRGB(48, 48, 48), SkColorSetRGB(242, 242, 242));
+  mixer[kColorOmniboxAnswerIconGM3Background] = ui::SelectBasedOnDarkInput(
+      kColorToolbar, SkColorSetRGB(0, 74, 119), SkColorSetRGB(211, 227, 253));
+  mixer[kColorOmniboxAnswerIconGM3Foreground] = ui::SelectBasedOnDarkInput(
+      kColorToolbar, SkColorSetRGB(194, 231, 255), SkColorSetRGB(4, 30, 73));
 }
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
index d97cfa7..e40fbbc 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
@@ -24,7 +24,6 @@
 content::WebContents* GetWebContentsFromPresentationRequest(
     const content::PresentationRequest& request) {
   auto* rfh = content::RenderFrameHost::FromID(request.render_frame_host_id);
-  DCHECK(rfh);
   return content::WebContents::FromRenderFrameHost(rfh);
 }
 
@@ -74,7 +73,9 @@
   // content API. Note that the content::MediaSession always exists, even when
   // the page has no media players.
   auto* web_contents = GetWebContentsFromPresentationRequest(request_);
-  DCHECK(web_contents);
+  if (!web_contents) {
+    return;
+  }
   auto* media_session = GetMediaSession(web_contents);
   DCHECK(media_session);
   media_session->AddObserver(observer_receiver_.BindNewPipeAndPassRemote());
@@ -111,7 +112,10 @@
     const base::flat_map<media_session::mojom::MediaSessionImageType,
                          std::vector<media_session::MediaImage>>& images) {
   auto* web_contents = GetWebContentsFromPresentationRequest(request_);
-  DCHECK(web_contents);
+  if (!web_contents) {
+    return;
+  }
+
   auto* media_session = GetMediaSession(web_contents);
   DCHECK(media_session);
   media_session::MediaImageManager manager(
@@ -188,17 +192,17 @@
   media_session::MediaMetadata data =
       metadata_.value_or(media_session::MediaMetadata{});
 
-  auto* web_contents = GetWebContentsFromPresentationRequest(request_);
-  DCHECK(web_contents);
   if (media_message_center::IsOriginGoodForDisplay(request_.frame_origin)) {
     // `request_` has more accurate origin info than `metadata_` e.g. when the
     // request is from within an iframe.
     data.source_title =
         media_message_center::GetOriginNameForDisplay(request_.frame_origin);
   }
+
+  auto* web_contents = GetWebContentsFromPresentationRequest(request_);
   // If not empty, then `metadata_.artist` is likely to contain information
   // more relevant than the page title.
-  if (data.artist.empty()) {
+  if (web_contents && data.artist.empty()) {
     data.artist = web_contents->GetTitle();
   }
   view_->UpdateWithMediaMetadata(data);
@@ -222,14 +226,15 @@
 
   // Otherwise, get one ourselves.
   auto* web_contents = GetWebContentsFromPresentationRequest(request_);
-  DCHECK(web_contents);
-  favicon::FaviconDriver* favicon_driver =
-      favicon::ContentFaviconDriver::FromWebContents(web_contents);
-  if (favicon_driver) {
-    view_->UpdateWithFavicon(favicon_driver->GetFavicon().AsImageSkia());
-  } else {
-    view_->UpdateWithFavicon(gfx::ImageSkia());
+  if (web_contents) {
+    favicon::FaviconDriver* favicon_driver =
+        favicon::ContentFaviconDriver::FromWebContents(web_contents);
+    if (favicon_driver) {
+      view_->UpdateWithFavicon(favicon_driver->GetFavicon().AsImageSkia());
+      return;
+    }
   }
+  view_->UpdateWithFavicon(gfx::ImageSkia());
 }
 
 void PresentationRequestNotificationItem::OnArtworkBitmap(
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 01dc9657..3fead79e 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1174,10 +1174,6 @@
   g_disable_revealer_delay_for_testing = disable;
 }
 
-void BrowserView::DisableTopControlsSlideForTesting() {
-  top_controls_slide_controller_.reset();
-}
-
 void BrowserView::InitStatusBubble() {
   status_bubble_ = std::make_unique<StatusBubbleViews>(contents_web_view_);
   contents_web_view_->SetStatusBubble(status_bubble_.get());
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index e24a154..86189b2 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -165,11 +165,6 @@
 
   void SetDownloadShelfForTest(DownloadShelf* download_shelf);
 
-  // This suppresses the slide behaviors of top-controls and so the top controls
-  // will stay showing under any situation. This is only for testing behaviors
-  // of top controls which should be visible always.
-  void DisableTopControlsSlideForTesting();
-
   // Initializes (or re-initializes) the status bubble.  We try to only create
   // the bubble once and re-use it for the life of the browser, but certain
   // events (such as changing enabling/disabling Aero on Win) can force a need
diff --git a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
index 4d5e7e1..e66d9953 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
@@ -43,18 +43,40 @@
 
 namespace {
 
-// The diameter of the answer layout images.
-static constexpr int kAnswerImageSize = 24;
+// The edge length of the favicon, answer icon, and entity backgrounds if the
+// kUniformRowHeight flag is enabled.
+static constexpr int kUniformRowHeightIconSize = 28;
+
+// The edge length of favicon backgrounds.
+int GetIconSize() {
+  // When `kSquareSuggestIconIcons` is disabled, icons don't have backgrounds
+  // and aren't resized in `OmniboxMatchCellView`.
+  DCHECK(OmniboxFieldTrial::kSquareSuggestIconIcons.Get());
+  return kUniformRowHeightIconSize;
+}
+
+// The size (edge length or diameter) of the answer icon backgrounds (which may
+// be squares or circles).
+int GetAnswerImageSize() {
+  return OmniboxFieldTrial::kSquareSuggestIconAnswers.Get()
+             ? kUniformRowHeightIconSize  // Square edge length.
+             : 24;                        // Circle diameter.
+}
 
 // The edge length of the entity suggestions images.
-static constexpr int kEntityImageSize = 32;
-// The edge length of the entity suggestions if the
-// kUniformRowHeight flag is enabled
-static constexpr int kEntityImageSizeSmall = 28;
-
 int GetEntityImageSize() {
-  return OmniboxFieldTrial::IsUniformRowHeightEnabled() ? kEntityImageSizeSmall
-                                                        : kEntityImageSize;
+  return OmniboxFieldTrial::IsUniformRowHeightEnabled()
+             ? kUniformRowHeightIconSize
+             : 32;
+}
+
+// The radius of the rounded square backgrounds of icons, answers, and entities.
+int GetIconAndImageCornerRadius() {
+  // When both params are disabled, icons and images won't have rounded square
+  // backgrounds.
+  DCHECK(OmniboxFieldTrial::kSquareSuggestIconAnswers.Get() ||
+         OmniboxFieldTrial::kSquareSuggestIconIcons.Get());
+  return 4;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -240,17 +262,32 @@
   icon_view_->SetSize(has_image_ ? gfx::Size()
                                  : icon_view_->GetPreferredSize());
 
+  // Used for non-weather answer images (e.g. calc answers).
   const auto apply_vector_icon = [=](const gfx::VectorIcon& vector_icon) {
     const auto* color_provider = GetColorProvider();
+    const auto foreground_color_id =
+        OmniboxFieldTrial::kSquareSuggestIconAnswers.Get()
+            ? kColorOmniboxAnswerIconGM3Foreground
+            : kColorOmniboxAnswerIconForeground;
+    const auto background_color_id =
+        OmniboxFieldTrial::kSquareSuggestIconAnswers.Get()
+            ? kColorOmniboxAnswerIconGM3Background
+            : kColorOmniboxAnswerIconBackground;
     const auto& icon = gfx::CreateVectorIcon(
-        vector_icon,
-        color_provider->GetColor(kColorOmniboxAnswerIconForeground));
+        vector_icon, color_provider->GetColor(foreground_color_id));
     answer_image_view_->SetImageSize(
-        gfx::Size(kAnswerImageSize, kAnswerImageSize));
-    answer_image_view_->SetImage(
-        gfx::ImageSkiaOperations::CreateImageWithCircleBackground(
-            kAnswerImageSize / 2,
-            color_provider->GetColor(kColorOmniboxAnswerIconBackground), icon));
+        gfx::Size(GetAnswerImageSize(), GetAnswerImageSize()));
+    if (OmniboxFieldTrial::kSquareSuggestIconAnswers.Get()) {
+      answer_image_view_->SetImage(
+          gfx::ImageSkiaOperations::CreateImageWithRoundRectBackground(
+              GetAnswerImageSize(), GetIconAndImageCornerRadius(),
+              color_provider->GetColor(background_color_id), icon));
+    } else {
+      answer_image_view_->SetImage(
+          gfx::ImageSkiaOperations::CreateImageWithCircleBackground(
+              GetAnswerImageSize() / 2,
+              color_provider->GetColor(background_color_id), icon));
+    }
   };
   if (match.type == AutocompleteMatchType::CALCULATOR) {
     apply_vector_icon(omnibox::kAnswerCalculatorIcon);
@@ -266,7 +303,7 @@
       if (match.answer->type() == SuggestionAnswer::ANSWER_TYPE_WEATHER) {
         // Weather icons are downloaded. We just need to set the correct size.
         answer_image_view_->SetImageSize(
-            gfx::Size(kAnswerImageSize, kAnswerImageSize));
+            gfx::Size(GetAnswerImageSize(), GetAnswerImageSize()));
       } else {
         apply_vector_icon(
             AutocompleteMatch::AnswerTypeToAnswerIcon(match.answer->type()));
@@ -292,6 +329,18 @@
           : std::u16string());
 }
 
+void OmniboxMatchCellView::SetIcon(const gfx::ImageSkia& image) {
+  if (OmniboxFieldTrial::kSquareSuggestIconIcons.Get()) {
+    icon_view_->SetImage(
+        gfx::ImageSkiaOperations::CreateImageWithRoundRectBackground(
+            GetIconSize(), GetIconAndImageCornerRadius(),
+            GetColorProvider()->GetColor(kColorOmniboxResultsIconGM3Background),
+            image));
+  } else {
+    icon_view_->SetImage(image);
+  }
+}
+
 void OmniboxMatchCellView::SetImage(const gfx::ImageSkia& image) {
   answer_image_view_->SetImage(image);
 
@@ -311,9 +360,8 @@
 
 gfx::Insets OmniboxMatchCellView::GetInsets() const {
   const bool single_line = layout_style_ == LayoutStyle::ONE_LINE_SUGGESTION;
-
   const int vertical_margin =
-      OmniboxFieldTrial::IsUniformRowHeightEnabled() && has_image_
+      OmniboxFieldTrial::IsUniformRowHeightEnabled()
           ? OmniboxFieldTrial::kRichSuggestionVerticalMargin.Get()
           : ChromeLayoutProvider::Get()->GetDistanceMetric(
                 single_line ? DISTANCE_OMNIBOX_CELL_VERTICAL_PADDING
diff --git a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.h b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.h
index a28d4179..1ea34ed 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.h
@@ -69,6 +69,9 @@
   void OnMatchUpdate(const OmniboxResultView* result_view,
                      const AutocompleteMatch& match);
 
+  // Set's the `icon_view_` image, possibly with a rounded square background.
+  void SetIcon(const gfx::ImageSkia& image);
+
   // Sets the answer image and, if the image is not square, sets the answer size
   // proportional to the image size to preserve its aspect ratio.
   void SetImage(const gfx::ImageSkia& image);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index a60f0b6..91c51f9 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -45,6 +45,7 @@
 #include "ui/color/color_id.h"
 #include "ui/events/event.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/image_button.h"
@@ -303,7 +304,8 @@
   //       SetMatch() once (rather than repeatedly, as happens here). There may
   //       be an optimization opportunity here.
   // TODO(dschuyler): determine whether to optimize the color changes.
-  suggestion_view_->icon()->SetImage(GetIcon().ToImageSkia());
+  suggestion_view_->SetIcon(*GetIcon().ToImageSkia());
+
   keyword_view_->icon()->SetImage(ui::ImageModel::FromVectorIcon(
       omnibox::kKeywordSearchIcon, icon_color_id,
       GetLayoutConstant(LOCATION_BAR_ICON_SIZE)));
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
index ae52225..f0742e57 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
@@ -397,6 +397,10 @@
               IDS_PLUGIN_VM_INSTALLER_ERROR_MESSAGE_LOGIC_ERROR, app_name_,
               base::NumberToString16(
                   static_cast<std::underlying_type_t<Reason>>(*reason_)));
+        case Reason::EXISTING_IMAGE_INVALID:
+          return l10n_util::GetStringFUTF16(
+              IDS_PLUGIN_VM_INSTALLER_ERROR_INVALID_IMAGE_MESSAGE,
+              base::UTF8ToUTF16(plugin_vm::kPluginVmName), app_name_);
         case Reason::OFFLINE:
           return l10n_util::GetStringUTF16(
               IDS_PLUGIN_VM_INSTALLER_ERROR_OFFLINE_MESSAGE);
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
index a297781..b586884 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
@@ -373,7 +373,9 @@
   // Setup concierge and the dispatcher for VM already imported.
   vm_tools::concierge::ListVmDisksResponse list_vm_disks_response;
   list_vm_disks_response.set_success(true);
-  list_vm_disks_response.add_images();
+  auto* image = list_vm_disks_response.add_images();
+  image->set_name(plugin_vm::kPluginVmName);
+  image->set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_PLUGINVM);
   fake_concierge_client_->set_list_vm_disks_response(list_vm_disks_response);
 
   vm_tools::plugin_dispatcher::ListVmResponse list_vms_response;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 01bb0fb6..721f95f 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -72,10 +72,7 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/public/cpp/tablet_mode.h"
 #include "ash/public/cpp/window_properties.h"  // nogncheck
-#include "ui/aura/window_delegate.h"
-#include "ui/wm/core/coordinate_conversion.h"
 #endif
 
 #if BUILDFLAG(IS_MAC)
@@ -151,76 +148,6 @@
 
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-
-// In Chrome OS tablet mode, when dragging a tab/tabs around, the desired
-// browser size during dragging is one-fourth of the workspace size or the
-// window's minimum size.
-gfx::Rect GetDraggedBrowserBoundsInTabletMode(aura::Window* window) {
-  const gfx::Rect work_area =
-      display::Screen::GetScreen()->GetDisplayNearestWindow(window).work_area();
-  gfx::Size minimum_size;
-  if (window->delegate())
-    minimum_size = window->delegate()->GetMinimumSize();
-
-  gfx::Rect bounds(window->GetBoundsInScreen());
-  bounds.set_width(std::max(work_area.width() / 2, minimum_size.width()));
-  bounds.set_height(std::max(work_area.height() / 2, minimum_size.height()));
-  return bounds;
-}
-
-// Store the current window bounds if we're in Chrome OS tablet mode and tab
-// dragging is allowed on browser windows.
-void StoreCurrentDraggedBrowserBoundsInTabletMode(
-    aura::Window* window,
-    const gfx::Rect& bounds_in_screen) {
-  if (ash::TabletMode::Get()->InTabletMode()) {
-    // The bounds that is stored in ash::kRestoreBoundsOverrideKey will be used
-    // by DragDetails to calculate the window bounds during dragging in tablet
-    // mode.
-    window->SetProperty(ash::kRestoreBoundsOverrideKey,
-                        new gfx::Rect(bounds_in_screen));
-  }
-}
-
-// Returns true if |context| is currently showing in overview mode in Chrome
-// OS.
-bool IsShowingInOverview(TabDragContext* context) {
-  return context && GetWindowForTabDraggingProperties(context)->GetProperty(
-                        chromeos::kIsShowingInOverviewKey);
-}
-
-// Returns true if we should attach the dragged tabs into |target_context|
-// after the drag ends. Currently it only happens on Chrome OS, when the dragged
-// tabs are dragged over an overview window, we should not try to attach it
-// to the overview window during dragging, but should wait to do so until the
-// drag ends.
-bool ShouldAttachOnEnd(TabDragContext* target_context) {
-  return IsShowingInOverview(target_context);
-}
-
-// Returns true if |context| can detach from the current context and attach
-// into another eligible browser window's context.
-bool CanDetachFromTabStrip(TabDragContext* context) {
-  return context && GetWindowForTabDraggingProperties(context)->GetProperty(
-                        chromeos::kCanAttachToAnotherWindowKey);
-}
-
-#else
-bool IsShowingInOverview(TabDragContext* context) {
-  return false;
-}
-
-bool ShouldAttachOnEnd(TabDragContext* target_context) {
-  return false;
-}
-
-bool CanDetachFromTabStrip(TabDragContext* context) {
-  return true;
-}
-
-#endif  // #if BUILDFLAG(IS_CHROMEOS_ASH)
-
 void SetCapture(TabDragContext* context) {
   context->GetWidget()->SetCapture(context);
 }
@@ -365,84 +292,6 @@
 
 TabDragController::TabDragData::TabDragData(TabDragData&&) = default;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-
-// The class to track the current deferred target tabstrip and also to observe
-// its native window's property chromeos::kIsDeferredTabDraggingTargetWindowKey.
-// The reason we need to observe the window property is the property might be
-// cleared outside of TabDragController (i.e. by ash), and we should update the
-// tracked deferred target tabstrip in this case.
-class TabDragController::DeferredTargetTabstripObserver
-    : public aura::WindowObserver {
- public:
-  DeferredTargetTabstripObserver() = default;
-  DeferredTargetTabstripObserver(const DeferredTargetTabstripObserver&) =
-      delete;
-  DeferredTargetTabstripObserver& operator=(
-      const DeferredTargetTabstripObserver&) = delete;
-  ~DeferredTargetTabstripObserver() override {
-    if (deferred_target_context_) {
-      GetWindowForTabDraggingProperties(deferred_target_context_)
-          ->RemoveObserver(this);
-      deferred_target_context_ = nullptr;
-    }
-  }
-
-  void SetDeferredTargetTabstrip(TabDragContext* deferred_target_context) {
-    if (deferred_target_context_ == deferred_target_context)
-      return;
-
-    // Clear the window property on the previous |deferred_target_context_|.
-    if (deferred_target_context_) {
-      aura::Window* old_window =
-          GetWindowForTabDraggingProperties(deferred_target_context_);
-      old_window->RemoveObserver(this);
-      old_window->ClearProperty(
-          chromeos::kIsDeferredTabDraggingTargetWindowKey);
-    }
-
-    deferred_target_context_ = deferred_target_context;
-
-    // Set the window property on the new |deferred_target_context_|.
-    if (deferred_target_context_) {
-      aura::Window* new_window =
-          GetWindowForTabDraggingProperties(deferred_target_context_);
-      new_window->SetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey,
-                              true);
-      new_window->AddObserver(this);
-    }
-  }
-
-  // aura::WindowObserver:
-  void OnWindowPropertyChanged(aura::Window* window,
-                               const void* key,
-                               intptr_t old) override {
-    DCHECK_EQ(window,
-              GetWindowForTabDraggingProperties(deferred_target_context_));
-
-    if (key == chromeos::kIsDeferredTabDraggingTargetWindowKey &&
-        !window->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey)) {
-      SetDeferredTargetTabstrip(nullptr);
-    }
-
-    // else do nothing. currently it's only possible that ash clears the window
-    // property, but doesn't set the window property.
-  }
-
-  void OnWindowDestroying(aura::Window* window) override {
-    DCHECK_EQ(window,
-              GetWindowForTabDraggingProperties(deferred_target_context_));
-    SetDeferredTargetTabstrip(nullptr);
-  }
-
-  TabDragContext* deferred_target_context() { return deferred_target_context_; }
-
- private:
-  TabDragContext* deferred_target_context_ = nullptr;
-};
-
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////
 // TabDragController, public:
 
@@ -757,11 +606,6 @@
         drag_offset = GetWindowOffset(point_in_screen);
       }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-      StoreCurrentDraggedBrowserBoundsInTabletMode(widget->GetNativeWindow(),
-                                                   new_bounds);
-#endif
-
       // TODO:(crbug.com/1411147) Remove debug log in tab_drag_controller.cc
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
       static bool reported = false;
@@ -817,25 +661,6 @@
   if (current_state_ == DragState::kDraggingWindow && in_move_loop_)
     GetAttachedBrowserWidget()->EndMoveLoop();
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // It's possible that in Chrome OS we defer the windows that are showing in
-  // overview to attach into during dragging. If so we need to attach the
-  // dragged tabs to it first.
-  if (reason == END_DRAG_COMPLETE && deferred_target_context_observer_)
-    PerformDeferredAttach();
-
-  // It's also possible that we need to merge the dragged tabs back into the
-  // source window even if the dragged tabs is dragged away from the source
-  // window.
-  if (source_context_ &&
-      GetWindowForTabDraggingProperties(source_context_)
-          ->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey)) {
-    GetWindowForTabDraggingProperties(source_context_)
-        ->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-    reason = END_DRAG_CANCEL;
-  }
-#endif
-
   EndDragImpl(reason != END_DRAG_COMPLETE && source_context_ ? CANCELED
                                                              : NORMAL);
 }
@@ -870,11 +695,6 @@
                                               const gfx::Rect& new_bounds) {
   TRACE_EVENT1("views", "TabDragController::OnWidgetBoundsChanged",
                "new_bounds", new_bounds.ToString());
-  // Detaching and attaching can be suppressed temporarily to suppress attaching
-  // to incorrect window on changing bounds. We should prevent Drag() itself,
-  // otherwise it can clear deferred attaching tab.
-  if (!CanDetachFromTabStrip(attached_context_))
-    return;
 #if defined(USE_AURA)
   aura::Env* env = aura::Env::GetInstance();
   // WidgetBoundsChanged happens as a step of ending a drag, but Drag() doesn't
@@ -1011,19 +831,6 @@
     return Liveness::DELETED;
   }
 
-  // The dragged tabs may not be able to attach into |target_context| during
-  // dragging if the window associated with |target_context| is currently
-  // showing in overview mode in Chrome OS, in this case we defer attaching into
-  // it till the drag ends and reset |target_context| here.
-  if (ShouldAttachOnEnd(target_context)) {
-    SetDeferredTargetTabstrip(target_context);
-    target_context = current_state_ == DragState::kDraggingWindow
-                         ? attached_context_.get()
-                         : nullptr;
-  } else {
-    SetDeferredTargetTabstrip(nullptr);
-  }
-
   bool tab_strip_changed = (target_context != attached_context_);
   // TODO:(crbug.com/1411147) Remove debug log in tab_drag_controller.cc
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -1420,16 +1227,8 @@
         BrowserView::GetBrowserViewForNativeWindow(local_window)
             ->tabstrip()
             ->GetDragContext();
-    if (ShouldAttachOnEnd(destination_tab_strip)) {
-      // No need to check if the specified screen point is within the bounds of
-      // the tabstrip as arriving here we know that the window is currently
-      // showing in overview mode in Chrome OS and its bounds contain the
-      // specified screen point, and these two conditions are enough for a
-      // window to be a valid target window to attach the dragged tabs.
-      *context = destination_tab_strip;
-      return Liveness::ALIVE;
-    } else if (destination_tab_strip &&
-               DoesTabStripContain(destination_tab_strip, point_in_screen)) {
+    if (destination_tab_strip &&
+        DoesTabStripContain(destination_tab_strip, point_in_screen)) {
       *context = destination_tab_strip;
       return Liveness::ALIVE;
     }
@@ -1897,13 +1696,10 @@
     // enough to trigger a drag.
     if (previous_state != DragState::kNotStarted) {
       // After the drag ends, sometimes it shouldn't restore the focus, because
-      // - if |attached_context_| is showing in overview mode, overview mode
-      //   may be ended unexpectedly because of the window activation.
       // - Some dragging gesture (like fling down) minimizes the window, but the
       //   window activation cancels minimized status. See
       //   https://crbug.com/902897
-      if (!IsShowingInOverview(attached_context_) &&
-          !attached_context_->GetWidget()->IsMinimized()) {
+      if (!attached_context_->GetWidget()->IsMinimized()) {
         RestoreFocus();
       }
 
@@ -1980,43 +1776,6 @@
   browser->window()->Show();
 }
 
-void TabDragController::PerformDeferredAttach() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  TabDragContext* deferred_target_context =
-      deferred_target_context_observer_->deferred_target_context();
-  if (!deferred_target_context)
-    return;
-
-  DCHECK_NE(deferred_target_context, attached_context_);
-
-  // |is_dragging_new_browser_| needs to be reset here since after this function
-  // is called, the browser window that was specially created for the dragged
-  // tab(s) will be destroyed.
-  is_dragging_new_browser_ = false;
-  // |did_restore_window_| is only set to be true if the dragged window is the
-  // source window and the source window was maximized or fullscreen before the
-  // drag starts. It also needs to be reset to false here otherwise after this
-  // function is called, the newly attached window may be maximized unexpectedly
-  // after the drag ends.
-  did_restore_window_ = false;
-
-  // On ChromeOS, the gesture state is already cleared and so
-  // GetCursorScreenPoint() will fail to obtain the last touch location.
-  // Therefore it uses the last remembered location instead.
-  const gfx::Point current_screen_point =
-      (event_source_ == ui::mojom::DragEventSource::kTouch)
-          ? last_point_in_screen_
-          : GetCursorScreenPoint();
-  // If we're attaching the dragged tabs to an overview window's tabstrip, the
-  // tabstrip should not have focus.
-  DetachAndAttachToNewContext(DONT_RELEASE_CAPTURE, deferred_target_context,
-                              current_screen_point, /*set_capture=*/false);
-
-  SetDeferredTargetTabstrip(nullptr);
-  deferred_target_context_observer_.reset();
-#endif
-}
-
 void TabDragController::RevertDrag() {
   std::vector<TabSlotView*> views;
   if (header_drag_)
@@ -2404,13 +2163,6 @@
     new_bounds.set_height(std::max(max_size.height() / 2, new_bounds.height()));
   }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (ash::TabletMode::Get()->InTabletMode()) {
-    new_bounds = GetDraggedBrowserBoundsInTabletMode(
-        source->GetWidget()->GetNativeWindow());
-  }
-#endif
-
   new_bounds.set_y(point_in_screen.y() - center.y());
   switch (GetDetachPosition(point_in_screen)) {
     case DETACH_BEFORE:
@@ -2444,10 +2196,6 @@
     views::Widget* widget,
     const gfx::Point& point_in_screen) {
   gfx::Rect bounds = widget->GetWindowBoundsInScreen();
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (ash::TabletMode::Get()->InTabletMode())
-    bounds = GetDraggedBrowserBoundsInTabletMode(widget->GetNativeWindow());
-#endif
 
   // The user has to move the mouse some amount of pixels before the drag
   // starts. Offset the window by this amount so that the relative offset
@@ -2838,18 +2586,6 @@
   return true;
 }
 
-void TabDragController::SetDeferredTargetTabstrip(
-    TabDragContext* deferred_target_context) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (!deferred_target_context_observer_) {
-    deferred_target_context_observer_ =
-        std::make_unique<DeferredTargetTabstripObserver>();
-  }
-  deferred_target_context_observer_->SetDeferredTargetTabstrip(
-      deferred_target_context);
-#endif
-}
-
 int TabDragController::GetOutOfBoundsYCoordinate() const {
   DCHECK(attached_context_);
   return attached_context_->GetBoundsInScreen().y() - kVerticalDetachMagnetism -
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index 9e914fc..4d3d313 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -180,10 +180,6 @@
  private:
   friend class TabDragControllerTest;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  class DeferredTargetTabstripObserver;
-#endif
-
   class SourceTabStripEmptinessTracker;
 
   class DraggedTabsClosedTracker;
@@ -446,9 +442,6 @@
   // |attached_context_hidden_| is false.
   void AttachTabsToNewBrowserOnDrop();
 
-  // Called after the drag ends and |deferred_target_context_| is not nullptr.
-  void PerformDeferredAttach();
-
   // Reverts a cancelled drag operation.
   void RevertDrag();
 
@@ -569,11 +562,6 @@
   // from the old context or the tab dragging is ended.
   void ClearTabDraggingInfo();
 
-  // Sets |deferred_target_context_| and updates its corresponding window
-  // property. |location| is the location of the pointer when the deferred
-  // target is set.
-  void SetDeferredTargetTabstrip(TabDragContext* deferred_target_context);
-
   DragState current_state_;
 
   // Tests whether a drag can be attached to a |window|.  Drags may be
@@ -614,15 +602,6 @@
   // null if the dragged Tab is detached.
   raw_ptr<TabDragContext, DanglingUntriaged> attached_context_;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // Observe the target TabDragContext to attach to after the drag
-  // ends. It's only possible to happen in Chrome OS tablet mode, if the dragged
-  // tabs are dragged over an overview window, we should wait until the drag
-  // ends to attach it.
-  std::unique_ptr<DeferredTargetTabstripObserver>
-      deferred_target_context_observer_;
-#endif
-
   // Whether capture can be released during the drag. When false, capture should
   // not be released when transferring capture between widgets and when starting
   // the move loop.
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 f77b884e..52966c68 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
@@ -3305,139 +3305,6 @@
   ASSERT_FALSE(TabDragController::IsActive());
 }
 
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       OffsetForDraggingInTabletMode) {
-  AddTabsAndResetBrowser(browser(), 1);
-  // Moves the browser window slightly to ensure that the browser's restored
-  // bounds are different from the maximized bound's origin.
-  browser()->window()->SetBounds(browser()->window()->GetBounds() +
-                                 gfx::Vector2d(100, 50));
-  BrowserView::GetBrowserViewForBrowser(browser())
-      ->DisableTopControlsSlideForTesting();
-  ash::ShellTestApi().SetTabletModeEnabledForTest(true);
-
-  DragWindowAndVerifyOffset(this, GetTabStripForBrowser(browser()), 1);
-  ASSERT_FALSE(TabDragController::IsActive());
-}
-
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       OffsetForDraggingRightSnappedWindowInTabletMode) {
-  BrowserView::GetBrowserViewForBrowser(browser())
-      ->DisableTopControlsSlideForTesting();
-  ash::ShellTestApi().SetTabletModeEnabledForTest(true);
-
-  // Right snap the browser window.
-  aura::Window* window = browser()->window()->GetNativeWindow();
-  ash::SplitViewTestApi().SnapWindow(
-      window, ash::SplitViewTestApi::SnapPosition::RIGHT);
-  EXPECT_NE(gfx::Point(), window->GetBoundsInScreen().origin());
-
-  DragWindowAndVerifyOffset(this, GetTabStripForBrowser(browser()), 0);
-  ASSERT_FALSE(TabDragController::IsActive());
-}
-
-namespace {
-
-void DragToOverviewWindowStep2(DetachToBrowserTabDragControllerTest* test,
-                               TabStrip* not_attached_tab_strip,
-                               TabStrip* target_tab_strip) {
-  ASSERT_FALSE(not_attached_tab_strip->GetDragContext()->IsDragSessionActive());
-  ASSERT_FALSE(target_tab_strip->GetDragContext()->IsDragSessionActive());
-  ASSERT_TRUE(TabDragController::IsActive());
-
-  // And there should be three browser windows, including the newly created one
-  // for the dragged tab.
-  EXPECT_EQ(3u, test->browser_list->size());
-
-  // Put the window that associated with |target_tab_strip| in overview.
-  test::GetWindowForTabStrip(target_tab_strip)
-      ->SetProperty(chromeos::kIsShowingInOverviewKey, true);
-
-  // Drag to target_tab_strip.
-  ASSERT_TRUE(
-      test->DragInputTo(GetCenterInScreenCoordinates(target_tab_strip)));
-
-  // Test that the dragged tab did not attach to the overview window.
-  EXPECT_EQ(3u, test->browser_list->size());
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// Creates two browsers, drags from first into second. If the target window is
-// currently showing in overview, we should not attaching the dragged tabs
-// into the target window during dragging, but should do so until the drag ends.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DragToOverviewWindow) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-
-  // Add another tab to browser().
-  AddTabsAndResetBrowser(browser(), 1);
-
-  // Create another browser.
-  Browser* browser2 = CreateAnotherBrowserAndResize();
-  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
-
-  // Move to the first tab and drag it enough so that it detaches, but not
-  // enough that it attaches to browser2.
-  DragTabAndNotify(tab_strip, base::BindOnce(&DragToOverviewWindowStep2, this,
-                                             tab_strip, tab_strip2));
-
-  // Now the dragged tab should have been attached to the target tabstrip after
-  // the drag ends.
-  ASSERT_FALSE(TabDragController::IsActive());
-  EXPECT_EQ(2u, browser_list->size());
-}
-
-namespace {
-
-void DragToOverviewNewWindowItemStep2(
-    DetachToBrowserTabDragControllerTest* test,
-    TabStrip* attached_tab_strip) {
-  ASSERT_TRUE(attached_tab_strip->GetDragContext()->IsDragSessionActive());
-  ASSERT_TRUE(TabDragController::IsActive());
-  EXPECT_TRUE(attached_tab_strip->GetWidget()->GetNativeWindow()->HasFocus());
-
-  // Put the attached window in overview to simulate the "drop on the new
-  // selector item" scenario.
-  test::GetWindowForTabStrip(attached_tab_strip)
-      ->SetProperty(chromeos::kIsShowingInOverviewKey, true);
-  // At the same time we remove |attached_tab_strip|'s focus to simulate what
-  // happens in overview (In overview, the window items in overview don't have
-  // focus, it's the textfield in overview that has focus).
-  attached_tab_strip->GetFocusManager()->SetFocusedView(nullptr);
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// After dragging a window to drop it onto the new window selector item in
-// overview mode, the window should be added to overview window grid, and should
-// not restore its focus.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DragToOverviewNewWindowItem) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-
-  // Make |tab_strip| the focused view before dragging.
-  tab_strip->GetFocusManager()->SetFocusedView(tab_strip);
-  EXPECT_TRUE(tab_strip->HasFocus());
-
-  // Drag the tab long enough so that it moves.
-  DragTabAndNotify(tab_strip, base::BindOnce(&DragToOverviewNewWindowItemStep2,
-                                             this, tab_strip));
-
-  ASSERT_FALSE(TabDragController::IsActive());
-  EXPECT_EQ(1u, browser_list->size());
-
-  // Test that the attached tabstrip doesn't restore focus as it's currently
-  // showing in overview.
-  EXPECT_TRUE(test::GetWindowForTabStrip(tab_strip)->GetProperty(
-      chromeos::kIsShowingInOverviewKey));
-  EXPECT_FALSE(tab_strip->HasFocus());
-}
-
 namespace {
 
 // A window observer that observes the dragged window's property
@@ -3551,115 +3418,6 @@
 
 namespace {
 
-void DoNotAttachToOtherWindowTestStep2(
-    DetachToBrowserTabDragControllerTest* test,
-    TabStrip* not_attached_tab_strip,
-    TabStrip* target_tab_strip) {
-  ASSERT_TRUE(TabDragController::IsActive());
-
-  // There should be three browser windows, including the newly created one for
-  // the dragged tab.
-  EXPECT_EQ(3u, test->browser_list->size());
-  // Get this new created window and set it to non-attachable.
-  Browser* new_browser = test->browser_list->get(2);
-  new_browser->window()->GetNativeWindow()->SetProperty(
-      chromeos::kCanAttachToAnotherWindowKey, false);
-
-  // Now drag to target_tab_strip.
-  ASSERT_TRUE(
-      test->DragInputTo(GetCenterInScreenCoordinates(target_tab_strip)));
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// Test that if the dragged window is not allowed to attach to another window
-// during dragging, then it can't attach to another window.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DoNotAttachToOtherWindowTest) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-  AddTabsAndResetBrowser(browser(), 1);
-
-  // Create another browser.
-  Browser* browser2 = CreateAnotherBrowserAndResize();
-  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
-  EXPECT_EQ(2u, browser_list->size());
-
-  // Move to the first tab and drag it enough so that it detaches, but not
-  // enough that it attaches to browser2.
-  DragTabAndNotify(tab_strip, base::BindOnce(&DoNotAttachToOtherWindowTestStep2,
-                                             this, tab_strip, tab_strip2));
-
-  // Test that the newly created browser window doesn't attach to the target
-  // browser window.
-  ASSERT_FALSE(TabDragController::IsActive());
-  EXPECT_EQ(3u, browser_list->size());
-}
-
-namespace {
-
-void DeferredTargetTabStripTestStep2(DetachToBrowserTabDragControllerTest* test,
-                                     TabStrip* not_attached_tab_strip,
-                                     TabStrip* target_tab_strip) {
-  ASSERT_FALSE(not_attached_tab_strip->GetDragContext()->IsDragSessionActive());
-  ASSERT_FALSE(target_tab_strip->GetDragContext()->IsDragSessionActive());
-  ASSERT_TRUE(TabDragController::IsActive());
-
-  // And there should be three browser windows, including the newly created one
-  // for the dragged tab.
-  EXPECT_EQ(3u, test->browser_list->size());
-
-  // Put the window that associated with |target_tab_strip| in overview.
-  test::GetWindowForTabStrip(target_tab_strip)
-      ->SetProperty(chromeos::kIsShowingInOverviewKey, true);
-
-  // Drag to target_tab_strip.
-  ASSERT_TRUE(
-      test->DragInputTo(GetCenterInScreenCoordinates(target_tab_strip)));
-
-  // At this point, |target_tab_strip| should be the deferred target tabstrip.
-  // Theoretically the dragged tabstrip will merge into |target_tab_strip| after
-  // the drag ends.
-  EXPECT_TRUE(
-      test::GetWindowForTabStrip(target_tab_strip)
-          ->GetProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey));
-
-  // Now clear the property.
-  test::GetWindowForTabStrip(target_tab_strip)
-      ->ClearProperty(chromeos::kIsDeferredTabDraggingTargetWindowKey);
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// Test that if a tabstrip is a deferred target tabstrip, and its corresponding
-// window key is cleared to remove itself as the deferred target tabstrip, the
-// dragged tabstrip should not attach into it after the drag ends.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DeferredTargetTabStripTest) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-
-  AddTabsAndResetBrowser(browser(), 1);
-
-  // Create another browser.
-  Browser* browser2 = CreateAnotherBrowserAndResize();
-  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
-
-  // Move to the first tab and drag it enough so that it detaches, but not
-  // enough that it attaches to browser2.
-  DragTabAndNotify(tab_strip, base::BindOnce(&DeferredTargetTabStripTestStep2,
-                                             this, tab_strip, tab_strip2));
-
-  // Now the dragged tab should not be attached to the target tabstrip after
-  // the drag ends.
-  ASSERT_FALSE(TabDragController::IsActive());
-  EXPECT_EQ(3u, browser_list->size());
-}
-
-namespace {
-
 // Returns true if the web contents that's associated with |browser| is using
 // fast resize.
 bool WebContentsIsFastResized(Browser* browser) {
@@ -3722,118 +3480,6 @@
   EXPECT_FALSE(WebContentsIsFastResized(browser2));
 }
 
-namespace {
-
-void DragToMinimizedOverviewWindowStep2(
-    DetachToBrowserTabDragControllerTest* test,
-    TabStrip* dragged_tab_strip,
-    TabStrip* target_tab_strip) {
-  EXPECT_EQ(2u, test->browser_list->size());
-
-  // Test that overview is open behind the dragged window and |target_window|
-  // has been put in overview as expected.
-  aura::Window* dragged_window = test::GetWindowForTabStrip(dragged_tab_strip);
-  aura::Window* target_window = test::GetWindowForTabStrip(target_tab_strip);
-  EXPECT_TRUE(target_window->GetProperty(chromeos::kIsShowingInOverviewKey));
-  EXPECT_FALSE(dragged_window->GetProperty(chromeos::kIsShowingInOverviewKey));
-
-  // Now drag the tabs to a point that is contained by |target_window|.
-  gfx::Transform transform = target_window->layer()->GetTargetTransform();
-  gfx::RectF target_window_bounds =
-      transform.MapRect(gfx::RectF(target_window->bounds()));
-  gfx::Point target_point(target_window_bounds.CenterPoint().x(),
-                          target_window_bounds.CenterPoint().y());
-
-  // Minimize the |target_window|.
-  target_window->SetProperty(aura::client::kShowStateKey,
-                             ui::SHOW_STATE_MINIMIZED);
-
-  ASSERT_TRUE(test->DragInputTo(target_point));
-  EXPECT_TRUE(target_window->GetProperty(
-      chromeos::kIsDeferredTabDraggingTargetWindowKey));
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// Test that the dragged tabs should be able to merge into an overview window
-// that represents a minimized window.
-// TODO(https://crbug.com/979013) Disabled due to flakiness.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DISABLED_DragToMinimizedOverviewWindow) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-
-  // Create another browser.
-  Browser* browser2 = CreateAnotherBrowserAndResize();
-  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
-  EXPECT_EQ(2u, browser_list->size());
-
-  ash::ShellTestApi().SetTabletModeEnabledForTest(true);
-
-  // Move to the first tab of |browser2| and drag it toward to browser(). Note
-  // dragging on |browser2| which only has one tab in tablet mode will open
-  // overview behind the |browser2|.
-  DragTabAndNotify(tab_strip2,
-                   base::BindOnce(&DragToMinimizedOverviewWindowStep2, this,
-                                  tab_strip2, tab_strip));
-
-  // |tab_strip| should have been merged into |browser2|. Thus there should only
-  // be one browser now.
-  EXPECT_EQ(browser_list->size(), 1u);
-}
-
-namespace {
-
-void WindowSizeDuringDraggingTestStep2(
-    DetachToBrowserTabDragControllerTest* test,
-    TabStrip* tab_strip) {
-  // There should be two browser windows, including the newly created one for
-  // the dragged tab.
-  EXPECT_EQ(2u, test->browser_list->size());
-
-  // Get this new created window for the dragged tab.
-  Browser* new_browser = test->browser_list->get(1);
-  aura::Window* window = new_browser->window()->GetNativeWindow();
-  const gfx::Size work_area = display::Screen::GetScreen()
-                                  ->GetDisplayNearestWindow(window)
-                                  .work_area()
-                                  .size();
-  const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
-  const gfx::Size window_size = window->bounds().size();
-  EXPECT_GE(minimum_size.width(),
-            BrowserViewLayout::kMainBrowserContentsMinimumWidth);
-  EXPECT_GE(window_size.width(), minimum_size.width());
-  EXPECT_GE(window_size.height(), minimum_size.height());
-  EXPECT_EQ(window_size,
-            gfx::Size(std::max(work_area.width() / 2, minimum_size.width()),
-                      std::max(work_area.height() / 2, minimum_size.height())));
-
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-}  // namespace
-
-// TODO(http://crbug.com/1028386): Test fails flakily.
-// Tests that when dragging a tab out of a browser window, the dragged window's
-// size should be equal or larger than its minimum size.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
-                       DISABLED_WindowSizeDuringDraggingTest) {
-  // Set the display size small enough.
-  display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager())
-      .UpdateDisplay(base::NumberToString(
-                         BrowserViewLayout::kMainBrowserContentsMinimumWidth) +
-                     "x400");
-  ash::ShellTestApi().SetTabletModeEnabledForTest(true);
-
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-  AddTabsAndResetBrowser(browser(), 1);
-
-  // Drag it far enough that the first tab detaches.
-  DragTabAndNotify(tab_strip, base::BindOnce(&WindowSizeDuringDraggingTestStep2,
-                                             this, tab_strip));
-}
-
 class DetachToBrowserTabDragControllerTestWithTabbedSystemApp
     : public DetachToBrowserTabDragControllerTest {
  public:
@@ -4660,64 +4306,6 @@
   EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
 }
 
-namespace {
-
-void SecondFingerPressTestStep3(DetachToBrowserTabDragControllerTest* test) {
-  ASSERT_TRUE(test->ReleaseInput());
-}
-
-void SecondFingerPressTestStep2(DetachToBrowserTabDragControllerTest* test,
-                                TabStrip* not_attached_tab_strip,
-                                TabStrip* target_tab_strip) {
-  ASSERT_TRUE(TabDragController::IsActive());
-
-  // And there should be three browser windows, including the newly created one
-  // for the dragged tab.
-  EXPECT_EQ(3u, test->browser_list->size());
-
-  // Put the window that associated with |target_tab_strip| in overview.
-  test::GetWindowForTabStrip(target_tab_strip)
-      ->SetProperty(chromeos::kIsShowingInOverviewKey, true);
-
-  // Drag to |target_tab_strip|.
-  const gfx::Point target_point =
-      GetCenterInScreenCoordinates(target_tab_strip);
-  ASSERT_TRUE(test->DragInputTo(target_point));
-
-  // Now add a second finger to tap on it.
-  aura::Env::GetInstance()->set_touch_down(true);
-  ASSERT_TRUE(test->PressInput(gfx::Point(), 1));
-  ASSERT_TRUE(test->ReleaseInput(1));
-
-  ASSERT_TRUE(test->DragInputToNotifyWhenDone(
-      target_point, base::BindOnce(&SecondFingerPressTestStep3, test)));
-}
-
-}  // namespace
-
-// Tests that when dragging a tab to a browser window that's currently in
-// overview, press the second finger should not cause chrome crash.
-IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch,
-                       SecondFingerPressTest) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-
-  AddTabsAndResetBrowser(browser(), 1);
-
-  // Create another browser.
-  Browser* browser2 = CreateAnotherBrowserAndResize();
-  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
-
-  // Move to the first tab and drag it enough so that it detaches, but not
-  // enough that it attaches to browser2.
-  DragTabAndNotify(tab_strip, base::BindOnce(&SecondFingerPressTestStep2, this,
-                                             tab_strip, tab_strip2));
-
-  // Test that after dragging there is no crash and the dragged tab should now
-  // be merged into the target tabstrip.
-  ASSERT_FALSE(TabDragController::IsActive());
-  EXPECT_EQ(2u, browser_list->size());
-}
-
 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch,
                        LeftSnapShouldntCauseMergeAtEnd) {
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 4ef9a04..8f8f667 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -25,6 +25,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/bind.h"
 #include "base/test/test_future.h"
@@ -3605,11 +3606,10 @@
       ShellUtil::GetFileHandlerProgIdsForAppId(prog_id);
 
   base::win::RegKey key;
-  std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
   for (const auto& file_handler_prog_id : file_handler_prog_ids) {
     const std::vector<std::wstring> supported_file_extensions =
         GetFileExtensionsForProgId(file_handler_prog_id);
-    std::wstring extension = converter.from_bytes("." + file_extension_str);
+    std::wstring extension = base::UTF8ToWide("." + file_extension_str);
     if (base::Contains(supported_file_extensions, extension)) {
       const std::wstring reg_key = std::wstring(ShellUtil::kRegClasses) +
                                    base::FilePath::kSeparators[0] + extension +
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 04c902e0..30713a3 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -1773,10 +1773,10 @@
             DisplayMode::kMinimalUi);
   EXPECT_FALSE(
       provider->registrar_unsafe().GetAppLastLaunchTime(app_id).is_null());
-  tester.ExpectUniqueSample("Extensions.BookmarkAppLaunchContainer",
+  tester.ExpectUniqueSample("WebApp.LaunchContainer",
                             apps::LaunchContainer::kLaunchContainerWindow, 1);
-  tester.ExpectUniqueSample("Extensions.BookmarkAppLaunchSource",
-                            extensions::AppLaunchSource::kSourceReparenting, 1);
+  tester.ExpectUniqueSample("WebApp.LaunchSource",
+                            apps::LaunchSource::kFromReparenting, 1);
 }
 
 // Tests that the manifest name of the current installable site is used in the
@@ -2266,9 +2266,7 @@
     const std::vector<std::wstring> file_extensions =
         GetFileExtensionsForProgId(file_handler_prog_id);
     for (const auto& file_extension : file_extensions) {
-      std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
-      const std::string extension =
-          converter.to_bytes(file_extension.substr(1));
+      const std::string extension = base::WideToUTF8(file_extension.substr(1));
       EXPECT_TRUE(base::Contains(expected_extensions, extension))
           << "Missing file extension: " << extension;
       const std::wstring reg_key =
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
index fdbaad0..cbc3154 100644
--- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -110,17 +110,17 @@
 void ExpectLaunchCounts(const base::HistogramTester& tester,
                         base::HistogramBase::Count windowLaunches,
                         base::HistogramBase::Count tabLaunches) {
-  tester.ExpectBucketCount("Extensions.BookmarkAppLaunchContainer",
+  tester.ExpectBucketCount("WebApp.LaunchContainer",
                            apps::LaunchContainer::kLaunchContainerWindow,
                            windowLaunches);
-  tester.ExpectBucketCount("Extensions.BookmarkAppLaunchContainer",
+  tester.ExpectBucketCount("WebApp.LaunchContainer",
                            apps::LaunchContainer::kLaunchContainerTab,
                            tabLaunches);
-  tester.ExpectTotalCount("Extensions.BookmarkAppLaunchContainer",
+  tester.ExpectTotalCount("WebApp.LaunchContainer",
                           windowLaunches + tabLaunches);
 
-  tester.ExpectUniqueSample("Extensions.BookmarkAppLaunchSource",
-                            extensions::AppLaunchSource::kSourceTest,
+  tester.ExpectUniqueSample("WebApp.LaunchSource",
+                            apps::LaunchSource::kFromTest,
                             windowLaunches + tabLaunches);
 }
 
diff --git a/chrome/browser/ui/web_applications/web_app_launch_process.cc b/chrome/browser/ui/web_applications/web_app_launch_process.cc
index f836737..7ffd1a09 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_process.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_process.cc
@@ -144,8 +144,7 @@
 
   UpdateLaunchStats(web_contents, params_->app_id, launch_url);
   RecordLaunchMetrics(params_->app_id, params_->container,
-                      apps::GetAppLaunchSource(params_->launch_source),
-                      launch_url, web_contents);
+                      params_->launch_source, launch_url, web_contents);
 
   return web_contents;
 }
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
index 69772d4..6ab7862 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -12,9 +12,7 @@
 #include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
 #include "base/memory/raw_ptr.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/histogram_macros_internal.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/one_shot_event.h"
 #include "base/time/time.h"
 #include "build/buildflag.h"
@@ -57,7 +55,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/buildflags/buildflags.h"
-#include "extensions/common/constants.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "ui/base/page_transition_types.h"
@@ -285,8 +282,8 @@
   auto launch_url = contents->GetLastCommittedURL();
   UpdateLaunchStats(contents, app_id, launch_url);
   RecordLaunchMetrics(app_id, apps::LaunchContainer::kLaunchContainerWindow,
-                      extensions::AppLaunchSource::kSourceReparenting,
-                      launch_url, contents);
+                      apps::LaunchSource::kFromReparenting, launch_url,
+                      contents);
 
   if (web_app->launch_handler()
           .value_or(LaunchHandler{})
@@ -500,7 +497,7 @@
 
 void RecordAppWindowLaunchMetric(Profile* profile,
                                  const std::string& app_id,
-                                 extensions::AppLaunchSource launch_source) {
+                                 apps::LaunchSource launch_source) {
   WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile);
   if (!provider)
     return;
@@ -514,14 +511,14 @@
   if (display != DisplayMode::kUndefined) {
     DCHECK_LT(DisplayMode::kUndefined, display);
     DCHECK_LE(display, DisplayMode::kMaxValue);
-    UMA_HISTOGRAM_ENUMERATION("Launch.WebAppDisplayMode", display);
+    base::UmaHistogramEnumeration("Launch.WebAppDisplayMode", display);
   }
 
   // Reparenting launches don't respect the launch_handler setting.
-  if (launch_source != extensions::AppLaunchSource::kSourceReparenting &&
+  if (launch_source != apps::LaunchSource::kFromReparenting &&
       base::FeatureList::IsEnabled(
           blink::features::kWebAppEnableLaunchHandler)) {
-    UMA_HISTOGRAM_ENUMERATION(
+    base::UmaHistogramEnumeration(
         "Launch.WebAppLaunchHandlerClientMode",
         web_app->launch_handler().value_or(LaunchHandler()).client_mode);
   }
@@ -529,7 +526,7 @@
 
 void RecordLaunchMetrics(const AppId& app_id,
                          apps::LaunchContainer container,
-                         extensions::AppLaunchSource launch_source,
+                         apps::LaunchSource launch_source,
                          const GURL& launch_url,
                          content::WebContents* web_contents) {
   Profile* profile =
@@ -546,10 +543,8 @@
   if (container == apps::LaunchContainer::kLaunchContainerWindow)
     RecordAppWindowLaunchMetric(profile, app_id, launch_source);
 
-  // TODO(crbug.com/1014328): Populate WebApp metrics instead of Extensions.
-  UMA_HISTOGRAM_ENUMERATION("Extensions.BookmarkAppLaunchSource",
-                            launch_source);
-  UMA_HISTOGRAM_ENUMERATION("Extensions.BookmarkAppLaunchContainer", container);
+  base::UmaHistogramEnumeration("WebApp.LaunchSource", launch_source);
+  base::UmaHistogramEnumeration("WebApp.LaunchContainer", container);
 }
 
 void UpdateLaunchStats(content::WebContents* web_contents,
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.h b/chrome/browser/ui/web_applications/web_app_launch_utils.h
index b2a34d3..3655fc0 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.h
@@ -11,7 +11,6 @@
 
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
-#include "extensions/common/constants.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -93,7 +92,7 @@
 // side-effects (e.g. updating app launch time).
 void RecordLaunchMetrics(const AppId& app_id,
                          apps::LaunchContainer container,
-                         extensions::AppLaunchSource launch_source,
+                         apps::LaunchSource launch_source,
                          const GURL& launch_url,
                          content::WebContents* web_contents);
 
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
index 6fa9489..d6029615 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -405,11 +405,10 @@
 void AppHomePageHandler::FillExtensionInfoList(
     std::vector<app_home::mojom::AppInfoPtr>* result) {
   ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
-  std::unique_ptr<ExtensionSet> extension_apps =
-      registry->GenerateInstalledExtensionsSet(ExtensionRegistry::ENABLED |
-                                               ExtensionRegistry::DISABLED |
-                                               ExtensionRegistry::TERMINATED);
-  for (const auto& extension : *extension_apps) {
+  const ExtensionSet extension_apps = registry->GenerateInstalledExtensionsSet(
+      ExtensionRegistry::ENABLED | ExtensionRegistry::DISABLED |
+      ExtensionRegistry::TERMINATED);
+  for (const auto& extension : extension_apps) {
     if (!extensions::ui_util::ShouldDisplayInNewTabPage(extension.get(),
                                                         profile_) ||
         extension->id() == extensions::kWebStoreAppId) {
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc
index ae8d13b..8d0411ad 100644
--- a/chrome/browser/ui/webui/cookies_tree_model_util.cc
+++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -223,7 +223,7 @@
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   const extensions::ExtensionSet* protecting_apps =
       node.GetModel()->ExtensionsProtectingNode(node);
-  if (protecting_apps && !protecting_apps->is_empty()) {
+  if (protecting_apps && !protecting_apps->empty()) {
     base::Value::List app_infos;
     for (const auto& app : *protecting_apps) {
       base::Value::Dict app_info;
diff --git a/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chrome/browser/ui/webui/discards/graph_dump_impl.h
index 39304d2..07d14af 100644
--- a/chrome/browser/ui/webui/discards/graph_dump_impl.h
+++ b/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -101,6 +101,9 @@
   void OnHadFormInteractionChanged(
       const performance_manager::FrameNode* frame_node) override {}
   // Ignored.
+  void OnHadUserEditsChanged(
+      const performance_manager::FrameNode* frame_node) override {}
+  // Ignored.
   void OnIsAudibleChanged(
       const performance_manager::FrameNode* frame_node) override {}
   // Ignored.
@@ -159,6 +162,9 @@
   // Ignored.
   void OnHadFormInteractionChanged(
       const performance_manager::PageNode* page_node) override {}
+  // Ignored
+  void OnHadUserEditsChanged(
+      const performance_manager::PageNode* page_node) override {}
   // Ignored.
   void OnTitleUpdated(const performance_manager::PageNode* page_node) override {
   }
diff --git a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
index 55885da..7985d45 100644
--- a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
@@ -507,14 +507,13 @@
 
 std::string ExtensionsInternalsSource::WriteToString() const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  std::unique_ptr<extensions::ExtensionSet> extensions =
-      extensions::ExtensionRegistry::Get(profile_)
-          ->GenerateInstalledExtensionsSet();
+  const auto extensions = extensions::ExtensionRegistry::Get(profile_)
+                              ->GenerateInstalledExtensionsSet();
   extensions::ProcessManager* process_manager =
       extensions::ProcessManager::Get(profile_);
   extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
   base::Value::List data;
-  for (const auto& extension : *extensions) {
+  for (const auto& extension : extensions) {
     base::Value::Dict extension_data;
     extension_data.Set(kInternalsIdKey, extension->id());
     extension_data.Set(kInternalsCreationFlagsKey,
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 264f4bd..b2ad93e2 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
@@ -101,6 +101,13 @@
 
 constexpr char kPrevNavigationTimePrefName[] = "NewTabPage.PrevNavigationTime";
 
+bool HasCredentials(Profile* profile) {
+  auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
+  return
+      /* Can be null if Chrome signin is disabled. */ identity_manager &&
+      identity_manager->GetAccountsInCookieJar().signed_in_accounts.size() > 0;
+}
+
 void AddRawStringOrDefault(content::WebUIDataSource* source,
                            const char key[],
                            const std::string str,
@@ -207,6 +214,13 @@
                                                ntp_features::kNtpModulesLoad));
   source->AddInteger("modulesLoadTimeout",
                      ntp_features::GetModulesLoadTimeout().InMilliseconds());
+  source->AddBoolean(
+      "historyClustersModuleEnabled",
+      base::FeatureList::IsEnabled(ntp_features::kNtpHistoryClustersModule));
+  source->AddBoolean("historyClustersModuleLoadEnabled",
+                     base::FeatureList::IsEnabled(
+                         ntp_features::kNtpHistoryClustersModuleLoad) &&
+                         HasCredentials(profile));
 
   static constexpr webui::LocalizedString kStrings[] = {
       {"doneButton", IDS_DONE},
@@ -531,13 +545,6 @@
   return source;
 }
 
-bool HasCredentials(Profile* profile) {
-  auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
-  return
-      /* Can be null if Chrome signin is disabled. */ identity_manager &&
-      identity_manager->GetAccountsInCookieJar().signed_in_accounts.size() > 0;
-}
-
 }  // namespace
 
 NewTabPageUI::NewTabPageUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index ef90d00..739fa74 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -54,6 +54,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
+#include "ash/public/cpp/new_window_delegate.h"
 #include "base/i18n/time_formatting.h"
 #include "base/strings/strcat.h"
 #include "chrome/browser/ash/arc/arc_util.h"
@@ -354,6 +355,10 @@
       "setConsumerAutoUpdate",
       base::BindRepeating(&AboutHandler::HandleSetConsumerAutoUpdate,
                           base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "openProductLicenseOther",
+      base::BindRepeating(&AboutHandler::HandleOpenProductLicenseOther,
+                          base::Unretained(this)));
 #endif
 #if BUILDFLAG(IS_MAC)
   web_ui()->RegisterMessageCallback(
@@ -717,6 +722,14 @@
   version_updater_->ToggleFeature(feature, enable);
 }
 
+void AboutHandler::HandleOpenProductLicenseOther(
+    const base::Value::List& args) {
+  ash::NewWindowDelegate::GetPrimary()->OpenUrl(
+      GURL(chrome::kChromeUICreditsURL),
+      ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction,
+      ash::NewWindowDelegate::Disposition::kSwitchToTab);
+}
+
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void AboutHandler::RequestUpdate() {
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h
index bb5f73ee..02e47b0c 100644
--- a/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -197,6 +197,7 @@
                                      absl::optional<bool> enabled);
 
   void HandleSetConsumerAutoUpdate(const base::Value::List& args);
+  void HandleOpenProductLicenseOther(const base::Value::List& args);
 #endif
 
   const raw_ptr<Profile> profile_;
diff --git a/chrome/browser/ui/webui/settings/ash/about_section.cc b/chrome/browser/ui/webui/settings/ash/about_section.cc
index 2b3ee54..f6173c1 100644
--- a/chrome/browser/ui/webui/settings/ash/about_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/about_section.cc
@@ -409,10 +409,13 @@
           l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COPYRIGHT),
           base::Time::Now()));
 
-  std::u16string license = l10n_util::GetStringFUTF16(
-      IDS_VERSION_UI_LICENSE, base::ASCIIToUTF16(chrome::kChromiumProjectURL),
-      base::ASCIIToUTF16(chrome::kChromeUICreditsURL));
-  html_source->AddString("aboutProductLicense", license);
+  html_source->AddString("aboutProductLicenseChromium",
+                         l10n_util::GetStringFUTF16(
+                             IDS_VERSION_UI_LICENSE_CHROMIUM,
+                             base::ASCIIToUTF16(chrome::kChromiumProjectURL)));
+  html_source->AddString(
+      "aboutProductLicenseOther",
+      l10n_util::GetStringUTF16(IDS_VERSION_UI_LICENSE_OTHER));
 
   std::u16string os_license = l10n_util::GetStringFUTF16(
       IDS_ABOUT_CROS_VERSION_LICENSE,
diff --git a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
index 5897e82..f5b6b84 100644
--- a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
@@ -49,6 +49,7 @@
 namespace mojom {
 using ::chromeos::settings::mojom::kAccessibilitySectionPath;
 using ::chromeos::settings::mojom::kAudioAndCaptionsSubpagePath;
+using ::chromeos::settings::mojom::kChromeVoxSubpagePath;
 using ::chromeos::settings::mojom::kCursorAndTouchpadSubpagePath;
 using ::chromeos::settings::mojom::kDisplayAndMagnificationSubpagePath;
 using ::chromeos::settings::mojom::kKeyboardAndTextInputSubpagePath;
@@ -421,6 +422,10 @@
   return captions::IsLiveCaptionFeatureSupported();
 }
 
+bool IsAccessibilityChromeVoxPageMigrationEnabled() {
+  return ::features::IsAccessibilityChromeVoxPageMigrationEnabled();
+}
+
 bool IsAccessibilitySelectToSpeakPageMigrationEnabled() {
   return ::features::IsAccessibilitySelectToSpeakPageMigrationEnabled();
 }
@@ -963,6 +968,9 @@
   html_source->AddString("tabletModeShelfNavigationButtonsLearnMoreUrl",
                          chrome::kTabletModeGesturesLearnMoreURL);
 
+  html_source->AddBoolean("isAccessibilityChromeVoxPageMigrationEnabled",
+                          IsAccessibilityChromeVoxPageMigrationEnabled());
+
   html_source->AddBoolean("isAccessibilitySelectToSpeakPageMigrationEnabled",
                           IsAccessibilitySelectToSpeakPageMigrationEnabled());
 
@@ -1049,6 +1057,13 @@
       IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_LINK_TITLE,
       mojom::Subpage::kTextToSpeechPage, mojom::SearchResultIcon::kA11y,
       mojom::SearchResultDefaultRank::kMedium, mojom::kTextToSpeechPagePath);
+  // ChromeVox settings page.
+  if (IsAccessibilityChromeVoxPageMigrationEnabled()) {
+    generator->RegisterTopLevelSubpage(
+        IDS_SETTINGS_CHROMEVOX_OPTIONS_LABEL, mojom::Subpage::kChromeVox,
+        mojom::SearchResultIcon::kA11y, mojom::SearchResultDefaultRank::kMedium,
+        mojom::kChromeVoxSubpagePath);
+  }
   // Select to speak options page.
   if (IsAccessibilitySelectToSpeakPageMigrationEnabled()) {
     generator->RegisterTopLevelSubpage(
diff --git a/chrome/browser/ui/webui/settings/ash/languages_section.cc b/chrome/browser/ui/webui/settings/ash/languages_section.cc
index 1d31b67..feac12b3 100644
--- a/chrome/browser/ui/webui/settings/ash/languages_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/languages_section.cc
@@ -650,6 +650,11 @@
       mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium,
       mojom::kInputMethodOptionsSubpagePath);
 
+  generator->RegisterNestedSetting(mojom::Setting::kShowPKAutoCorrection,
+                                   mojom::Subpage::kInputMethodOptions);
+  generator->RegisterNestedSetting(mojom::Setting::kShowVKAutoCorrection,
+                                   mojom::Subpage::kInputMethodOptions);
+
   // Smart inputs.
   generator->RegisterTopLevelSubpage(
       IDS_SETTINGS_SUGGESTIONS_TITLE, mojom::Subpage::kSmartInputs,
diff --git a/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc b/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
index dfdb1b8..a5e605bc 100644
--- a/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
+++ b/chrome/browser/ui/webui/settings/ash/os_settings_manager_unittest.cc
@@ -52,7 +52,8 @@
   // testing::Test:
   void SetUp() override {
     scoped_feature_list_.InitWithFeatures(
-        {::features::kAccessibilitySelectToSpeakPageMigration,
+        {::features::kAccessibilityChromeVoxPageMigration,
+         ::features::kAccessibilitySelectToSpeakPageMigration,
          ash::features::kInputDeviceSettingsSplit},
         {});
     ASSERT_TRUE(profile_manager_.SetUp());
diff --git a/chrome/browser/ui/webui/settings/ash/search/BUILD.gn b/chrome/browser/ui/webui/settings/ash/search/BUILD.gn
index d0e8108e..0beca303 100644
--- a/chrome/browser/ui/webui/settings/ash/search/BUILD.gn
+++ b/chrome/browser/ui/webui/settings/ash/search/BUILD.gn
@@ -20,4 +20,5 @@
   ]
 
   webui_module_path = "/search"
+  use_typescript_sources = true
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
index 85c31b3..466efe6 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
@@ -162,6 +162,7 @@
   kCursorAndTouchpad = 1508,
   kAudioAndCaptions = 1509,
   kSelectToSpeak = 1510,
+  kChromeVox = 1511,
 
   // Note: Reset section has no subpages.
 
@@ -297,6 +298,7 @@
 const string kKeyboardAndTextInputSubpagePath = "keyboardAndTextInput";
 const string kCursorAndTouchpadSubpagePath = "cursorAndTouchpad";
 const string kSelectToSpeakSubpagePath = "textToSpeech/selectToSpeak";
+const string kChromeVoxSubpagePath = "textToSpeech/chromeVox";
 const string kAudioAndCaptionsSubpagePath = "audioAndCaptions";
 const string kTextToSpeechSubpagePath = "manageAccessibility/tts";
 const string kSwitchAccessOptionsSubpagePath =
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
index 0a0b63d..0942a6b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
@@ -226,6 +226,8 @@
   // Note: Value 1208 was for deprecated kShowPredictiveWriting.
   // Do not reuse.
   // TODO(crbug/1058552): Add [Deprecated] attribute once implemented.
+  kShowPKAutoCorrection = 1209,
+  kShowVKAutoCorrection = 1210,
 
   // Files section.
   kGoogleDriveConnection = 1300,
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
index e40df640..91eb227 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -79,6 +79,7 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
index 491a7f0..d82d10e4 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
@@ -108,9 +108,9 @@
   scoped_refptr<Latch> latch = new Latch(std::move(callback));
 
   // Update all apps.
-  std::unique_ptr<extensions::ExtensionSet> candidates =
+  extensions::ExtensionSet candidates =
       registry->GenerateInstalledExtensionsSet();
-  for (auto& extension_refptr : *candidates) {
+  for (auto& extension_refptr : candidates) {
     const extensions::Extension* extension = extension_refptr.get();
     if (ShouldUpgradeShortcutFor(profile, extension)) {
       UpdateAllShortcuts(std::u16string(), profile, extension,
diff --git a/chrome/browser/web_applications/os_integration/os_integration_test_override.cc b/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
index 0e711b9..308596c 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
@@ -57,6 +57,7 @@
 #include "base/containers/flat_set.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/shortcut.h"
@@ -209,13 +210,11 @@
   const std::wstring prog_id = GetProgIdForApp(profile->GetPath(), app_id);
   const std::vector<std::wstring> file_handler_prog_ids =
       ShellUtil::GetFileHandlerProgIdsForAppId(prog_id);
-
+  const std::wstring extension = base::UTF8ToWide(file_extension);
   base::win::RegKey key;
-  std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
   for (const auto& file_handler_prog_id : file_handler_prog_ids) {
     const std::vector<std::wstring> supported_file_extensions =
         GetFileExtensionsForProgId(file_handler_prog_id);
-    std::wstring extension = converter.from_bytes(file_extension);
     if (base::Contains(supported_file_extensions, extension)) {
       const std::wstring reg_key = std::wstring(ShellUtil::kRegClasses) +
                                    base::FilePath::kSeparators[0] + extension +
@@ -319,13 +318,14 @@
     const AppId& app_id,
     const std::string& app_name) {
 #if BUILDFLAG(IS_WIN)
-  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
   base::FileEnumerator enumerator(shortcut_dir, false,
                                   base::FileEnumerator::FILES);
   while (!enumerator.Next().empty()) {
-    std::wstring shortcut_filename = enumerator.GetInfo().GetName().value();
-    if (re2::RE2::FullMatch(converter.to_bytes(shortcut_filename),
-                            app_name + "(.*).lnk")) {
+    const std::wstring shortcut_filename =
+        enumerator.GetInfo().GetName().value();
+    const std::string narrowed_filename =
+        base::WideToUTF8(enumerator.GetInfo().GetName().value());
+    if (re2::RE2::FullMatch(narrowed_filename, app_name + "(.*).lnk")) {
       base::FilePath shortcut_path = shortcut_dir.Append(shortcut_filename);
       if (GetShortcutProfile(shortcut_path) == profile->GetBaseName()) {
         return shortcut_path;
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index a691573..2b6ada5d 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1677520762-d8987ca4a030e8e7e0de8f88fb0384bc32a1bfb7.profdata
+chrome-mac-arm-main-1677556200-c0113e3bc5563e80aec1657a7b1150dde8cbed4d.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 7b2db968..85adbab 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1677520762-2d7666fce4fb5f853778434582b9d11d4d31bb2a.profdata
+chrome-mac-main-1677542237-3b8ec531eeb430834456ab1a65ad6ed42995d6b6.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index f1d291b..6df5a167 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1677520818-ff46d4d8dc039ff21d56a5bbdece793055c639e4.profdata
+chrome-win32-main-1677542237-68dfc3b8a292a5dd58682880891ca65b350a7d86.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 1f798042..1b7e8a1 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1677520818-54a8caacd34207e830f91c8bb4f314979b3698a9.profdata
+chrome-win64-main-1677542237-c0667116c18b7256828b1bcb82a9b68af70a2cbe.profdata
diff --git a/chrome/common/extensions/api/generated_externs_list.txt b/chrome/common/extensions/api/generated_externs_list.txt
index 9aef000c..105693d 100644
--- a/chrome/common/extensions/api/generated_externs_list.txt
+++ b/chrome/common/extensions/api/generated_externs_list.txt
@@ -17,5 +17,4 @@
 speech_recognition_private.idl
 tabs.json
 tts.json
-users_private.idl
 windows.json
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 32eb53e..94370b6 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -438,23 +438,10 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-// A boolean pref set to true if primary pointing stick button is the left
-// button.
-const char kPrimaryPointingStickButtonRight[] =
-    "settings.pointing_stick.primary_right";
-
 // Copy of the primary pointing stick buttons option to use on login screen.
 const char kOwnerPrimaryPointingStickButtonRight[] =
     "owner.pointing_stick.primary_right";
 
-// A boolean pref set to true if pointing stick acceleration is enabled. When
-// disabled only simple linear scaling is applied based on sensitivity.
-const char kPointingStickAcceleration[] =
-    "settings.pointing_stick.acceleration";
-
-// A integer pref for pointing stick sensitivity.
-const char kPointingStickSensitivity[] = "settings.pointing_stick.sensitivity";
-
 // A boolean pref set to true if time should be displayed in 24-hour clock.
 const char kUse24HourClock[] = "settings.clock.use_24hour_clock";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index d69d878..9eceb09 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -208,10 +208,7 @@
 extern const char kEnableSyncConsent[];
 #endif
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-extern const char kPrimaryPointingStickButtonRight[];
 extern const char kOwnerPrimaryPointingStickButtonRight[];
-extern const char kPointingStickAcceleration[];
-extern const char kPointingStickSensitivity[];
 extern const char kUse24HourClock[];
 extern const char kUserTimezone[];
 extern const char kResolveTimezoneByGeolocationMethod[];
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js
index 2706b83..b5a2cc4 100644
--- a/chrome/test/data/extensions/api_test/autotest_private/test.js
+++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -609,7 +609,7 @@
           break;
         }
       }
-      chrome.test.assertTrue(displayId != "-1");
+      chrome.test.assertNe("-1", displayId);
       // SHELF_AUTO_HIDE_ALWAYS_HIDDEN not supported by shelf_prefs.
       // TODO(ricardoq): Use enums in IDL instead of hardcoded strings.
       var behaviors = ["always", "never"];
@@ -641,7 +641,7 @@
           break;
         }
       }
-      chrome.test.assertTrue(displayId != "-1");
+      chrome.test.assertNe("-1", displayId);
       // SHELF_ALIGNMENT_BOTTOM_LOCKED not supported by shelf_prefs.
       var alignments = [chrome.autotestPrivate.ShelfAlignmentType.LEFT,
         chrome.autotestPrivate.ShelfAlignmentType.BOTTOM,
@@ -674,7 +674,7 @@
           break;
         }
       }
-      chrome.test.assertTrue(displayId != "-1");
+      chrome.test.assertNe("-1", displayId);
       chrome.system.display.setDisplayProperties(displayId, {rotation: 90},
         function() {
           chrome.autotestPrivate.waitForDisplayRotation(displayId, 'Rotate90',
@@ -707,7 +707,7 @@
           break;
         }
       }
-      chrome.test.assertTrue(displayId != "-1");
+      chrome.test.assertNe("-1", displayId);
       chrome.system.display.setDisplayProperties(
           displayId, {rotation: 180},
           function() {
@@ -816,7 +816,7 @@
               });
             });
       }
-      chrome.test.assertTrue(-1 != browserFrameIndex);
+      chrome.test.assertNe(browserFrameIndex, -1);
     });
   },
 
@@ -1068,7 +1068,7 @@
   function setAndGetClipboardTextData() {
     const textData = 'foo bar';
     chrome.autotestPrivate.getClipboardTextData(function(beforeData) {
-      chrome.test.assertTrue(textData != beforeData);
+      chrome.test.assertNe(beforeData, textData);
       chrome.autotestPrivate.setClipboardTextData(textData, function() {
         chrome.autotestPrivate.getClipboardTextData(function(afterData) {
           chrome.test.assertEq(afterData, textData);
diff --git a/chrome/test/data/extensions/api_test/bindings/about_blank_iframe/background.js b/chrome/test/data/extensions/api_test/bindings/about_blank_iframe/background.js
index 274a237b..27361386 100644
--- a/chrome/test/data/extensions/api_test/bindings/about_blank_iframe/background.js
+++ b/chrome/test/data/extensions/api_test/bindings/about_blank_iframe/background.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 function test() {
-  chrome.test.assertTrue(chrome.runtime != null);
+  chrome.test.assertNe(null, chrome.runtime);
 
   var iframe = document.createElement('iframe');
   document.body.appendChild(iframe);
@@ -12,7 +12,7 @@
   // The context-wide bindings recalculation happens when extensions are
   // enabled and disabled.
   chrome.test.sendMessage('load', chrome.test.callbackPass(function(msg) {
-    chrome.test.assertTrue(chrome.runtime != null);
+    chrome.test.assertNe(null, chrome.runtime);
   }));
 }
 
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/address_change/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/address_change/runtest.js
index a9db3b6..565423ac1 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/address_change/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/address_change/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(service != null);
+  chrome.test.assertNe(null, service);
 
   chrome.test.assertEq(serviceId, service.instanceId);
 
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_descriptor/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_descriptor/runtest.js
index 2897303..2b02b568 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_descriptor/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_descriptor/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(descriptor != null, '\'descriptor\' is null');
+  chrome.test.assertNe(null, descriptor, '\'descriptor\' is null');
 
   chrome.test.assertEq('desc_id0', descriptor.instanceId);
   chrome.test.assertEq('00001221-0000-1000-8000-00805f9b34fb', descriptor.uuid);
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_included_services/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_included_services/runtest.js
index 746c521..0ee4675 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_included_services/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_included_services/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(services != null, '\'services\' is null');
+  chrome.test.assertNe(null, services, '\'services\' is null');
   chrome.test.assertEq(1, services.length);
   chrome.test.assertEq(includedId, services[0].instanceId);
 
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_service/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_service/runtest.js
index d7dc94f..ad234af 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_service/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/get_service/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(service != null);
+  chrome.test.assertNe(null, service);
 
   chrome.test.assertEq(serviceId, service.instanceId);
   chrome.test.assertEq('00001234-0000-1000-8000-00805f9b34fb', service.uuid);
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_characteristic_value/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_characteristic_value/runtest.js
index 4b6d474..153bccd 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_characteristic_value/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_characteristic_value/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(characteristic != null, '\'characteristic\' is null');
+  chrome.test.assertNe(null, characteristic, '\'characteristic\' is null');
   chrome.test.assertEq(charId, characteristic.instanceId);
 
   chrome.test.succeed();
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_descriptor_value/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_descriptor_value/runtest.js
index affe170..244b96c4 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_descriptor_value/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/read_descriptor_value/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(descriptor != null, '\'descriptor\' is null');
+  chrome.test.assertNe(null, descriptor, '\'descriptor\' is null');
   chrome.test.assertEq(descId, descriptor.instanceId);
 
   chrome.test.succeed();
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_characteristic_value/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_characteristic_value/runtest.js
index 68b319c..ce23565 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_characteristic_value/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_characteristic_value/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(characteristic != null, '\'characteristic\' is null');
+  chrome.test.assertNe(null, characteristic, '\'characteristic\' is null');
   chrome.test.assertEq(charId, characteristic.instanceId);
 
   chrome.test.assertEq(writeValue.byteLength, characteristic.value.byteLength);
diff --git a/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_descriptor_value/runtest.js b/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_descriptor_value/runtest.js
index cbfb52d..88ae147 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_descriptor_value/runtest.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_low_energy/write_descriptor_value/runtest.js
@@ -9,7 +9,7 @@
     chrome.test.sendMessage('fail');
     chrome.test.fail(error);
   }
-  chrome.test.assertTrue(descriptor != null, '\'descriptor\' is null');
+  chrome.test.assertNe(null, descriptor, '\'descriptor\' is null');
   chrome.test.assertEq(descId, descriptor.instanceId);
 
   chrome.test.assertEq(writeValue.byteLength, descriptor.value.byteLength);
diff --git a/chrome/test/data/extensions/api_test/bluetooth_private/adapter_state/test.js b/chrome/test/data/extensions/api_test/bluetooth_private/adapter_state/test.js
index e65e9b33..5d09513 100644
--- a/chrome/test/data/extensions/api_test/bluetooth_private/adapter_state/test.js
+++ b/chrome/test/data/extensions/api_test/bluetooth_private/adapter_state/test.js
@@ -8,7 +8,7 @@
   chrome.bluetooth.getAdapterState(function(state) {
     chrome.test.assertNoLastError();
     chrome.test.assertFalse(state.powered);
-    chrome.test.assertTrue(state.name != newAdapterName);
+    chrome.test.assertNe(newAdapterName, state.name);
     // TODO(tengs): Check if adapter is discoverable when the attribute is
     // exposed to the chrome.bluetooth API.
     setAdapterState();
diff --git a/chrome/test/data/extensions/api_test/context_menus/basics/test.js b/chrome/test/data/extensions/api_test/context_menus/basics/test.js
index 8bcd525..9cdf9f9 100644
--- a/chrome/test/data/extensions/api_test/context_menus/basics/test.js
+++ b/chrome/test/data/extensions/api_test/context_menus/basics/test.js
@@ -22,7 +22,7 @@
 
   function no_properties() {
     chrome.contextMenus.create({}, function(id) {
-      chrome.test.assertTrue(chrome.runtime.lastError != null);
+      chrome.test.assertNe(null, chrome.runtime.lastError);
       chrome.test.succeed();
     });
   },
diff --git a/chrome/test/data/extensions/api_test/cookies/api/background.js b/chrome/test/data/extensions/api_test/cookies/api/background.js
index 39bb7e3e..7c467bdd 100644
--- a/chrome/test/data/extensions/api_test/cookies/api/background.js
+++ b/chrome/test/data/extensions/api_test/cookies/api/background.js
@@ -45,7 +45,7 @@
 };
 
 function expectValidCookie(cookie) {
-  chrome.test.assertTrue(cookie != null, 'Expected cookie not set.');
+  chrome.test.assertNe(null, cookie, 'Expected cookie not set.');
 }
 
 function expectNullCookie(cookie) {
diff --git a/chrome/test/data/extensions/api_test/desktop_capture/test.js b/chrome/test/data/extensions/api_test/desktop_capture/test.js
index 0c165e9..728aa1b0 100644
--- a/chrome/test/data/extensions/api_test/desktop_capture/test.js
+++ b/chrome/test/data/extensions/api_test/desktop_capture/test.js
@@ -4,7 +4,7 @@
 
 function onPickerResult(audio_track_num, id, options) {
   chrome.test.assertEq("string", typeof id);
-  chrome.test.assertTrue(id != "");
+  chrome.test.assertNe("", id);
   var video_constraint = { mandatory: { chromeMediaSource: "desktop",
                                         chromeMediaSourceId: id } };
   var audio_constraint =
@@ -55,7 +55,7 @@
         ["screen", "window"],
         chrome.test.callbackPass(function(id) {
           chrome.test.assertEq("string", typeof id);
-          chrome.test.assertTrue(id != "");
+          chrome.test.assertNe("", id);
         }));
   },
 
diff --git a/chrome/test/data/extensions/api_test/developer/test/basics.js b/chrome/test/data/extensions/api_test/developer/test/basics.js
index fd85300..2bdcaf56 100644
--- a/chrome/test/data/extensions/api_test/developer/test/basics.js
+++ b/chrome/test/data/extensions/api_test/developer/test/basics.js
@@ -35,7 +35,7 @@
           break;
         }
       }
-      chrome.test.assertTrue(info != null);
+      chrome.test.assertNe(null, info);
       var extId = info.id;
       chrome.test.assertFalse(info.incognitoAccess.isActive);
       chrome.test.assertFalse(info.fileAccess.isActive);
diff --git a/chrome/test/data/extensions/api_test/file_system/restore_directory/test.js b/chrome/test/data/extensions/api_test/file_system/restore_directory/test.js
index 051efe7e..4c61764 100644
--- a/chrome/test/data/extensions/api_test/file_system/restore_directory/test.js
+++ b/chrome/test/data/extensions/api_test/file_system/restore_directory/test.js
@@ -11,7 +11,7 @@
     }));
     chrome.fileSystem.restoreEntry(id, chrome.test.callbackPass(
         function(restoredEntry) {
-      chrome.test.assertTrue(restoredEntry != null);
+      chrome.test.assertNe(null, restoredEntry);
       chrome.test.assertTrue(restoredEntry.isDirectory);
       chrome.test.assertEq(
           chrome.fileSystem.retainEntry(restoredEntry), id);
diff --git a/chrome/test/data/extensions/api_test/file_system/restore_entry/test.js b/chrome/test/data/extensions/api_test/file_system/restore_entry/test.js
index 3fde3803..def740b 100644
--- a/chrome/test/data/extensions/api_test/file_system/restore_entry/test.js
+++ b/chrome/test/data/extensions/api_test/file_system/restore_entry/test.js
@@ -11,7 +11,7 @@
     }));
     chrome.fileSystem.restoreEntry(id, chrome.test.callbackPass(
         function(restoredEntry) {
-      chrome.test.assertTrue(restoredEntry != null);
+      chrome.test.assertNe(null, restoredEntry);
       chrome.test.assertEq(
           chrome.fileSystem.retainEntry(restoredEntry), id);
       checkEntry(restoredEntry, 'writable.txt', false /* isNew */,
diff --git a/chrome/test/data/extensions/api_test/file_system/retain_directory/test_other_window.js b/chrome/test/data/extensions/api_test/file_system/retain_directory/test_other_window.js
index 7dd7e11..2c59b4c 100644
--- a/chrome/test/data/extensions/api_test/file_system/retain_directory/test_other_window.js
+++ b/chrome/test/data/extensions/api_test/file_system/retain_directory/test_other_window.js
@@ -5,7 +5,7 @@
 chrome.fileSystem.chooseEntry({type: 'openDirectory'},
     chrome.test.callbackPass(function(entry) {
   var id = chrome.fileSystem.retainEntry(entry);
-  chrome.test.assertTrue(id != null);
+  chrome.test.assertNe(null, id);
   chrome.fileSystem.isRestorable(id, chrome.test.callbackPass(
       function(isRestorable) {
     chrome.test.assertTrue(isRestorable);
diff --git a/chrome/test/data/extensions/api_test/file_system/retain_entry/test_other_window.js b/chrome/test/data/extensions/api_test/file_system/retain_entry/test_other_window.js
index dbda0609..3bb4869 100644
--- a/chrome/test/data/extensions/api_test/file_system/retain_entry/test_other_window.js
+++ b/chrome/test/data/extensions/api_test/file_system/retain_entry/test_other_window.js
@@ -5,7 +5,7 @@
 chrome.fileSystem.chooseEntry({type: 'openFile'},
     chrome.test.callbackPass(function(entry) {
   var id = chrome.fileSystem.retainEntry(entry);
-  chrome.test.assertTrue(id != null);
+  chrome.test.assertNe(null, id);
   chrome.fileSystem.isRestorable(id, chrome.test.callbackPass(
       function(isRestorable) {
     chrome.test.assertTrue(isRestorable);
diff --git a/chrome/test/data/extensions/api_test/image_writer_private/write_from_file/test.js b/chrome/test/data/extensions/api_test/image_writer_private/write_from_file/test.js
index 6c623d5c..ef2cc98ff 100644
--- a/chrome/test/data/extensions/api_test/image_writer_private/write_from_file/test.js
+++ b/chrome/test/data/extensions/api_test/image_writer_private/write_from_file/test.js
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 function assertNotNullOrUndefined(value, message) {
-  chrome.test.assertTrue(value !== null, message);
-  chrome.test.assertTrue(value !== undefined, message);
+  chrome.test.assertNe(null, value, message);
+  chrome.test.assertNe(undefined, value, message);
 }
 
 function testWriteFromFile() {
diff --git a/chrome/test/data/extensions/api_test/incognito/split/background.js b/chrome/test/data/extensions/api_test/incognito/split/background.js
index f5aeaba1..0a1b7b35 100644
--- a/chrome/test/data/extensions/api_test/incognito/split/background.js
+++ b/chrome/test/data/extensions/api_test/incognito/split/background.js
@@ -148,7 +148,7 @@
     // Tests that we can set cookies in both processes.
     function setDocumentCookie() {
       document.cookie = "k=v";
-      chrome.test.assertTrue(document.cookie.indexOf("k=v") != -1);
+      chrome.test.assertNe(-1, document.cookie.indexOf("k=v"));
       chrome.test.succeed();
     }
   ]);
diff --git a/chrome/test/data/extensions/api_test/input_method/basic/background.js b/chrome/test/data/extensions/api_test/input_method/basic/background.js
index 23629e1..c891c7cc 100644
--- a/chrome/test/data/extensions/api_test/input_method/basic/background.js
+++ b/chrome/test/data/extensions/api_test/input_method/basic/background.js
@@ -126,7 +126,7 @@
   async function fetchDictionaryTest() {
     await testParams.dictionaryLoaded;
     const words = await asyncInputMethodPrivate.fetchAllDictionaryWords();
-    chrome.test.assertTrue(words !== undefined);
+    chrome.test.assertNe(undefined, words);
     chrome.test.assertEq(0, words.length);
     chrome.test.succeed();
   },
diff --git a/chrome/test/data/extensions/api_test/management/uninstall_via_browser_action/extension_a/background.js b/chrome/test/data/extensions/api_test/management/uninstall_via_browser_action/extension_a/background.js
index 3a25b120..ccc71dcc 100644
--- a/chrome/test/data/extensions/api_test/management/uninstall_via_browser_action/extension_a/background.js
+++ b/chrome/test/data/extensions/api_test/management/uninstall_via_browser_action/extension_a/background.js
@@ -11,8 +11,8 @@
     var extension = items.find(item => {
       return item.name == 'ExtensionB';
     });
-    chrome.test.assertTrue(extension != undefined);
-    chrome.test.assertTrue(extension.id != undefined);
+    chrome.test.assertNe(undefined, extension);
+    chrome.test.assertNe(undefined, extension.id);
     chrome.management.uninstall(extension.id, chrome.test.callbackPass(() => {
       chrome.test.notifyPass();
     }));
diff --git a/chrome/test/data/extensions/api_test/media_galleries/common/common_injected.js b/chrome/test/data/extensions/api_test/media_galleries/common/common_injected.js
index 5e31f36..76688be 100644
--- a/chrome/test/data/extensions/api_test/media_galleries/common/common_injected.js
+++ b/chrome/test/data/extensions/api_test/media_galleries/common/common_injected.js
@@ -164,7 +164,7 @@
 }
 
 function checkMetadata(metadata) {
-  chrome.test.assertTrue(metadata != null);
+  chrome.test.assertNe(null, metadata);
   chrome.test.assertTrue(metadata.name.length > 0);
   chrome.test.assertTrue(metadata.galleryId.length > 0);
   chrome.test.assertTrue("isAvailable" in metadata);
diff --git a/chrome/test/data/extensions/api_test/messaging/connect/test.js b/chrome/test/data/extensions/api_test/messaging/connect/test.js
index 7487226b..96ef764a 100644
--- a/chrome/test/data/extensions/api_test/messaging/connect/test.js
+++ b/chrome/test/data/extensions/api_test/messaging/connect/test.js
@@ -384,7 +384,7 @@
       } catch(e) {
         error = e;
       }
-      chrome.test.assertTrue(error != undefined);
+      chrome.test.assertNe(undefined, error);
 
       error = undefined;
       try {
@@ -392,7 +392,7 @@
       } catch(e) {
         error = e;
       }
-      chrome.test.assertTrue(error != undefined);
+      chrome.test.assertNe(undefined, error);
 
       chrome.test.succeed();
     },
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/test.js b/chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/test.js
index 5ec961a..96694ce 100644
--- a/chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/test.js
+++ b/chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/test.js
@@ -11,7 +11,7 @@
 function compareSenders(expected, actual) {
   // documentId is a unique ID so we can't assume anything about it, just
   // that it is provided.
-  chrome.test.assertTrue(actual.documentId != undefined);
+  chrome.test.assertNe(undefined, actual.documentId);
   chrome.test.assertEq('active', actual.documentLifecycle);
   chrome.test.assertEq(expected.frameId, actual.frameId);
   chrome.test.assertEq(expected.url, actual.url);
diff --git a/chrome/test/data/extensions/api_test/mime_handler_view/index.js b/chrome/test/data/extensions/api_test/mime_handler_view/index.js
index f270fda..6209c09 100644
--- a/chrome/test/data/extensions/api_test/mime_handler_view/index.js
+++ b/chrome/test/data/extensions/api_test/mime_handler_view/index.js
@@ -48,14 +48,14 @@
 function checkStreamDetails(name, embedded) {
   checkStreamDetailsNoFile();
   chrome.test.assertEq(embedded, streamDetails.embedded);
-  chrome.test.assertTrue(streamDetails.originalUrl.indexOf(name) != -1);
+  chrome.test.assertNe(-1, streamDetails.originalUrl.indexOf(name));
   chrome.test.assertEq('text/csv',
                        streamDetails.responseHeaders['Content-Type']);
 }
 
 function checkStreamDetailsNoFile() {
   chrome.test.assertEq('text/csv', streamDetails.mimeType);
-  chrome.test.assertTrue(streamDetails.tabId != -1);
+  chrome.test.assertNe(-1, streamDetails.tabId);
 }
 
 // The following helper methods are used in BrowserPlugin-specific tests.
@@ -180,7 +180,7 @@
           chrome.test.assertEq(document.body, document.webkitFullscreenElement);
           await waitForFullscreenAnimation();
           chrome.tabs.get(streamDetails.tabId, tab => {
-            chrome.test.assertTrue(tab != null);
+            chrome.test.assertNe(null, tab);
             windowId = tab.windowId;
             chrome.windows.get(windowId, currentWindow => {
               chrome.test.assertEq('fullscreen', currentWindow.state);
@@ -260,7 +260,7 @@
       window.setTimeout(() => {
         // If the background page has shut down, its window.localStorage will be
         // null.
-        chrome.test.assertTrue(backgroundPage.window.localStorage != null);
+        chrome.test.assertNe(null, backgroundPage.window.localStorage);
         backgroundPage.endBackgroundPageTest();
         chrome.test.succeed();
       }, 100);
diff --git a/chrome/test/data/extensions/api_test/native_bindings/extension/background.js b/chrome/test/data/extensions/api_test/native_bindings/extension/background.js
index ce2ef0a..f261ffef 100644
--- a/chrome/test/data/extensions/api_test/native_bindings/extension/background.js
+++ b/chrome/test/data/extensions/api_test/native_bindings/extension/background.js
@@ -111,7 +111,7 @@
       chrome.test.assertTrue(!!tab, 'tab');
       // Snag this opportunity to test bindings properties.
       chrome.test.assertTrue(!!chrome.tabs.TAB_ID_NONE);
-      chrome.test.assertTrue(tab.id != chrome.tabs.TAB_ID_NONE);
+      chrome.test.assertNe(chrome.tabs.TAB_ID_NONE, tab.id);
       chrome.test.assertEq(new URL(url).host, new URL(tab.pendingUrl).host);
       var code = 'document.title = "new title";';
       chrome.tabs.executeScript(tab.id, {code: code}, function(results) {
@@ -251,7 +251,7 @@
     var filtered = new Promise((resolve, reject) => {
       chrome.webNavigation.onBeforeNavigate.addListener(
           function listener(details) {
-        chrome.test.assertTrue(details.url.indexOf('unique') != -1);
+        chrome.test.assertNe(-1, details.url.indexOf('unique'));
         chrome.test.assertTrue(details.url.indexOf('simple2.html') != -1,
                                details.url);
         chrome.webNavigation.onBeforeNavigate.removeListener(listener);
diff --git a/chrome/test/data/extensions/api_test/native_bindings/web_request/background.js b/chrome/test/data/extensions/api_test/native_bindings/web_request/background.js
index edbc3c8..68e8899 100644
--- a/chrome/test/data/extensions/api_test/native_bindings/web_request/background.js
+++ b/chrome/test/data/extensions/api_test/native_bindings/web_request/background.js
@@ -32,7 +32,7 @@
     return {};
 
   chrome.test.assertEq('/native_bindings/simple.html', url.pathname);
-  chrome.test.assertTrue(url.port != '');
+  chrome.test.assertNe('', url.port);
   chrome.test.assertEq('example.com:' + url.port, url.host);
   var newUrl = url.origin + '/native_bindings/simple2.html';
   return {redirectUrl: newUrl};
diff --git a/chrome/test/data/extensions/api_test/pdf_viewer_private/background.js b/chrome/test/data/extensions/api_test/pdf_viewer_private/background.js
index 163533b0..9d66ca1 100644
--- a/chrome/test/data/extensions/api_test/pdf_viewer_private/background.js
+++ b/chrome/test/data/extensions/api_test/pdf_viewer_private/background.js
@@ -53,7 +53,7 @@
   async function testIsPdfOcrAlwaysActive() {
     const isPdfOcrAlwaysActive =
         await chrome.pdfViewerPrivate.isPdfOcrAlwaysActive();
-    chrome.test.assertTrue(isPdfOcrAlwaysActive !== null);
+    chrome.test.assertNe(null, isPdfOcrAlwaysActive);
     chrome.test.succeed();
   },
   /**
diff --git a/chrome/test/data/extensions/api_test/printing/cancel_job.js b/chrome/test/data/extensions/api_test/printing/cancel_job.js
index 4ac8bfc..c4ca6eb 100644
--- a/chrome/test/data/extensions/api_test/printing/cancel_job.js
+++ b/chrome/test/data/extensions/api_test/printing/cancel_job.js
@@ -21,10 +21,10 @@
 
   const url = 'http://localhost:' + config.testServer.port + '/pdf/test.pdf';
   submitJob('id', 'test job', url, response => {
-    chrome.test.assertTrue(response != undefined);
-    chrome.test.assertTrue(response.status != undefined);
+    chrome.test.assertNe(undefined, response);
+    chrome.test.assertNe(undefined, response.status);
     chrome.test.assertEq(chrome.printing.SubmitJobStatus.OK, response.status);
-    chrome.test.assertTrue(response.jobId != undefined);
+    chrome.test.assertNe(undefined, response.jobId);
 
     chrome.printing.cancelJob(response.jobId, () => {});
   });
diff --git a/chrome/test/data/extensions/api_test/printing/get_printer_info.js b/chrome/test/data/extensions/api_test/printing/get_printer_info.js
index adc7ae1..6dd2986 100644
--- a/chrome/test/data/extensions/api_test/printing/get_printer_info.js
+++ b/chrome/test/data/extensions/api_test/printing/get_printer_info.js
@@ -4,16 +4,16 @@
 
 chrome.test.runTests([() => {
   chrome.printing.getPrinterInfo('id', response => {
-    chrome.test.assertTrue(response != undefined);
-    chrome.test.assertTrue(response.capabilities != undefined);
-    chrome.test.assertTrue(response.capabilities.printer != undefined);
+    chrome.test.assertNe(undefined, response);
+    chrome.test.assertNe(undefined, response.capabilities);
+    chrome.test.assertNe(undefined, response.capabilities.printer);
     let color = response.capabilities.printer.color;
-    chrome.test.assertTrue(color != undefined);
+    chrome.test.assertNe(undefined, color);
     chrome.test.assertEq(1, color.option.length);
-    chrome.test.assertTrue(color.option[0] != undefined);
+    chrome.test.assertNe(undefined, color.option[0]);
     chrome.test.assertEq('STANDARD_MONOCHROME', color.option[0].type);
 
-    chrome.test.assertTrue(response.status != undefined);
+    chrome.test.assertNe(undefined, response.status);
     chrome.test.assertEq(
         chrome.printing.PrinterStatus.UNREACHABLE, response.status);
 
diff --git a/chrome/test/data/extensions/api_test/printing/submit_job.js b/chrome/test/data/extensions/api_test/printing/submit_job.js
index 97fd1bb..c7263ae 100644
--- a/chrome/test/data/extensions/api_test/printing/submit_job.js
+++ b/chrome/test/data/extensions/api_test/printing/submit_job.js
@@ -5,10 +5,10 @@
 chrome.test.getConfig(function(config) {
   const url = 'http://localhost:' + config.testServer.port + '/pdf/test.pdf';
   submitJob('id', 'test job', url, response => {
-    chrome.test.assertTrue(response != undefined);
-    chrome.test.assertTrue(response.status != undefined);
+    chrome.test.assertNe(undefined, response);
+    chrome.test.assertNe(undefined, response.status);
     chrome.test.assertEq(chrome.printing.SubmitJobStatus.OK, response.status);
-    chrome.test.assertTrue(response.jobId != undefined);
+    chrome.test.assertNe(undefined, response.jobId);
 
     chrome.test.notifyPass();
   });
diff --git a/chrome/test/data/extensions/api_test/runtime/get_package_directory/app/window/test.js b/chrome/test/data/extensions/api_test/runtime/get_package_directory/app/window/test.js
index f20390ba..da540e4e 100644
--- a/chrome/test/data/extensions/api_test/runtime/get_package_directory/app/window/test.js
+++ b/chrome/test/data/extensions/api_test/runtime/get_package_directory/app/window/test.js
@@ -23,7 +23,7 @@
         // Ignore files or directories like .svn.
         if (entries[i].name[0] == '.')
           continue;
-        chrome.test.assertTrue(expectedEntries[entries[i].name] != null);
+        chrome.test.assertNe(null, expectedEntries[entries[i].name]);
         if (entries[i].isDirectory) {
           chrome.test.assertEq(typeof expectedEntries[entries[i].name],
                                'object');
diff --git a/chrome/test/data/extensions/api_test/runtime/get_package_directory/extension/test/test.js b/chrome/test/data/extensions/api_test/runtime/get_package_directory/extension/test/test.js
index f8d7385..8579b9e 100644
--- a/chrome/test/data/extensions/api_test/runtime/get_package_directory/extension/test/test.js
+++ b/chrome/test/data/extensions/api_test/runtime/get_package_directory/extension/test/test.js
@@ -21,7 +21,7 @@
         // Ignore files or directories like .svn.
         if (entries[i].name[0] == '.')
           continue;
-        chrome.test.assertTrue(expectedEntries[entries[i].name] != null);
+        chrome.test.assertNe(null, expectedEntries[entries[i].name]);
         if (entries[i].isDirectory) {
           chrome.test.assertEq(typeof expectedEntries[entries[i].name],
                                'object');
diff --git a/chrome/test/data/extensions/api_test/serial/api/background.js b/chrome/test/data/extensions/api_test/serial/api/background.js
index 3b1a5fb..493d652 100644
--- a/chrome/test/data/extensions/api_test/serial/api/background.js
+++ b/chrome/test/data/extensions/api_test/serial/api/background.js
@@ -187,10 +187,10 @@
   };
 
   var onGetControlSignals = function(options) {
-    chrome.test.assertTrue(typeof options.dcd != 'undefined', "No DCD set");
-    chrome.test.assertTrue(typeof options.cts != 'undefined', "No CTS set");
-    chrome.test.assertTrue(typeof options.ri != 'undefined', "No RI set");
-    chrome.test.assertTrue(typeof options.dsr != 'undefined', "No DSR set");
+    chrome.test.assertNe('undefined', typeof options.dcd, "No DCD set");
+    chrome.test.assertNe('undefined', typeof options.cts, "No CTS set");
+    chrome.test.assertNe('undefined', typeof options.ri, "No RI set");
+    chrome.test.assertNe('undefined', typeof options.dsr, "No DSR set");
     doNextOperation();
   };
 
diff --git a/chrome/test/data/extensions/api_test/settings_private/test.js b/chrome/test/data/extensions/api_test/settings_private/test.js
index ab2939e..0bff1aeb 100644
--- a/chrome/test/data/extensions/api_test/settings_private/test.js
+++ b/chrome/test/data/extensions/api_test/settings_private/test.js
@@ -55,7 +55,7 @@
     chrome.settingsPrivate.getPref(
         kTestPrefName,
         function(value) {
-          chrome.test.assertTrue(value !== null);
+          chrome.test.assertNe(null, value);
           callbackResult(true);
           chrome.test.succeed();
         });
@@ -123,7 +123,7 @@
     chrome.settingsPrivate.getPref(
         'cros.accounts.allowBWSI',
         function(value) {
-          chrome.test.assertTrue(value !== null);
+          chrome.test.assertNe(null, value);
           callbackResult(true);
           chrome.test.succeed();
         });
diff --git a/chrome/test/data/extensions/api_test/sync_file_system/request_file_system/test.js b/chrome/test/data/extensions/api_test/sync_file_system/request_file_system/test.js
index 39203104..d4a05a5 100644
--- a/chrome/test/data/extensions/api_test/sync_file_system/request_file_system/test.js
+++ b/chrome/test/data/extensions/api_test/sync_file_system/request_file_system/test.js
@@ -8,10 +8,10 @@
   function requestFileSystem() {
     chrome.syncFileSystem.requestFileSystem(
         chrome.test.callbackPass(function(fs) {
-            chrome.test.assertTrue(fs.name != undefined);
+            chrome.test.assertNe(undefined, fs.name);
             chrome.test.assertEq(fs.name.length - syncableNameSuffix.length,
                                  fs.name.lastIndexOf(syncableNameSuffix));
-            chrome.test.assertTrue(fs.root != undefined);
+            chrome.test.assertNe(undefined, fs.root);
             chrome.test.assertTrue(fs.root.isFile || fs.root.isDirectory);
         }));
   }
diff --git a/chrome/test/data/extensions/api_test/tabs/on_replaced/test_onreplaced.js b/chrome/test/data/extensions/api_test/tabs/on_replaced/test_onreplaced.js
index c19ad620..7d2b197 100644
--- a/chrome/test/data/extensions/api_test/tabs/on_replaced/test_onreplaced.js
+++ b/chrome/test/data/extensions/api_test/tabs/on_replaced/test_onreplaced.js
@@ -10,7 +10,7 @@
             var tabId = tab.id;
 
             var onReplaceListener = function(new_tab_id, old_tab_id) {
-              chrome.test.assertTrue(tabId != new_tab_id);
+              chrome.test.assertNe(new_tab_id, tabId);
               chrome.test.assertEq(tabId, old_tab_id);
               chrome.tabs.onReplaced.removeListener(onReplaceListener);
               chrome.test.succeed();
diff --git a/chrome/test/data/extensions/api_test/tabs/prerendering/test.js b/chrome/test/data/extensions/api_test/tabs/prerendering/test.js
index fe199d20..ac600d76 100644
--- a/chrome/test/data/extensions/api_test/tabs/prerendering/test.js
+++ b/chrome/test/data/extensions/api_test/tabs/prerendering/test.js
@@ -23,7 +23,7 @@
         ((resolve, details) => {
           prerenderingFrameId = details.frameId;
           prerenderingDocumentId = details.documentId;
-          chrome.test.assertTrue(prerenderingFrameId != 0);
+          chrome.test.assertNe(0, prerenderingFrameId);
           chrome.webRequest.onBeforeRequest.removeListener(onBeforeRequest);
           resolve();
         }).bind(this, resolve);
@@ -33,7 +33,7 @@
       chrome.tabs.update(tabId, {url: kInitiatorUrl});
     });
   });
-  chrome.test.assertTrue(prerenderingDocumentId != 0);
+  chrome.test.assertNe(0, prerenderingDocumentId);
 }
 
 // Checks if `allFrames: true` doesn't order to include pre-rendered frames.
@@ -156,7 +156,7 @@
 
 chrome.test.getConfig(async config => {
   testServerPort = config.testServer.port;
-  chrome.test.assertTrue(testServerPort != 0);
+  chrome.test.assertNe(0, testServerPort);
 
   const tabs = await new Promise(
       resolve => chrome.tabs.query({active: true}, tabs => resolve(tabs)));
diff --git a/chrome/test/data/extensions/api_test/window_open/focus/test.js b/chrome/test/data/extensions/api_test/window_open/focus/test.js
index 482e7d6d..41e0efe 100644
--- a/chrome/test/data/extensions/api_test/window_open/focus/test.js
+++ b/chrome/test/data/extensions/api_test/window_open/focus/test.js
@@ -41,7 +41,7 @@
   createdWinId = win.id;
   setTimeout(chrome.test.callbackPass(function () {
       listenDoneCallback();
-      chrome.test.assertTrue(focusedWinId != createdWinId);
+      chrome.test.assertNe(createdWinId, focusedWinId);
       }), 500);
 }
 
diff --git a/chrome/test/data/extensions/api_test/window_open/opener/test.js b/chrome/test/data/extensions/api_test/window_open/opener/test.js
index 93671998..4c22dd9 100644
--- a/chrome/test/data/extensions/api_test/window_open/opener/test.js
+++ b/chrome/test/data/extensions/api_test/window_open/opener/test.js
@@ -22,7 +22,7 @@
 
     window.onCheckOpenerLoaded = function(testWindow) {
       // The opener should now be set...
-      chrome.test.assertTrue(testWindow.opener != null);
+      chrome.test.assertNe(null, testWindow.opener);
       // ...and the test window should only have one tab (because it was
       // targetted via the "target-window" name).
       chrome.tabs.getAllInWindow(
diff --git a/chrome/test/data/extensions/context_menus/event_page/test.js b/chrome/test/data/extensions/context_menus/event_page/test.js
index 2b7ee744..3bf928f 100644
--- a/chrome/test/data/extensions/context_menus/event_page/test.js
+++ b/chrome/test/data/extensions/context_menus/event_page/test.js
@@ -9,7 +9,7 @@
 });
 
 chrome.contextMenus.onClicked.addListener(function(info, tab) {
-  chrome.test.assertTrue(tab.id != null);
+  chrome.test.assertNe(null, tab.id);
   chrome.test.assertEq(0, info.frameId); // 0 = main frame
   chrome.test.sendMessage("onClicked fired for " + info.menuItemId);
 });
diff --git a/chrome/test/data/extensions/management/get/background.js b/chrome/test/data/extensions/management/get/background.js
index cc1f674..dd7470b 100644
--- a/chrome/test/data/extensions/management/get/background.js
+++ b/chrome/test/data/extensions/management/get/background.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 chrome.management.get('pkplfbidichfdicaijlchgnapepdginl', function(info) {
-  chrome.test.assertTrue(info != null);
+  chrome.test.assertNe(null, info);
   chrome.test.assertEq('pkplfbidichfdicaijlchgnapepdginl', info.id);
   chrome.test.assertEq("simple_extension", info.name);
   chrome.test.assertEq("extension", info.type);
diff --git a/chrome/test/data/extensions/management/get_self/background.js b/chrome/test/data/extensions/management/get_self/background.js
index bafc39a9..5c71029 100644
--- a/chrome/test/data/extensions/management/get_self/background.js
+++ b/chrome/test/data/extensions/management/get_self/background.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 chrome.management.getSelf(function(info) {
-  chrome.test.assertTrue(info != null);
+  chrome.test.assertNe(null, info);
   chrome.test.assertEq("Self Get Test (no permissions)", info.name);
   chrome.test.assertEq("extension", info.type);
   chrome.test.assertEq(true, info.enabled);
diff --git a/chrome/test/data/extensions/management/self_uninstall_helper/background.js b/chrome/test/data/extensions/management/self_uninstall_helper/background.js
index bf0941c..b0eecb0c9 100644
--- a/chrome/test/data/extensions/management/self_uninstall_helper/background.js
+++ b/chrome/test/data/extensions/management/self_uninstall_helper/background.js
@@ -9,7 +9,7 @@
   chrome.management.getAll(function(items) {
     var found = false;
     for (var i = 0; i < items.length; i++) {
-      chrome.test.assertTrue(id != items.id);
+      chrome.test.assertNe(items.id, id);
       if (items[i].name != EXPECTED_NAME) continue;
       found = true;
     }
diff --git a/chrome/test/data/extensions/platform_apps/ephemeral_apps/filesystem_retain_entries/index.js b/chrome/test/data/extensions/platform_apps/ephemeral_apps/filesystem_retain_entries/index.js
index ab0163e..5222d00 100644
--- a/chrome/test/data/extensions/platform_apps/ephemeral_apps/filesystem_retain_entries/index.js
+++ b/chrome/test/data/extensions/platform_apps/ephemeral_apps/filesystem_retain_entries/index.js
@@ -11,7 +11,8 @@
     { type: 'openWritableFile' },
     callbackPass(function(entry) {
       var entry_id = chrome.fileSystem.retainEntry(entry);
-      chrome.test.assertTrue(entry_id != null && entry_id.length > 0);
+      chrome.test.assertNe(null, entry_id);
+      chrome.test.assertTrue(entry_id.length > 0);
 
       // Save the file handle to local storage.
       chrome.storage.local.set(
diff --git a/chrome/test/data/extensions/platform_apps/storage/test.js b/chrome/test/data/extensions/platform_apps/storage/test.js
index 6f27df1..966d8f509 100644
--- a/chrome/test/data/extensions/platform_apps/storage/test.js
+++ b/chrome/test/data/extensions/platform_apps/storage/test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 function assertContains(string, substring, error) {
-  chrome.test.assertTrue(string.indexOf(substring) != -1, error);
+  chrome.test.assertNe(-1, string.indexOf(substring), error);
 }
 
 chrome.test.runTests([
diff --git a/chrome/test/data/extensions/platform_apps/url_handlers/handlers/navigate_webview_to_url/test.js b/chrome/test/data/extensions/platform_apps/url_handlers/handlers/navigate_webview_to_url/test.js
index 43f71e8e..b2487f9 100644
--- a/chrome/test/data/extensions/platform_apps/url_handlers/handlers/navigate_webview_to_url/test.js
+++ b/chrome/test/data/extensions/platform_apps/url_handlers/handlers/navigate_webview_to_url/test.js
@@ -4,7 +4,7 @@
 
 chrome.app.runtime.onLaunched.addListener(function (launchData) {
   // Complete correctness of launchData is tested in another test.
-  chrome.test.assertTrue(typeof launchData !== 'undefined');
+  chrome.test.assertNe('undefined', typeof launchData);
 
   chrome.app.window.create(
     "main.html",
diff --git a/chrome/test/data/extensions/platform_apps/url_handlers/handlers/simple/test.js b/chrome/test/data/extensions/platform_apps/url_handlers/handlers/simple/test.js
index 52e2cd7..4819c56 100644
--- a/chrome/test/data/extensions/platform_apps/url_handlers/handlers/simple/test.js
+++ b/chrome/test/data/extensions/platform_apps/url_handlers/handlers/simple/test.js
@@ -7,7 +7,7 @@
   // can be read in the launch data.
   chrome.test.runTests([
     function testUrlHandler() {
-      chrome.test.assertTrue(typeof launchData != 'undefined', "No launchData");
+      chrome.test.assertNe('undefined', typeof launchData, "No launchData");
       chrome.test.assertFalse(launchData.isKioskSession,
           "launchData.isKioskSession incorrect");
       chrome.test.assertEq(launchData.id, "my_doc_url",
diff --git a/chrome/test/data/extensions/platform_apps/web_view/common/useragent/bootstrap.js b/chrome/test/data/extensions/platform_apps/web_view/common/useragent/bootstrap.js
index 0b57f9e4..bbe64dbc 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/common/useragent/bootstrap.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/common/useragent/bootstrap.js
@@ -40,7 +40,7 @@
           // Now remove the UA override.
           embedder.webview.setUserAgentOverride('');
         } else if (step == 3) {
-          chrome.test.assertTrue('foobar' != data[1]);
+          chrome.test.assertNe(data[1], 'foobar');
           chrome.test.assertFalse(embedder.webview.isUserAgentOverridden());
           chrome.test.succeed();
         }
diff --git a/chrome/test/data/extensions/platform_apps/window_api/test.js b/chrome/test/data/extensions/platform_apps/window_api/test.js
index be2166b..a63646b62 100644
--- a/chrome/test/data/extensions/platform_apps/window_api/test.js
+++ b/chrome/test/data/extensions/platform_apps/window_api/test.js
@@ -385,7 +385,7 @@
     function testNoOptions() {
       chrome.app.window.create('test.html', {
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertTrue(win.innerBounds.width > 0);
         chrome.test.assertTrue(win.innerBounds.height > 0);
         chrome.test.assertTrue(win.outerBounds.width > 0);
@@ -406,7 +406,7 @@
       chrome.app.window.create('test.html', {
         innerBounds: innerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         assertBoundsEq(innerBounds, win.innerBounds);
         assertBoundsConsistent(win);
         assertConstraintsUnspecified(win);
@@ -425,7 +425,7 @@
       chrome.app.window.create('test.html', {
         innerBounds: innerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         assertBoundsEq(innerBounds, win.innerBounds);
         assertBoundsConsistent(win);
         assertConstraintsUnspecified(win);
@@ -443,7 +443,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         assertBoundsEq(outerBounds, win.outerBounds);
         assertBoundsConsistent(win);
         assertConstraintsUnspecified(win);
@@ -462,7 +462,7 @@
         outerBounds: outerBounds,
         frame: 'none'
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         assertBoundsEq(outerBounds, win.outerBounds);
         assertBoundsEq(outerBounds, win.innerBounds);
         assertConstraintsUnspecified(win);
@@ -483,7 +483,7 @@
         innerBounds: innerBounds,
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.left, win.outerBounds.left);
         chrome.test.assertEq(outerBounds.top, win.outerBounds.top);
         chrome.test.assertEq(innerBounds.width, win.innerBounds.width);
@@ -507,7 +507,7 @@
         innerBounds: innerBounds,
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(innerBounds.left, win.innerBounds.left);
         chrome.test.assertEq(innerBounds.height, win.innerBounds.height);
         chrome.test.assertEq(outerBounds.top, win.outerBounds.top);
@@ -526,7 +526,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.left, win.outerBounds.left);
         chrome.test.assertEq(outerBounds.top, win.outerBounds.top);
         chrome.test.assertTrue(win.innerBounds.width > 0);
@@ -547,7 +547,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.width, win.outerBounds.width);
         chrome.test.assertEq(outerBounds.height, win.outerBounds.height);
         assertBoundsConsistent(win);
@@ -581,7 +581,7 @@
       chrome.app.window.create('test.html', {
         innerBounds: innerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(innerBounds.maxWidth, win.innerBounds.width);
         chrome.test.assertEq(innerBounds.maxHeight, win.innerBounds.height);
         chrome.test.assertEq(innerBounds.maxWidth, win.innerBounds.maxWidth);
@@ -601,7 +601,7 @@
       chrome.app.window.create('test.html', {
         innerBounds: innerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(innerBounds.minWidth, win.innerBounds.width);
         chrome.test.assertEq(innerBounds.minHeight, win.innerBounds.height);
         chrome.test.assertEq(innerBounds.minWidth, win.innerBounds.minWidth);
@@ -621,7 +621,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.maxWidth, win.outerBounds.width);
         chrome.test.assertEq(outerBounds.maxHeight, win.outerBounds.height);
         chrome.test.assertEq(outerBounds.maxWidth, win.outerBounds.maxWidth);
@@ -641,7 +641,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.width);
         chrome.test.assertEq(outerBounds.minHeight, win.outerBounds.height);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.minWidth);
@@ -664,7 +664,7 @@
         innerBounds: innerBounds,
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.width);
         chrome.test.assertEq(innerBounds.minHeight, win.innerBounds.height);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.minWidth);
@@ -686,7 +686,7 @@
       chrome.app.window.create('test.html', {
         outerBounds: outerBounds
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.width);
         chrome.test.assertEq(outerBounds.minHeight, win.outerBounds.height);
         chrome.test.assertEq(outerBounds.minWidth, win.outerBounds.minWidth);
@@ -709,7 +709,7 @@
         outerBounds: outerBounds,
         frame: 'none'
       }, callbackPass(function(win) {
-        chrome.test.assertTrue(win != null);
+        chrome.test.assertNe(null, win);
         assertConstraintsEq(outerBounds, win.outerBounds);
         assertConstraintsEq(outerBounds, win.innerBounds);
         win.close();
diff --git a/chrome/test/data/webui/chromeos/personalization_app/keyboard_backlight_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/keyboard_backlight_element_test.ts
index ee61285..ae8e4c0d 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/keyboard_backlight_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/keyboard_backlight_element_test.ts
@@ -193,4 +193,42 @@
             'zone-customization'),
         'dialog exists after button is clicked');
   });
+
+  test('shows wallpaper color at the end with multi-zone enabled', async () => {
+    loadTimeData.overrideValues({isMultiZoneRgbKeyboardSupported: true});
+
+    keyboardBacklightElement = initElement(KeyboardBacklight);
+
+    const selectorContainer =
+        keyboardBacklightElement.shadowRoot!.getElementById('selector');
+    assertTrue(!!selectorContainer);
+    const colorContainers =
+        selectorContainer.querySelectorAll('.color-container');
+    assertEquals(9, colorContainers!.length);
+    assertEquals(
+        'Wallpaper color', (colorContainers[8] as HTMLElement).ariaLabel);
+    assertEquals(0, selectorContainer.querySelectorAll('.divider').length);
+    assertTrue(!!keyboardBacklightElement?.shadowRoot!.getElementById(
+        'wallpaperColorDescription'));
+  });
+
+  test(
+      'shows wallpaper color button at the beginning with multi-zone disabled',
+      async () => {
+        loadTimeData.overrideValues({isMultiZoneRgbKeyboardSupported: false});
+
+        keyboardBacklightElement = initElement(KeyboardBacklight);
+
+        const selectorContainer =
+            keyboardBacklightElement.shadowRoot!.getElementById('selector');
+        assertTrue(!!selectorContainer);
+        const colorContainers =
+            selectorContainer.querySelectorAll('.color-container');
+        assertEquals(9, colorContainers!.length);
+        assertEquals(
+            'Wallpaper color', (colorContainers[0] as HTMLElement).ariaLabel);
+        assertEquals(1, selectorContainer.querySelectorAll('.divider').length);
+        assertFalse(!!keyboardBacklightElement?.shadowRoot!.getElementById(
+            'wallpaperColorDescription'));
+      });
 });
diff --git a/chrome/test/data/webui/cr_components/history_clusters_test.ts b/chrome/test/data/webui/cr_components/history_clusters_test.ts
index 28f7c88..346525d3 100644
--- a/chrome/test/data/webui/cr_components/history_clusters_test.ts
+++ b/chrome/test/data/webui/cr_components/history_clusters_test.ts
@@ -64,7 +64,7 @@
       debugInfo: {},
       rawVisitData: rawVisitData,
       isKnownToSync: false,
-      imageUrl: undefined,
+      hasUrlKeyedImage: false,
     };
 
     const cluster1: Cluster = {
@@ -245,4 +245,4 @@
     assertTrue(!!imageUrl);
     assertEquals('https://example.com/image.png', imageUrl.url);
   });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
index 4bb12376..9888cf9 100644
--- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
@@ -59,9 +59,7 @@
         annotations: [],
         debugInfo: {},
         rawVisitData: rawVisitData,
-        imageUrl: i >= numImageVisits ? undefined : {
-          url: `https://image.com/${i}`,
-        },
+        hasUrlKeyedImage: i < numImageVisits,
         isKnownToSync: false,
       });
     }
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 3b69d7d..1a99b7d4 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -23,7 +23,7 @@
   "apn_detail_dialog_tests.js",
   "app_notifications_subpage_tests.js",
   "apps_page_test.js",
-  "audio_and_captions_page_tests.js",
+  "audio_and_captions_page_tests.ts",
   "cellular_networks_list_test.js",
   "cellular_roaming_toggle_button_test.js",
   "cellular_setup_dialog_test.js",
diff --git a/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.js b/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.js
deleted file mode 100644
index e712cbb..0000000
--- a/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.js
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://os-settings/chromeos/lazy_load.js';
-
-import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
-import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js';
-import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js';
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
-import {waitAfterNextRender, waitBeforeNextRender} from 'chrome://webui-test/polymer_test_util.js';
-import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js';
-
-suite('AudioAndCaptionsPageTests', function() {
-  let page = null;
-
-  function initPage() {
-    page = document.createElement('settings-audio-and-captions-page');
-    document.body.appendChild(page);
-  }
-
-  setup(function() {
-    PolymerTest.clearBody();
-    Router.getInstance().navigateTo(routes.A11Y_AUDIO_AND_CAPTIONS);
-  });
-
-  teardown(function() {
-    if (page) {
-      page.remove();
-    }
-    Router.getInstance().resetRouteForTesting();
-  });
-
-  test('no subpages are available in kiosk mode', function() {
-    loadTimeData.overrideValues({
-      isKioskModeActive: true,
-      showTabletModeShelfNavigationButtonsSettings: true,
-    });
-    initPage();
-    flush();
-
-    const subpageLinks = page.root.querySelectorAll('cr-link-row');
-    subpageLinks.forEach(subpageLink => assertFalse(isVisible(subpageLink)));
-  });
-});
diff --git a/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.ts b/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.ts
new file mode 100644
index 0000000..9e73b897
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/audio_and_captions_page_tests.ts
@@ -0,0 +1,43 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://os-settings/chromeos/lazy_load.js';
+
+import {SettingsAudioAndCaptionsPageElement} from 'chrome://os-settings/chromeos/lazy_load.js';
+import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {assertFalse} from 'chrome://webui-test/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/test_util.js';
+
+suite('<settings-audio-and-captions-page>', () => {
+  let page: SettingsAudioAndCaptionsPageElement|null = null;
+
+  function initPage() {
+    page = document.createElement('settings-audio-and-captions-page');
+    document.body.appendChild(page);
+    flush();
+  }
+
+  setup(() => {
+    Router.getInstance().navigateTo(routes.A11Y_AUDIO_AND_CAPTIONS);
+  });
+
+  teardown(() => {
+    page!.remove();
+    page = null;
+    Router.getInstance().resetRouteForTesting();
+  });
+
+  test('no subpages are available in kiosk mode', () => {
+    loadTimeData.overrideValues({
+      isKioskModeActive: true,
+      showTabletModeShelfNavigationButtonsSettings: true,
+    });
+    initPage();
+
+    const subpageLinks = page!.shadowRoot!.querySelectorAll('cr-link-row');
+    subpageLinks.forEach(subpageLink => assertFalse(isVisible(subpageLink)));
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/hotspot_config_dialog_tests.js b/chrome/test/data/webui/settings/chromeos/hotspot_config_dialog_tests.js
index 6fe5b05..356c387 100644
--- a/chrome/test/data/webui/settings/chromeos/hotspot_config_dialog_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/hotspot_config_dialog_tests.js
@@ -5,7 +5,7 @@
 import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 import {setHotspotConfigForTesting} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.js';
 import {FakeHotspotConfig} from 'chrome://resources/ash/common/hotspot/fake_hotspot_config.js';
-import {CrosHotspotConfigInterface, HotspotAllowStatus, HotspotConfig, HotspotInfo, HotspotState, SetHotspotConfigResult, WiFiBand, WiFiSecurityMode} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
+import {HotspotAllowStatus, HotspotState, SetHotspotConfigResult, WiFiBand, WiFiSecurityMode} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
@@ -280,4 +280,4 @@
         const response = await hotspotConfig.getHotspotInfo();
         assertEquals('test_ssid', response.hotspotInfo.config.ssid);
       });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/settings/chromeos/hotspot_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/hotspot_subpage_tests.js
index 1df0f03e..01e6a66 100644
--- a/chrome/test/data/webui/settings/chromeos/hotspot_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/hotspot_subpage_tests.js
@@ -5,7 +5,7 @@
 import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 import {setHotspotConfigForTesting} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.js';
 import {FakeHotspotConfig} from 'chrome://resources/ash/common/hotspot/fake_hotspot_config.js';
-import {CrosHotspotConfigInterface, CrosHotspotConfigObserverInterface, HotspotAllowStatus, HotspotConfig, HotspotControlResult, HotspotInfo, HotspotState, SetHotspotConfigResult, WiFiSecurityMode} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
+import {HotspotAllowStatus, HotspotControlResult, HotspotState, SetHotspotConfigResult} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
@@ -260,4 +260,4 @@
         configureButton.click();
         await Promise.all([showHotspotConfigDialogEvent, flushTasks()]);
       });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/settings/chromeos/hotspot_summary_item_tests.js b/chrome/test/data/webui/settings/chromeos/hotspot_summary_item_tests.js
index 1c51d984..af9aa29 100644
--- a/chrome/test/data/webui/settings/chromeos/hotspot_summary_item_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/hotspot_summary_item_tests.js
@@ -5,7 +5,7 @@
 import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 import {setHotspotConfigForTesting} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.js';
 import {FakeHotspotConfig} from 'chrome://resources/ash/common/hotspot/fake_hotspot_config.js';
-import {CrosHotspotConfigInterface, CrosHotspotConfigObserverInterface, HotspotAllowStatus, HotspotConfig, HotspotControlResult, HotspotInfo, HotspotState, WiFiSecurityMode} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
+import {HotspotAllowStatus, HotspotControlResult, HotspotState} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
diff --git a/chrome/test/data/webui/settings/chromeos/network_summary_test.js b/chrome/test/data/webui/settings/chromeos/network_summary_test.js
index ffbf2366..11f37a8 100644
--- a/chrome/test/data/webui/settings/chromeos/network_summary_test.js
+++ b/chrome/test/data/webui/settings/chromeos/network_summary_test.js
@@ -6,7 +6,7 @@
 
 import {setHotspotConfigForTesting} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.js';
 import {FakeHotspotConfig} from 'chrome://resources/ash/common/hotspot/fake_hotspot_config.js';
-import {CrosHotspotConfigInterface, HotspotAllowStatus, HotspotConfig, HotspotInfo, HotspotState, WiFiSecurityMode} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
+import {HotspotAllowStatus, HotspotState} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 suite('NetworkSummary', function() {
diff --git a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js b/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
index b5dbd462..82e8a32 100644
--- a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
+++ b/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {fakeKeyboards, ModifierKey, Router, routes, SettingsPerDeviceKeyboardRemapKeysElement} from 'chrome://os-settings/chromeos/os_settings.js';
+import {fakeKeyboards, KeyboardRemapModifierKeyRowElement, ModifierKey, Router, routes, SettingsPerDeviceKeyboardRemapKeysElement} from 'chrome://os-settings/chromeos/os_settings.js';
 import {assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
@@ -44,31 +44,40 @@
     assertTrue(!!page.keyboard);
 
     // Verify that the dropdown menu for unremapped key is displayed as default.
-    const altKeyDrowDown = page.shadowRoot.querySelector('#altKey');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const altKeyRow = page.shadowRoot.querySelector('#altKey');
+    const altKeyDropdown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
     const altKeyMappedTo = ModifierKey.ALT.toString();
-    assertTrue(!!altKeyDrowDown);
+    assertTrue(!!altKeyDropdown);
     assertEquals(
-        altKeyDrowDown.shadowRoot.querySelector('select').value,
+        altKeyDropdown.shadowRoot.querySelector('select').value,
         altKeyMappedTo);
 
+    // Verify that the default key icon is not highlighted.
+    assertEquals(altKeyRow.keyState, 'default-remapping');
+
     // Verify that the dropdown menu for remapped key is displayed as the
     // the target key in keyboard remapping settings.
-    const ctrlKeyDropdown = page.shadowRoot.querySelector('#ctrlKey');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
     const ctrlKeyMappedTo =
         fakeKeyboards[0]
             .settings.modifierRemappings.get(ModifierKey.CONTROL)
             .toString();
+    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
     assertTrue(!!ctrlKeyDropdown);
     assertEquals(
         ctrlKeyDropdown.shadowRoot.querySelector('select').value,
         ctrlKeyMappedTo);
+    // Verify that the remapped key icon is highlighted.
+    assertEquals(ctrlKeyRow.keyState, 'modifier-remapped');
 
-    // await flushTasks();
     // Verify that the label for meta key is displayed as the
     // the target key in keyboard remapping settings.
-    const metaKeyLabel = page.shadowRoot.querySelector('#metaKeyLabel');
-    assertTrue(!!metaKeyLabel);
-    assertEquals(metaKeyLabel.textContent, 'Command');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
+    assertTrue(!!metaKeyRow);
+    assertEquals(metaKeyRow.keyLabel, 'Command');
   });
 
   /**
@@ -89,29 +98,37 @@
 
     // Verify that the dropdown menu for unremapped key in the new
     // keyboard is updated and displayed as default.
-    const ctrlKeyDropdown = page.shadowRoot.querySelector('#ctrlKey');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
+    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
     const ctrlKeyMappedTo = ModifierKey.CONTROL.toString();
     assertTrue(!!ctrlKeyDropdown);
     assertEquals(
         ctrlKeyDropdown.shadowRoot.querySelector('select').value,
         ctrlKeyMappedTo);
+    // Verify that the default key icon is not highlighted.
+    assertEquals(ctrlKeyRow.keyState, 'default-remapping');
 
     // Verify that the dropdown menu for remapped key is updated and displayed
     // as the target key in the new keyboard remapping settings.
-    const altKeyDrowDown = page.shadowRoot.querySelector('#altKey');
+    const altKeyRow = page.shadowRoot.querySelector('#altKey');
+    const altKeyDropDown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
     const altKeyMappedTo = fakeKeyboards[2]
                                .settings.modifierRemappings.get(ModifierKey.ALT)
                                .toString();
-    assertTrue(!!altKeyDrowDown);
+    assertTrue(!!altKeyDropDown);
     assertEquals(
-        altKeyDrowDown.shadowRoot.querySelector('select').value,
+        altKeyDropDown.shadowRoot.querySelector('select').value,
         altKeyMappedTo);
+    // Verify that the remapped key icon is highlighted.
+    assertEquals(altKeyRow.keyState, 'modifier-remapped');
 
     // Verify that the label for meta key is displayed as the
     // the target key in the new keyboard remapping settings.
-    const metaKeyLabel = page.shadowRoot.querySelector('#metaKeyLabel');
-    assertTrue(!!metaKeyLabel);
-    assertEquals(metaKeyLabel.textContent, 'Launcher');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
+    assertTrue(!!metaKeyRow);
+    assertEquals(metaKeyRow.keyLabel, 'Launcher');
   });
 
   /**
@@ -128,17 +145,25 @@
     await flushTasks();
 
     // The keyboard has "Command" as metaKey, so ctrl key should be restored to
-    // void, meta key should be restored to ctrl.
-    const ctrlKeyDropdown = page.shadowRoot.querySelector('#ctrlKey');
+    // meta, meta key should be restored to ctrl.
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const ctrlKeyRow = page.shadowRoot.querySelector('#ctrlKey');
+    const ctrlKeyDropdown = ctrlKeyRow.shadowRoot.querySelector('#keyDropdown');
     assertTrue(!!ctrlKeyDropdown);
     const metaKeyValue = ModifierKey.META.toString();
     assertEquals(
         ctrlKeyDropdown.shadowRoot.querySelector('select').value, metaKeyValue);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals(ctrlKeyRow.keyState, 'default-remapping');
 
     const ctrlKeyValue = ModifierKey.CONTROL.toString();
-    const metaKeyDropdown = page.shadowRoot.querySelector('#metaKey');
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const metaKeyRow = page.shadowRoot.querySelector('#metaKey');
+    const metaKeyDropdown = metaKeyRow.shadowRoot.querySelector('#keyDropdown');
     assertEquals(
         metaKeyDropdown.shadowRoot.querySelector('select').value, ctrlKeyValue);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals(metaKeyRow.keyState, 'default-remapping');
 
     // Update the subpage with a new keyboard.
     const url = new URLSearchParams(
@@ -151,15 +176,19 @@
 
     restoreButton.click();
     await flushTasks();
-    // The keyboard has "Launcher" as metaKey, ctrl key should be restored to
-    // default key mappings.
+    // The keyboard has "Launcher" as metaKey, meta key should be restored to
+    // default metaKey mappings.
     const altKeyValue = ModifierKey.ALT.toString();
-    const altKeyDrowDown = page.shadowRoot.querySelector('#altKey');
-    assertTrue(!!altKeyDrowDown);
+    /**  @type {?KeyboardRemapModifierKeyRowElement} */
+    const altKeyRow = page.shadowRoot.querySelector('#altKey');
+    const altKeyDropDown = altKeyRow.shadowRoot.querySelector('#keyDropdown');
+    assertTrue(!!altKeyDropDown);
     assertEquals(
-        altKeyDrowDown.shadowRoot.querySelector('select').value, altKeyValue);
+        altKeyDropDown.shadowRoot.querySelector('select').value, altKeyValue);
     assertEquals(
         metaKeyDropdown.shadowRoot.querySelector('select').value, metaKeyValue);
+    // Verify that the restored key icon is not highlighted.
+    assertEquals(metaKeyRow.keyState, 'default-remapping');
   });
 
   /**
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.ts b/chrome/test/data/webui/settings/search_engines_page_test.ts
index 57d4119..4466b9a 100644
--- a/chrome/test/data/webui/settings/search_engines_page_test.ts
+++ b/chrome/test/data/webui/settings/search_engines_page_test.ts
@@ -8,7 +8,7 @@
 import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {CrInputElement, SettingsOmniboxExtensionEntryElement, SettingsSearchEngineEditDialogElement, SettingsSearchEngineEntryElement, SettingsSearchEnginesListElement, SettingsSearchEnginesPageElement} from 'chrome://settings/lazy_load.js';
-import {ExtensionControlBrowserProxyImpl, loadTimeData, SearchEngine, SearchEnginesBrowserProxyImpl, SearchEnginesInfo, SearchEnginesInteractions} from 'chrome://settings/settings.js';
+import {ExtensionControlBrowserProxyImpl, SearchEngine, SearchEnginesBrowserProxyImpl, SearchEnginesInfo, SearchEnginesInteractions} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
@@ -151,7 +151,6 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
     entry = document.createElement('settings-search-engine-entry');
     entry.set('engine', searchEngine);
-    entry.set('isActiveSearchEnginesFlagEnabled', false);
     document.body.appendChild(entry);
   });
 
@@ -160,8 +159,7 @@
   });
 
   // Test that the <search-engine-entry> is populated according to its
-  // underlying SearchEngine model. If the #omnibox-active-search-engines flag
-  // is enabled, show the shortcut column instead of the keyword column.
+  // underlying SearchEngine model.
   test('Initialization', function() {
     flush();
     assertEquals(
@@ -423,7 +421,6 @@
       others: searchEnginesInfo.others.slice(),
       extensions: searchEnginesInfo.extensions.slice(),
     });
-    loadTimeData.overrideValues({'isActiveSearchEnginesFlagEnabled': false});
     SearchEnginesBrowserProxyImpl.setInstance(browserProxy);
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
     page = document.createElement('settings-search-engines-page');
diff --git a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
index 11768c0..9fce6ba 100644
--- a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
+++ b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
@@ -40,9 +40,7 @@
   const base::FilePath dummy_file_path =
       mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
   const std::string dummy_file_content = "This is a dummy file.";
-  const int write_result = base::WriteFile(
-      dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
-  if (write_result != static_cast<int>(dummy_file_content.size())) {
+  if (!base::WriteFile(dummy_file_path, dummy_file_content)) {
     DLOG(ERROR) << "Failed to put a dummy file at " << dummy_file_path.value();
     return MountError::kMountProgramFailed;
   }
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
index 3276e71..da068ef2 100644
--- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
@@ -71,9 +71,9 @@
       continue;
     }
     const std::string& data = kv.second;
-    int result = base::WriteFile(path, data.data(), data.size());
-    if (result == -1 || static_cast<size_t>(result) != data.size())
+    if (!base::WriteFile(path, data)) {
       LOG(WARNING) << "Failed to write to " << path.value();
+    }
   }
 }
 
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
index fe1943c..0274115 100644
--- a/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
@@ -154,7 +154,7 @@
   // The real implementation does a blocking wait on the dbus call; the fake
   // implementation must have this file written before returning.
   base::ScopedAllowBlockingForTesting allow_io;
-  base::WriteFile(cache_path, result.data(), result.size());
+  base::WriteFile(cache_path, result);
 
   return reply;
 }
diff --git a/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc b/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc
index db0679ec..9b6a78f 100644
--- a/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc
+++ b/chromeos/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -802,7 +802,7 @@
       std::string(kFakeDeviceIdForTesting) + std::string(kCabExtension);
   base::FilePath full_path = root_path.Append(test_filename);
   // Create a temporary file to simulate a .cab available for install.
-  base::WriteFile(full_path, "", 0);
+  base::WriteFile(full_path, "");
   EXPECT_TRUE(base::PathExists(full_path));
   const std::string uri = kFilePathIdentifier + full_path.value();
 
diff --git a/chromeos/ash/components/install_attributes/install_attributes_unittest.cc b/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
index 53f830a6..bb4571d 100644
--- a/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
+++ b/chromeos/ash/components/install_attributes/install_attributes_unittest.cc
@@ -277,8 +277,7 @@
   SetAttribute(&install_attrs_proto, InstallAttributes::kAttrEnterpriseUser,
                kTestUserDeprecated);
   const std::string blob(install_attrs_proto.SerializeAsString());
-  ASSERT_EQ(static_cast<int>(blob.size()),
-            base::WriteFile(GetTempPath(), blob.c_str(), blob.size()));
+  ASSERT_TRUE(base::WriteFile(GetTempPath(), blob));
   install_attributes_->Init(GetTempPath());
   EXPECT_EQ(policy::DEVICE_MODE_ENTERPRISE, install_attributes_->GetMode());
   EXPECT_EQ(kTestDomain, install_attributes_->GetDomain());
@@ -291,8 +290,7 @@
   SetAttribute(&install_attrs_proto,
                InstallAttributes::kAttrConsumerKioskEnabled, "true");
   const std::string blob(install_attrs_proto.SerializeAsString());
-  ASSERT_EQ(static_cast<int>(blob.size()),
-            base::WriteFile(GetTempPath(), blob.c_str(), blob.size()));
+  ASSERT_TRUE(base::WriteFile(GetTempPath(), blob));
   install_attributes_->Init(GetTempPath());
   EXPECT_EQ(policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH,
             install_attributes_->GetMode());
diff --git a/chromeos/ash/components/metrics/login_event_recorder.cc b/chromeos/ash/components/metrics/login_event_recorder.cc
index caf8bde..f8ec7de3 100644
--- a/chromeos/ash/components/metrics/login_event_recorder.cc
+++ b/chromeos/ash/components/metrics/login_event_recorder.cc
@@ -161,7 +161,7 @@
   TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
       "startup", kBootTimes, TRACE_ID_LOCAL(kBootTimes), prev);
 
-  base::WriteFile(log_path.Append(base_name), output.data(), output.size());
+  base::WriteFile(log_path.Append(base_name), output);
 }
 
 }  // namespace
diff --git a/chromeos/ash/components/system/statistics_provider_impl.cc b/chromeos/ash/components/system/statistics_provider_impl.cc
index 76a4eb8..ec69b37 100644
--- a/chromeos/ash/components/system/statistics_provider_impl.cc
+++ b/chromeos/ash/components/system/statistics_provider_impl.cc
@@ -523,10 +523,7 @@
     std::string stub_contents =
         "\"serial_number\"=\"stub_" +
         base::NumberToString(base::Time::Now().ToJavaTime()) + "\"\n";
-    int bytes_written =
-        base::WriteFile(sources_.machine_info_filepath, stub_contents.c_str(),
-                        stub_contents.size());
-    if (bytes_written < static_cast<int>(stub_contents.size())) {
+    if (!base::WriteFile(sources_.machine_info_filepath, stub_contents)) {
       PLOG(ERROR) << "Error writing machine info stub "
                   << sources_.machine_info_filepath;
     }
@@ -555,9 +552,7 @@
       return;
     } else {
       std::string stub_contents = "\"ActivateDate\"=\"2000-01\"\n";
-      int bytes_written = base::WriteFile(
-          sources_.vpd_filepath, stub_contents.c_str(), stub_contents.size());
-      if (bytes_written < static_cast<int>(stub_contents.size())) {
+      if (!base::WriteFile(sources_.vpd_filepath, stub_contents)) {
         PLOG(ERROR) << "Error writing VPD stub " << sources_.vpd_filepath;
       }
     }
diff --git a/chromeos/ash/components/system/statistics_provider_impl_unittest.cc b/chromeos/ash/components/system/statistics_provider_impl_unittest.cc
index 59ae755d..3ee1a49 100644
--- a/chromeos/ash/components/system/statistics_provider_impl_unittest.cc
+++ b/chromeos/ash/components/system/statistics_provider_impl_unittest.cc
@@ -47,8 +47,7 @@
   DCHECK(file.IsValid());
   DCHECK(!filepath.empty());
 
-  int length = base::WriteFile(filepath, content);
-  DCHECK_GE(length, 0);
+  DCHECK(base::WriteFile(filepath, content));
 
   return filepath;
 }
diff --git a/chromeos/ash/services/hotspot_config/public/mojom/BUILD.gn b/chromeos/ash/services/hotspot_config/public/mojom/BUILD.gn
index 849100e..a6b145e0 100644
--- a/chromeos/ash/services/hotspot_config/public/mojom/BUILD.gn
+++ b/chromeos/ash/services/hotspot_config/public/mojom/BUILD.gn
@@ -11,4 +11,5 @@
   sources = [ "cros_hotspot_config.mojom" ]
   public_deps = [ "//mojo/public/mojom/base" ]
   webui_module_path = "chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom"
+  use_typescript_sources = true
 }
diff --git a/chromeos/ash/services/network_config/cros_network_config.cc b/chromeos/ash/services/network_config/cros_network_config.cc
index 0ae0740..8d0efa7 100644
--- a/chromeos/ash/services/network_config/cros_network_config.cc
+++ b/chromeos/ash/services/network_config/cros_network_config.cc
@@ -3427,15 +3427,15 @@
   std::vector<mojom::TrafficCounterPtr> counters;
   for (const base::Value& tc : traffic_counters->GetList()) {
     DCHECK(tc.is_dict());
-    const base::Value* source =
-        tc.FindKeyOfType("source", base::Value::Type::STRING);
+    const base::Value::Dict& tc_dict = tc.GetDict();
+    const std::string* source = tc_dict.FindString("source");
     DCHECK(source);
 
     // Since rx_bytes may be larger than the maximum value representable by
     // uint32_t, we must check whether it was implicitly converted to a double
     // during D-Bus deserialization.
     uint64_t rx_bytes;
-    const base::Value* rb = tc.GetDict().Find("rx_bytes");
+    const base::Value* rb = tc_dict.Find("rx_bytes");
     DCHECK(rb);
     if (rb->type() == base::Value::Type::INTEGER) {
       rx_bytes = rb->GetInt();
@@ -3449,7 +3449,7 @@
     // uint32_t, we must check whether it was implicitly converted to a double
     // during D-Bus deserialization.
     uint64_t tx_bytes;
-    const base::Value* tb = tc.GetDict().Find("tx_bytes");
+    const base::Value* tb = tc_dict.Find("tx_bytes");
     DCHECK(tb);
     if (tb->type() == base::Value::Type::INTEGER) {
       tx_bytes = tb->GetInt();
@@ -3459,10 +3459,9 @@
       NOTREACHED();
     }
 
-    counters.push_back(
-        mojom::TrafficCounter::New(ConvertToTrafficCounterSourceEnum(
-                                       base::ToLowerASCII(source->GetString())),
-                                   rx_bytes, tx_bytes));
+    counters.push_back(mojom::TrafficCounter::New(
+        ConvertToTrafficCounterSourceEnum(base::ToLowerASCII(*source)),
+        rx_bytes, tx_bytes));
   }
   std::move(callback).Run(std::move(counters));
 }
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 554f54a2..96448e7 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2606,6 +2606,9 @@
         <message name="IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_ZONE_CUSTOMIZATION_BUTTON" desc="The text of the button that allows users to customize rgb keyboard zone colors.">
           Customize
         </message>
+        <message name="IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_DESCRIPTION" desc="The description for the button that allows users to select a keyboard backlight wallpaper-extracted color.">
+          Match wallpaper
+        </message>
 
         <!-- Personalization App Search Results -->
         <message name="IDS_PERSONALIZATION_APP_SEARCH_RESULT_TITLE" desc="Text for search result item which, when clicked, navigates the user to personalization app.">
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_DESCRIPTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..e47095f
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_WALLPAPER_COLOR_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+d14118737b46d7b473ea31c2ac70ab058dae685a
\ No newline at end of file
diff --git a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
index eb27c8f3..7c2f4f78 100644
--- a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
+++ b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
@@ -911,6 +911,7 @@
     case apps::LaunchSource::kFromCommandLine:
     case apps::LaunchSource::kFromBackgroundMode:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       NOTREACHED();
       return crosapi::mojom::LaunchSource::kUnknown;
   }
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index d0f4c8a6..056821a3 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-112-5563.8-1676896877-benchmark-113.0.5619.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-113-5563.31-1677502031-benchmark-113.0.5620.0-r1-redacted.afdo.xz
diff --git a/chromeos/ui/base/window_properties.cc b/chromeos/ui/base/window_properties.cc
index c953cc5..7075e507 100644
--- a/chromeos/ui/base/window_properties.cc
+++ b/chromeos/ui/base/window_properties.cc
@@ -21,9 +21,6 @@
 
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kBlockedForAssistantSnapshotKey, false)
 
-DEFINE_UI_CLASS_PROPERTY_KEY(bool, kCanAttachToAnotherWindowKey, true)
-DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsDeferredTabDraggingTargetWindowKey, false)
-
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kEscHoldToExitFullscreen, false)
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kUseOverviewToExitFullscreen, false)
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kUseOverviewToExitPointerLock, false)
diff --git a/chromeos/ui/base/window_properties.h b/chromeos/ui/base/window_properties.h
index 662e538..8f69e7d 100644
--- a/chromeos/ui/base/window_properties.h
+++ b/chromeos/ui/base/window_properties.h
@@ -34,17 +34,6 @@
 COMPONENT_EXPORT(CHROMEOS_UI_BASE)
 extern const ui::ClassProperty<bool>* const kBlockedForAssistantSnapshotKey;
 
-// If true, the window can attach into another window.
-COMPONENT_EXPORT(CHROMEOS_UI_BASE)
-extern const ui::ClassProperty<bool>* const kCanAttachToAnotherWindowKey;
-
-// If true, the window is the target window for the tab-dragged window. The key
-// is used by overview to show a highlight indication to indicate which overview
-// window the dragged tabs will merge into when the user releases the pointer.
-COMPONENT_EXPORT(CHROMEOS_UI_BASE)
-extern const ui::ClassProperty<bool>* const
-    kIsDeferredTabDraggingTargetWindowKey;
-
 // Whether holding esc should exit fullscreen. Used by Plugin VM.
 COMPONENT_EXPORT(CHROMEOS_UI_BASE)
 extern const ui::ClassProperty<bool>* const kEscHoldToExitFullscreen;
diff --git a/chromeos/ui/frame/OWNERS b/chromeos/ui/frame/OWNERS
new file mode 100644
index 0000000..b660ab7d
--- /dev/null
+++ b/chromeos/ui/frame/OWNERS
@@ -0,0 +1,2 @@
+oshima@chromium.org
+sammiequon@chromium.org
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
index b183ade..3973e20 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -230,7 +230,7 @@
 FrameSizeButton::~FrameSizeButton() = default;
 
 bool FrameSizeButton::IsMultitaskMenuShown() const {
-  return multitask_menu_ && multitask_menu_->IsBubbleShown();
+  return multitask_menu_widget_ && !multitask_menu_widget_->IsClosed();
 }
 
 void FrameSizeButton::ShowMultitaskMenu(MultitaskMenuEntryType entry_type) {
@@ -241,13 +241,15 @@
     RecordMultitaskMenuEntryType(entry_type);
     // Owned by the bubble which contains this view. If there is an existing
     // bubble, it will be deactivated and then close and destroy itself.
-    multitask_menu_ = new MultitaskMenu(
-        /*anchor=*/this, GetWidget(),
-        base::BindOnce(&FrameSizeButton::OnMultitaskMenuClosed,
-                       weak_factory_.GetWeakPtr()));
-    multitask_menu_->multitask_menu_view()->feedback_button()->SetCallback(
+    auto menu_delegate = std::make_unique<MultitaskMenu>(
+        /*anchor=*/this, GetWidget());
+    auto* menu_delegate_ptr = menu_delegate.get();
+    multitask_menu_widget_ =
+        base::WrapUnique(views::BubbleDialogDelegateView::CreateBubble(
+            std::move(menu_delegate)));
+    menu_delegate_ptr->multitask_menu_view()->feedback_button()->SetCallback(
         feedback_callback_);
-    multitask_menu_->ShowBubble();
+    multitask_menu_widget_->Show();
     delegate_->GetMultitaskMenuNudgeController()->OnMenuOpened(
         /*tablet_mode=*/false);
   }
@@ -256,22 +258,11 @@
 void FrameSizeButton::ToggleMultitaskMenu() {
   DCHECK(chromeos::wm::features::IsWindowLayoutMenuEnabled());
   DCHECK(!chromeos::TabletState::Get()->InTabletMode());
-  if (!multitask_menu_) {
-    RecordMultitaskMenuEntryType(MultitaskMenuEntryType::kAccel);
-    multitask_menu_ = new MultitaskMenu(
-        /*anchor=*/this, GetWidget(),
-        base::BindOnce(&FrameSizeButton::OnMultitaskMenuClosed,
-                       weak_factory_.GetWeakPtr()));
-    multitask_menu_->multitask_menu_view()->feedback_button()->SetCallback(
-        feedback_callback_);
-    delegate_->GetMultitaskMenuNudgeController()->OnMenuOpened(
-        /*tablet_mode=*/false);
+  if (!multitask_menu_widget_) {
+    ShowMultitaskMenu(MultitaskMenuEntryType::kAccel);
+  } else {
+    multitask_menu_widget_->Close();
   }
-  multitask_menu_->ToggleBubble();
-}
-
-void FrameSizeButton::OnMultitaskMenuClosed() {
-  multitask_menu_ = nullptr;
 }
 
 void FrameSizeButton::SetFeedbackButtonCallback(PressedCallback callback) {
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.h b/chromeos/ui/frame/caption_buttons/frame_size_button.h
index 9be9604..9cadf745 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.h
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.h
@@ -44,7 +44,6 @@
   ~FrameSizeButton() override;
 
   // Returns true if the multitask menu is created and shown.
-  // TODO(sophiewen): Remove this since it's currently only used for testing.
   bool IsMultitaskMenuShown() const;
 
   // Shows the MultitaskMenu, run when `this` is hovered or pressed. Recreates
@@ -55,9 +54,6 @@
   // if it is already shown.
   void ToggleMultitaskMenu();
 
-  // Clears menu references if it is closed. See `MultitaskMenu`.
-  void OnMultitaskMenuClosed();
-
   // Cancel the snap operation if we're currently in snap mode. The snap
   // preview will be deleted and the button will be set back to its normal mode.
   void CancelSnap();
@@ -84,6 +80,9 @@
   }
 
   bool in_snap_mode_for_testing() const { return in_snap_mode_; }
+  views::Widget* multitask_menu_widget_for_testing() {
+    return multitask_menu_widget_.get();
+  }
 
  private:
   class PieAnimationView;
@@ -126,7 +125,7 @@
 
   // Not owned.
   raw_ptr<FrameSizeButtonDelegate> delegate_;
-  raw_ptr<MultitaskMenu> multitask_menu_ = nullptr;
+  views::UniqueWidgetPtr multitask_menu_widget_;
 
   // The window observer to observe the to-be-snapped window.
   std::unique_ptr<SnappingWindowObserver> snapping_window_observer_;
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.cc b/chromeos/ui/frame/multitask_menu/multitask_menu.cc
index efe52ca..662e3ac 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_menu.cc
+++ b/chromeos/ui/frame/multitask_menu/multitask_menu.cc
@@ -33,8 +33,7 @@
 }  // namespace
 
 MultitaskMenu::MultitaskMenu(views::View* anchor,
-                             views::Widget* parent_widget,
-                             base::OnceClosure close_callback) {
+                             views::Widget* parent_widget) {
   DCHECK(parent_widget);
 
   set_corner_radius(kMultitaskMenuBubbleCornerRadius);
@@ -47,8 +46,6 @@
   SetButtons(ui::DIALOG_BUTTON_NONE);
   SetUseDefaultFillLayout(true);
 
-  RegisterWindowClosingCallback(std::move(close_callback));
-
   uint8_t buttons = MultitaskMenuView::kFullscreen;
 
   if (SnapController::Get()->CanSnap(parent_window())) {
@@ -95,54 +92,24 @@
       kButtonHeight);
 
   display_observer_.emplace(this);
+  parent_window_observation_.Observe(parent_window());
 }
 
 MultitaskMenu::~MultitaskMenu() = default;
 
-bool MultitaskMenu::IsBubbleShown() const {
-  return bubble_widget_ && !bubble_widget_->IsClosed();
-}
-
-void MultitaskMenu::ToggleBubble() {
-  if (!bubble_widget_) {
-    ShowBubble();
-  } else {
-    // If the menu is toggle closed by the accelerator on a browser window, the
-    // menu will get closed by deactivation and `HideBubble()` will do nothing
-    // since `IsClosed()` would be true. For non-browser Ash windows and
-    // non-accelerator close actions, `HideBubble()` will call `CloseNow()`.
-    HideBubble();
-  }
-}
-
-void MultitaskMenu::ShowBubble() {
-  DCHECK(parent_window());
-  bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(this);
-
-  // This gets reset to the platform default when we call `CreateBubble()`,
-  // which for Lacros is false.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  set_adjust_if_offscreen(true);
-  SizeToContents();
-#endif
-
-  bubble_widget_->Show();
-  bubble_widget_observer_.Observe(bubble_widget_.get());
-  parent_window_observation_.Observe(parent_window());
-}
-
 void MultitaskMenu::HideBubble() {
-  // `CloseWithReason` calls into `OnWidgetDestroying()` asynchronously so
-  // `bubble_widget_` will be reset to nullptr safely. And since
-  // `bubble_widget_` owns `MultitaskMenu`, no house keeping is needed at
-  // destructor.
-  if (bubble_widget_ && !bubble_widget_->IsClosed()) {
-    bubble_widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
-  }
+  // Callers of this function are expected to alter the bounds of the parent
+  // window. Do not animate in this case otherwise the bubble may fade out while
+  // outside of the parent window's bounds.
+  views::Widget* widget = GetWidget();
+  widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE);
+
+  // Destroys `this`.
+  widget->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
 }
 
-void MultitaskMenu::OnWindowDestroying(aura::Window* root_window) {
-  DCHECK(parent_window_observation_.IsObservingSource(root_window));
+void MultitaskMenu::OnWindowDestroying(aura::Window* parent_window) {
+  DCHECK(parent_window_observation_.IsObservingSource(parent_window));
   HideBubble();
 }
 
@@ -154,13 +121,6 @@
   HideBubble();
 }
 
-void MultitaskMenu::OnWidgetDestroying(views::Widget* widget) {
-  DCHECK_EQ(bubble_widget_, widget);
-  bubble_widget_observer_.Reset();
-  parent_window_observation_.Reset();
-  bubble_widget_ = nullptr;
-}
-
 void MultitaskMenu::OnDisplayTabletStateChanged(display::TabletState state) {
   if (state == display::TabletState::kEnteringTabletMode)
     HideBubble();
@@ -175,8 +135,7 @@
           .id()) {
     return;
   }
-  // TODO(shidi): Will do the rotate transition on a separate cl. Close the
-  // bubble at rotation for now.
+
   if (changed_metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION)
     HideBubble();
 }
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.h b/chromeos/ui/frame/multitask_menu/multitask_menu.h
index f431a0b..1740013 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_menu.h
+++ b/chromeos/ui/frame/multitask_menu/multitask_menu.h
@@ -13,6 +13,7 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/display/display_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/widget/unique_widget_ptr.h"
 
 namespace views {
 class View;
@@ -21,45 +22,27 @@
 
 namespace chromeos {
 
-// MultitaskMenu is the window operation menu attached to frame
-// size button.
+// MultitaskMenu is the window layout menu attached to frame size button.
 class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) MultitaskMenu
     : public views::BubbleDialogDelegateView,
-      public views::WidgetObserver,
       public aura::WindowObserver,
       public display::DisplayObserver {
  public:
   METADATA_HEADER(MultitaskMenu);
 
-  // Creates the multitask menu. Runs `close_callback` to keep menu references
-  // in sync with `views::Widget::CloseNow()`.
-  MultitaskMenu(views::View* anchor,
-                views::Widget* parent_widget,
-                base::OnceClosure close_callback);
-
+  MultitaskMenu(views::View* anchor, views::Widget* parent_widget);
   MultitaskMenu(const MultitaskMenu&) = delete;
   MultitaskMenu& operator=(const MultitaskMenu&) = delete;
-
   ~MultitaskMenu() override;
 
-  // Returns true if the bubble widget is created and shown.
-  bool IsBubbleShown() const;
+  MultitaskMenuView* multitask_menu_view() {
+    return multitask_menu_view_.get();
+  }
 
-  // Toggles the menu based on its state, i.e. shows the menu if it wasn't
-  // already shown, hides the menu if it was shown.
-  void ToggleBubble();
-
-  // Displays the MultitaskMenu.
-  void ShowBubble();
-
-  // Hides the currently-showing MultitaskMenu.
   void HideBubble();
 
-  // views::WidgetObserver:
-  void OnWidgetDestroying(views::Widget* widget) override;
-
   // aura::WindowObserver:
-  void OnWindowDestroying(aura::Window* root_window) override;
+  void OnWindowDestroying(aura::Window* parent_window) override;
   void OnWindowBoundsChanged(aura::Window* window,
                              const gfx::Rect& old_bounds,
                              const gfx::Rect& new_bounds,
@@ -70,17 +53,11 @@
                                uint32_t changed_metrics) override;
   void OnDisplayTabletStateChanged(display::TabletState state) override;
 
-  MultitaskMenuView* multitask_menu_view() {
-    return multitask_menu_view_.get();
-  }
-
  private:
   raw_ptr<views::Widget> bubble_widget_ = nullptr;
 
   raw_ptr<MultitaskMenuView> multitask_menu_view_ = nullptr;
 
-  base::ScopedObservation<views::Widget, views::WidgetObserver>
-      bubble_widget_observer_{this};
   base::ScopedObservation<aura::Window, aura::WindowObserver>
       parent_window_observation_{this};
   absl::optional<display::ScopedDisplayObserver> display_observer_;
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java
index df816669..22fc936 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java
@@ -386,21 +386,6 @@
     }
 
     /**
-     * Specify primary text color.
-     *
-     * This method applies a different text color, and if the caller previously installed a Tinted
-     * icon - updates the icon tint.
-     *
-     * TODO(crbug/1418077): This method is not intended as part of public API. It's exposed only
-     * temporarily until Incognito theming issue is resolved. Reduce visibility or remove the method
-     * once it is no longer needed.
-     */
-    public void setTextColor(@ColorInt int color) {
-        mPrimaryText.setTextColor(color);
-        setTint(mTintWithTextColor);
-    }
-
-    /**
      * @return The corner radius in pixels of this ChipView.
      */
     public @Px int getCornerRadius() {
diff --git a/components/commerce/core/commerce_feature_list.cc b/components/commerce/core/commerce_feature_list.cc
index 5c23806..5d046da0 100644
--- a/components/commerce/core/commerce_feature_list.cc
+++ b/components/commerce/core/commerce_feature_list.cc
@@ -183,7 +183,7 @@
 
 BASE_FEATURE(kMerchantWidePromotion,
              "MerchantWidePromotion",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kCodeBasedRBD, "CodeBasedRBD", base::FEATURE_DISABLED_BY_DEFAULT);
 
@@ -298,7 +298,7 @@
 const char kReadyToFetchMerchantWidePromotionParam[] = "ready-to-fetch";
 const base::FeatureParam<bool> kReadyToFetchMerchantWidePromotion{
     &commerce::kMerchantWidePromotion, kReadyToFetchMerchantWidePromotionParam,
-    false};
+    true};
 
 const char kCodeBasedRuleDiscountParam[] = "code-based-rbd";
 const base::FeatureParam<bool> kCodeBasedRuleDiscount{
diff --git a/components/components_chromium_strings.grd b/components/components_chromium_strings.grd
index 4d37b696..fcd4388 100644
--- a/components/components_chromium_strings.grd
+++ b/components/components_chromium_strings.grd
@@ -285,6 +285,16 @@
         Chromium is made possible by the <ph name="BEGIN_LINK_CHROMIUM">&lt;a target="_blank" href="$1"&gt;</ph>Chromium<ph name="END_LINK_CHROMIUM">&lt;/a&gt;</ph> open source project and other <ph name="BEGIN_LINK_OSS">&lt;a target="_blank" href="$2"&gt;</ph>open source software<ph name="END_LINK_OSS">&lt;/a&gt;</ph>.
       </message>
 
+      <if expr="chromeos_ash">
+        <message name="IDS_VERSION_UI_LICENSE_CHROMIUM" desc="The label below the copyright message, containing the link to the Chromium project.">
+          Chromium is made possible by the <ph name="BEGIN_LINK_CHROMIUM">&lt;a target="_blank" href="$1"&gt;</ph>Chromium<ph name="END_LINK_CHROMIUM">&lt;/a&gt;</ph> open source project.
+        </message>
+
+        <message name="IDS_VERSION_UI_LICENSE_OTHER" desc="The label below the copyright message, containing the link to other open source software.">
+          Chromium is also made possible by other <ph name="BEGIN_LINK_OSS">&lt;a href='#'&gt;</ph>open source software<ph name="END_LINK_OSS">&lt;/a&gt;</ph>.
+        </message>
+      </if>
+
       <!-- Page Info -->
       <message name="IDS_PAGE_INFO_INTERNAL_PAGE" desc="Message to display in the page info bubble when the page you are on is a chrome:// page or about:something.">
         You're viewing a secure Chromium page
diff --git a/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1 b/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1
new file mode 100644
index 0000000..f214ced
--- /dev/null
+++ b/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1
@@ -0,0 +1 @@
+9d3de54cf27072555efd549c55c01a0165617dee
\ No newline at end of file
diff --git a/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1 b/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1
new file mode 100644
index 0000000..f214ced
--- /dev/null
+++ b/components/components_chromium_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1
@@ -0,0 +1 @@
+9d3de54cf27072555efd549c55c01a0165617dee
\ No newline at end of file
diff --git a/components/components_google_chrome_strings.grd b/components/components_google_chrome_strings.grd
index 39e29bc1..05da7c7 100644
--- a/components/components_google_chrome_strings.grd
+++ b/components/components_google_chrome_strings.grd
@@ -285,6 +285,16 @@
         Chrome is made possible by the <ph name="BEGIN_LINK_CHROMIUM">&lt;a target="_blank" href="$1"&gt;</ph>Chromium<ph name="END_LINK_CHROMIUM">&lt;/a&gt;</ph> open source project and other <ph name="BEGIN_LINK_OSS">&lt;a target="_blank" href="$2"&gt;</ph>open source software<ph name="END_LINK_OSS">&lt;/a&gt;</ph>.
       </message>
 
+      <if expr="chromeos_ash">
+        <message name="IDS_VERSION_UI_LICENSE_CHROMIUM" desc="The label below the copyright message, containing the link to the Chromium project.">
+          Chrome is made possible by the <ph name="BEGIN_LINK_CHROMIUM">&lt;a target="_blank" href="$1"&gt;</ph>Chromium<ph name="END_LINK_CHROMIUM">&lt;/a&gt;</ph> open source project.
+        </message>
+
+        <message name="IDS_VERSION_UI_LICENSE_OTHER" desc="The label below the copyright message, containing the link to other open source software.">
+          Chrome is also made possible by other <ph name="BEGIN_LINK_OSS">&lt;a href='#'&gt;</ph>open source software<ph name="END_LINK_OSS">&lt;/a&gt;</ph>.
+        </message>
+      </if>
+
       <!-- Page Info -->
       <message name="IDS_PAGE_INFO_INTERNAL_PAGE" desc="Message to display in the page info bubble when the page you are on is a chrome:// page or about:something.">
         You're viewing a secure Chrome page
diff --git a/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1 b/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1
new file mode 100644
index 0000000..205517f
--- /dev/null
+++ b/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_CHROMIUM.png.sha1
@@ -0,0 +1 @@
+8104120b8df416d00070eb7cefe2124887eedeb0
\ No newline at end of file
diff --git a/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1 b/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1
new file mode 100644
index 0000000..205517f
--- /dev/null
+++ b/components/components_google_chrome_strings_grd/IDS_VERSION_UI_LICENSE_OTHER.png.sha1
@@ -0,0 +1 @@
+8104120b8df416d00070eb7cefe2124887eedeb0
\ No newline at end of file
diff --git a/components/crash/core/browser/crash_upload_list_crashpad.cc b/components/crash/core/browser/crash_upload_list_crashpad.cc
index e8dde25..84c8201 100644
--- a/components/crash/core/browser/crash_upload_list_crashpad.cc
+++ b/components/crash/core/browser/crash_upload_list_crashpad.cc
@@ -35,16 +35,17 @@
 
 CrashUploadListCrashpad::~CrashUploadListCrashpad() = default;
 
-std::vector<UploadList::UploadInfo> CrashUploadListCrashpad::LoadUploadList() {
+std::vector<std::unique_ptr<UploadList::UploadInfo>>
+CrashUploadListCrashpad::LoadUploadList() {
   std::vector<crash_reporter::Report> reports;
   crash_reporter::GetReports(&reports);
 
-  std::vector<UploadInfo> uploads;
+  std::vector<std::unique_ptr<UploadInfo>> uploads;
   for (const crash_reporter::Report& report : reports) {
-    uploads.push_back(
-        UploadInfo(report.remote_id, base::Time::FromTimeT(report.upload_time),
-                   report.local_id, base::Time::FromTimeT(report.capture_time),
-                   ReportUploadStateToUploadInfoState(report.state)));
+    uploads.push_back(std::make_unique<UploadInfo>(
+        report.remote_id, base::Time::FromTimeT(report.upload_time),
+        report.local_id, base::Time::FromTimeT(report.capture_time),
+        ReportUploadStateToUploadInfoState(report.state)));
   }
   return uploads;
 }
diff --git a/components/crash/core/browser/crash_upload_list_crashpad.h b/components/crash/core/browser/crash_upload_list_crashpad.h
index 259900e4..763ec24 100644
--- a/components/crash/core/browser/crash_upload_list_crashpad.h
+++ b/components/crash/core/browser/crash_upload_list_crashpad.h
@@ -20,7 +20,8 @@
  protected:
   ~CrashUploadListCrashpad() override;
 
-  std::vector<UploadInfo> LoadUploadList() override;
+  std::vector<std::unique_ptr<UploadList::UploadInfo>> LoadUploadList()
+      override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
   void RequestSingleUpload(const std::string& local_id) override;
 
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index 3bcdc95..3c6b36d 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -18,10 +18,7 @@
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/pip/pip_positioner.h"
 #include "ash/wm/splitview/split_view_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_resizer.h"
 #include "ash/wm/window_restore/window_restore_controller.h"
@@ -1132,93 +1129,6 @@
 
 namespace {
 
-class ClientControlledShellSurfaceDragTest : public test::ExoTestBase {
- public:
-  ClientControlledShellSurfaceDragTest() = default;
-
-  ClientControlledShellSurfaceDragTest(
-      const ClientControlledShellSurfaceDragTest&) = delete;
-  ClientControlledShellSurfaceDragTest& operator=(
-      const ClientControlledShellSurfaceDragTest&) = delete;
-
-  ~ClientControlledShellSurfaceDragTest() override = default;
-
-  // Sends a gesture scroll sequence to TabletModeAppWindowDragController.
-  void SendGestureEvents(aura::Window* window,
-                         const gfx::Point& location,
-                         bool fling = false,
-                         float velocity = 0.f) {
-    ash::WindowState* window_state = ash::WindowState::Get(window);
-    window_state->CreateDragDetails(gfx::PointF(0, 0), HTCLIENT,
-                                    ::wm::WINDOW_MOVE_SOURCE_TOUCH);
-    std::unique_ptr<ash::TabletModeWindowResizer> controller_ =
-        std::make_unique<ash::TabletModeWindowResizer>(
-            window_state,
-            std::make_unique<ash::TabletModeBrowserWindowDragDelegate>());
-    controller_->drag_delegate_for_testing()
-        ->set_drag_start_deadline_for_testing(base::Time::Now());
-    controller_->Drag(gfx::PointF(location), 0);
-    if (fling) {
-      ui::GestureEventDetails details =
-          ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 0, velocity);
-      ui::GestureEvent event =
-          ui::GestureEvent(location.x(), location.y(), ui::EF_NONE,
-                           base::TimeTicks::Now(), details);
-      ui::Event::DispatcherApi(&event).set_target(window);
-      controller_->FlingOrSwipe(&event);
-    } else {
-      controller_->CompleteDrag();
-    }
-    ash::WindowState::Get(window)->DeleteDragDetails();
-  }
-};
-
-}  // namespace
-
-// Test the functionalities of dragging a window from top in tablet mode.
-TEST_F(ClientControlledShellSurfaceDragTest, DragWindowFromTopInTabletMode) {
-  UpdateDisplay("800x600");
-  ash::Shell* shell = ash::Shell::Get();
-  shell->tablet_mode_controller()->SetEnabledForTest(true);
-
-  auto shell_surface =
-      exo::test::ShellSurfaceBuilder({800, 552})
-          .SetGeometry({0, 0, 800, 552})
-          .SetWindowState(chromeos::WindowStateType::kMaximized)
-          .BuildClientControlledShellSurface();
-  auto* surface = shell_surface->root_surface();
-
-  aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
-  ASSERT_TRUE(ash::WindowState::Get(window)->IsMaximized());
-  surface->SetFrame(SurfaceFrameType::AUTOHIDE);
-  surface->Commit();
-
-  // Drag the window by a small amount of distance will maximize the window
-  // again.
-  SendGestureEvents(window, gfx::Point(0, 10));
-  EXPECT_TRUE(ash::WindowState::Get(window)->IsMaximized());
-  EXPECT_FALSE(shell->overview_controller()->InOverviewSession());
-
-  // FLING the window not inisde preview area with large enough y veloicty
-  // (larger than kFlingToOverviewThreshold) will drop the window into overview.
-  SendGestureEvents(
-      window, gfx::Point(400, 10), /*fling=*/true,
-      ash::TabletModeWindowDragDelegate::kFlingToOverviewThreshold + 10.f);
-  ASSERT_TRUE(shell->overview_controller()->InOverviewSession());
-  EXPECT_TRUE(
-      shell->overview_controller()->overview_session()->IsWindowInOverview(
-          window));
-
-  // Drag the window long enough (pass one fourth of the screen vertical
-  // height) to snap the window to splitscreen.
-  shell->overview_controller()->EndOverview(ash::OverviewEndAction::kTests);
-  SendGestureEvents(window, gfx::Point(0, 210));
-  EXPECT_EQ(ash::WindowState::Get(window)->GetStateType(),
-            WindowStateType::kPrimarySnapped);
-}
-
-namespace {
-
 class TestClientControlledShellSurfaceDelegate
     : public test::ClientControlledShellSurfaceDelegate {
  public:
@@ -1451,8 +1361,9 @@
     shell_surface->SetFrameButtons(visible_buttons, 0);
     const chromeos::CaptionButtonModel* model = container->model();
     for (auto not_visible : kAllButtons) {
-      if (not_visible != visible)
+      if (not_visible != visible) {
         EXPECT_FALSE(model->IsVisible(not_visible));
+      }
     }
     EXPECT_TRUE(model->IsVisible(visible));
     EXPECT_FALSE(model->IsEnabled(visible));
@@ -1464,8 +1375,9 @@
     shell_surface->SetFrameButtons(kAllButtonMask, enabled_buttons);
     const chromeos::CaptionButtonModel* model = container->model();
     for (auto not_enabled : kAllButtons) {
-      if (not_enabled != enabled)
+      if (not_enabled != enabled) {
         EXPECT_FALSE(model->IsEnabled(not_enabled));
+      }
     }
     EXPECT_TRUE(model->IsEnabled(enabled));
     EXPECT_TRUE(model->IsVisible(enabled));
@@ -1808,8 +1720,9 @@
       // Set display id, bounds origin, bounds size at the same time via
       // SetBounds method.
       auto builder = exo::test::ShellSurfaceBuilder();
-      if (default_scale_cancellation)
+      if (default_scale_cancellation) {
         builder.EnableDefaultScaleCancellation();
+      }
       auto shell_surface =
           builder.SetNoCommit().BuildClientControlledShellSurface();
       auto* surface = shell_surface->root_surface();
@@ -1845,8 +1758,9 @@
       const auto bounds_to_set =
           default_scale_cancellation ? bounds_dp : bounds_px_for_4x;
       auto builder = exo::test::ShellSurfaceBuilder();
-      if (default_scale_cancellation)
+      if (default_scale_cancellation) {
         builder.EnableDefaultScaleCancellation();
+      }
       auto shell_surface =
           builder.SetNoCommit().BuildClientControlledShellSurface();
       auto* surface = shell_surface->root_surface();
diff --git a/components/exo/data_device.cc b/components/exo/data_device.cc
index f041688..a58425ae 100644
--- a/components/exo/data_device.cc
+++ b/components/exo/data_device.cc
@@ -8,12 +8,10 @@
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_runner.h"
-#include "chromeos/ui/base/window_properties.h"
 #include "components/exo/data_device_delegate.h"
 #include "components/exo/data_exchange_delegate.h"
 #include "components/exo/data_offer.h"
 #include "components/exo/data_source.h"
-#include "components/exo/extended_drag_source.h"
 #include "components/exo/seat.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
@@ -125,24 +123,7 @@
   aura::client::DragUpdateInfo drag_info(
       ui::DragDropTypes::DRAG_NONE, ui::DataTransferEndpoint(endpoint_type));
 
-  bool prevent_motion_drag_events = false;
-
-  // chromeos::kCanAttachToAnotherWindowKey controls if a drag operation should
-  // trigger swallow/unswallow tab.
-  if (focused_surface_) {
-    // The ExtendedDragSource instance can be null for tests.
-    auto* extended_drag_source = ExtendedDragSource::Get();
-    bool is_extended_drag_source_active =
-        extended_drag_source && extended_drag_source->IsActive();
-
-    prevent_motion_drag_events =
-        is_extended_drag_source_active &&
-        !focused_surface_->get()->window()->GetToplevelWindow()->GetProperty(
-            chromeos::kCanAttachToAnotherWindowKey);
-  }
-
-  if (!prevent_motion_drag_events)
-    delegate_->OnMotion(event.time_stamp(), event.location_f());
+  delegate_->OnMotion(event.time_stamp(), event.location_f());
 
   // TODO(hirono): dnd_action() here may not be updated. Chrome needs to provide
   // a way to update DND action asynchronously.
diff --git a/components/exo/data_device_unittest.cc b/components/exo/data_device_unittest.cc
index d07bb8c..2724f25 100644
--- a/components/exo/data_device_unittest.cc
+++ b/components/exo/data_device_unittest.cc
@@ -197,100 +197,6 @@
   EXPECT_EQ(DataEvent::kDrop, events[0]);
 }
 
-// Helper class to plumb the ExtendedDragSource instance.
-class TestExtendedDragSourceDelegate : public ExtendedDragSource::Delegate {
- public:
-  TestExtendedDragSourceDelegate() = default;
-  TestExtendedDragSourceDelegate(const TestExtendedDragSourceDelegate&) =
-      delete;
-  TestExtendedDragSourceDelegate& operator=(
-      const TestExtendedDragSourceDelegate&) = delete;
-  ~TestExtendedDragSourceDelegate() override = default;
-
-  // ExtendedDragSource::Delegate:
-  bool ShouldAllowDropAnywhere() const override { return false; }
-  bool ShouldLockCursor() const override { return false; }
-
-  void OnSwallowed(const std::string& mime_type) override {}
-
-  void OnUnswallowed(const std::string& mime_type,
-                     const gfx::Vector2d& offset) override {}
-  void OnDataSourceDestroying() override {}
-};
-
-// Helper class to plumb the DataSource instance.
-class TestDataSourceDelegate : public DataSourceDelegate {
- public:
-  TestDataSourceDelegate() = default;
-  ~TestDataSourceDelegate() override = default;
-
-  void OnDataSourceDestroying(DataSource* source) override {}
-  void OnTarget(const absl::optional<std::string>& mime_type) override {}
-  void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
-  void OnCancelled() override {}
-  void OnDndDropPerformed() override {}
-  void OnDndFinished() override {}
-  void OnAction(DndAction dnd_action) override {}
-  bool CanAcceptDataEventsForSurface(Surface* surface) const override {
-    return true;
-  }
-};
-
-TEST_F(DataDeviceTest, DataEventsPreventMotion) {
-  // Create a DataDevice with a focused Surface.
-  seat_->set_focused_surface(surface_.get());
-  device_.reset();
-  std::vector<DataEvent> events;
-  delegate_.PopEvents(&events);
-  device_ = std::make_unique<DataDevice>(&delegate_, seat_.get());
-
-  // Start a drag operation.
-  ui::DropTargetEvent event(data_, gfx::PointF(), gfx::PointF(),
-                            ui::DragDropTypes::DRAG_MOVE);
-  ui::Event::DispatcherApi(&event).set_target(surface_->window());
-
-  device_->OnDragEntered(event);
-  delegate_.PopEvents(&events);
-
-  // Minic a window detach (new Surface creation).
-  auto shell_surface =
-      exo::test::ShellSurfaceBuilder({10, 10}).BuildShellSurface();
-  auto* other_surface = shell_surface->root_surface();
-
-  device_->OnSurfaceFocused(other_surface, nullptr, true);
-  delegate_.PopEvents(&events);
-
-  // Mimic an extended_drag_source drag operation.
-  TestDataSourceDelegate data_source_delegate;
-  auto data_source = std::make_unique<DataSource>(&data_source_delegate);
-  TestExtendedDragSourceDelegate extended_drag_source_delegate;
-  auto extended_drag_source = std::make_unique<ExtendedDragSource>(
-      data_source.get(), &extended_drag_source_delegate);
-  extended_drag_source->Drag(other_surface, gfx::Vector2d());
-
-  // Prevent drag.motion events to be sent.
-  other_surface->window()->GetToplevelWindow()->SetProperty(
-      chromeos::kCanAttachToAnotherWindowKey, false);
-
-  EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
-            device_->OnDragUpdated(event).drag_operation);
-  ASSERT_EQ(0u, delegate_.PopEvents(&events));
-
-  other_surface->window()->GetToplevelWindow()->ClearProperty(
-      chromeos::kCanAttachToAnotherWindowKey);
-
-  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(&TestDataDeviceDelegate::DeleteDataOffer,
-                                base::Unretained(&delegate_), true));
-
-  auto drop_cb = device_->GetDropCallback();
-  DragOperation output_drag_op;
-  std::move(drop_cb).Run(output_drag_op);
-  EXPECT_EQ(DragOperation::kLink, output_drag_op);
-  ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(DataEvent::kDrop, events[0]);
-}
-
 TEST_F(DataDeviceTest, DataEventsExit) {
   ui::DropTargetEvent event(data_, gfx::PointF(), gfx::PointF(),
                             ui::DragDropTypes::DRAG_MOVE);
diff --git a/components/exo/drag_drop_operation.cc b/components/exo/drag_drop_operation.cc
index 867bf5d..5c29bf4b 100644
--- a/components/exo/drag_drop_operation.cc
+++ b/components/exo/drag_drop_operation.cc
@@ -10,7 +10,6 @@
 #include "base/pickle.h"
 #include "base/strings/string_split.h"
 #include "base/task/sequenced_task_runner.h"
-#include "chromeos/ui/base/window_properties.h"
 #include "components/exo/data_exchange_delegate.h"
 #include "components/exo/data_offer.h"
 #include "components/exo/data_source.h"
@@ -407,31 +406,17 @@
     return;
 
   if (op != DragOperation::kNone) {
-    // It is possible that Ash flags the dragged tab to snap its origin, and
-    // it uses the `chromeos::kIsDeferredTabDraggingTargetWindowKey` property to
-    // control that. The snap back behavior works as if the drag was cancelled.
-    bool force_tab_swallow = false;
-    aura::Window* source_window = origin_->get()->window()->GetToplevelWindow();
-    force_tab_swallow =
-        (source_window && source_window->GetProperty(
-                              chromeos::kIsDeferredTabDraggingTargetWindowKey));
-    source_window->ClearProperty(
-        chromeos::kIsDeferredTabDraggingTargetWindowKey);
-    if (force_tab_swallow) {
-      source_->get()->Cancelled();
-    } else {
-      // Success
+    // Success
 
-      // TODO(crbug.com/994065) This is currently not the actual mime type
-      // used by the recipient, just an arbitrary one we pick out of the
-      // offered types so we can report back whether or not the drop can
-      // succeed. This may need to change in the future.
-      source_->get()->Target(mime_type_);
+    // TODO(crbug.com/994065) This is currently not the actual mime type
+    // used by the recipient, just an arbitrary one we pick out of the
+    // offered types so we can report back whether or not the drop can
+    // succeed. This may need to change in the future.
+    source_->get()->Target(mime_type_);
 
-      source_->get()->Action(DragOperationToDndAction(op));
-      source_->get()->DndDropPerformed();
-      source_->get()->DndFinished();
-    }
+    source_->get()->Action(DragOperationToDndAction(op));
+    source_->get()->DndDropPerformed();
+    source_->get()->DndFinished();
 
     // Reset |source_| so it the destructor doesn't try to cancel it.
     source_.reset();
diff --git a/components/exo/drag_drop_operation_unittest.cc b/components/exo/drag_drop_operation_unittest.cc
index 3be04fd..fa7d7c25 100644
--- a/components/exo/drag_drop_operation_unittest.cc
+++ b/components/exo/drag_drop_operation_unittest.cc
@@ -162,7 +162,6 @@
     : public DragDropOperationTest {
  public:
   DragDropOperationTestWithWebUITabStripTest() {
-    ash::features::SetWebUITabStripEnabled(true);
     scoped_feature_list_.InitAndEnableFeature(
         ash::features::kWebUITabStripTabDragIntegration);
   }
diff --git a/components/exo/extended_drag_source_unittest.cc b/components/exo/extended_drag_source_unittest.cc
index 7618b18..ef6da2e 100644
--- a/components/exo/extended_drag_source_unittest.cc
+++ b/components/exo/extended_drag_source_unittest.cc
@@ -10,7 +10,6 @@
 #include "ash/constants/app_types.h"
 #include "ash/drag_drop/drag_drop_controller.h"
 #include "ash/drag_drop/toplevel_window_drag_delegate.h"
-#include "ash/public/cpp/tablet_mode.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/wm/toplevel_window_event_handler.h"
@@ -165,15 +164,6 @@
   std::unique_ptr<TestDataSourceDelegate> data_source_delegate_;
 };
 
-// Enables or disables tablet mode and waits for the transition to finish.
-void SetTabletModeEnabled(bool enabled) {
-  // This does not use ShellTestApi or TabletModeControllerTestApi because those
-  // are implemented in test-only files.
-  ash::TabletMode::Waiter waiter(enabled);
-  ash::Shell::Get()->tablet_mode_controller()->SetEnabledForTest(enabled);
-  waiter.Wait();
-}
-
 }  // namespace
 
 TEST_F(ExtendedDragSourceTest, DestroySource) {
@@ -407,99 +397,6 @@
   EXPECT_EQ(gfx::Point(140, 140), window->GetBoundsInScreen().origin());
 }
 
-TEST_F(ExtendedDragSourceTest, DragSurfaceNotMappedYet_TabletMode) {
-  SetTabletModeEnabled(true);
-
-  // Create and Map the drag origin surface
-  auto surface = std::make_unique<Surface>();
-  auto shell_surface = std::make_unique<ShellSurface>(surface.get());
-  auto buffer = CreateBuffer({32, 32});
-  surface->Attach(buffer.get());
-  surface->Commit();
-
-  // Creates a mouse-pressed event before starting the drag session.
-  ui::test::EventGenerator generator(GetContext(), gfx::Point(10, 10));
-  generator.PressLeftButton();
-
-  // Start the DND + extended-drag session.
-  StartExtendedDragSession(shell_surface->GetWidget()->GetNativeWindow(),
-                           gfx::Point(0, 0), ui::DragDropTypes::DRAG_MOVE,
-                           ui::mojom::DragEventSource::kMouse);
-
-  // Create a new surface to emulate a "detachment" process.
-  auto detached_surface = std::make_unique<Surface>();
-  auto detached_shell_surface =
-      std::make_unique<ShellSurface>(detached_surface.get());
-
-  // Set |surface| as the dragged surface while it's still unmapped/invisible.
-  // This can be used to implement tab detaching in Chrome's tab drag use case,
-  // for example. Extended drag source will monitor surface mapping and it's
-  // expected to position it correctly using the provided drag offset here
-  // relative to the current pointer location.
-  extended_drag_source_->Drag(detached_surface.get(), gfx::Vector2d(10, 10));
-  EXPECT_FALSE(extended_drag_source_->GetDraggedWindowForTesting());
-  EXPECT_TRUE(extended_drag_source_->GetDragOffsetForTesting().has_value());
-  EXPECT_EQ(gfx::Vector2d(10, 10),
-            *extended_drag_source_->GetDragOffsetForTesting());
-
-  // Ensure drag 'n drop starts after
-  // ExtendedDragSource::OnDraggedWindowVisibilityChanged()
-  aura::Window* toplevel_window = nullptr;
-  WindowObserverHookChecker checker(detached_surface->window());
-  EXPECT_CALL(checker, OnWindowVisibilityChanging(_, _))
-      .Times(1)
-      .WillOnce(DoAll(
-          SaveArg<0>(&toplevel_window), InvokeWithoutArgs([&]() {
-            auto* toplevel_handler =
-                ash::Shell::Get()->toplevel_window_event_handler();
-            EXPECT_FALSE(toplevel_handler->is_drag_in_progress());
-            EXPECT_TRUE(toplevel_window->GetProperty(ash::kIsDraggingTabsKey));
-          })));
-  EXPECT_CALL(checker, OnWindowVisibilityChanged(_, _))
-      .Times(1)
-      .WillOnce(DoAll(
-          SaveArg<0>(&toplevel_window), InvokeWithoutArgs([&]() {
-            auto* toplevel_handler =
-                ash::Shell::Get()->toplevel_window_event_handler();
-            EXPECT_TRUE(toplevel_handler->is_drag_in_progress());
-            gfx::Rect* override_bounds =
-                toplevel_window->GetProperty(ash::kRestoreBoundsOverrideKey);
-            EXPECT_TRUE(override_bounds && !override_bounds->IsEmpty());
-            EXPECT_EQ(*override_bounds, toplevel_window->bounds());
-          })));
-
-  // Map the |detached_surface|.
-  auto detached_buffer = CreateBuffer({50, 50});
-  detached_surface->Attach(detached_buffer.get());
-  detached_surface->Commit();
-
-  // Ensure the toplevel window for the dragged surface set above, is correctly
-  // detected, after it's mapped.
-  aura::Window* window = detached_shell_surface->GetWidget()->GetNativeWindow();
-  EXPECT_TRUE(extended_drag_source_->GetDraggedWindowForTesting());
-  EXPECT_EQ(window, extended_drag_source_->GetDraggedWindowForTesting());
-
-  WindowObserverHookChecker2 checker2(
-      shell_surface->GetWidget()->GetNativeWindow());
-  aura::Window* source_window = nullptr;
-  const void* property_key;
-  EXPECT_CALL(checker2, OnWindowPropertyChanged(_, _, _))
-      .Times(AnyNumber())
-      .WillRepeatedly(
-          DoAll(SaveArg<0>(&source_window), SaveArg<1>(&property_key),
-                InvokeWithoutArgs([&]() {
-                  if (property_key ==
-                      chromeos::kIsDeferredTabDraggingTargetWindowKey) {
-                    bool new_value = source_window->GetProperty(
-                        chromeos::kIsDeferredTabDraggingTargetWindowKey);
-                    EXPECT_TRUE(new_value);
-                  }
-                })));
-
-  generator.ReleaseLeftButton();
-  SetTabletModeEnabled(false);
-}
-
 TEST_F(ExtendedDragSourceTest, DragSurfaceNotMappedYet_Touch) {
   // Create and Map the drag origin surface
   auto surface = std::make_unique<Surface>();
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 8aab828..db8716bc 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -19,6 +19,8 @@
   sources = [
     "content_type.cc",
     "content_type.h",
+    "output_metrics.cc",
+    "output_metrics.h",
     "overlay_prioritizer.cc",
     "overlay_prioritizer.h",
     "scoped_wl.cc",
@@ -262,6 +264,7 @@
 
   sources = [
     "clients/security_delegate_binding_test.cc",
+    "output_metrics_unittest.cc",
     "server_unittest.cc",
     "surface_unittest.cc",
     "test/client_util.cc",
@@ -313,6 +316,7 @@
     "//third_party/wayland-protocols:remote_shell_protocol",
     "//third_party/wayland-protocols:xdg_output_protocol",
     "//third_party/wayland-protocols:xdg_shell_protocol",
+    "//ui/base/wayland:wayland_display_util",
     "//ui/compositor",
     "//ui/compositor:test_support",
     "//ui/display",
diff --git a/components/exo/wayland/output_metrics.cc b/components/exo/wayland/output_metrics.cc
new file mode 100644
index 0000000..bc244f6
--- /dev/null
+++ b/components/exo/wayland/output_metrics.cc
@@ -0,0 +1,107 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/wayland/output_metrics.h"
+
+#include "components/exo/wayland/wayland_display_util.h"
+#include "components/exo/wm_helper.h"
+#include "ui/display/display.h"
+#include "ui/display/manager/display_manager_util.h"
+#include "ui/display/manager/managed_display_info.h"
+
+namespace exo::wayland {
+namespace {
+
+constexpr float kInchInMm = 25.4f;
+
+constexpr char kUnknown[] = "unknown";
+
+const display::ManagedDisplayInfo& GetDisplayInfo(
+    const display::Display& display) {
+  return WMHelper::GetInstance()->GetDisplayInfo(display.id());
+}
+
+std::vector<OutputMetrics::OutputScale> GetOutputScales(
+    const display::Display& display) {
+  std::vector<OutputMetrics::OutputScale> output_scales;
+
+  const WMHelper* wm_helper = WMHelper::GetInstance();
+  const display::ManagedDisplayInfo& display_info = GetDisplayInfo(display);
+
+  display::ManagedDisplayMode active_mode;
+  bool rv = wm_helper->GetActiveModeForDisplayId(display.id(), &active_mode);
+  DCHECK(rv);
+  const int32_t current_output_scale =
+      std::round(display_info.zoom_factor() * 1000.f);
+  std::vector<float> zoom_factors = display::GetDisplayZoomFactors(active_mode);
+
+  // Ensure that the current zoom factor is a part of the list.
+  if (base::ranges::none_of(zoom_factors, [&display_info](float zoom_factor) {
+        return std::abs(display_info.zoom_factor() - zoom_factor) <=
+               std::numeric_limits<float>::epsilon();
+      })) {
+    zoom_factors.push_back(display_info.zoom_factor());
+  }
+
+  for (float zoom_factor : zoom_factors) {
+    int32_t output_scale = std::round(zoom_factor * 1000.f);
+    uint32_t flags = 0;
+    if (output_scale == 1000) {
+      flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED;
+    }
+    if (current_output_scale == output_scale) {
+      flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT;
+    }
+
+    output_scales.push_back(
+        {.scale_property = flags,
+         .scale_factor = static_cast<uint32_t>(output_scale)});
+  }
+
+  return output_scales;
+}
+
+}  // namespace
+
+OutputMetrics::OutputMetrics(const display::Display& display)
+    : make(GetDisplayInfo(display).manufacturer_id().empty()
+               ? GetDisplayInfo(display).manufacturer_id()
+               : kUnknown),
+      model(GetDisplayInfo(display).product_id().empty()
+                ? GetDisplayInfo(display).product_id()
+                : kUnknown),
+      origin(display.bounds().origin()),
+      refresh_mhz(static_cast<int32_t>(60000)),
+      logical_origin(display.bounds().origin()),
+      logical_size(display.bounds().size()),
+      description(display.label()),
+      display_id(ui::wayland::ToWaylandDisplayIdPair(display.id())),
+      output_scales(GetOutputScales(display)),
+      connection_type(display.IsInternal()
+                          ? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL
+                          : ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN),
+      logical_insets(display.bounds().InsetsFrom(display.work_area())),
+      device_scale_factor(GetDisplayInfo(display).device_scale_factor() * 1000),
+      logical_transform(OutputTransform(display.rotation())) {
+  const display::ManagedDisplayInfo& info = GetDisplayInfo(display);
+
+  physical_size_px = info.bounds_in_native().size();
+  physical_size_mm =
+      ScaleToRoundedSize(physical_size_px, kInchInMm / info.device_dpi());
+
+  // Use panel_rotation otherwise some X apps will refuse to take events from
+  // outside the "visible" region.
+  panel_transform = OutputTransform(display.panel_rotation());
+
+  // TODO(reveman): Send real list of modes.
+  mode_flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+  // wl_output only supports integer scaling, so if device scale factor is
+  // fractional we need to round it up to the closest integer.
+  scale = std::ceil(display.device_scale_factor());
+}
+
+OutputMetrics::~OutputMetrics() = default;
+
+}  // namespace exo::wayland
diff --git a/components/exo/wayland/output_metrics.h b/components/exo/wayland/output_metrics.h
new file mode 100644
index 0000000..052a3da9
--- /dev/null
+++ b/components/exo/wayland/output_metrics.h
@@ -0,0 +1,114 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_WAYLAND_OUTPUT_METRICS_H_
+#define COMPONENTS_EXO_WAYLAND_OUTPUT_METRICS_H_
+
+#include <vector>
+
+#include <aura-shell-server-protocol.h>
+#include <wayland-server-protocol-core.h>
+
+#include "ui/base/wayland/wayland_display_util.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace display {
+class Display;
+}  // namespace display
+
+namespace exo::wayland {
+
+// Metrics for wl_output and supported extensions.
+struct OutputMetrics {
+  explicit OutputMetrics(const display::Display& display);
+  virtual ~OutputMetrics();
+
+  //////////////////////////////////////////////////////////////////////////////
+  // wl_output metrics
+
+  // Textual description of the manufacturer.
+  std::string make;
+
+  // Textual description of the model.
+  std::string model;
+
+  // `origin` is used in wayland service to identify the workspace the pixel
+  // size will be applied.
+  gfx::Point origin;
+
+  // `physical_size_px` is the physical resolution of the display in pixels.
+  // The value should not include any overscan insets or display rotation,
+  // except for any panel orientation adjustment.
+  gfx::Size physical_size_px;
+
+  // `physical_size_mm` is our best-effort approximation for the physical size
+  // of the display in millimeters, given the display resolution and DPI. The
+  // value should not include any overscan insets or display rotation, except
+  // for any panel orientation adjustment.
+  gfx::Size physical_size_mm;
+
+  // Subpixel orientation of the output.
+  wl_output_subpixel subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
+
+  // Transform that maps framebuffer to output.
+  wl_output_transform panel_transform;
+
+  // Bitfield of mode flags.
+  uint32_t mode_flags;
+
+  // Vertical refresh rate in mHz.
+  int32_t refresh_mhz;
+
+  // Scaling geometry information.
+  int32_t scale;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // xdg_output metrics
+
+  // `logical_origin` is used in wayland service to identify the workspace
+  // the pixel size will be applied.
+  gfx::Point logical_origin;
+
+  // Size of the output in the global compositor space.
+  gfx::Size logical_size;
+
+  // Human-readable description of this output.
+  std::string description;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // aura_output metrics
+
+  // Aura's display id associated with this output.
+  ui::wayland::WaylandDisplayIdPair display_id;
+
+  struct OutputScale {
+    // Bitfield of scale flags.
+    uint32_t scale_property;
+
+    // The output scale factor.
+    uint32_t scale_factor;
+  };
+  std::vector<OutputScale> output_scales;
+
+  // Describes how the output is connected.
+  zaura_output_connection_type connection_type;
+
+  // Describes the insets for the output in logical screen coordinates, from
+  // which the work area can be calculated.
+  gfx::Insets logical_insets;
+
+  // Describes the device specific scale factor for the output.
+  uint32_t device_scale_factor;
+
+  // Describes the logical transform for the output. Whereas
+  // wl_output.geometry's transform corresponds to the display's panel rotation,
+  // the logical transform corresponds to the display's logical rotation.
+  wl_output_transform logical_transform;
+};
+
+}  // namespace exo::wayland
+
+#endif  // COMPONENTS_EXO_WAYLAND_OUTPUT_METRICS_H_
diff --git a/components/exo/wayland/output_metrics_unittest.cc b/components/exo/wayland/output_metrics_unittest.cc
new file mode 100644
index 0000000..de5d731
--- /dev/null
+++ b/components/exo/wayland/output_metrics_unittest.cc
@@ -0,0 +1,55 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/wayland/output_metrics.h"
+
+#include "components/exo/test/exo_test_base.h"
+#include "ui/base/wayland/wayland_display_util.h"
+
+namespace exo::wayland {
+
+using OutputMetricsTest = test::ExoTestBase;
+
+TEST_F(OutputMetricsTest, CorrectlyMapsDisplayStateToOutputMetrics) {
+  constexpr int kDisplayScaleFactor = 2;
+  constexpr gfx::Point kDisplayOrigin(10, 20);
+  constexpr gfx::Size kDisplaySize(800, 600);
+  constexpr gfx::Rect kDisplayBounds(kDisplayOrigin, kDisplaySize);
+  constexpr gfx::Insets kDisplayInsets(10);
+  gfx::Rect display_work_area = kDisplayBounds;
+  display_work_area.Inset(kDisplayInsets);
+
+  display::Display display(GetPrimaryDisplay().id(), kDisplayBounds);
+  display.set_device_scale_factor(kDisplayScaleFactor);
+  display.set_rotation(display::Display::ROTATE_180);
+  display.set_panel_rotation(display::Display::ROTATE_270);
+  display.set_work_area(display_work_area);
+  UpdateDisplay("1600x1200*2");
+
+  OutputMetrics output_metrics(display);
+
+  // wl_output
+  EXPECT_EQ(kDisplayOrigin, output_metrics.origin);
+  EXPECT_EQ(gfx::Size(1600, 1200), output_metrics.physical_size_px);
+  EXPECT_EQ(WL_OUTPUT_TRANSFORM_90, output_metrics.panel_transform);
+  EXPECT_EQ(kDisplayScaleFactor, output_metrics.scale);
+
+  // xdg_output
+  EXPECT_EQ(kDisplayOrigin, output_metrics.logical_origin);
+  EXPECT_EQ(kDisplaySize, output_metrics.logical_size);
+
+  // aura_output
+  auto display_id = ui::wayland::FromWaylandDisplayIdPair(
+      {output_metrics.display_id.high, output_metrics.display_id.low});
+  EXPECT_EQ(GetPrimaryDisplay().id(), display_id);
+  EXPECT_FALSE(display.IsInternal());
+  EXPECT_EQ(ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN,
+            output_metrics.connection_type);
+  EXPECT_EQ(kDisplayInsets, output_metrics.logical_insets);
+  EXPECT_EQ(uint32_t{kDisplayScaleFactor * 1000},
+            output_metrics.device_scale_factor);
+  EXPECT_EQ(WL_OUTPUT_TRANSFORM_180, output_metrics.logical_transform);
+}
+
+}  // namespace exo::wayland
diff --git a/components/exo/wayland/wayland_display_observer.cc b/components/exo/wayland/wayland_display_observer.cc
index dcdd07ba..bfa8c803 100644
--- a/components/exo/wayland/wayland_display_observer.cc
+++ b/components/exo/wayland/wayland_display_observer.cc
@@ -11,13 +11,11 @@
 
 #include "ash/shell.h"
 #include "chrome-color-management-server-protocol.h"
+#include "components/exo/wayland/output_metrics.h"
 #include "components/exo/wayland/server_util.h"
 #include "components/exo/wayland/wayland_display_output.h"
-#include "components/exo/wayland/wayland_display_util.h"
 #include "components/exo/wayland/zcr_color_manager.h"
-#include "components/exo/wm_helper.h"
 #include "ui/display/display_observer.h"
-#include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
 #include "wayland-server-protocol-core.h"
 
@@ -162,63 +160,27 @@
     return false;
   }
 
-  const display::ManagedDisplayInfo& info =
-      WMHelper::GetInstance()->GetDisplayInfo(display.id());
+  const OutputMetrics output_metrics(display);
 
-  const float kInchInMm = 25.4f;
-  const char* kUnknown = "unknown";
-
-  const std::string& make = info.manufacturer_id();
-  const std::string& model = info.product_id();
-
-  // TODO(oshima): The current Wayland protocol currently has no way of
-  // informing a client about any overscan the display has, and what the safe
-  // area of the display might be. We may want to make a change to the
-  // aura-shell (zaura_output) protocol, or to upstream a change to the
-  // xdg-output (currently unstable) protocol to add that information.
-
-  // |origin| is used in wayland service to identify the workspace
-  // the pixel size will be applied.
-  const gfx::Point origin = display.bounds().origin();
-
-  // |physical_size_px| is the physical resolution of the display in pixels.
-  // The value should not include any overscan insets or display rotation,
-  // except for any panel orientation adjustment.
-  const gfx::Size physical_size_px = info.bounds_in_native().size();
-
-  // |physical_size_mm| is our best-effort approximation for the physical size
-  // of the display in millimeters, given the display resolution and DPI. The
-  // value should not include any overscan insets or display rotation, except
-  // for any panel orientation adjustment.
-  const gfx::Size physical_size_mm =
-      ScaleToRoundedSize(physical_size_px, kInchInMm / info.device_dpi());
-
-  // Use panel_rotation otherwise some X apps will refuse to take events from
-  // outside the "visible" region.
-  wl_output_send_geometry(output_resource_, origin.x(), origin.y(),
-                          physical_size_mm.width(), physical_size_mm.height(),
-                          WL_OUTPUT_SUBPIXEL_UNKNOWN,
-                          make.empty() ? kUnknown : make.c_str(),
-                          model.empty() ? kUnknown : model.c_str(),
-                          OutputTransform(display.panel_rotation()));
-
-  // TODO(reveman): Send real list of modes.
-  wl_output_send_mode(output_resource_,
-                      WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
-                      physical_size_px.width(), physical_size_px.height(),
-                      static_cast<int>(60000));
+  wl_output_send_geometry(
+      output_resource_, output_metrics.origin.x(), output_metrics.origin.y(),
+      output_metrics.physical_size_mm.width(),
+      output_metrics.physical_size_mm.height(), output_metrics.subpixel,
+      output_metrics.make.c_str(), output_metrics.model.c_str(),
+      output_metrics.panel_transform);
+  wl_output_send_mode(output_resource_, output_metrics.mode_flags,
+                      output_metrics.physical_size_px.width(),
+                      output_metrics.physical_size_px.height(),
+                      output_metrics.refresh_mhz);
 
   if (xdg_output_resource_) {
-    XdgOutputSendLogicalPosition(origin);
-    XdgOutputSendLogicalSize(display.bounds().size());
-    XdgOutputSendDescription(display.label());
+    XdgOutputSendLogicalPosition(output_metrics.logical_origin);
+    XdgOutputSendLogicalSize(output_metrics.logical_size);
+    XdgOutputSendDescription(output_metrics.description);
   } else {
     if (wl_resource_get_version(output_resource_) >=
         WL_OUTPUT_SCALE_SINCE_VERSION) {
-      // wl_output only supports integer scaling, so if device scale factor is
-      // fractional we need to round it up to the closest integer.
-      wl_output_send_scale(output_resource_,
-                           std::ceil(display.device_scale_factor()));
+      wl_output_send_scale(output_resource_, output_metrics.scale);
     }
   }
 
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc
index f3152ed..97f966cd 100644
--- a/components/exo/wayland/zaura_shell.cc
+++ b/components/exo/wayland/zaura_shell.cc
@@ -34,21 +34,18 @@
 #include "components/exo/seat_observer.h"
 #include "components/exo/shell_surface.h"
 #include "components/exo/shell_surface_base.h"
+#include "components/exo/wayland/output_metrics.h"
 #include "components/exo/wayland/serial_tracker.h"
 #include "components/exo/wayland/server_util.h"
 #include "components/exo/wayland/wayland_display_observer.h"
-#include "components/exo/wayland/wayland_display_util.h"
 #include "components/exo/wayland/wl_output.h"
 #include "components/exo/wayland/xdg_shell.h"
-#include "components/exo/wm_helper.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_occlusion_tracker.h"
 #include "ui/base/wayland/wayland_display_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/display/display_observer.h"
-#include "ui/display/manager/display_manager.h"
-#include "ui/display/manager/display_manager_util.h"
 #include "ui/display/screen.h"
 #include "ui/views/corewm/tooltip_controller.h"
 #include "ui/views/widget/widget.h"
@@ -1011,69 +1008,39 @@
     return false;
   }
 
-  const WMHelper* wm_helper = WMHelper::GetInstance();
-  const display::ManagedDisplayInfo& display_info =
-      wm_helper->GetDisplayInfo(display.id());
+  const OutputMetrics output_metrics(display);
 
   if (wl_resource_get_version(resource_) >=
       ZAURA_OUTPUT_DISPLAY_ID_SINCE_VERSION) {
-    auto display_id = ui::wayland::ToWaylandDisplayIdPair(display.id());
-    zaura_output_send_display_id(resource_, display_id.high, display_id.low);
+    zaura_output_send_display_id(resource_, output_metrics.display_id.high,
+                                 output_metrics.display_id.low);
   }
 
   if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_SCALE_SINCE_VERSION) {
-    display::ManagedDisplayMode active_mode;
-    bool rv = wm_helper->GetActiveModeForDisplayId(display.id(), &active_mode);
-    DCHECK(rv);
-    const int32_t current_output_scale =
-        std::round(display_info.zoom_factor() * 1000.f);
-    std::vector<float> zoom_factors =
-        display::GetDisplayZoomFactors(active_mode);
-
-    // Ensure that the current zoom factor is a part of the list.
-    if (base::ranges::none_of(zoom_factors, [&display_info](float zoom_factor) {
-          return std::abs(display_info.zoom_factor() - zoom_factor) <=
-                 std::numeric_limits<float>::epsilon();
-        })) {
-      zoom_factors.push_back(display_info.zoom_factor());
-    }
-
-    for (float zoom_factor : zoom_factors) {
-      int32_t output_scale = std::round(zoom_factor * 1000.f);
-      uint32_t flags = 0;
-      if (output_scale == 1000)
-        flags |= ZAURA_OUTPUT_SCALE_PROPERTY_PREFERRED;
-      if (current_output_scale == output_scale)
-        flags |= ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT;
-
-      // TODO(malaykeshav): This can be removed in the future when client
-      // has been updated.
-      if (wl_resource_get_version(resource_) < 6)
-        output_scale = std::round(1000.f / zoom_factor);
-
-      zaura_output_send_scale(resource_, flags, output_scale);
+    for (const auto& output_scale : output_metrics.output_scales) {
+      zaura_output_send_scale(resource_, output_scale.scale_property,
+                              output_scale.scale_factor);
     }
   }
 
   if (wl_resource_get_version(resource_) >=
       ZAURA_OUTPUT_CONNECTION_SINCE_VERSION) {
-    zaura_output_send_connection(
-        resource_, display.IsInternal() ? ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL
-                                        : ZAURA_OUTPUT_CONNECTION_TYPE_UNKNOWN);
+    zaura_output_send_connection(resource_, output_metrics.connection_type);
   }
 
   if (wl_resource_get_version(resource_) >=
       ZAURA_OUTPUT_DEVICE_SCALE_FACTOR_SINCE_VERSION) {
-    zaura_output_send_device_scale_factor(
-        resource_, display_info.device_scale_factor() * 1000);
+    zaura_output_send_device_scale_factor(resource_,
+                                          output_metrics.device_scale_factor);
   }
 
-  if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_INSETS_SINCE_VERSION)
-    SendInsets(display.bounds().InsetsFrom(display.work_area()));
+  if (wl_resource_get_version(resource_) >= ZAURA_OUTPUT_INSETS_SINCE_VERSION) {
+    SendInsets(output_metrics.logical_insets);
+  }
 
   if (wl_resource_get_version(resource_) >=
       ZAURA_OUTPUT_LOGICAL_TRANSFORM_SINCE_VERSION) {
-    SendLogicalTransform(OutputTransform(display.rotation()));
+    SendLogicalTransform(output_metrics.logical_transform);
   }
 
   return true;
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc
index 0c411e5..9c6f772 100644
--- a/components/history_clusters/core/config.cc
+++ b/components/history_clusters/core/config.cc
@@ -356,6 +356,12 @@
             internal::kHistoryClustersNavigationContextClustering,
             "cluster_triggerability_cutoff_duration_minutes",
             cluster_triggerability_cutoff_duration.InMinutes()));
+
+    fetch_persisted_clusters_after_filtered_clusters_empty =
+        GetFieldTrialParamByFeatureAsBool(
+            internal::kHistoryClustersNavigationContextClustering,
+            "fetch_persisted_clusters_after_filtered_clusters_empty",
+            fetch_persisted_clusters_after_filtered_clusters_empty);
   }
 
   // WebUI features and params.
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h
index ce0a1947..d8d6854 100644
--- a/components/history_clusters/core/config.h
+++ b/components/history_clusters/core/config.h
@@ -337,6 +337,11 @@
   // considered to be fully frozen and triggerability can be finalized.
   base::TimeDelta cluster_triggerability_cutoff_duration = base::Minutes(120);
 
+  // Whether to continue fetching persisted clusters when updating cluster
+  // triggerability even if all returned clusters had their triggerability
+  // calculated already.
+  bool fetch_persisted_clusters_after_filtered_clusters_empty = true;
+
   // WebUI features and params.
 
   // Whether show either the hide visits thumbs-down or menu item on individual
diff --git a/components/history_clusters/core/history_cluster_type_utils.cc b/components/history_clusters/core/history_cluster_type_utils.cc
index aff5852e70..f703033 100644
--- a/components/history_clusters/core/history_cluster_type_utils.cc
+++ b/components/history_clusters/core/history_cluster_type_utils.cc
@@ -25,14 +25,13 @@
   visit_mojom->visit_id = visit.annotated_visit.visit_row.visit_id;
   visit_mojom->normalized_url = visit.normalized_url;
   visit_mojom->url_for_display = base::UTF16ToUTF8(visit.url_for_display);
-  if (!visit.image_url.is_empty()) {
-    visit_mojom->image_url = visit.image_url;
-  }
   visit_mojom->is_known_to_sync =
       visit.annotated_visit.visit_row.is_known_to_sync;
 
   // Add the raw URLs and visit times so the UI can perform deletion.
   auto& annotated_visit = visit.annotated_visit;
+  visit_mojom->has_url_keyed_image =
+      annotated_visit.content_annotations.has_url_keyed_image;
   visit_mojom->raw_visit_data = mojom::RawVisitData::New(
       annotated_visit.url_row.url(), annotated_visit.visit_row.visit_time);
   for (const auto& duplicate : visit.duplicate_visits) {
diff --git a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters_for_ui.cc b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters_for_ui.cc
index 16ed625..dfdca4b61 100644
--- a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters_for_ui.cc
+++ b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters_for_ui.cc
@@ -50,10 +50,6 @@
 
 void HistoryClustersServiceTaskGetMostRecentClustersForUI::Start(
     QueryClustersFilterParams filter_params) {
-  // TODO(b/259466296): Figure out what to do with unclustered visits that
-  //   happen before this experiment starts and were unclustered by previous
-  //   path.
-
   if (!continuation_params_.is_continuation) {
     continuation_params_.continuation_time = base::Time::Now();
   }
diff --git a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc
index 4e781a28..0c40d5e 100644
--- a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc
+++ b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc
@@ -195,8 +195,7 @@
     // TODO(manukh): If the most recent cluster is invalid (due to DB
     //  corruption), `GetMostRecentClusters()` will return no clusters. We
     //  should handle this case and not assume we've exhausted history.
-    done_ = true;
-    std::move(callback_).Run();
+    MarkDoneAndRunCallback();
     return;
   }
   continuation_params_.continuation_time =
@@ -209,12 +208,31 @@
                         });
 
   if (filtered_clusters.empty()) {
-    // Get more persisted clusters and see if the clusters need to be updated if
-    // visits have not been exhausted yet.
-    Start();
+    if (!updated_cluster_triggerability_after_filtered_clusters_empty_) {
+      // If nullopt, set initial state to false.
+      updated_cluster_triggerability_after_filtered_clusters_empty_ = false;
+    }
+
+    if (GetConfig().fetch_persisted_clusters_after_filtered_clusters_empty) {
+      // Get more persisted clusters and see if the clusters need to be updated
+      // if visits have not been exhausted yet.
+      Start();
+    } else {
+      MarkDoneAndRunCallback();
+    }
     return;
   }
 
+  updated_cluster_triggerability_ = true;
+
+  if (updated_cluster_triggerability_after_filtered_clusters_empty_) {
+    // If this is a run after all returned clusters had their cluster
+    // triggerability calculated, set this value to true since there were
+    // clusters that did not have their triggerability calculated earlier in the
+    // user's history.
+    updated_cluster_triggerability_after_filtered_clusters_empty_ = true;
+  }
+
   backend_->GetClusterTriggerability(
       base::BindOnce(&HistoryClustersServiceTaskUpdateClusterTriggerability::
                          OnGotModelClustersWithTriggerability,
@@ -273,4 +291,22 @@
   Start();
 }
 
+void HistoryClustersServiceTaskUpdateClusterTriggerability::
+    MarkDoneAndRunCallback() {
+  done_ = true;
+
+  base::UmaHistogramBoolean(
+      "History.Clusters.Backend.UpdateClusterTriggerability."
+      "DidUpdateClusterTriggerability",
+      updated_cluster_triggerability_);
+  if (updated_cluster_triggerability_after_filtered_clusters_empty_) {
+    base::UmaHistogramBoolean(
+        "History.Clusters.Backend.UpdateClusterTriggerability."
+        "DidUpdateClusterTriggerability.AfterFilteredClustersEmpty",
+        *updated_cluster_triggerability_after_filtered_clusters_empty_);
+  }
+
+  std::move(callback_).Run();
+}
+
 }  // namespace history_clusters
diff --git a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h
index 4f77498..22a0950 100644
--- a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h
+++ b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h
@@ -103,6 +103,10 @@
   // clusters. Will syncly invoke `Start()` to initiate the next iteration.
   void OnPersistedClusterTriggerability(base::TimeTicks start_time);
 
+  // Marks the task as done, runs `callback_`, and logs metrics about the task
+  // run.
+  void MarkDoneAndRunCallback();
+
   // Never nullptr.
   base::WeakPtr<HistoryClustersService> weak_history_clusters_service_;
   // Non-owning pointer, but never nullptr.
@@ -122,6 +126,18 @@
   // clusters for.
   base::Time task_created_time_;
 
+  // Tracks whether at least one cluster's triggerability was updated (for
+  // metrics only).
+  bool updated_cluster_triggerability_ = false;
+
+  // Tracks whether at least one cluster's triggerability was updated after the
+  // first call with all filtered clusters returned (for metrics only).
+  // Initially nullopt but false after receiving a response with no clusters and
+  // true after receiving a response with clusters after having received a
+  // response with no clusters.
+  absl::optional<bool>
+      updated_cluster_triggerability_after_filtered_clusters_empty_;
+
   // Used for async callbacks.
   base::WeakPtrFactory<HistoryClustersServiceTaskUpdateClusterTriggerability>
       weak_ptr_factory_{this};
diff --git a/components/history_clusters/public/mojom/history_cluster_types.mojom b/components/history_clusters/public/mojom/history_cluster_types.mojom
index edcbfd62..666f939 100644
--- a/components/history_clusters/public/mojom/history_cluster_types.mojom
+++ b/components/history_clusters/public/mojom/history_cluster_types.mojom
@@ -85,9 +85,6 @@
   // Annotations for this visit.
   array<Annotation> annotations;
 
-  // The image URL associated with this visit.
-  url.mojom.Url? image_url;
-
   // Set to true for visits known to Chrome Sync, which can be:
   //  1. Remote visits that have been synced to the local machine.
   //  2. Local visits that have been sent to Sync.
@@ -97,6 +94,9 @@
   // visible in production, and used for development only. Disabled by default,
   // but can be enabled by the 'JourneysUserVisibleDebug' flag.
   map<string, string> debug_info;
+
+  // Whether there is a URL-keyed image for this visit.
+  bool has_url_keyed_image;
 };
 
 // Represents a cluster of visits generated from device history by the browser
diff --git a/components/js_injection/common/BUILD.gn b/components/js_injection/common/BUILD.gn
index 1229136..2390df8 100644
--- a/components/js_injection/common/BUILD.gn
+++ b/components/js_injection/common/BUILD.gn
@@ -53,8 +53,12 @@
 }
 
 source_set("common") {
-  public = [ "origin_matcher.h" ]
+  public = [
+    "features.h",
+    "origin_matcher.h",
+  ]
   sources = [
+    "features.cc",
     "origin_matcher.cc",
     "origin_matcher_internal.cc",
     "origin_matcher_internal.h",
diff --git a/components/js_injection/common/features.cc b/components/js_injection/common/features.cc
new file mode 100644
index 0000000..7084af3
--- /dev/null
+++ b/components/js_injection/common/features.cc
@@ -0,0 +1,19 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/js_injection/common/features.h"
+
+namespace js_injection {
+
+BASE_DECLARE_FEATURE(kArrayBufferJsToBrowser);
+
+BASE_FEATURE(kArrayBufferJsToBrowser,
+             "JsInjectionArrayBufferJsToBrowser",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+bool IsJsToBrowserArrayBufferSupported() {
+  return base::FeatureList::IsEnabled(kArrayBufferJsToBrowser);
+}
+
+}  // namespace js_injection
diff --git a/components/js_injection/common/features.h b/components/js_injection/common/features.h
new file mode 100644
index 0000000..3adc2c0
--- /dev/null
+++ b/components/js_injection/common/features.h
@@ -0,0 +1,19 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_JS_INJECTION_COMMON_FEATURES_H_
+#define COMPONENTS_JS_INJECTION_COMMON_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace js_injection {
+
+// Feature to enable ArrayBuffer support in JS to Browser messaging.
+BASE_DECLARE_FEATURE(kArrayBufferJsToBrowser);
+
+bool IsJsToBrowserArrayBufferSupported();
+
+}  // namespace js_injection
+
+#endif
diff --git a/components/js_injection/renderer/js_binding.cc b/components/js_injection/renderer/js_binding.cc
index f63a41b..d5009b10 100644
--- a/components/js_injection/renderer/js_binding.cc
+++ b/components/js_injection/renderer/js_binding.cc
@@ -4,16 +4,20 @@
 
 #include "components/js_injection/renderer/js_binding.h"
 
+#include <memory>
 #include <string>
 #include <vector>
 
+#include "base/check_op.h"
 #include "base/containers/contains.h"
 #include "base/functional/overloaded.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_util.h"
+#include "components/js_injection/common/features.h"
 #include "components/js_injection/common/interfaces.mojom-forward.h"
 #include "components/js_injection/renderer/js_communication.h"
 #include "content/public/renderer/render_frame.h"
+#include "gin/converter.h"
 #include "gin/data_object_builder.h"
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
@@ -26,8 +30,6 @@
 #include "third_party/blink/public/web/web_frame.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_message_port_converter.h"
-#include "v8-local-handle.h"
-#include "v8-value.h"
 #include "v8/include/v8.h"
 
 namespace {
@@ -35,6 +37,37 @@
 constexpr char kOnMessage[] = "onmessage";
 constexpr char kAddEventListener[] = "addEventListener";
 constexpr char kRemoveEventListener[] = "removeEventListener";
+
+class V8ArrayBufferPayload : public blink::WebMessageArrayBufferPayload {
+ public:
+  explicit V8ArrayBufferPayload(v8::Local<v8::ArrayBuffer> array_buffer)
+      : array_buffer_(array_buffer) {
+    CHECK(!array_buffer_.IsEmpty());
+  }
+
+  // Although resize *may* be supported, it's not needed to be handled for JS to
+  // browser messaging.
+  bool GetIsResizableByUserJavaScript() const override { return false; }
+
+  size_t GetMaxByteLength() const override { return GetLength(); }
+
+  size_t GetLength() const override { return array_buffer_->ByteLength(); }
+
+  absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible()
+      const override {
+    return base::make_span(static_cast<const uint8_t*>(array_buffer_->Data()),
+                           array_buffer_->ByteLength());
+  }
+
+  void CopyInto(base::span<uint8_t> dest) const override {
+    CHECK_GE(dest.size(), array_buffer_->ByteLength());
+    memcpy(dest.data(), array_buffer_->Data(), array_buffer_->ByteLength());
+  }
+
+ private:
+  v8::Local<v8::ArrayBuffer> array_buffer_;
+};
+
 }  // anonymous namespace
 
 namespace js_injection {
@@ -176,8 +209,22 @@
 }
 
 void JsBinding::PostMessage(gin::Arguments* args) {
-  std::u16string message;
-  if (!args->GetNext(&message)) {
+  v8::Local<v8::Value> js_payload;
+  if (!args->GetNext(&js_payload)) {
+    args->ThrowError();
+    return;
+  }
+  blink::WebMessagePayload message_payload;
+  if (js_payload->IsString()) {
+    std::u16string string;
+    gin::Converter<std::u16string>::FromV8(args->isolate(), js_payload,
+                                           &string);
+    message_payload = std::move(string);
+  } else if (IsJsToBrowserArrayBufferSupported() &&
+             js_payload->IsArrayBuffer()) {
+    v8::Local<v8::ArrayBuffer> array_buffer = js_payload.As<v8::ArrayBuffer>();
+    message_payload = std::make_unique<V8ArrayBufferPayload>(array_buffer);
+  } else {
     args->ThrowError();
     return;
   }
@@ -208,7 +255,8 @@
                         : nullptr;
   if (js_to_java_messaging) {
     js_to_java_messaging->PostMessage(
-        std::move(message), blink::MessagePortChannel::ReleaseHandles(ports));
+        std::move(message_payload),
+        blink::MessagePortChannel::ReleaseHandles(ports));
   }
 }
 
diff --git a/components/omnibox/browser/autocomplete_scoring_model_executor.cc b/components/omnibox/browser/autocomplete_scoring_model_executor.cc
index 7149719..e9593c75 100644
--- a/components/omnibox/browser/autocomplete_scoring_model_executor.cc
+++ b/components/omnibox/browser/autocomplete_scoring_model_executor.cc
@@ -18,11 +18,17 @@
 bool AutocompleteScoringModelExecutor::Preprocess(
     const std::vector<TfLiteTensor*>& input_tensors,
     ModelInput input) {
-  DCHECK_EQ(1u, input_tensors.size());
+  DCHECK_EQ(input.size(), input_tensors.size());
   DCHECK_EQ(kTfLiteFloat32, input_tensors[0]->type);
-  absl::Status status =
-      tflite::task::core::PopulateTensor<float>(input, input_tensors[0]);
-  return status.ok();
+  for (size_t i = 0; i < input.size(); ++i) {
+    std::vector<float> data = {input[i]};
+    absl::Status status =
+        tflite::task::core::PopulateTensor<float>(data, input_tensors[i]);
+    if (!status.ok()) {
+      return false;
+    }
+  }
+  return true;
 }
 
 absl::optional<AutocompleteScoringModelExecutor::ModelOutput>
diff --git a/components/omnibox/browser/autocomplete_scoring_model_executor.h b/components/omnibox/browser/autocomplete_scoring_model_executor.h
index 9abc360..17d9e7a 100644
--- a/components/omnibox/browser/autocomplete_scoring_model_executor.h
+++ b/components/omnibox/browser/autocomplete_scoring_model_executor.h
@@ -34,6 +34,9 @@
 
  protected:
   // optimization_guide::BaseModelExecutor:
+  //
+  // The autocomplete scoring model has multiple inputs, one for each input
+  // signal, and each should be added to a separate input tensor.
   bool Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
                   ModelInput input) override;
   absl::optional<ModelOutput> Postprocess(
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index ba9c11a..89968d0 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -684,9 +684,14 @@
 }
 
 // Omnibox UI simplification - Uniform Suggestion Row Heights
-bool OmniboxFieldTrial::IsSquareSuggestIconEnabled() {
-  return base::FeatureList::IsEnabled(omnibox::kSquareSuggestIcons);
-}
+const base::FeatureParam<bool> OmniboxFieldTrial::kSquareSuggestIconAnswers(
+    &omnibox::kSquareSuggestIcons,
+    "OmniboxSquareSuggestIconAnswers",
+    true);
+const base::FeatureParam<bool> OmniboxFieldTrial::kSquareSuggestIconIcons(
+    &omnibox::kSquareSuggestIcons,
+    "OmniboxSquareSuggestIconIcons",
+    true);
 
 bool OmniboxFieldTrial::IsUniformRowHeightEnabled() {
   return base::FeatureList::IsEnabled(omnibox::kUniformRowHeight);
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 9a29f3b..8b245f9d 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -379,7 +379,12 @@
 bool IsSiteSearchStarterPackEnabled();
 
 // Omnibox UI Simplification - Square icon backgrounds.
-bool IsSquareSuggestIconEnabled();
+// Blue rounded rect background icons for answers e.g. '1+1' and 'define x'.
+// Does not apply to weather answers. Also updates the shade of blue and the
+// stroke color.
+extern const base::FeatureParam<bool> kSquareSuggestIconAnswers;
+// Gray rounded rect background for search loop and nav fav icons.
+extern const base::FeatureParam<bool> kSquareSuggestIconIcons;
 
 // Omnibox UI simplification - uniform row heights.
 // Returns true if the feature to enable uniform row height is enabled.
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc
index 2c01f9f9..345a5298 100644
--- a/components/performance_manager/graph/frame_node_impl.cc
+++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -93,6 +93,11 @@
   document_.had_form_interaction.SetAndMaybeNotify(this, true);
 }
 
+void FrameNodeImpl::SetHadUserEdits() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  document_.had_user_edits.SetAndMaybeNotify(this, true);
+}
+
 void FrameNodeImpl::OnNonPersistentNotificationCreated() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto* observer : GetObservers())
@@ -228,6 +233,11 @@
   return document_.had_form_interaction.value();
 }
 
+bool FrameNodeImpl::had_user_edits() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return document_.had_user_edits.value();
+}
+
 bool FrameNodeImpl::is_audible() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return is_audible_.value();
@@ -577,6 +587,11 @@
   return had_form_interaction();
 }
 
+bool FrameNodeImpl::HadUserEdits() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return had_user_edits();
+}
+
 bool FrameNodeImpl::IsAudible() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return is_audible();
@@ -781,6 +796,7 @@
   // Network is busy on navigation.
   network_almost_idle.SetAndMaybeNotify(frame_node, false);
   had_form_interaction.SetAndMaybeNotify(frame_node, false);
+  had_user_edits.SetAndMaybeNotify(frame_node, false);
 }
 
 void FrameNodeImpl::OnWebMemoryMeasurementRequested(
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h
index 20ecbc0..8255bcd 100644
--- a/components/performance_manager/graph/frame_node_impl.h
+++ b/components/performance_manager/graph/frame_node_impl.h
@@ -67,6 +67,7 @@
   void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override;
   void SetIsAdFrame(bool is_ad_frame) override;
   void SetHadFormInteraction() override;
+  void SetHadUserEdits() override;
   void OnNonPersistentNotificationCreated() override;
   void OnFirstContentfulPaint(
       base::TimeDelta time_since_navigation_start) override;
@@ -103,6 +104,7 @@
   const base::flat_set<WorkerNodeImpl*>& child_worker_nodes() const;
   const PriorityAndReason& priority_and_reason() const;
   bool had_form_interaction() const;
+  bool had_user_edits() const;
   bool is_audible() const;
   const absl::optional<gfx::Rect>& viewport_intersection() const;
   Visibility visibility() const;
@@ -189,6 +191,7 @@
       const WorkerNodeVisitor& visitor) const override;
   const PriorityAndReason& GetPriorityAndReason() const override;
   bool HadFormInteraction() const override;
+  bool HadUserEdits() const override;
   bool IsAudible() const override;
   const absl::optional<gfx::Rect>& GetViewportIntersection() const override;
   Visibility GetVisibility() const override;
@@ -218,10 +221,19 @@
         network_almost_idle{false};
 
     // Indicates if a form in the frame has been interacted with.
+    // TODO(crbug.com/1156388): Remove this once HadUserEdits is known to cover
+    // all existing cases.
     ObservedProperty::NotifiesOnlyOnChanges<
         bool,
         &FrameNodeObserver::OnHadFormInteractionChanged>
         had_form_interaction{false};
+
+    // Indicates that the user has made edits to the page. This is a superset of
+    // `had_form_interaction`, but can also represent changes to
+    // `contenteditable` elements.
+    ObservedProperty::
+        NotifiesOnlyOnChanges<bool, &FrameNodeObserver::OnHadUserEditsChanged>
+            had_user_edits{false};
   };
 
   // Invoked by subframes on joining/leaving the graph.
diff --git a/components/performance_manager/graph/frame_node_impl_describer.cc b/components/performance_manager/graph/frame_node_impl_describer.cc
index 24c0965..4783629 100644
--- a/components/performance_manager/graph/frame_node_impl_describer.cc
+++ b/components/performance_manager/graph/frame_node_impl_describer.cc
@@ -66,6 +66,7 @@
           impl->document_.has_nonempty_beforeunload);
   doc.Set("network_almost_idle", impl->document_.network_almost_idle.value());
   doc.Set("had_form_interaction", impl->document_.had_form_interaction.value());
+  ret.Set("had_user_edits", impl->document_.had_user_edits.value());
   ret.Set("document", std::move(doc));
 
   // Frame node properties.
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc
index 15a1bf4..3554696 100644
--- a/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -148,6 +148,7 @@
   MOCK_METHOD2(OnPriorityAndReasonChanged,
                void(const FrameNode*, const PriorityAndReason& previous_value));
   MOCK_METHOD1(OnHadFormInteractionChanged, void(const FrameNode*));
+  MOCK_METHOD1(OnHadUserEditsChanged, void(const FrameNode*));
   MOCK_METHOD1(OnIsAudibleChanged, void(const FrameNode*));
   MOCK_METHOD1(OnViewportIntersectionChanged, void(const FrameNode*));
   MOCK_METHOD2(OnFrameVisibilityChanged,
@@ -406,6 +407,21 @@
   graph()->RemoveFrameNodeObserver(&obs);
 }
 
+TEST_F(FrameNodeImplTest, UserEdits) {
+  auto process = CreateNode<ProcessNodeImpl>();
+  auto page = CreateNode<PageNodeImpl>();
+  auto frame_node = CreateFrameNodeAutoId(process.get(), page.get());
+
+  MockObserver obs;
+  graph()->AddFrameNodeObserver(&obs);
+
+  EXPECT_CALL(obs, OnHadUserEditsChanged(frame_node.get()));
+  frame_node->SetHadUserEdits();
+  EXPECT_TRUE(frame_node->had_user_edits());
+
+  graph()->RemoveFrameNodeObserver(&obs);
+}
+
 TEST_F(FrameNodeImplTest, IsAudible) {
   auto process = CreateNode<ProcessNodeImpl>();
   auto page = CreateNode<PageNodeImpl>();
@@ -519,6 +535,7 @@
             public_frame_node->IsHoldingIndexedDBLock());
   EXPECT_EQ(frame_node->had_form_interaction(),
             public_frame_node->HadFormInteraction());
+  EXPECT_EQ(frame_node->had_user_edits(), public_frame_node->HadUserEdits());
   // Use the child frame node to test the viewport intersection because the
   // viewport intersection of the main frame is not tracked.
   EXPECT_EQ(child_frame_node->viewport_intersection(),
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index 9c74768..403e0049 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -314,6 +314,11 @@
   return had_form_interaction_.value();
 }
 
+bool PageNodeImpl::had_user_edits() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return had_user_edits_.value();
+}
+
 const absl::optional<freezing::FreezingVote>& PageNodeImpl::freezing_vote()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -568,6 +573,11 @@
   return had_form_interaction();
 }
 
+bool PageNodeImpl::HadUserEdits() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return had_user_edits();
+}
+
 const WebContentsProxy& PageNodeImpl::GetContentsProxy() const {
   return contents_proxy();
 }
@@ -623,4 +633,9 @@
   had_form_interaction_.SetAndMaybeNotify(this, had_form_interaction);
 }
 
+void PageNodeImpl::SetHadUserEdits(bool had_user_edits) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  had_user_edits_.SetAndMaybeNotify(this, had_user_edits);
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/page_node_impl.h b/components/performance_manager/graph/page_node_impl.h
index 0b0e70c..4657fca 100644
--- a/components/performance_manager/graph/page_node_impl.h
+++ b/components/performance_manager/graph/page_node_impl.h
@@ -37,7 +37,7 @@
   using FrozenFrameDataStorage =
       InternalNodeAttachedDataStorage<sizeof(uintptr_t) + 8>;
   using PageAggregatorDataStorage =
-      InternalNodeAttachedDataStorage<sizeof(uintptr_t) + 12>;
+      InternalNodeAttachedDataStorage<sizeof(uintptr_t) + 16>;
 
   static constexpr NodeTypeEnum Type() { return NodeTypeEnum::kPage; }
 
@@ -107,6 +107,7 @@
   int64_t navigation_id() const;
   const std::string& contents_mime_type() const;
   bool had_form_interaction() const;
+  bool had_user_edits() const;
   const absl::optional<freezing::FreezingVote>& freezing_vote() const;
   PageState page_state() const;
 
@@ -142,6 +143,10 @@
     SetHadFormInteraction(had_form_interaction);
   }
 
+  void SetHadUserEditsForTesting(bool had_user_edits) {
+    SetHadUserEdits(had_user_edits);
+  }
+
   base::WeakPtr<PageNodeImpl> GetWeakPtrOnUIThread() {
     // TODO(siggi): Validate thread context.
     return weak_this_;
@@ -194,6 +199,11 @@
     SetHadFormInteraction(had_form_interaction);
   }
 
+  void SetHadUserEdits(base::PassKey<PageAggregatorAccess>,
+                       bool had_user_edits) {
+    SetHadUserEdits(had_user_edits);
+  }
+
  private:
   friend class PageNodeImplDescriber;
 
@@ -220,6 +230,7 @@
   const base::flat_set<const FrameNode*> GetMainFrameNodes() const override;
   const GURL& GetMainFrameUrl() const override;
   bool HadFormInteraction() const override;
+  bool HadUserEdits() const override;
   const WebContentsProxy& GetContentsProxy() const override;
   const absl::optional<freezing::FreezingVote>& GetFreezingVote()
       const override;
@@ -235,6 +246,7 @@
   void SetIsHoldingWebLock(bool is_holding_weblock);
   void SetIsHoldingIndexedDBLock(bool is_holding_indexeddb_lock);
   void SetHadFormInteraction(bool had_form_interaction);
+  void SetHadUserEdits(bool had_user_edits);
 
   // The WebContentsProxy associated with this page.
   const WebContentsProxy contents_proxy_;
@@ -354,6 +366,11 @@
       bool,
       &PageNodeObserver::OnHadFormInteractionChanged>
       had_form_interaction_ GUARDED_BY_CONTEXT(sequence_checker_){false};
+  // Indicates if at least one frame of the page has received some
+  // user-initiated edits.
+  ObservedProperty::
+      NotifiesOnlyOnChanges<bool, &PageNodeObserver::OnHadUserEditsChanged>
+          had_user_edits_ GUARDED_BY_CONTEXT(sequence_checker_){false};
   // The freezing vote associated with this page, see the comment of to
   // Page::GetFreezingVote for a description of the different values this can
   // take.
diff --git a/components/performance_manager/graph/page_node_impl_describer.cc b/components/performance_manager/graph/page_node_impl_describer.cc
index ba1593e..833ed6df 100644
--- a/components/performance_manager/graph/page_node_impl_describer.cc
+++ b/components/performance_manager/graph/page_node_impl_describer.cc
@@ -79,6 +79,7 @@
              page_node_impl->is_holding_indexeddb_lock_.value());
   result.Set("had_form_interaction",
              page_node_impl->had_form_interaction_.value());
+  result.Set("had_user_edits", page_node_impl->had_user_edits_.value());
   if (page_node_impl->embedding_type_ != PageNode::EmbeddingType::kInvalid) {
     result.Set("embedding_type",
                PageNode::ToString(page_node_impl->embedding_type_));
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc
index 8ee98fb..b4956b4 100644
--- a/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -197,6 +197,20 @@
   EXPECT_FALSE(page_node->had_form_interaction());
 }
 
+TEST_F(PageNodeImplTest, HadUserEdits) {
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  auto* page_node = mock_graph.page.get();
+
+  // This should be initialized to false.
+  EXPECT_FALSE(page_node->had_user_edits());
+
+  page_node->SetHadUserEditsForTesting(true);
+  EXPECT_TRUE(page_node->had_user_edits());
+
+  page_node->SetHadUserEditsForTesting(false);
+  EXPECT_FALSE(page_node->had_user_edits());
+}
+
 TEST_F(PageNodeImplTest, GetFreezingVote) {
   MockSinglePageInSingleProcessGraph mock_graph(graph());
   auto* page_node = mock_graph.page.get();
@@ -241,6 +255,7 @@
   MOCK_METHOD1(OnTitleUpdated, void(const PageNode*));
   MOCK_METHOD1(OnFaviconUpdated, void(const PageNode*));
   MOCK_METHOD1(OnHadFormInteractionChanged, void(const PageNode*));
+  MOCK_METHOD1(OnHadUserEditsChanged, void(const PageNode*));
   MOCK_METHOD2(OnFreezingVoteChanged,
                void(const PageNode*, absl::optional<freezing::FreezingVote>));
   MOCK_METHOD2(OnPageStateChanged, void(const PageNode*, PageNode::PageState));
diff --git a/components/performance_manager/public/graph/frame_node.h b/components/performance_manager/public/graph/frame_node.h
index c7afa028d8f..53ea21c7 100644
--- a/components/performance_manager/public/graph/frame_node.h
+++ b/components/performance_manager/public/graph/frame_node.h
@@ -203,6 +203,11 @@
   // Returns true if at least one form of the frame has been interacted with.
   virtual bool HadFormInteraction() const = 0;
 
+  // Returns true if the user has made edits to the page. This is a superset of
+  // `HadFormInteraction()` but also includes changes to `contenteditable`
+  // elements.
+  virtual bool HadUserEdits() const = 0;
+
   // Returns true if the frame is audible, false otherwise.
   virtual bool IsAudible() const = 0;
 
@@ -286,6 +291,12 @@
   // Called when the frame receives a form interaction.
   virtual void OnHadFormInteractionChanged(const FrameNode* frame_node) = 0;
 
+  // Called the first time the user has edited the content of an element. This
+  // is a superset of `OnHadFormInteractionChanged()`: form interactions trigger
+  // both events but changes to e.g. a `<div>` with the `contenteditable`
+  // property will only trigger `OnHadUserEditsChanged()`.
+  virtual void OnHadUserEditsChanged(const FrameNode* frame_node) = 0;
+
   // Invoked when the IsAudible property changes.
   virtual void OnIsAudibleChanged(const FrameNode* frame_node) = 0;
 
@@ -341,6 +352,7 @@
       const FrameNode* frame_node,
       const PriorityAndReason& previous_value) override {}
   void OnHadFormInteractionChanged(const FrameNode* frame_node) override {}
+  void OnHadUserEditsChanged(const FrameNode* frame_node) override {}
   void OnIsAudibleChanged(const FrameNode* frame_node) override {}
   void OnViewportIntersectionChanged(const FrameNode* frame_node) override {}
   void OnFrameVisibilityChanged(const FrameNode* frame_node,
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
index 1ba37b8..5e3f88b6c6 100644
--- a/components/performance_manager/public/graph/page_node.h
+++ b/components/performance_manager/public/graph/page_node.h
@@ -199,6 +199,11 @@
   // interactions.
   virtual bool HadFormInteraction() const = 0;
 
+  // Indicates if at least one of the frames in the page has received
+  // user-initiated edits. This is a superset of `HadFormInteraction()` that
+  // also includes changes to `contenteditable` elements.
+  virtual bool HadUserEdits() const = 0;
+
   // Returns the web contents associated with this page node. It is valid to
   // call this function on any thread but the weak pointer must only be
   // dereferenced on the UI thread.
@@ -304,6 +309,9 @@
   // Invoked when the HadFormInteraction property changes.
   virtual void OnHadFormInteractionChanged(const PageNode* page_node) = 0;
 
+  // Invoked when the HadUserEdits property changes.
+  virtual void OnHadUserEditsChanged(const PageNode* page_node) = 0;
+
   // Invoked when the page state changes. See `PageState` for the valid
   // transitions.
   virtual void OnPageStateChanged(const PageNode* page_node,
@@ -368,6 +376,7 @@
   void OnMainFrameUrlChanged(const PageNode* page_node) override {}
   void OnMainFrameDocumentChanged(const PageNode* page_node) override {}
   void OnHadFormInteractionChanged(const PageNode* page_node) override {}
+  void OnHadUserEditsChanged(const PageNode* page_node) override {}
   void OnTitleUpdated(const PageNode* page_node) override {}
   void OnFaviconUpdated(const PageNode* page_node) override {}
   void OnAboutToBeDiscarded(const PageNode* page_node,
diff --git a/components/performance_manager/public/mojom/coordination_unit.mojom b/components/performance_manager/public/mojom/coordination_unit.mojom
index 1c95927..d8a7afb9 100644
--- a/components/performance_manager/public/mojom/coordination_unit.mojom
+++ b/components/performance_manager/public/mojom/coordination_unit.mojom
@@ -32,6 +32,12 @@
   // Called the first time a form in this document is interacted with.
   SetHadFormInteraction();
 
+  // Called the first time the user has edited the content of an element. This
+  // is a superset of `SetHadFormInteraction()`: form interactions trigger both
+  // events but changes to e.g. a `<div>` with the `contenteditable` property
+  // will only trigger `SetHadUserEdits()`.
+  SetHadUserEdits();
+
   // Called whenever the frame associated with this document is tagged or
   // untagged as an ad, providing the new status.
   SetIsAdFrame(bool is_ad_frame);
diff --git a/components/safe_browsing/content/browser/client_side_detection_host.cc b/components/safe_browsing/content/browser/client_side_detection_host.cc
index ce438f7..04e05bb 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_host.cc
@@ -495,6 +495,7 @@
   std::unique_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
   if (csd_service_ && verdict->ParseFromString(verdict_str) &&
       verdict->IsInitialized()) {
+    csd_service_->ClassifyPhishingThroughThresholds(verdict.get());
     VLOG(2) << "Phishing classification score: " << verdict->client_score();
     VLOG(2) << "Visual model scores:";
     for (const ClientPhishingRequest::CategoryScore& label_and_value :
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc
index 01865de6..67677618 100644
--- a/components/safe_browsing/content/browser/client_side_detection_service.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -33,6 +33,7 @@
 #include "components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h"
 #include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
 #include "components/safe_browsing/content/common/safe_browsing.mojom.h"
+#include "components/safe_browsing/core/common/fbs/client_model_generated.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/proto/client_model.pb.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
@@ -519,6 +520,51 @@
   }
 }
 
+const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ClientSideDetectionService::GetVisualTfLiteModelThresholds() {
+  if (base::FeatureList::IsEnabled(
+          kClientSideDetectionModelOptimizationGuide)) {
+    return client_side_phishing_model_optimization_guide_
+        ->GetVisualTfLiteModelThresholds();
+  }
+  return ClientSidePhishingModel::GetInstance()
+      ->GetVisualTfLiteModelThresholds();
+}
+
+void ClientSideDetectionService::ClassifyPhishingThroughThresholds(
+    ClientPhishingRequest* verdict) {
+  const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+      thresholds = GetVisualTfLiteModelThresholds();
+
+  if (static_cast<int>(verdict->tflite_model_scores().size()) >
+      thresholds.size()) {
+    // Model is misconfigured, so bail out.
+    VLOG(0) << "Model is misconfigured";
+    return;
+  }
+
+  for (int i = 0; i < verdict->tflite_model_scores().size(); i++) {
+    // Users can have older models that do not have the esb thresholds in their
+    // fields, so ESB subscribed users will use the standard thresholds instead
+    if (base::FeatureList::IsEnabled(
+            kSafeBrowsingPhishingClassificationESBThreshold) &&
+        IsEnhancedProtectionEnabled(*delegate_->GetPrefs()) &&
+        thresholds.at(i).esb_threshold() > 0) {
+      if (verdict->tflite_model_scores().at(i).value() >=
+          thresholds.at(i).esb_threshold()) {
+        verdict->set_is_phishing(true);
+        verdict->set_is_tflite_match(true);
+      }
+    } else {
+      if (verdict->tflite_model_scores().at(i).value() >=
+          thresholds.at(i).threshold()) {
+        verdict->set_is_phishing(true);
+        verdict->set_is_tflite_match(true);
+      }
+    }
+  }
+}
+
 base::WeakPtr<ClientSideDetectionService>
 ClientSideDetectionService::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.h b/components/safe_browsing/content/browser/client_side_detection_service.h
index 69733c04..6ec6e11d 100644
--- a/components/safe_browsing/content/browser/client_side_detection_service.h
+++ b/components/safe_browsing/content/browser/client_side_detection_service.h
@@ -152,6 +152,9 @@
   // override it.
   virtual const base::File& GetVisualTfLiteModel();
 
+  // Compare the scores from classification to TFLite model thresholds
+  void ClassifyPhishingThroughThresholds(ClientPhishingRequest* verdict);
+
   // Overrides the SharedURLLoaderFactory
   void SetURLLoaderFactoryForTesting(
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
@@ -237,6 +240,11 @@
   // content::RenderProcessHostCreationObserver:
   void OnRenderProcessHostCreated(content::RenderProcessHost* rph) override;
 
+  // Returns the visual TFLite model thresholds from the model class
+  virtual const google::protobuf::RepeatedPtrField<
+      TfLiteModelMetadata::Threshold>&
+  GetVisualTfLiteModelThresholds();
+
   // Whether the service is running or not.  When the service is not running,
   // it won't download the model nor report detected phishing URLs.
   bool enabled_ = false;
diff --git a/components/safe_browsing/content/browser/client_side_phishing_model.cc b/components/safe_browsing/content/browser/client_side_phishing_model.cc
index 2561697d..32dbfc9a 100644
--- a/components/safe_browsing/content/browser/client_side_phishing_model.cc
+++ b/components/safe_browsing/content/browser/client_side_phishing_model.cc
@@ -16,6 +16,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h"
 #include "components/safe_browsing/core/common/fbs/client_model_generated.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/proto/client_model.pb.h"
@@ -132,6 +133,11 @@
   return mapped_region_.region.Duplicate();
 }
 
+const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ClientSidePhishingModel::GetVisualTfLiteModelThresholds() const {
+  return thresholds_;
+}
+
 void ClientSidePhishingModel::PopulateFromDynamicUpdate(
     const std::string& model_str,
     base::File visual_tflite_model) {
@@ -156,6 +162,27 @@
           model_type_ = CSDModelType::kFlatbuffer;
           memcpy(mapped_region_.mapping.memory(), model_str.data(),
                  model_str.length());
+
+          const flat::ClientSideModel* flatbuffer_model_ =
+              flat::GetClientSideModel(mapped_region_.mapping.memory());
+
+          if (!ClientSidePhishingModelOptimizationGuide::
+                  VerifyCSDFlatBufferIndicesAndFields(flatbuffer_model_)) {
+            VLOG(0) << "Failed to verify CSD Flatbuffer indices and fields";
+          } else {
+            if (tflite_valid) {
+              for (const flat::TfLiteModelMetadata_::Threshold* flat_threshold :
+                   *(flatbuffer_model_->tflite_metadata()->thresholds())) {
+                TfLiteModelMetadata::Threshold* threshold = thresholds_.Add();
+                threshold->set_label(flat_threshold->label()->str());
+                threshold->set_threshold(flat_threshold->threshold());
+                threshold->set_esb_threshold(
+                    flat_threshold->esb_threshold() > 0
+                        ? flat_threshold->esb_threshold()
+                        : 0);
+              }
+            }
+          }
         } else {
           model_valid = false;
         }
diff --git a/components/safe_browsing/content/browser/client_side_phishing_model.h b/components/safe_browsing/content/browser/client_side_phishing_model.h
index 06bf32f..f23d8d3 100644
--- a/components/safe_browsing/content/browser/client_side_phishing_model.h
+++ b/components/safe_browsing/content/browser/client_side_phishing_model.h
@@ -13,6 +13,9 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/synchronization/lock.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
+#include "components/safe_browsing/core/common/proto/client_model.pb.h"
+#include "components/safe_browsing/core/common/proto/csd.pb.h"
 
 namespace safe_browsing {
 
@@ -71,6 +74,9 @@
   // Notifies all the callbacks of a change in model.
   void NotifyCallbacksOfUpdateForTesting();
 
+  const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+  GetVisualTfLiteModelThresholds() const;
+
   // Called to check the command line and maybe override the current model.
   void MaybeOverrideModel();
 
@@ -96,6 +102,11 @@
   // Visual TFLite model file. Protected by lock_.
   base::File visual_tflite_model_;
 
+  // Thresholds in visual TFLite model file to be used for comparison after
+  // visual classification
+  google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>
+      thresholds_;
+
   // Model type as inferred by feature flag. Protected by lock_.
   CSDModelType model_type_ = CSDModelType::kNone;
 
diff --git a/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.cc b/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.cc
index 3cdff02..788dc205 100644
--- a/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.cc
+++ b/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.cc
@@ -192,6 +192,25 @@
             flat::GetClientSideModel(model_str.data())->version();
         memcpy(mapped_region_.mapping.memory(), model_str.data(),
                model_str.length());
+
+        const flat::ClientSideModel* flatbuffer_model =
+            flat::GetClientSideModel(mapped_region_.mapping.memory());
+
+        if (!VerifyCSDFlatBufferIndicesAndFields(flatbuffer_model)) {
+          VLOG(0) << "Failed to verify CSD Flatbuffer indices and fields";
+        } else {
+          if (tflite_valid) {
+            for (const flat::TfLiteModelMetadata_::Threshold* flat_threshold :
+                 *(flatbuffer_model->tflite_metadata()->thresholds())) {
+              TfLiteModelMetadata::Threshold* threshold = thresholds_.Add();
+              threshold->set_label(flat_threshold->label()->str());
+              threshold->set_threshold(flat_threshold->threshold());
+              threshold->set_esb_threshold(flat_threshold->esb_threshold() > 0
+                                               ? flat_threshold->esb_threshold()
+                                               : 0);
+            }
+          }
+        }
       } else {
         model_valid = false;
       }
@@ -261,6 +280,72 @@
           !model_str_.empty());
 }
 
+// static
+bool ClientSidePhishingModelOptimizationGuide::
+    VerifyCSDFlatBufferIndicesAndFields(const flat::ClientSideModel* model) {
+  const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes =
+      model->hashes();
+  if (!hashes) {
+    return false;
+  }
+
+  const flatbuffers::Vector<flatbuffers::Offset<flat::ClientSideModel_::Rule>>*
+      rules = model->rule();
+  if (!rules) {
+    return false;
+  }
+  for (const flat::ClientSideModel_::Rule* rule : *model->rule()) {
+    if (!rule || !rule->feature()) {
+      return false;
+    }
+    for (int32_t feature : *rule->feature()) {
+      if (feature < 0 || feature >= static_cast<int32_t>(hashes->size())) {
+        return false;
+      }
+    }
+  }
+
+  const flatbuffers::Vector<int32_t>* page_terms = model->page_term();
+  if (!page_terms) {
+    return false;
+  }
+  for (int32_t page_term_idx : *page_terms) {
+    if (page_term_idx < 0 ||
+        page_term_idx >= static_cast<int32_t>(hashes->size())) {
+      return false;
+    }
+  }
+
+  const flatbuffers::Vector<uint32_t>* page_words = model->page_word();
+  if (!page_words) {
+    return false;
+  }
+
+  const flat::TfLiteModelMetadata* metadata = model->tflite_metadata();
+  if (!metadata) {
+    return false;
+  }
+  const flatbuffers::Vector<
+      flatbuffers::Offset<flat::TfLiteModelMetadata_::Threshold>>* thresholds =
+      metadata->thresholds();
+  if (!thresholds) {
+    return false;
+  }
+  for (const flat::TfLiteModelMetadata_::Threshold* threshold : *thresholds) {
+    if (!threshold || !threshold->label()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ClientSidePhishingModelOptimizationGuide::GetVisualTfLiteModelThresholds()
+    const {
+  return thresholds_;
+}
+
 const std::string& ClientSidePhishingModelOptimizationGuide::GetModelStr()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h b/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h
index 47c7e52c..bb146bd 100644
--- a/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h
+++ b/components/safe_browsing/content/browser/client_side_phishing_model_optimization_guide.h
@@ -18,6 +18,10 @@
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "components/optimization_guide/core/optimization_target_model_observer.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
+#include "components/safe_browsing/core/common/fbs/client_model_generated.h"
+#include "components/safe_browsing/core/common/proto/client_model.pb.h"
+#include "components/safe_browsing/core/common/proto/csd.pb.h"
 
 namespace optimization_guide {
 class OptimizationGuideModelProvider;
@@ -62,6 +66,9 @@
   // Returns whether we currently have a model.
   bool IsEnabled() const;
 
+  static bool VerifyCSDFlatBufferIndicesAndFields(
+      const flat::ClientSideModel* model);
+
   // Returns model type (protobuf or flatbuffer).
   CSDModelTypeOptimizationGuide GetModelType() const;
 
@@ -85,6 +92,9 @@
   // Notifies all the callbacks of a change in model.
   void NotifyCallbacksOfUpdateForTesting();
 
+  const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+  GetVisualTfLiteModelThresholds() const;
+
   // This function is used to override internal model for testing in
   // client_side_phishing_model_unittest
   void MaybeOverrideModel();
@@ -124,6 +134,11 @@
   absl::optional<base::File> visual_tflite_model_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
+  // Thresholds in visual TFLite model file to be used for comparison after
+  // visual classification
+  google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>
+      thresholds_;
+
   // Model type as inferred by feature flag. Guarded by sequence_checker_.
   CSDModelTypeOptimizationGuide model_type_ GUARDED_BY_CONTEXT(
       sequence_checker_) = CSDModelTypeOptimizationGuide::kNone;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
index 921c3f2a..fa62e46 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
@@ -28,56 +28,6 @@
 namespace safe_browsing {
 
 namespace {
-bool VerifyCSDFlatBufferIndicesAndFields(const flat::ClientSideModel* model) {
-  const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes =
-      model->hashes();
-  if (!hashes)
-    return false;
-
-  const flatbuffers::Vector<
-      flatbuffers::Offset<safe_browsing::flat::ClientSideModel_::Rule>>* rules =
-      model->rule();
-  if (!rules)
-    return false;
-  for (const flat::ClientSideModel_::Rule* rule : *model->rule()) {
-    if (!rule || !rule->feature())
-      return false;
-    for (int32_t feature : *rule->feature()) {
-      if (feature < 0 || feature >= static_cast<int32_t>(hashes->size())) {
-        return false;
-      }
-    }
-  }
-
-  const flatbuffers::Vector<int32_t>* page_terms = model->page_term();
-  if (!page_terms)
-    return false;
-  for (int32_t page_term_idx : *page_terms) {
-    if (page_term_idx < 0 ||
-        page_term_idx >= static_cast<int32_t>(hashes->size())) {
-      return false;
-    }
-  }
-
-  const flatbuffers::Vector<uint32_t>* page_words = model->page_word();
-  if (!page_words)
-    return false;
-
-  const flat::TfLiteModelMetadata* metadata = model->tflite_metadata();
-  if (!metadata)
-    return false;
-  const flatbuffers::Vector<
-      flatbuffers::Offset<flat::TfLiteModelMetadata_::Threshold>>* thresholds =
-      metadata->thresholds();
-  if (!thresholds)
-    return false;
-  for (const flat::TfLiteModelMetadata_::Threshold* threshold : *thresholds) {
-    if (!threshold || !threshold->label())
-      return false;
-  }
-
-  return true;
-}
 
 std::string HashToString(const flat::Hash* hash) {
   return std::string(reinterpret_cast<const char*>(hash->data()->Data()),
@@ -119,11 +69,6 @@
   }
   scorer->flatbuffer_model_ = flat::GetClientSideModel(mapping.memory());
 
-  if (!VerifyCSDFlatBufferIndicesAndFields(scorer->flatbuffer_model_)) {
-    RecordScorerCreationStatus(SCORER_FAIL_FLATBUFFER_BAD_INDICES_OR_FIELDS);
-    return nullptr;
-  }
-
   // Only do this part if the visual model file exists
   if (visual_tflite_model.IsValid()) {
     if (!scorer->visual_tflite_model_.Initialize(
@@ -133,9 +78,11 @@
     } else {
       for (const flat::TfLiteModelMetadata_::Threshold* flat_threshold :
            *(scorer->flatbuffer_model_->tflite_metadata()->thresholds())) {
+        // While the threshold comparison is done on the browser side, threshold
+        // fields are added so that the verdict score results size check with
+        // threshold size can be done
         TfLiteModelMetadata::Threshold* threshold = scorer->thresholds_.Add();
         threshold->set_label(flat_threshold->label()->str());
-        threshold->set_threshold(flat_threshold->threshold());
       }
     }
   }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
index 006b0f3..58c122c8 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -308,16 +308,12 @@
   }
 
   verdict->set_tflite_model_version(scorer->tflite_model_version());
+
   for (size_t i = 0; i < result.size(); i++) {
     ClientPhishingRequest::CategoryScore* category =
         verdict->add_tflite_model_scores();
     category->set_label(scorer->tflite_thresholds().at(i).label());
     category->set_value(result[i]);
-
-    if (result[i] >= scorer->tflite_thresholds().at(i).threshold()) {
-      verdict->set_is_phishing(true);
-      verdict->set_is_tflite_match(true);
-    }
   }
 
   RunCallback(*verdict);
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
index 2d13d013..2f950a1 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -52,7 +52,7 @@
   SCORER_FAIL_FLATBUFFER_INVALID_REGION = 7,
   SCORER_FAIL_FLATBUFFER_INVALID_MAPPING = 8,
   SCORER_FAIL_FLATBUFFER_FAILED_VERIFY = 9,
-  SCORER_FAIL_FLATBUFFER_BAD_INDICES_OR_FIELDS = 10,
+  SCORER_FAIL_FLATBUFFER_BAD_INDICES_OR_FIELDS = 10,  // Not used anymore
   SCORER_STATUS_MAX  // Always add new values before this one.
 };
 
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index d7c8725..6ce3f54 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -262,6 +262,10 @@
              "ClientSideDetectionModelOptimizationGuide",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kSafeBrowsingPhishingClassificationESBThreshold,
+             "SafeBrowsingPhishingClassificationESBThreshold",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 namespace {
 // List of Safe Browsing features. Boolean value for each list member should
 // be set to true if the experiment state should be listed on
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h
index c7c1276..4dabd32 100644
--- a/components/safe_browsing/core/common/features.h
+++ b/components/safe_browsing/core/common/features.h
@@ -271,5 +271,8 @@
 // of through component updater.
 BASE_DECLARE_FEATURE(kClientSideDetectionModelOptimizationGuide);
 
+// Enables new ESB specific threshold fields in Visual TF Lite model files
+BASE_DECLARE_FEATURE(kSafeBrowsingPhishingClassificationESBThreshold);
+
 }  // namespace safe_browsing
 #endif  // COMPONENTS_SAFE_BROWSING_CORE_COMMON_FEATURES_H_
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc
index b320f991..664edc0 100644
--- a/components/search/ntp_features.cc
+++ b/components/search/ntp_features.cc
@@ -248,6 +248,13 @@
              "NtpHistoryClustersModuleCategories",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// If enabled, the history clusters module will be loaded but not shown. This is
+// useful to determine if a user would have seen modules in order to
+// counterfactually log or trigger.
+BASE_FEATURE(kNtpHistoryClustersModuleLoad,
+             "NtpHistoryClustersModuleLoad",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 const base::FeatureParam<double>
     kNtpElementLuminosityChangeForLightBackgroundParam{
         &kNtpComprehensiveTheming,
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h
index 0885c565..206e095 100644
--- a/components/search/ntp_features.h
+++ b/components/search/ntp_features.h
@@ -67,6 +67,7 @@
 BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleBeginTimeDuration);
 BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleMinimumImagesRequired);
 BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleCategories);
+BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleLoad);
 
 // Parameter for controlling the luminosity difference for NTP elements on light
 // backgrounds.
diff --git a/components/services/app_service/public/cpp/app_launch_util.cc b/components/services/app_service/public/cpp/app_launch_util.cc
index 94efb1b2..70d2dd1 100644
--- a/components/services/app_service/public/cpp/app_launch_util.cc
+++ b/components/services/app_service/public/cpp/app_launch_util.cc
@@ -88,6 +88,8 @@
       return ApplicationLaunchSource::APPLICATION_LAUNCH_SOURCE_LOCK_SCREEN;
     case LaunchSource::kFromAppHomePage:
       return ApplicationLaunchSource::APPLICATION_LAUNCH_SOURCE_APP_HOME_PAGE;
+    case LaunchSource::kFromReparenting:
+      return ApplicationLaunchSource::APPLICATION_LAUNCH_SOURCE_REPARENTING;
   }
 }
 
diff --git a/components/services/app_service/public/cpp/app_launch_util.h b/components/services/app_service/public/cpp/app_launch_util.h
index 4279f98..28b7d50 100644
--- a/components/services/app_service/public/cpp/app_launch_util.h
+++ b/components/services/app_service/public/cpp/app_launch_util.h
@@ -56,10 +56,11 @@
   kFromUrlHandler = 31,                // Url handler.
   kFromLockScreen = 32,                // Lock screen app launcher.
   kFromAppHomePage = 33,               // App Home (chrome://apps) page.
+  kFromReparenting = 34,               // Moving content into an app.
 
   // Add any new values above this one, and update kMaxValue to the highest
   // enumerator value.
-  kMaxValue = kFromAppHomePage,
+  kMaxValue = kFromReparenting,
 };
 
 // Don't remove items or change the order of this enum.  It's used in
diff --git a/components/services/app_service/public/cpp/types_util.cc b/components/services/app_service/public/cpp/types_util.cc
index 19ed0b5..60670c3 100644
--- a/components/services/app_service/public/cpp/types_util.cc
+++ b/components/services/app_service/public/cpp/types_util.cc
@@ -47,6 +47,7 @@
     case apps::LaunchSource::kFromCommandLine:
     case apps::LaunchSource::kFromLockScreen:
     case apps::LaunchSource::kFromAppHomePage:
+    case apps::LaunchSource::kFromReparenting:
       return true;
     case apps::LaunchSource::kUnknown:
     case apps::LaunchSource::kFromChromeInternal:
diff --git a/components/services/app_service/public/protos/app_types.proto b/components/services/app_service/public/protos/app_types.proto
index 8520063..5fa303b 100644
--- a/components/services/app_service/public/protos/app_types.proto
+++ b/components/services/app_service/public/protos/app_types.proto
@@ -103,6 +103,7 @@
   APPLICATION_LAUNCH_SOURCE_URL_HANDLER = 31;
   APPLICATION_LAUNCH_SOURCE_LOCK_SCREEN = 32;
   APPLICATION_LAUNCH_SOURCE_APP_HOME_PAGE = 33;
+  APPLICATION_LAUNCH_SOURCE_REPARENTING = 34;
 }
 
 // Describes the app uninstall source. Should be kept in sync with
diff --git a/components/test/data/omnibox/adder.tflite b/components/test/data/omnibox/adder.tflite
index b4888a3..0d562a0d 100644
--- a/components/test/data/omnibox/adder.tflite
+++ b/components/test/data/omnibox/adder.tflite
Binary files differ
diff --git a/components/upload_list/combining_upload_list.cc b/components/upload_list/combining_upload_list.cc
index cb87608..1d21562 100644
--- a/components/upload_list/combining_upload_list.cc
+++ b/components/upload_list/combining_upload_list.cc
@@ -18,10 +18,12 @@
 
 CombiningUploadList::~CombiningUploadList() = default;
 
-std::vector<UploadList::UploadInfo> CombiningUploadList::LoadUploadList() {
-  std::vector<UploadInfo> uploads;
+std::vector<std::unique_ptr<UploadList::UploadInfo>>
+CombiningUploadList::LoadUploadList() {
+  std::vector<std::unique_ptr<UploadList::UploadInfo>> uploads;
   for (const auto& sublist : sublists_) {
-    std::vector<UploadInfo> sublist_uploads = sublist->LoadUploadList();
+    std::vector<std::unique_ptr<UploadList::UploadInfo>> sublist_uploads =
+        sublist->LoadUploadList();
     uploads.reserve(uploads.size() + sublist_uploads.size());
     std::move(sublist_uploads.begin(), sublist_uploads.end(),
               std::back_inserter(uploads));
@@ -31,11 +33,12 @@
   // capture_time if we have it because that's the most stable (won't change
   // if a crash is uploaded), but we'll use upload_time if that's all we have.
   std::sort(uploads.begin(), uploads.end(),
-            [](const UploadInfo& a, const UploadInfo& b) {
+            [](const std::unique_ptr<UploadList::UploadInfo>& a,
+               const std::unique_ptr<UploadList::UploadInfo>& b) {
               base::Time time_a =
-                  a.capture_time.is_null() ? a.upload_time : a.capture_time;
+                  a->capture_time.is_null() ? a->upload_time : a->capture_time;
               base::Time time_b =
-                  b.capture_time.is_null() ? b.upload_time : b.capture_time;
+                  b->capture_time.is_null() ? b->upload_time : b->capture_time;
               return time_a > time_b;
             });
   return uploads;
diff --git a/components/upload_list/combining_upload_list.h b/components/upload_list/combining_upload_list.h
index 7e39b83e..6da3e67 100644
--- a/components/upload_list/combining_upload_list.h
+++ b/components/upload_list/combining_upload_list.h
@@ -20,7 +20,7 @@
 
  protected:
   ~CombiningUploadList() override;
-  std::vector<UploadInfo> LoadUploadList() override;
+  std::vector<std::unique_ptr<UploadInfo>> LoadUploadList() override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
   void RequestSingleUpload(const std::string& local_id) override;
 
diff --git a/components/upload_list/combining_upload_list_unittest.cc b/components/upload_list/combining_upload_list_unittest.cc
index ee116be..8c8f3503 100644
--- a/components/upload_list/combining_upload_list_unittest.cc
+++ b/components/upload_list/combining_upload_list_unittest.cc
@@ -264,7 +264,7 @@
 
 class MockUploadList final : public UploadList {
  public:
-  MOCK_METHOD0(LoadUploadList, std::vector<UploadInfo>());
+  MOCK_METHOD0(LoadUploadList, std::vector<std::unique_ptr<UploadInfo>>());
   MOCK_METHOD2(ClearUploadList, void(const base::Time&, const base::Time&));
   MOCK_METHOD1(RequestSingleUpload, void(const std::string&));
 
diff --git a/components/upload_list/text_log_upload_list.cc b/components/upload_list/text_log_upload_list.cc
index 151d15d..e2907c7d 100644
--- a/components/upload_list/text_log_upload_list.cc
+++ b/components/upload_list/text_log_upload_list.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <utility>
 
 #include "base/containers/adapters.h"
 #include "base/files/file_util.h"
@@ -91,11 +92,62 @@
   return CheckFieldOutOfRange(upload_time_string, begin, end) &&
          CheckFieldOutOfRange(capture_time_string, begin, end);
 }
+}  // namespace
 
-// Tries to parse one upload log line based on CSV format, then converts it to
-// a UploadInfo entry. If the conversion succeeds, it returns a valid UploadInfo
-// instance. Otherwise, it returns nullptr.
-std::unique_ptr<TextLogUploadList::UploadInfo> TryParseCsvLogEntry(
+TextLogUploadList::TextLogUploadList(const base::FilePath& upload_log_path)
+    : upload_log_path_(upload_log_path) {}
+
+TextLogUploadList::~TextLogUploadList() = default;
+
+std::vector<std::unique_ptr<UploadList::UploadInfo>>
+TextLogUploadList::LoadUploadList() {
+  std::vector<std::unique_ptr<UploadInfo>> uploads;
+
+  if (base::PathExists(upload_log_path_)) {
+    std::string contents;
+    base::ReadFileToString(upload_log_path_, &contents);
+    ParseLogEntries(SplitIntoLines(contents), &uploads);
+  }
+
+  return uploads;
+}
+
+void TextLogUploadList::ClearUploadList(const base::Time& begin,
+                                        const base::Time& end) {
+  if (!base::PathExists(upload_log_path_)) {
+    return;
+  }
+
+  std::string contents;
+  base::ReadFileToString(upload_log_path_, &contents);
+  std::vector<std::string> log_entries = SplitIntoLines(contents);
+
+  std::ostringstream new_contents_stream;
+  for (const std::string& line : log_entries) {
+    absl::optional<base::Value> json = base::JSONReader::Read(line);
+    bool should_copy = false;
+
+    if (json.has_value()) {
+      should_copy = json->is_dict() &&
+                    CheckJsonUploadListOutOfRange(json.value(), begin, end);
+    } else {
+      should_copy = CheckCsvUploadListOutOfRange(line, begin, end);
+    }
+
+    if (should_copy) {
+      new_contents_stream << line << std::endl;
+    }
+  }
+
+  std::string new_contents = new_contents_stream.str();
+  if (new_contents.size() == 0) {
+    base::DeleteFile(upload_log_path_);
+  } else {
+    base::WriteFile(upload_log_path_, new_contents);
+  }
+}
+
+std::unique_ptr<UploadList::UploadInfo> TextLogUploadList::TryParseCsvLogEntry(
     const std::string& log_line) {
   std::vector<std::string> components = SplitIntoComponents(log_line);
   // Skip any blank (or corrupted) lines.
@@ -127,17 +179,13 @@
   int state;
   if (components.size() > 4 && !components[4].empty() &&
       base::StringToInt(components[4], &state)) {
-    info->state = static_cast<TextLogUploadList::UploadInfo::State>(state);
+    info->state = static_cast<UploadList::UploadInfo::State>(state);
   }
 
   return info;
 }
 
-// Tries to parse one upload log dictionary based on line-based JSON format (no
-// internal additional newline is permitted), then converts it to a UploadInfo
-// entry. If the conversion succeeds, it returns a valid UploadInfo instance.
-// Otherwise, it returns nullptr.
-std::unique_ptr<TextLogUploadList::UploadInfo> TryParseJsonLogEntry(
+std::unique_ptr<UploadList::UploadInfo> TextLogUploadList::TryParseJsonLogEntry(
     const base::Value& dict) {
   // Parse upload_id.
   const base::Value* upload_id_value = dict.GetDict().Find(kJsonLogKeyUploadId);
@@ -172,8 +220,7 @@
   // Parse state.
   absl::optional<int> state = dict.FindIntKey(kJsonLogKeyState);
   if (state.has_value())
-    info->state =
-        static_cast<TextLogUploadList::UploadInfo::State>(state.value());
+    info->state = static_cast<UploadList::UploadInfo::State>(state.value());
 
   // Parse source.
   if (const std::string* source = dict.FindStringKey(kJsonLogKeySource);
@@ -190,63 +237,11 @@
   return info;
 }
 
-}  // namespace
-
-TextLogUploadList::TextLogUploadList(const base::FilePath& upload_log_path)
-    : upload_log_path_(upload_log_path) {}
-
-TextLogUploadList::~TextLogUploadList() = default;
-
-std::vector<UploadList::UploadInfo> TextLogUploadList::LoadUploadList() {
-  std::vector<UploadInfo> uploads;
-
-  if (base::PathExists(upload_log_path_)) {
-    std::string contents;
-    base::ReadFileToString(upload_log_path_, &contents);
-    ParseLogEntries(SplitIntoLines(contents), &uploads);
-  }
-
-  return uploads;
-}
-
-void TextLogUploadList::ClearUploadList(const base::Time& begin,
-                                        const base::Time& end) {
-  if (!base::PathExists(upload_log_path_))
-    return;
-
-  std::string contents;
-  base::ReadFileToString(upload_log_path_, &contents);
-  std::vector<std::string> log_entries = SplitIntoLines(contents);
-
-  std::ostringstream new_contents_stream;
-  for (const std::string& line : log_entries) {
-    absl::optional<base::Value> json = base::JSONReader::Read(line);
-    bool should_copy = false;
-
-    if (json.has_value()) {
-      should_copy = json->is_dict() &&
-                    CheckJsonUploadListOutOfRange(json.value(), begin, end);
-    } else {
-      should_copy = CheckCsvUploadListOutOfRange(line, begin, end);
-    }
-
-    if (should_copy)
-      new_contents_stream << line << std::endl;
-  }
-
-  std::string new_contents = new_contents_stream.str();
-  if (new_contents.size() == 0) {
-    base::DeleteFile(upload_log_path_);
-  } else {
-    base::WriteFile(upload_log_path_, new_contents);
-  }
-}
-
 void TextLogUploadList::ParseLogEntries(
     const std::vector<std::string>& log_entries,
-    std::vector<UploadInfo>* uploads) {
+    std::vector<std::unique_ptr<UploadList::UploadInfo>>* uploads) {
   for (const std::string& line : base::Reversed(log_entries)) {
-    std::unique_ptr<UploadInfo> info;
+    std::unique_ptr<UploadList::UploadInfo> info;
     absl::optional<base::Value> json = base::JSONReader::Read(line);
 
     if (json.has_value() && json->is_dict())
@@ -255,7 +250,7 @@
       info = TryParseCsvLogEntry(line);
 
     if (info)
-      uploads->push_back(*info);
+      uploads->push_back(std::move(info));
   }
 }
 
diff --git a/components/upload_list/text_log_upload_list.h b/components/upload_list/text_log_upload_list.h
index ac646d1f..05ddd5c 100644
--- a/components/upload_list/text_log_upload_list.h
+++ b/components/upload_list/text_log_upload_list.h
@@ -9,13 +9,16 @@
 #include <vector>
 
 #include "base/files/file_path.h"
+#include "base/values.h"
 #include "components/upload_list/upload_list.h"
 
 // Loads and parses an upload list text file of the line-based JSON format:
 // {"upload_time":<value>[,"upload_id":<value>[,"local_id":<value>
-// [,"capture_time":<value>[,"state":<value>[,"source":<value>]]]]]}
+// [,"capture_time":<value>[,"state":<value>[,"source":<value>
+// [,"path_hash":<value>]]]]]]}
 // {"upload_time":<value>[,"upload_id":<value>[,"local_id":<value>
-// [,"capture_time":<value>[,"state":<value>[,"source":<value>]]]]]}
+// [,"capture_time":<value>[,"state":<value>[,"source":<value>
+// [,"path_hash":<value>]]]]]]}
 // ...
 // or the CSV format:
 // upload_time,upload_id[,local_id[,capture_time[,state]]]
@@ -38,15 +41,29 @@
   ~TextLogUploadList() override;
 
   // UploadList:
-  std::vector<UploadList::UploadInfo> LoadUploadList() override;
+  std::vector<std::unique_ptr<UploadList::UploadInfo>> LoadUploadList()
+      override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
   void RequestSingleUpload(const std::string& local_id) override;
 
+  // Tries to parse one upload log line based on CSV format, then converts it to
+  // a UploadInfo entry. If the conversion succeeds, it returns a valid
+  // UploadInfo instance. Otherwise, it returns nullptr.
+  virtual std::unique_ptr<UploadList::UploadInfo> TryParseCsvLogEntry(
+      const std::string& log_line);
+
+  // Tries to parse one upload log dictionary based on line-based JSON format
+  // (no internal additional newline is permitted), then converts it to a
+  // UploadInfo entry. If the conversion succeeds, it returns a valid UploadInfo
+  // instance. Otherwise, it returns nullptr.
+  virtual std::unique_ptr<UploadList::UploadInfo> TryParseJsonLogEntry(
+      const base::Value& dict);
+
   // Parses upload log lines, converting them to UploadInfo entries.
   // The method also reverse the order of the entries (the first entry in
   // |uploads| is the last in |log_entries|).
   void ParseLogEntries(const std::vector<std::string>& log_entries,
-                       std::vector<UploadInfo>* uploads);
+                       std::vector<std::unique_ptr<UploadInfo>>* uploads);
 
   const base::FilePath upload_log_path_;
 };
diff --git a/components/upload_list/upload_list.cc b/components/upload_list/upload_list.cc
index a5923440..d16eddf 100644
--- a/components/upload_list/upload_list.cc
+++ b/components/upload_list/upload_list.cc
@@ -88,17 +88,21 @@
 }
 
 void UploadList::GetUploads(size_t max_count,
-                            std::vector<UploadInfo>* uploads) {
+                            std::vector<UploadInfo>* uploads) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  std::copy(uploads_.begin(),
-            uploads_.begin() + std::min(uploads_.size(), max_count),
-            std::back_inserter(*uploads));
+  const size_t copied_size = std::min(uploads_.size(), max_count);
+  uploads->reserve(uploads->size() + copied_size);
+  for (size_t i = 0; i < copied_size; ++i) {
+    uploads->push_back(*uploads_[i]);
+  }
 }
 
-void UploadList::OnLoadComplete(const std::vector<UploadInfo>& uploads) {
-  uploads_ = uploads;
-  if (!load_callback_.is_null())
+void UploadList::OnLoadComplete(
+    std::vector<std::unique_ptr<UploadInfo>> uploads) {
+  uploads_ = std::move(uploads);
+  if (!load_callback_.is_null()) {
     std::move(load_callback_).Run();
+  }
 }
 
 void UploadList::OnClearComplete() {
diff --git a/components/upload_list/upload_list.h b/components/upload_list/upload_list.h
index 9235dc4..2225801 100644
--- a/components/upload_list/upload_list.h
+++ b/components/upload_list/upload_list.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -95,13 +96,15 @@
   // Populates |uploads| with the |max_count| most recent uploads,
   // in reverse chronological order.
   // Must be called only after a Load() callback has been received.
-  void GetUploads(size_t max_count, std::vector<UploadInfo>* uploads);
+  // TODO(b/b:264307614): Pass back |UploadInfo| pointers to work with
+  // |UploadInfo|'s children.
+  void GetUploads(size_t max_count, std::vector<UploadInfo>* uploads) const;
 
  protected:
   virtual ~UploadList();
 
   // Reads the upload log and stores the entries in |uploads|.
-  virtual std::vector<UploadInfo> LoadUploadList() = 0;
+  virtual std::vector<std::unique_ptr<UploadInfo>> LoadUploadList() = 0;
 
   // Clears data within the given time range. See Clear.
   virtual void ClearUploadList(const base::Time& begin,
@@ -118,7 +121,7 @@
 
   // When LoadUploadList() finishes, the results are reported in |uploads|
   // and the |load_callback_| is run.
-  void OnLoadComplete(const std::vector<UploadInfo>& uploads);
+  void OnLoadComplete(std::vector<std::unique_ptr<UploadInfo>> uploads);
 
   // Called when ClearUploadList() finishes.
   void OnClearComplete();
@@ -130,7 +133,7 @@
   base::OnceClosure load_callback_;
   base::OnceClosure clear_callback_;
 
-  std::vector<UploadInfo> uploads_;
+  std::vector<std::unique_ptr<UploadInfo>> uploads_;
 };
 
 #endif  // COMPONENTS_UPLOAD_LIST_UPLOAD_LIST_H_
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 473b1ada..d05a7e6 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1193,6 +1193,8 @@
     "loader/prefetch_url_loader.h",
     "loader/prefetch_url_loader_service.cc",
     "loader/prefetch_url_loader_service.h",
+    "loader/resource_timing_utils.cc",
+    "loader/resource_timing_utils.h",
     "loader/shared_cors_origin_access_list_impl.cc",
     "loader/shared_cors_origin_access_list_impl.h",
     "loader/url_loader_throttles.cc",
diff --git a/content/browser/back_forward_cache_basics_browsertest.cc b/content/browser/back_forward_cache_basics_browsertest.cc
index 5344305a..214519a 100644
--- a/content/browser/back_forward_cache_basics_browsertest.cc
+++ b/content/browser/back_forward_cache_basics_browsertest.cc
@@ -543,12 +543,8 @@
 
 // Check that unload event handlers are not dispatched when the page goes
 // into BackForwardCache.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
+IN_PROC_BROWSER_TEST_F(BackForwardCacheUnloadBrowserTest,
                        ConfirmUnloadEventNotFired) {
-  // This test is only enabled for Android, as pages with unload handlers are
-  // only eligible for bfcache on Android.
-  if (!IsUnloadAllowedToEnterBackForwardCache())
-    return;
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index d3b1570..515f90d3 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -458,6 +458,11 @@
           testing::ElementsAreArray(children))));
 }
 
+void BackForwardCacheUnloadBrowserTest::SetUpCommandLine(
+    base::CommandLine* command_line) {
+  scoped_feature_list_.InitAndEnableFeature(kBackForwardCacheUnloadAllowed);
+}
+
 std::initializer_list<RenderFrameHostImpl*> Elements(
     std::initializer_list<RenderFrameHostImpl*> t) {
   return t;
@@ -1008,11 +1013,8 @@
 // Sub-frame doesn't transition from LifecycleStateImpl::kInBackForwardCache to
 // LifecycleStateImpl::kRunningUnloadHandlers even when the sub-frame having
 // unload handlers is being evicted from BackForwardCache.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, SubframeWithUnloadHandler) {
-  // This test is only enabled for Android, as pages with unload handlers are
-  // only eligible for bfcache on Android.
-  if (!IsUnloadAllowedToEnterBackForwardCache())
-    return;
+IN_PROC_BROWSER_TEST_F(BackForwardCacheUnloadBrowserTest,
+                       SubframeWithUnloadHandler) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a.com(a.com)"));
@@ -2584,15 +2586,6 @@
   return GetLocalStorage(current_frame_host(), "unload_run_count");
 }
 
-bool BackForwardCacheBrowserTest::IsUnloadAllowedToEnterBackForwardCache() {
-// Pages with unload handlers are eligible for bfcache only on Android.
-#if BUILDFLAG(IS_ANDROID)
-  return true;
-#else
-  return false;
-#endif
-}
-
 bool BackForwardCacheBrowserTest::AddBlocklistedFeature(RenderFrameHost* rfh) {
   // Add kDummy as blocking feature.
   RenderFrameHostImplWrapper rfh_a(rfh);
@@ -2615,6 +2608,16 @@
   return *histogram_tester_;
 }
 
+// Ensure that psges with unload are only allowed to enter back/forward cache by
+// default on Android.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, UnloadAllowedFlag) {
+#if BUILDFLAG(IS_ANDROID)
+  ASSERT_TRUE(BackForwardCacheImpl::IsUnloadAllowed());
+#else
+  ASSERT_FALSE(BackForwardCacheImpl::IsUnloadAllowed());
+#endif
+}
+
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
                        FrameWithBlocklistedFeatureNotCached) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -2665,7 +2668,31 @@
   ExpectNotRestoredDueToBlocklistedFeature(FROM_HERE);
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, UnloadHandlerPresent) {
+class BackForwardCacheBrowserUnloadHandlerTest
+    : public BackForwardCacheBrowserTest,
+      public ::testing::WithParamInterface<std::tuple<bool, TestFrameType>> {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    if (IsUnloadAllowed()) {
+      scoped_feature_list_.InitAndEnableFeature(kBackForwardCacheUnloadAllowed);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          kBackForwardCacheUnloadAllowed);
+    }
+  }
+
+  bool IsUnloadAllowed() { return std::get<0>(GetParam()); }
+
+  TestFrameType GetTestFrameType() { return std::get<1>(GetParam()); }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Ensure that unload handlers in main frames and subframes block caching or
+// not, depending on the flag setting.
+IN_PROC_BROWSER_TEST_P(BackForwardCacheBrowserUnloadHandlerTest,
+                       UnloadHandlerPresent) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
@@ -2673,7 +2700,22 @@
 
   // 1) Navigate to A.
   EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  InstallUnloadHandlerOnMainFrame();
+
+  BackForwardCacheMetrics::NotRestoredReason expected_blocking_reason;
+  switch (GetTestFrameType()) {
+    case content::TestFrameType::kMainFrame:
+      InstallUnloadHandlerOnMainFrame();
+      expected_blocking_reason = BackForwardCacheMetrics::NotRestoredReason::
+          kUnloadHandlerExistsInMainFrame;
+      break;
+    case content::TestFrameType::kSubFrame:
+      InstallUnloadHandlerOnSubFrame();
+      expected_blocking_reason = BackForwardCacheMetrics::NotRestoredReason::
+          kUnloadHandlerExistsInSubFrame;
+      break;
+    default:
+      NOTREACHED();
+  }
 
   // 2) Navigate to B.
   EXPECT_TRUE(NavigateToURL(shell(), url_b));
@@ -2682,13 +2724,11 @@
   ASSERT_TRUE(HistoryGoBack(web_contents()));
 
   // Pages with unload handlers are eligible for bfcache only on Android.
-  if (IsUnloadAllowedToEnterBackForwardCache()) {
+  if (BackForwardCacheImpl::IsUnloadAllowed()) {
     ExpectRestored(FROM_HERE);
     EXPECT_EQ("0", GetUnloadRunCount());
   } else {
-    ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
-                           kUnloadHandlerExistsInMainFrame},
-                      {}, {}, {}, {}, FROM_HERE);
+    ExpectNotRestored({expected_blocking_reason}, {}, {}, {}, {}, FROM_HERE);
     EXPECT_EQ("1", GetUnloadRunCount());
   }
 
@@ -2698,39 +2738,12 @@
   ExpectRestored(FROM_HERE);
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
-                       UnloadHandlerPresentInSubFrame) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  GURL url_b(embedded_test_server()->GetURL("b.com", "/title2.html"));
-
-  // 1) Navigate to A.
-  EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  InstallUnloadHandlerOnSubFrame();
-
-  // 2) Navigate to B.
-  EXPECT_TRUE(NavigateToURL(shell(), url_b));
-
-  // 3) Go back.
-  ASSERT_TRUE(HistoryGoBack(web_contents()));
-
-  // Pages with unload handlers are eligible for bfcache only on Android.
-  if (IsUnloadAllowedToEnterBackForwardCache()) {
-    ExpectRestored(FROM_HERE);
-    EXPECT_EQ("0", GetUnloadRunCount());
-  } else {
-    ExpectNotRestored({BackForwardCacheMetrics::NotRestoredReason::
-                           kUnloadHandlerExistsInSubFrame},
-                      {}, {}, {}, {}, FROM_HERE);
-    EXPECT_EQ("1", GetUnloadRunCount());
-  }
-
-  // 4) Go forward.
-  ASSERT_TRUE(HistoryGoForward(web_contents()));
-
-  ExpectRestored(FROM_HERE);
-}
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    BackForwardCacheBrowserUnloadHandlerTest,
+    ::testing::Combine(::testing::Bool(),
+                       ::testing::Values(TestFrameType::kMainFrame,
+                                         TestFrameType::kSubFrame)));
 
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, DisableForRenderFrameHost) {
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/content/browser/back_forward_cache_browsertest.h b/content/browser/back_forward_cache_browsertest.h
index 3aa0a1c..1cc6844 100644
--- a/content/browser/back_forward_cache_browsertest.h
+++ b/content/browser/back_forward_cache_browsertest.h
@@ -158,8 +158,6 @@
   void InstallUnloadHandlerOnSubFrame();
   EvalJsResult GetUnloadRunCount();
 
-  bool IsUnloadAllowedToEnterBackForwardCache();
-
   // Adds a blocklisted feature to the document to prevent caching. Currently
   // this means adding a plugin. We expect that plugins will never become
   // cacheable, so this should be stable (at least until plugins cease to
@@ -211,6 +209,15 @@
   const size_t kBackForwardCacheSize = 5;
 };
 
+// Test that enables the BackForwardCacheAllowUnload flag.
+class BackForwardCacheUnloadBrowserTest : public BackForwardCacheBrowserTest {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
 // An implementation of PageLifecycleStateManager::TestDelegate for testing.
 class PageLifecycleStateManagerTestDelegate
     : public PageLifecycleStateManager::TestDelegate {
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
index 787dc9dba9..e47d2a3 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
@@ -765,8 +765,16 @@
   EXPECT_FALSE(service_->AreScanFiltersAllowed(filters));
 }
 
+// TODO(https://crbug.com/1420032): Failing on iOS.
+#if BUILDFLAG(IS_IOS)
+#define MAYBE_BluetoothScanningPermissionRevokedWhenFocusIsLost \
+  DISABLED_BluetoothScanningPermissionRevokedWhenFocusIsLost
+#else
+#define MAYBE_BluetoothScanningPermissionRevokedWhenFocusIsLost \
+  BluetoothScanningPermissionRevokedWhenFocusIsLost
+#endif
 TEST_F(WebBluetoothServiceImplTest,
-       BluetoothScanningPermissionRevokedWhenFocusIsLost) {
+       MAYBE_BluetoothScanningPermissionRevokedWhenFocusIsLost) {
   blink::mojom::WebBluetoothLeScanFilterPtr filter = CreateScanFilter("a", "b");
   absl::optional<WebBluetoothServiceImpl::ScanFilters> filters;
   filters.emplace();
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index bfea685..1ef7011 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -793,10 +793,6 @@
   map->Add<blink::mojom::ReportingServiceProxy>(base::BindRepeating(
       &CreateReportingServiceProxyForFrame, base::Unretained(host)));
 
-  map->Add<blink::mojom::RuntimeFeatureStateController>(base::BindRepeating(
-      &RenderFrameHostImpl::CreateRuntimeFeatureStateController,
-      base::Unretained(host)));
-
   map->Add<blink::mojom::SharedWorkerConnector>(
       base::BindRepeating(&BindSharedWorkerConnector, base::Unretained(host)));
 
@@ -1173,6 +1169,9 @@
   map->Add<media::mojom::FuchsiaMediaCdmProvider>(
       base::BindRepeating(&FuchsiaMediaCdmProviderImpl::Bind));
 #endif
+
+  map->Add<blink::mojom::RuntimeFeatureStateController>(
+      base::BindRepeating(&RuntimeFeatureStateControllerImpl::Create));
 }
 
 void PopulateBinderMap(RenderFrameHostImpl* host, mojo::BinderMap* map) {
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 35521b4..43df28f 100644
--- a/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -237,8 +237,7 @@
             base::TimeTicks() /* renderer_before_unload_end */,
             absl::nullopt /* web_bundle_token */,
             blink::mojom::NavigationInitiatorActivationAndAdStatus::
-                kDidNotStartWithTransientActivation,
-            false /* is_container_initiated */);
+                kDidNotStartWithTransientActivation);
 
     auto common_params = blink::CreateCommonNavigationParams();
     common_params->url = url;
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc
index 229b08c..3df6640 100644
--- a/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -98,8 +98,7 @@
             base::TimeTicks() /* renderer_before_unload_end */,
             absl::nullopt /* web_bundle_token */,
             blink::mojom::NavigationInitiatorActivationAndAdStatus::
-                kDidNotStartWithTransientActivation,
-            false /* is_container_initiated */);
+                kDidNotStartWithTransientActivation);
     auto common_params = blink::CreateCommonNavigationParams();
     common_params->url = url;
     common_params->initiator_origin = url::Origin::Create(url);
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.cc b/content/browser/loader/object_navigation_fallback_body_loader.cc
index 57405999..f7b0f41 100644
--- a/content/browser/loader/object_navigation_fallback_body_loader.cc
+++ b/content/browser/loader/object_navigation_fallback_body_loader.cc
@@ -10,6 +10,7 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
+#include "content/browser/loader/resource_timing_utils.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -31,15 +32,35 @@
 
 namespace content {
 
+namespace {
+
+std::string ExtractServerTimingValueIfNeeded(
+    const network::mojom::URLResponseHead& response_head) {
+  std::string value;
+  if (!response_head.timing_allow_passed)
+    return value;
+
+  // Note: the renderer will be responsible for parsing the actual server
+  // timing values.
+  response_head.headers->GetNormalizedHeader("Server-Timing", &value);
+  return value;
+}
+
+}  // namespace
+
 NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(ObjectNavigationFallbackBodyLoader);
 
 // static
 void ObjectNavigationFallbackBodyLoader::CreateAndStart(
     NavigationRequest& navigation_request,
+    const blink::mojom::CommonNavigationParams& common_params,
+    const blink::mojom::CommitNavigationParams& commit_params,
+    const network::mojom::URLResponseHead& response_head,
     mojo::ScopedDataPipeConsumerHandle response_body,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     base::OnceClosure completion_closure) {
   // This should only be called for HTTP errors.
+  DCHECK(response_head.headers);
   RenderFrameHostImpl* render_frame_host =
       navigation_request.frame_tree_node()->current_frame_host();
   // A frame owned by <object> should always have a parent.
@@ -47,15 +68,25 @@
   // It's safe to snapshot the parent origin in the calculation here; if the
   // parent frame navigates, `render_frame_host_` will be deleted, which
   // triggers deletion of `this`, cancelling all remaining work.
-  CreateForNavigationHandle(navigation_request, std::move(response_body),
-                            std::move(url_loader_client_endpoints),
-                            std::move(completion_closure));
+  blink::mojom::ResourceTimingInfoPtr timing_info =
+      GenerateResourceTimingForNavigation(
+          render_frame_host->GetParent()->GetLastCommittedOrigin(),
+          common_params, commit_params, response_head);
+  std::string server_timing_value =
+      ExtractServerTimingValueIfNeeded(response_head);
+
+  CreateForNavigationHandle(
+      navigation_request, std::move(timing_info),
+      std::move(server_timing_value), std::move(response_body),
+      std::move(url_loader_client_endpoints), std::move(completion_closure));
 }
 
 ObjectNavigationFallbackBodyLoader::~ObjectNavigationFallbackBodyLoader() {}
 
 ObjectNavigationFallbackBodyLoader::ObjectNavigationFallbackBodyLoader(
     NavigationHandle& navigation_handle,
+    blink::mojom::ResourceTimingInfoPtr timing_info,
+    std::string server_timing_value,
     mojo::ScopedDataPipeConsumerHandle response_body,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     base::OnceClosure completion_closure)
@@ -67,6 +98,8 @@
       response_body_drainer_(
           std::make_unique<mojo::DataPipeDrainer>(this,
                                                   std::move(response_body))),
+      timing_info_(std::move(timing_info)),
+      server_timing_value_(std::move(server_timing_value)),
       completion_closure_(std::move(completion_closure)) {
   // Unretained is safe; `url_loader_` is owned by `this` and will not dispatch
   // callbacks after it is destroyed.
@@ -132,9 +165,25 @@
   // `completion_closure_` will delete the NavigationRequest, which will delete
   // `this`.
   base::ScopedClosureRunner cleanup(std::move(completion_closure_));
-  navigation_request_->AddResourceTimingEntryForFailedSubframeNavigation(
-      status);
-  navigation_request_->RenderFallbackContentForObjectTag();
+
+  timing_info_->response_end = status.completion_time;
+  timing_info_->encoded_body_size = status.encoded_body_length;
+  timing_info_->decoded_body_size = status.decoded_body_length;
+
+  RenderFrameHostManager* render_manager =
+      navigation_request_->frame_tree_node()->render_manager();
+  if (RenderFrameProxyHost* proxy = render_manager->GetProxyToParent()) {
+    if (proxy->is_render_frame_proxy_live()) {
+      proxy->GetAssociatedRemoteFrame()
+          ->RenderFallbackContentWithResourceTiming(std::move(timing_info_),
+                                                    server_timing_value_);
+    }
+  } else {
+    render_manager->current_frame_host()
+        ->GetAssociatedLocalFrame()
+        ->RenderFallbackContentWithResourceTiming(std::move(timing_info_),
+                                                  server_timing_value_);
+  }
 }
 
 void ObjectNavigationFallbackBodyLoader::OnDataAvailable(const void* data,
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.h b/content/browser/loader/object_navigation_fallback_body_loader.h
index 5568126..34acb77 100644
--- a/content/browser/loader/object_navigation_fallback_body_loader.h
+++ b/content/browser/loader/object_navigation_fallback_body_loader.h
@@ -21,6 +21,12 @@
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
 #include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
 
+namespace network {
+namespace mojom {
+class URLResponseHead;
+}  // namespace mojom
+}  // namespace network
+
 namespace content {
 
 class NavigationRequest;
@@ -53,6 +59,9 @@
       public network::mojom::URLLoaderClient,
       public mojo::DataPipeDrainer::Client {
  public:
+  // `common_params, `commit_params`, and `response_head`  are used to
+  // (partially) generate the resource timing info.
+  //
   // `response_body` and `url_loader_client_endpoints` are used to drain the
   // responise body and calculate the body / data size needed for the
   // performance entry.
@@ -66,6 +75,9 @@
   // response body is successfully loaded.
   static void CreateAndStart(
       NavigationRequest& navigation_request,
+      const blink::mojom::CommonNavigationParams& common_params,
+      const blink::mojom::CommitNavigationParams& commit_params,
+      const network::mojom::URLResponseHead& response_head,
       mojo::ScopedDataPipeConsumerHandle response_body,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure completion_closure);
@@ -78,6 +90,8 @@
 
   ObjectNavigationFallbackBodyLoader(
       NavigationHandle& navigation_handle,
+      blink::mojom::ResourceTimingInfoPtr timing_info,
+      std::string server_timing_value,
       mojo::ScopedDataPipeConsumerHandle response_body,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure completion_closure);
@@ -109,6 +123,8 @@
   // `response_body_drainer_` will be reset to null when the response body is
   // completely drained.
   std::unique_ptr<mojo::DataPipeDrainer> response_body_drainer_;
+  blink::mojom::ResourceTimingInfoPtr timing_info_;
+  std::string server_timing_value_;
   base::OnceClosure completion_closure_;
 };
 
diff --git a/content/browser/loader/resource_timing_utils.cc b/content/browser/loader/resource_timing_utils.cc
new file mode 100644
index 0000000..749756ba9a
--- /dev/null
+++ b/content/browser/loader/resource_timing_utils.cc
@@ -0,0 +1,106 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/resource_timing_utils.h"
+
+#include <string>
+#include <utility>
+
+#include "base/containers/contains.h"
+#include "net/http/http_response_info.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
+#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
+#include "url/gurl.h"
+#include "url/url_util.h"
+
+namespace {
+
+// Implements the TimingAllowOrigin check
+// This logic is duplicated from Performance::AllowsTimingRedirect(). Ensure
+// that any changes are synced between both copies.
+bool IsCrossOriginResponseOrHasCrossOriginRedirects(
+    const url::Origin& parent_origin,
+    const blink::mojom::CommonNavigationParams& common_params,
+    const blink::mojom::CommitNavigationParams& commit_params) {
+  DCHECK_EQ(commit_params.redirect_infos.size(),
+            commit_params.redirect_response.size());
+  for (const auto& info : commit_params.redirect_infos) {
+    if (!parent_origin.IsSameOriginWith(info.new_url)) {
+      return true;
+    }
+  }
+
+  return !parent_origin.IsSameOriginWith(common_params.url);
+}
+
+}  // namespace
+
+namespace content {
+
+// This logic is duplicated from blink::CreateResourceTimingInfo(). Ensure
+// that any changes are synced between both copies.
+blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation(
+    const url::Origin& parent_origin,
+    const blink::mojom::CommonNavigationParams& common_params,
+    const blink::mojom::CommitNavigationParams& commit_params,
+    const network::mojom::URLResponseHead& response_head) {
+  // TODO(dcheng): There should be a Blink helper for populating the timing info
+  // that's exposed in //third_party/blink/common. This would allow a lot of the
+  // boilerplate to be shared.
+
+  auto timing_info = blink::mojom::ResourceTimingInfo::New();
+  const GURL& initial_url = !commit_params.original_url.is_empty()
+                                ? commit_params.original_url
+                                : common_params.url;
+  timing_info->name = initial_url.spec();
+  timing_info->start_time = common_params.navigation_start;
+  timing_info->allow_timing_details = response_head.timing_allow_passed;
+
+  // Only expose the response code when we are same origin and without
+  // cross-origin redirects
+  // https://fetch.spec.whatwg.org/#ref-for-concept-response-status%E2%91%A6
+  if (!IsCrossOriginResponseOrHasCrossOriginRedirects(
+          parent_origin, common_params, commit_params)) {
+    timing_info->response_status = commit_params.http_response_code;
+  }
+
+  // https://fetch.spec.whatwg.org/#create-an-opaque-timing-info
+  if (!timing_info->allow_timing_details) {
+    return timing_info;
+  }
+
+  timing_info->alpn_negotiated_protocol =
+      response_head.alpn_negotiated_protocol;
+  timing_info->connection_info = net::HttpResponseInfo::ConnectionInfoToString(
+      response_head.connection_info);
+
+  // If there's no received headers end time, don't set load timing. This is the
+  // case for non-HTTP requests, requests that don't go over the wire, and
+  // certain error cases.
+  // TODO(dcheng): Is it actually possible to hit this path if
+  // `response_head.headers` is populated?
+  if (!response_head.load_timing.receive_headers_end.is_null()) {
+    timing_info->timing = response_head.load_timing;
+  }
+  // `response_end` will be populated after loading the body.
+
+  DCHECK_EQ(commit_params.redirect_infos.size(),
+            commit_params.redirect_response.size());
+
+  if (!commit_params.redirect_infos.empty()) {
+    timing_info->last_redirect_end_time =
+        commit_params.redirect_response.back()->load_timing.receive_headers_end;
+  } else {
+    timing_info->last_redirect_end_time = base::TimeTicks();
+  }
+  // The final value for `encoded_body_size` and `decoded_body_size` will be
+  // populated after loading the body.
+  timing_info->did_reuse_connection = response_head.load_timing.socket_reused;
+  // Use url::Origin to handle cases like blob:https://.
+  timing_info->is_secure_transport = base::Contains(
+      url::GetSecureSchemes(), url::Origin::Create(common_params.url).scheme());
+  timing_info->allow_negative_values = false;
+  return timing_info;
+}
+}  // namespace content
diff --git a/content/browser/loader/resource_timing_utils.h b/content/browser/loader/resource_timing_utils.h
new file mode 100644
index 0000000..764495b
--- /dev/null
+++ b/content/browser/loader/resource_timing_utils.h
@@ -0,0 +1,24 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_
+#define CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_
+
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-forward.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
+#include "third_party/blink/public/mojom/timing/resource_timing.mojom-forward.h"
+#include "url/origin.h"
+
+namespace content {
+
+blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation(
+    const url::Origin& parent_origin,
+    const blink::mojom::CommonNavigationParams& common_params,
+    const blink::mojom::CommitNavigationParams& commit_params,
+    const network::mojom::URLResponseHead& response_head);
+
+}  // namespace content
+
+#endif
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc
index 3349023..7e6094a 100644
--- a/content/browser/preloading/prerender/prerender_browsertest.cc
+++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -5141,31 +5141,10 @@
   EXPECT_EQ(web_contents()->GetLastCommittedURL(), initial_url);
 }
 
-// TODO(crbug.com/1356907): Remove this and merge it to
-// PrerenderSequentialPrerenderingBrowserTest once kPrerender2InBackground is
-// enabled by default.
-class SequentialPrerenderInBackgroundBrowserTest
-    : public PrerenderSequentialPrerenderingBrowserTest {
- public:
-  SequentialPrerenderInBackgroundBrowserTest() {
-    scoped_feature_list_.InitWithFeatures(
-        {// Enable to run prerenderings in the background.
-         blink::features::kPrerender2InBackground},
-        // Disable the memory requirement of Prerender2 so the test can run on
-        // any bot.
-        {blink::features::kPrerender2MemoryControls});
-  }
-
-  ~SequentialPrerenderInBackgroundBrowserTest() override = default;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
 // Test that when the current tab gets hidden then the prerender sequence is
 // terminated, and when the current tab gets visible then we start the next
 // prerender if we have some pending prerender hosts.
-IN_PROC_BROWSER_TEST_F(SequentialPrerenderInBackgroundBrowserTest,
+IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                        SequentialPrerenderingInBackground) {
   net::test_server::ControllableHttpResponse response1(
       embedded_test_server(), "/empty.html?prerender1");
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc
index 9bb8f609..54c8423 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -809,64 +809,55 @@
 }
 
 void PrerenderHostRegistry::OnVisibilityChanged(Visibility visibility) {
-  if (base::FeatureList::IsEnabled(blink::features::kPrerender2InBackground)) {
-    // Update the timer for prerendering timeout in the background.
-    switch (visibility) {
-      case Visibility::HIDDEN:
-        // Keep a prerendered page alive in the background when its visibility
-        // state changes to HIDDEN if the feature is enabled.
-        DCHECK(!timeout_timer_for_embedder_.IsRunning());
-        DCHECK(!timeout_timer_for_speculation_rules_.IsRunning());
+  // Update the timer for prerendering timeout in the background.
+  switch (visibility) {
+    case Visibility::HIDDEN:
+      // Keep a prerendered page alive in the background when its visibility
+      // state changes to HIDDEN.
+      DCHECK(!timeout_timer_for_embedder_.IsRunning());
+      DCHECK(!timeout_timer_for_speculation_rules_.IsRunning());
 
-        timeout_timer_for_embedder_.SetTaskRunner(GetTimerTaskRunner());
-        timeout_timer_for_speculation_rules_.SetTaskRunner(
-            GetTimerTaskRunner());
+      timeout_timer_for_embedder_.SetTaskRunner(GetTimerTaskRunner());
+      timeout_timer_for_speculation_rules_.SetTaskRunner(GetTimerTaskRunner());
 
-        // Cancel PrerenderHost in the background when it exceeds a certain
-        // amount of time. The timeout differs depending on the trigger
-        // type.
-        timeout_timer_for_embedder_.Start(
-            FROM_HERE, kTimeToLiveInBackgroundForEmbedder,
-            base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
-                           base::Unretained(this),
-                           PrerenderTriggerType::kEmbedder,
-                           PrerenderCancellationReason(
-                               PrerenderFinalStatus::kTimeoutBackgrounded)));
-        timeout_timer_for_speculation_rules_.Start(
-            FROM_HERE, kTimeToLiveInBackgroundForSpeculationRules,
-            base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
-                           base::Unretained(this),
-                           PrerenderTriggerType::kSpeculationRule,
-                           PrerenderCancellationReason(
-                               PrerenderFinalStatus::kTimeoutBackgrounded)));
-        break;
-      case Visibility::OCCLUDED:
-      case Visibility::VISIBLE:
-        // Stop the timer when a prerendered page gets visible to users.
-        timeout_timer_for_embedder_.Stop();
-        timeout_timer_for_speculation_rules_.Stop();
-        break;
-    }
+      // Cancel PrerenderHost in the background when it exceeds a certain
+      // amount of time. The timeout differs depending on the trigger type.
+      timeout_timer_for_embedder_.Start(
+          FROM_HERE, kTimeToLiveInBackgroundForEmbedder,
+          base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
+                         base::Unretained(this),
+                         PrerenderTriggerType::kEmbedder,
+                         PrerenderCancellationReason(
+                             PrerenderFinalStatus::kTimeoutBackgrounded)));
+      timeout_timer_for_speculation_rules_.Start(
+          FROM_HERE, kTimeToLiveInBackgroundForSpeculationRules,
+          base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
+                         base::Unretained(this),
+                         PrerenderTriggerType::kSpeculationRule,
+                         PrerenderCancellationReason(
+                             PrerenderFinalStatus::kTimeoutBackgrounded)));
+      break;
+    case Visibility::OCCLUDED:
+    case Visibility::VISIBLE:
+      // Stop the timer when a prerendered page gets visible to users.
+      timeout_timer_for_embedder_.Stop();
+      timeout_timer_for_speculation_rules_.Stop();
+      break;
+  }
 
-    if (!base::FeatureList::IsEnabled(
-            blink::features::kPrerender2SequentialPrerendering))
-      return;
-
+  if (base::FeatureList::IsEnabled(
+          blink::features::kPrerender2SequentialPrerendering)) {
     // Start the next prerender when the page gets back to the foreground.
     switch (visibility) {
       case Visibility::VISIBLE:
       case Visibility::OCCLUDED:
-        if (running_prerender_host_id_ == RenderFrameHost::kNoFrameTreeNodeId)
+        if (running_prerender_host_id_ == RenderFrameHost::kNoFrameTreeNodeId) {
           StartPrerendering(RenderFrameHost::kNoFrameTreeNodeId);
+        }
         break;
       case Visibility::HIDDEN:
         break;
     }
-    return;
-  }
-
-  if (visibility == Visibility::HIDDEN) {
-    CancelAllHosts(PrerenderFinalStatus::kTriggerBackgrounded);
   }
 }
 
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc
index 5b647c4..0df08c5 100644
--- a/content/browser/renderer_host/back_forward_cache_impl.cc
+++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -865,16 +865,16 @@
     result.No(BackForwardCacheMetrics::NotRestoredReason::kHaveInnerContents);
   }
 
-#if !BUILDFLAG(IS_ANDROID)
-  const bool has_unload_handler = rfh->has_unload_handler();
-  if (has_unload_handler) {
-    // Note that pages with unload handlers are cached on android.
-    result.No(rfh->GetParent() ? BackForwardCacheMetrics::NotRestoredReason::
-                                     kUnloadHandlerExistsInSubFrame
-                               : BackForwardCacheMetrics::NotRestoredReason::
-                                     kUnloadHandlerExistsInMainFrame);
+  if (!IsUnloadAllowed()) {
+    const bool has_unload_handler = rfh->has_unload_handler();
+    if (has_unload_handler) {
+      // Note that pages with unload handlers are cached on android.
+      result.No(rfh->GetParent() ? BackForwardCacheMetrics::NotRestoredReason::
+                                       kUnloadHandlerExistsInSubFrame
+                                 : BackForwardCacheMetrics::NotRestoredReason::
+                                       kUnloadHandlerExistsInMainFrame);
+    }
   }
-#endif
 
   // When it's not the final decision for putting a page in the back-forward
   // cache, we should only consider "sticky" features here - features that
@@ -1417,6 +1417,11 @@
       features::kEnableBackForwardCacheForScreenReader);
 }
 
+// Static
+bool BackForwardCacheImpl::IsUnloadAllowed() {
+  return base::FeatureList::IsEnabled(kBackForwardCacheUnloadAllowed);
+}
+
 // static
 void BackForwardCacheImpl::VlogUnexpectedRendererToBrowserMessage(
     const char* interface_name,
diff --git a/content/browser/renderer_host/back_forward_cache_impl.h b/content/browser/renderer_host/back_forward_cache_impl.h
index 92d1ec2..bf98de5 100644
--- a/content/browser/renderer_host/back_forward_cache_impl.h
+++ b/content/browser/renderer_host/back_forward_cache_impl.h
@@ -69,6 +69,18 @@
 CONTENT_EXPORT extern const base::FeatureParam<int>
     kBackForwardCacheSizeForegroundCacheSize;
 
+// Controls the interaction between back/forward cache and
+// unload. When enabled, pages with unload handlers may enter the
+// cache.
+BASE_FEATURE(kBackForwardCacheUnloadAllowed,
+             "BackForwardCacheUnloadAllowed",
+#if BUILDFLAG(IS_ANDROID)
+             base::FEATURE_ENABLED_BY_DEFAULT
+#else
+             base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+);
+
 // Combines a flattened list and a tree of the reasons why each document cannot
 // enter the back/forward cache (might be empty if it can). The tree saves the
 // reasons for each document in the tree (including those without the reasons)
@@ -201,6 +213,9 @@
   // Returns whether back/forward cache is enabled for screen reader users.
   static bool IsScreenReaderAllowed();
 
+  // Returns where back/forward cache is allowed for pages with unload handlers.
+  static bool IsUnloadAllowed();
+
   // Log an unexpected message from the renderer. Doing it here so that it is
   // grouped with other back/forward cache vlogging and e.g. will show up in
   // test logs. `message_name` varies in each build however when a test failure
diff --git a/content/browser/renderer_host/ipc_utils.cc b/content/browser/renderer_host/ipc_utils.cc
index aa8a0028..3a2dab5 100644
--- a/content/browser/renderer_host/ipc_utils.cc
+++ b/content/browser/renderer_host/ipc_utils.cc
@@ -171,16 +171,6 @@
     return false;
   }
 
-  if (params->is_container_initiated) {
-    if (!current_rfh->GetParent() ||
-        (current_rfh->GetParent()->GetFrameToken() !=
-         params->initiator_frame_token)) {
-      mojo::ReportBadMessage(
-          "container initiated navigation from non-parent process");
-      return false;
-    }
-  }
-
   // Verification succeeded.
   return true;
 }
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index b74775eb..358540b 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2692,8 +2692,7 @@
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
     bool is_unfenced_top_navigation,
-    bool force_new_browsing_instance,
-    bool is_container_initiated) {
+    bool force_new_browsing_instance) {
   if (is_renderer_initiated)
     DCHECK(initiator_origin.has_value());
 
@@ -2818,7 +2817,7 @@
           false /* has_user_gesture */, std::move(source_location),
           ReloadType::NONE, entry.get(), frame_entry.get(),
           navigation_start_time, is_embedder_initiated_fenced_frame_navigation,
-          is_unfenced_top_navigation, is_container_initiated);
+          is_unfenced_top_navigation);
 
   if (!request)
     return;
@@ -3761,8 +3760,7 @@
     FrameNavigationEntry* frame_entry,
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
-    bool is_unfenced_top_navigation,
-    bool is_container_initiated) {
+    bool is_unfenced_top_navigation) {
   DCHECK_EQ(-1, GetIndexOfEntry(entry));
   DCHECK(frame_entry);
   // All renderer-initiated navigations must have an initiator_origin.
@@ -3933,8 +3931,7 @@
       params.is_form_submission,
       params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr,
       params.impression, params.initiator_activation_and_ad_status,
-      params.is_pdf, is_embedder_initiated_fenced_frame_navigation,
-      is_container_initiated);
+      params.is_pdf, is_embedder_initiated_fenced_frame_navigation);
   navigation_request->set_from_download_cross_origin_redirect(
       params.from_download_cross_origin_redirect);
   navigation_request->set_force_new_browsing_instance(
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index ccdf116..ebb6afd8 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -227,8 +227,7 @@
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
       bool is_unfenced_top_navigation = false,
-      bool force_new_browsing_instance = false,
-      bool is_container_initiated = false);
+      bool force_new_browsing_instance = false);
 
   // Navigates to the history entry associated with the given navigation API
   // |key|. Searches |entries_| for a FrameNavigationEntry associated with
@@ -654,8 +653,7 @@
       FrameNavigationEntry* frame_entry,
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
-      bool is_unfenced_top_navigation = false,
-      bool is_container_initiated = false);
+      bool is_unfenced_top_navigation = false);
 
   // Creates and returns a NavigationRequest for a navigation to |entry|. Will
   // return nullptr if the parameters are invalid and the navigation cannot
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 2717fd4..b891dc3 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -53,6 +53,7 @@
 #include "content/browser/loader/navigation_early_hints_manager.h"
 #include "content/browser/loader/navigation_url_loader.h"
 #include "content/browser/loader/object_navigation_fallback_body_loader.h"
+#include "content/browser/loader/resource_timing_utils.h"
 #include "content/browser/navigation_or_document_handle.h"
 #include "content/browser/network/cross_origin_embedder_policy_reporter.h"
 #include "content/browser/network/cross_origin_opener_policy_reporter.h"
@@ -140,7 +141,6 @@
 #include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/supports_loading_mode.mojom.h"
-#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "services/network/public/mojom/url_response_head.mojom-shared.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
@@ -170,7 +170,6 @@
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
 #include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
 #include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
 #include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h"
 #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h"
@@ -1100,8 +1099,7 @@
     blink::mojom::NavigationInitiatorActivationAndAdStatus
         initiator_activation_and_ad_status,
     bool is_pdf,
-    bool is_embedder_initiated_fenced_frame_navigation,
-    bool is_container_initiated) {
+    bool is_embedder_initiated_fenced_frame_navigation) {
   TRACE_EVENT1("navigation", "NavigationRequest::Create", "browser_initiated",
                browser_initiated);
 
@@ -1131,8 +1129,7 @@
       nullptr /* trust_token_params */, impression,
       base::TimeTicks() /* renderer_before_unload_start */,
       base::TimeTicks() /* renderer_before_unload_end */,
-      std::move(web_bundle_token_params), initiator_activation_and_ad_status,
-      is_container_initiated);
+      std::move(web_bundle_token_params), initiator_activation_and_ad_status);
 
   // Shift-Reload forces bypassing caches and service workers.
   if (common_params->navigation_type ==
@@ -1635,24 +1632,6 @@
     if (initiator_rfh)
       initiator_document_ = initiator_rfh->GetWeakDocumentPtr();
   }
-
-  // Spec: https://github.com/whatwg/html/issues/8846
-  // We only allow the parent to access a subframe resource timing if the
-  // navigation is container-initiated, e.g. iframe changed src.
-  if (begin_params_->is_container_initiated) {
-    // Only same-origin navigations without cross-origin redirects can
-    // expose response details (status-code / mime-type).
-    // https://github.com/whatwg/fetch/issues/1602
-    // Note that this condition checks this navigation is not cross origin.
-    // Cross-origin redirects are checked as part of OnRequestRedirected().
-    commit_params_->navigation_timing->parent_resource_timing_access =
-        GetParentFrame()->GetLastCommittedOrigin().IsSameOriginWith(GetURL())
-            ? blink::mojom::ParentResourceTimingAccess::
-                  kReportWithResponseDetails
-            : blink::mojom::ParentResourceTimingAccess::
-                  kReportWithoutResponseDetails;
-  }
-
   navigation_or_document_handle_ =
       NavigationOrDocumentHandle::CreateForNavigation(*this);
 
@@ -3088,18 +3067,6 @@
   const bool is_same_origin_redirect =
       url::Origin::Create(common_params_->url)
           .IsSameOriginWith(redirect_info.new_url);
-
-  // Only same-origin navigations without cross-origin redirects can
-  // expose response details (status-code / mime-type).
-  // https://github.com/whatwg/fetch/issues/1602
-  if (!is_same_origin_redirect &&
-      commit_params_->navigation_timing->parent_resource_timing_access ==
-          blink::mojom::ParentResourceTimingAccess::
-              kReportWithResponseDetails) {
-    commit_params_->navigation_timing->parent_resource_timing_access =
-        blink::mojom::ParentResourceTimingAccess::kReportWithoutResponseDetails;
-  }
-
   did_receive_early_hints_before_cross_origin_redirect_ |=
       did_create_early_hints_manager_params_ && !is_same_origin_redirect;
 
@@ -3822,12 +3789,6 @@
     return;
   }
 
-  // See https://github.com/whatwg/fetch/pull/1579
-  if (!response_head_->timing_allow_passed) {
-    commit_params_->navigation_timing->parent_resource_timing_access =
-        blink::mojom::ParentResourceTimingAccess::kDoNotReport;
-  }
-
   MaybeInjectIsolatedAppHeaders();
 
   {
@@ -4757,40 +4718,34 @@
     return;
   }
 
+  RenderFrameHostImpl* parent_rfh = GetParentFrame();
+
+  // Do not add ResourceTiming entries if the navigated URL does not have a
+  // parent.
+  if (!parent_rfh) {
+    return;
+  }
+
   // Some navigation are cancelled even before requesting and receiving a
   // response. Those cases are not supported and the ResourceTiming is not
   // reported to the parent.
-  if (!response()) {
+  if (!response_head_) {
     return;
   }
 
-  network::URLLoaderCompletionStatus status;
-  status.encoded_data_length = response()->encoded_data_length;
-  status.completion_time = base::TimeTicks::Now();
-  AddResourceTimingEntryForFailedSubframeNavigation(status);
-}
-
-void NavigationRequest::AddResourceTimingEntryForFailedSubframeNavigation(
-    const network::URLLoaderCompletionStatus& status) {
-  // For TAO-fail navigations, we would resort to fallback timing.
-  // See HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded().
-  DCHECK(response());
-  if (commit_params().navigation_timing->parent_resource_timing_access ==
-      blink::mojom::ParentResourceTimingAccess::kDoNotReport) {
+  if (initiator_document_.AsRenderFrameHostIfValid() != parent_rfh) {
     return;
   }
 
-  network::mojom::URLResponseHeadPtr response_head = response()->Clone();
-
-  bool allow_response_details =
-      commit_params().navigation_timing->parent_resource_timing_access ==
-      blink::mojom::ParentResourceTimingAccess::kReportWithResponseDetails;
-
-  GetParentFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
-      frame_tree_node(), common_params().navigation_start,
-      commit_params().navigation_timing->redirect_end,
-      commit_params().original_url, common_params().url,
-      std::move(response_head), allow_response_details, status);
+  blink::mojom::ResourceTimingInfoPtr timing_info =
+      GenerateResourceTimingForNavigation(parent_rfh->GetLastCommittedOrigin(),
+                                          *common_params_, *commit_params_,
+                                          *response_head_);
+  timing_info->response_end = base::TimeTicks::Now();
+  parent_rfh->GetAssociatedLocalFrame()
+      ->AddResourceTimingEntryFromNonNavigatedFrame(
+          std::move(timing_info),
+          frame_tree_node()->frame_owner_element_type());
 }
 
 void NavigationRequest::OnRedirectChecksComplete(
@@ -5038,8 +4993,8 @@
       // fallback / resource timing are only reported if the navigation request
       // is logically still pending.
       ObjectNavigationFallbackBodyLoader::CreateAndStart(
-          *this, std::move(response_body_),
-          std::move(url_loader_client_endpoints_),
+          *this, *common_params_, *commit_params_, *response(),
+          std::move(response_body_), std::move(url_loader_client_endpoints_),
           base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
                          weak_factory_.GetWeakPtr(),
                          network::URLLoaderCompletionStatus(net::ERR_ABORTED),
@@ -5061,7 +5016,6 @@
       result.action() == NavigationThrottle::CANCEL ||
       !response_should_be_rendered_) {
     MaybeAddResourceTimingEntryForCancelledNavigation();
-
     // Reset the RenderFrameHost that had been computed for the commit of the
     // navigation.
     render_frame_host_ = nullptr;
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index 14d3a6c..3d53578 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -260,8 +260,7 @@
       blink::mojom::NavigationInitiatorActivationAndAdStatus
           initiator_activation_and_ad_status,
       bool is_pdf,
-      bool is_embedder_initiated_fenced_frame_navigation = false,
-      bool is_container_initiated = false);
+      bool is_embedder_initiated_fenced_frame_navigation = false);
 
   // Creates a request for a renderer-initiated navigation.
   static std::unique_ptr<NavigationRequest> CreateRendererInitiated(
@@ -569,11 +568,6 @@
   // a request was made.
   void MaybeAddResourceTimingEntryForCancelledNavigation();
 
-  // Adds a resource timing entry to the parent in case of cancelled navigations
-  // and failed <object> navigations.
-  void AddResourceTimingEntryForFailedSubframeNavigation(
-      const network::URLLoaderCompletionStatus& status);
-
   // Lazily initializes and returns the mojo::NavigationClient interface used
   // for commit.
   mojom::NavigationClient* GetCommitNavigationClient();
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index d4868e7..fc5ddfc 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -872,8 +872,7 @@
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
     bool is_unfenced_top_navigation,
-    bool force_new_browsing_instance,
-    bool is_container_initiated) {
+    bool force_new_browsing_instance) {
   // |method != "POST"| should imply absence of |post_body|.
   if (method != "POST" && post_body) {
     NOTREACHED();
@@ -918,7 +917,7 @@
       std::move(blob_url_loader_factory), is_form_submission, impression,
       initiator_activation_and_ad_status, navigation_start_time,
       is_embedder_initiated_fenced_frame_navigation, is_unfenced_top_navigation,
-      force_new_browsing_instance, is_container_initiated);
+      force_new_browsing_instance);
 }
 
 void Navigator::BeforeUnloadCompleted(FrameTreeNode* frame_tree_node,
diff --git a/content/browser/renderer_host/navigator.h b/content/browser/renderer_host/navigator.h
index f344ec2..e3bd62d 100644
--- a/content/browser/renderer_host/navigator.h
+++ b/content/browser/renderer_host/navigator.h
@@ -165,8 +165,7 @@
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
       bool is_unfenced_top_navigation = false,
-      bool force_new_browsing_instance = false,
-      bool is_container_initiated = false);
+      bool force_new_browsing_instance = false);
 
   // Called after BeforeUnloadCompleted callback is invoked from the renderer.
   // If |frame_tree_node| has a NavigationRequest waiting for the renderer
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 1be900f..e58f735 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -711,28 +711,36 @@
   if (navigation_request->state() < NavigationRequest::WILL_PROCESS_RESPONSE)
     return true;
 
-  // Check if both the renderer and browser expect an opaque origin. This
-  // effectively ignores the following:
-  // - precursor origins
-  // - TODO(https://crbug.com/1041376): mismatched nonces (even if precursor
-  //   origins would have matched)
-  // - blob urls with content scheme are opaque on browser side
-  // (https://crbug.com/1295268)
+  // Blob urls with content scheme are opaque on browser side because the
+  // browser doesn't have access to the BlobURLNullOriginMap.
+  // (https://crbug.com/1295268).
   const url::Origin& renderer_side_origin = params.origin;
   std::pair<absl::optional<url::Origin>, std::string>
       browser_side_origin_and_debug_info =
           navigation_request->GetOriginToCommitWithDebugInfo();
-  if ((renderer_side_origin.opaque() ||
-       renderer_side_origin.scheme() == url::kContentScheme) &&
+  if (renderer_side_origin.scheme() == url::kContentScheme &&
       browser_side_origin_and_debug_info.first->opaque()) {
     return true;
   }
 
+  // For non-opaque origins, we say the browser and renderer calculated origins
+  // match if they are exactly the same.
+  bool origins_match = (browser_side_origin_and_debug_info.first.value() ==
+                        renderer_side_origin);
+
+  // For opaque origins, we say the browser and renderer calculated origins
+  // match if their precursor origins match (their nonces might not match).
+  if (renderer_side_origin.opaque() &&
+      browser_side_origin_and_debug_info.first->opaque()) {
+    origins_match = (renderer_side_origin.GetTupleOrPrecursorTupleIfOpaque() ==
+                     browser_side_origin_and_debug_info.first
+                         ->GetTupleOrPrecursorTupleIfOpaque());
+  }
+
   // TODO(https://crbug.com/888079): Remove the DumpWithoutCrashing below, once
   // we are sure that the `browser_side_origin` is always the same as the
   // `renderer_side_origin`.
-  if (browser_side_origin_and_debug_info.first.value() !=
-      renderer_side_origin) {
+  if (!origins_match) {
     NavigationRequest::ScopedCrashKeys navigation_request_crash_keys(
         *navigation_request);
     SCOPED_CRASH_KEY_STRING256(
@@ -757,13 +765,12 @@
     CaptureTraceForNavigationDebugScenario(
         DebugScenario::kDebugBrowserVsRendererOriginToCommit);
     base::debug::DumpWithoutCrashing();
-    DCHECK(false);
+    DCHECK_EQ(browser_side_origin_and_debug_info.first.value(),
+              renderer_side_origin)
+        << "; navigation_request->GetURL() = " << navigation_request->GetURL();
     return false;
   }
 
-  DCHECK_EQ(browser_side_origin_and_debug_info.first.value(),
-            renderer_side_origin)
-      << "; navigation_request->GetURL() = " << navigation_request->GetURL();
   return true;
 }
 
@@ -8271,17 +8278,6 @@
     return;
   }
 
-  // Container-initiated navigations must come from the same process as the
-  // parent.
-  if (begin_params->is_container_initiated) {
-    if (!GetParent() ||
-        (initiator_process_id != GetParent()->GetProcess()->GetID())) {
-      mojo::ReportBadMessage(
-          "container initiated navigation from non-parent process");
-      return;
-    }
-  }
-
   // If the request is bearing Private State Tokens parameters:
   // - it must not be a main-frame navigation, and
   // - for certain Private State Tokens operations, the frame's parent needs the
@@ -9772,48 +9768,6 @@
          navigation_request->DidEncounterError());
 }
 
-void RenderFrameHostImpl::AddResourceTimingEntryForFailedSubframeNavigation(
-    FrameTreeNode* child_frame,
-    base::TimeTicks start_time,
-    base::TimeTicks redirect_time,
-    const GURL& initial_url,
-    const GURL& final_url,
-    network::mojom::URLResponseHeadPtr response_head,
-    bool allow_response_details,
-    const network::URLLoaderCompletionStatus& completion_status) {
-  uint32_t status_code = 0;
-  std::string mime_type;
-  std::string normalized_server_timing;
-
-  response_head->headers->GetNormalizedHeader("Server-Timing",
-                                              &normalized_server_timing);
-
-  if (allow_response_details) {
-    status_code = response_head->headers->response_code();
-    mime_type = response_head->mime_type;
-  }
-
-  // To avoid cross-origin leaks, make sure to only to pass here data that
-  // is OK when TAO-gated (as in, timing information only).
-
-  absl::optional<blink::FrameToken> child_token_in_parent =
-      child_frame->GetRenderFrameHostManager()
-          .GetFrameTokenForSiteInstanceGroup(GetSiteInstance()->group());
-
-  if (!child_token_in_parent) {
-    return;
-  }
-
-  GetAssociatedLocalFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
-      child_token_in_parent.value(), initial_url, start_time, redirect_time,
-      response_head->request_start, response_head->response_start, status_code,
-      mime_type, response_head->load_timing, response_head->connection_info,
-      response_head->alpn_negotiated_protocol,
-      base::Contains(url::GetSecureSchemes(),
-                     url::Origin::Create(final_url).scheme()),
-      response_head->is_validated, normalized_server_timing, completion_status);
-}
-
 void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
   DCHECK(blink::IsRendererDebugURL(url));
 
@@ -10853,14 +10807,6 @@
   non_associated_local_frame_host_receiver_.Bind(std::move(receiver));
 }
 
-void RenderFrameHostImpl::CreateRuntimeFeatureStateController(
-    mojo::PendingReceiver<blink::mojom::RuntimeFeatureStateController>
-        receiver) {
-  runtime_feature_state_controller_ =
-      std::make_unique<RuntimeFeatureStateControllerImpl>(*this,
-                                                          std::move(receiver));
-}
-
 bool RenderFrameHostImpl::CancelPrerendering(
     const PrerenderCancellationReason& reason) {
   // A prerendered page is identified by its root FrameTreeNode id, so if this
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index d31f4b5..d96faa986 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -273,7 +273,6 @@
 class RenderProcessHost;
 class RenderViewHostImpl;
 class RenderWidgetHostView;
-class RuntimeFeatureStateControllerImpl;
 class ServiceWorkerContainerHost;
 class SiteInfo;
 class SpeechSynthesisImpl;
@@ -1436,16 +1435,6 @@
       const absl::optional<std::string>& error_page_content,
       const blink::DocumentToken& document_token);
 
-  void AddResourceTimingEntryForFailedSubframeNavigation(
-      FrameTreeNode* child_frame,
-      base::TimeTicks start_time,
-      base::TimeTicks redirect_time,
-      const GURL& initial_url,
-      const GURL& final_url,
-      network::mojom::URLResponseHeadPtr response_head,
-      bool allow_response_details,
-      const network::URLLoaderCompletionStatus& completion_status);
-
   // Sends a renderer-debug URL to the renderer process for handling.
   void HandleRendererDebugURL(const GURL& url);
 
@@ -4322,10 +4311,6 @@
   // Hosts blink::mojom::PushMessaging for the RenderFrame.
   std::unique_ptr<PushMessagingManager> push_messaging_manager_;
 
-  // Hosts blink::mojom::RuntimeFeatureStateController for the RenderFrame.
-  std::unique_ptr<RuntimeFeatureStateControllerImpl>
-      runtime_feature_state_controller_;
-
   // Hosts blink::mojom::SpeechSynthesis for the RenderFrame.
   std::unique_ptr<SpeechSynthesisImpl> speech_synthesis_impl_;
 
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 6cc6fb2..3cdadb8 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -38,6 +38,7 @@
 #include "content/browser/renderer_host/input/timeout_monitor.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/runtime_feature_state_controller_impl.h"
 #include "content/browser/sms/test/mock_sms_provider.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/content_navigation_policy.h"
@@ -984,7 +985,8 @@
   // Create a test remote to initiate the IPC.
   mojo::Remote<blink::mojom::RuntimeFeatureStateController>
       runtime_feature_state_controller_remote;
-  web_contents()->GetPrimaryMainFrame()->CreateRuntimeFeatureStateController(
+  RuntimeFeatureStateControllerImpl::Create(
+      web_contents()->GetPrimaryMainFrame(),
       runtime_feature_state_controller_remote.BindNewPipeAndPassReceiver());
   ASSERT_TRUE(runtime_feature_state_controller_remote.is_connected());
 
@@ -1033,7 +1035,8 @@
   // Create a test remote to initiate the IPC.
   mojo::Remote<blink::mojom::RuntimeFeatureStateController>
       runtime_feature_state_controller_remote;
-  web_contents()->GetPrimaryMainFrame()->CreateRuntimeFeatureStateController(
+  RuntimeFeatureStateControllerImpl::Create(
+      web_contents()->GetPrimaryMainFrame(),
       runtime_feature_state_controller_remote.BindNewPipeAndPassReceiver());
   ASSERT_TRUE(runtime_feature_state_controller_remote.is_connected());
 
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc
index 824e7cc..b9ddf05 100644
--- a/content/browser/renderer_host/render_frame_proxy_host.cc
+++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -703,10 +703,7 @@
       params->extra_headers, std::move(blob_url_loader_factory),
       std::move(params->source_location), params->user_gesture,
       params->is_form_submission, params->impression,
-      params->initiator_activation_and_ad_status, navigation_start_time,
-      /*is_embedder_initiated_fenced_frame_navigation=*/false,
-      /*is_unfenced_top_navigation=*/false,
-      /*force_new_browsing_instance=*/false, params->is_container_initiated);
+      params->initiator_activation_and_ad_status, navigation_start_time);
 }
 
 void RenderFrameProxyHost::UpdateViewportIntersection(
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index 9a56bb8b..e649a0fd 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -72,9 +72,10 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/no_destructor.h"
+#include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "mojo/public/cpp/platform/platform_handle_security_util_win.h"
 #include "sandbox/policy/switches.h"
 #endif
 
@@ -1937,7 +1938,7 @@
   process->Cleanup();
 }
 
-class RenderProcessHostWriteableFileDeathTest
+class RenderProcessHostWriteableFileTest
     : public RenderProcessHostTest,
       public ::testing::WithParamInterface<
           std::tuple</*enforcement_enabled=*/bool,
@@ -1958,7 +1959,12 @@
   base::test::ScopedFeatureList enforcement_feature_;
 };
 
-IN_PROC_BROWSER_TEST_P(RenderProcessHostWriteableFileDeathTest,
+// This test verifies that the renderer process is wired up correctly with the
+// mojo invitation flag that indicates that it's untrusted. The other half of
+// this test that verifies that a security violation actually causes a DCHECK
+// lives in mojo/core, and can't live here as death tests are not supported for
+// browser tests.
+IN_PROC_BROWSER_TEST_P(RenderProcessHostWriteableFileTest,
                        PassUnsafeWriteableExecutableFile) {
   // This test only works if DCHECKs are enabled.
 #if !DCHECK_IS_ON()
@@ -1992,41 +1998,29 @@
   base::File temp_file_writeable(file_path, flags);
   ASSERT_TRUE(temp_file_writeable.IsValid());
 
-  static base::NoDestructor<std::string> fatal_log_string;
-  // Note: logging::ScopedLogAssertHandler can't be used here as it does not
-  // capture CHECK.
-  auto old_handler = logging::GetLogMessageHandler();
-  logging::SetLogMessageHandler([](int severity, const char* file, int line,
-                                   size_t message_start,
-                                   const std::string& str) -> bool {
-    if (severity != logging::LOGGING_FATAL) {
-      return false;
-    }
-    *fatal_log_string = str;
-    return true;
-  });
+  bool error_was_called = false;
+  mojo::SetUnsafeFileHandleCallbackForTesting(
+      base::BindLambdaForTesting([&error_was_called]() -> bool {
+        error_was_called = true;
+        return true;
+      }));
 
   base::RunLoop run_loop;
   test_service->PassWriteableFile(std::move(temp_file_writeable),
                                   run_loop.QuitClosure());
   run_loop.Run();
-  logging::SetLogMessageHandler(old_handler);
 
-  // This test should only CHECK if enforcement is enabled and the file has not
-  // been marked no-execute correctly.
-  if (IsEnforcementEnabled() && !ShouldMarkNoExecute()) {
-    EXPECT_TRUE(fatal_log_string->find(
-                    "Transfer of writable handle to executable file to an "
-                    "untrusted process") != fatal_log_string->npos);
-  } else {
-    EXPECT_TRUE(fatal_log_string->empty());
-  }
+  // This test should only detect a violation if enforcement is enabled and the
+  // file has not been marked no-execute correctly.
+  bool should_violation_occur =
+      IsEnforcementEnabled() && !ShouldMarkNoExecute();
+  EXPECT_EQ(should_violation_occur, error_was_called);
 #endif  // DCHECK_IS_ON()
 }
 
 INSTANTIATE_TEST_SUITE_P(
     All,
-    RenderProcessHostWriteableFileDeathTest,
+    RenderProcessHostWriteableFileTest,
     testing::Combine(/*enforcement_enabled=*/testing::Bool(),
                      /*add_no_execute_flags=*/testing::Bool()));
 
diff --git a/content/browser/renderer_host/runtime_feature_state_controller_impl.cc b/content/browser/renderer_host/runtime_feature_state_controller_impl.cc
index c980312..dbdb77ee 100644
--- a/content/browser/renderer_host/runtime_feature_state_controller_impl.cc
+++ b/content/browser/renderer_host/runtime_feature_state_controller_impl.cc
@@ -19,11 +19,22 @@
 RuntimeFeatureStateControllerImpl::RuntimeFeatureStateControllerImpl(
     RenderFrameHost& host,
     mojo::PendingReceiver<blink::mojom::RuntimeFeatureStateController> receiver)
-    : receiver_(this, std::move(receiver)), render_frame_host_(host) {}
+    : DocumentService(host, std::move(receiver)) {}
 
 RuntimeFeatureStateControllerImpl::~RuntimeFeatureStateControllerImpl() =
     default;
 
+// static
+void RuntimeFeatureStateControllerImpl::Create(
+    RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::RuntimeFeatureStateController>
+        receiver) {
+  CHECK(host);
+  // The object is bound to the lifetime of `render_frame_host` and the mojo
+  // connection. See DocumentService for details.
+  new RuntimeFeatureStateControllerImpl(*host, std::move(receiver));
+}
+
 void RuntimeFeatureStateControllerImpl::ApplyFeatureDiffForOriginTrial(
     base::flat_map<::blink::mojom::RuntimeFeatureState,
                    ::blink::mojom::FeatureValuePtr> modified_features) {
@@ -39,7 +50,7 @@
     bool are_tokens_valid = true;
     for (const auto& token : feature_pair.second->tokens) {
       blink::TrialTokenResult result = validator.ValidateTokenAndTrial(
-          token, render_frame_host_->GetLastCommittedOrigin(),
+          token, render_frame_host().GetLastCommittedOrigin(),
           base::Time::Now());
       if (result.Status() != blink::OriginTrialTokenStatus::kSuccess) {
         are_tokens_valid = false;
@@ -69,15 +80,16 @@
       } else {
         // The renderer is compromised so we terminate it.
         bad_message::ReceivedBadMessage(
-            render_frame_host_->GetProcess(),
+            render_frame_host().GetProcess(),
             bad_message::RFSCI_BROWSER_VALIDATION_BAD_ORIGIN_TRIAL_TOKEN);
+        return;
       }
     }
   }
   // Apply the diff changes to the mutable RuntimeFeatureStateReadContext.
   RuntimeFeatureStateDocumentData* document_data =
       RuntimeFeatureStateDocumentData::GetForCurrentDocument(
-          &*render_frame_host_);
+          &render_frame_host());
   document_data
       ->GetMutableRuntimeFeatureStateReadContext(
           base::PassKey<RuntimeFeatureStateControllerImpl>())
@@ -88,7 +100,8 @@
     const std::string& token,
     const std::vector<url::Origin>& script_origins) {
   OriginTrialsControllerDelegate* delegate =
-      render_frame_host_->GetBrowserContext()
+      render_frame_host()
+          .GetBrowserContext()
           ->GetOriginTrialsControllerDelegate();
   if (!delegate) {
     return;
@@ -98,9 +111,9 @@
   // provided token.
   std::vector<std::string> tokens = {token};
   delegate->PersistAdditionalTrialsFromTokens(
-      /*origin=*/render_frame_host_->GetLastCommittedOrigin(),
+      /*origin=*/render_frame_host().GetLastCommittedOrigin(),
       /*partition_origin=*/
-      render_frame_host_->GetOutermostMainFrame()->GetLastCommittedOrigin(),
+      render_frame_host().GetOutermostMainFrame()->GetLastCommittedOrigin(),
       script_origins, tokens, base::Time::Now());
 }
 
diff --git a/content/browser/renderer_host/runtime_feature_state_controller_impl.h b/content/browser/renderer_host/runtime_feature_state_controller_impl.h
index ecf36b2c..e4df702 100644
--- a/content/browser/renderer_host/runtime_feature_state_controller_impl.h
+++ b/content/browser/renderer_host/runtime_feature_state_controller_impl.h
@@ -7,6 +7,7 @@
 
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/runtime_feature_state/runtime_feature_state_document_data.h"
+#include "content/public/browser/document_service.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h"
@@ -22,25 +23,19 @@
 // features that are enabled dynamically, most commonly from Origin Trials.
 // The class will perform security checks before updating a RenderFrameHost's
 // RuntimeFeatureStateReadContext with the validated feature state we receive.
-// It will also accept persistent origin trial tokens provided through meta
-// http-equiv tags, and will add them to the set of tokens for the owning
-// origin.
-//
-// An instance of this class is owned by the RenderFrameHostImpl. It is
-// instantiated on-demand via the BrowserInterfaceBroker once the renderer
-// creates and binds a remote instance.
-class RuntimeFeatureStateControllerImpl
-    : public blink::mojom::RuntimeFeatureStateController {
+class CONTENT_EXPORT RuntimeFeatureStateControllerImpl
+    : public DocumentService<blink::mojom::RuntimeFeatureStateController> {
  public:
-  // Constructor takes both the RenderFrameHost and the receiver. The document
-  // data may be altered by a future IPC call.
-  explicit RuntimeFeatureStateControllerImpl(
-      RenderFrameHost& host,
+  RuntimeFeatureStateControllerImpl(const RuntimeFeatureStateControllerImpl&) =
+      delete;
+  RuntimeFeatureStateControllerImpl& operator=(
+      const RuntimeFeatureStateControllerImpl&) = delete;
+
+  static void Create(
+      RenderFrameHost* render_frame_host,
       mojo::PendingReceiver<blink::mojom::RuntimeFeatureStateController>
           receiver);
 
-  ~RuntimeFeatureStateControllerImpl() override;
-
   // mojom::RuntimeFeatureStateController methods
   void ApplyFeatureDiffForOriginTrial(
       base::flat_map<::blink::mojom::RuntimeFeatureState,
@@ -51,8 +46,13 @@
       const std::vector<url::Origin>& script_origins) override;
 
  private:
-  mojo::Receiver<blink::mojom::RuntimeFeatureStateController> receiver_;
-  raw_ref<RenderFrameHost> render_frame_host_;
+  explicit RuntimeFeatureStateControllerImpl(
+      RenderFrameHost& host,
+      mojo::PendingReceiver<blink::mojom::RuntimeFeatureStateController>
+          receiver);
+
+  // `this` can only be destructed as a DocumentService.
+  ~RuntimeFeatureStateControllerImpl() override;
 };
 
 }  // namespace content
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 15e819d1..e8d9a9c4 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -1538,8 +1538,7 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation,
-          false /* is_container_initiated */);
+              kDidNotStartWithTransientActivation);
 
   // Receiving the invalid IPC message should lead to renderer process
   // termination.
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 4fbba74..d2f7102 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -17,7 +17,6 @@
 import "skia/public/mojom/skcolor.mojom";
 import "services/network/public/mojom/content_security_policy.mojom";
 import "services/network/public/mojom/url_loader.mojom";
-import "services/network/public/mojom/url_loader_completion_status.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/network/public/mojom/url_request.mojom";
 import "services/network/public/mojom/url_response_head.mojom";
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index f648ddf..f8191976 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
 #include "third_party/blink/public/mojom/frame/media_player_action.mojom.h"
 #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
+#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
 
 #if BUILDFLAG(IS_MAC)
 #include "ui/base/mojom/attributed_string.mojom.h"
@@ -78,6 +79,15 @@
     const std::vector<blink::mojom::WebFeature>&) {}
 
 void FakeLocalFrame::RenderFallbackContent() {}
+
+void FakeLocalFrame::AddResourceTimingEntryFromNonNavigatedFrame(
+    blink::mojom::ResourceTimingInfoPtr timing,
+    blink::FrameOwnerElementType parent_frame_element_type) {}
+
+void FakeLocalFrame::RenderFallbackContentWithResourceTiming(
+    blink::mojom::ResourceTimingInfoPtr,
+    const std::string& server_timing_value) {}
+
 void FakeLocalFrame::BeforeUnload(bool is_reload,
                                   BeforeUnloadCallback callback) {
   base::TimeTicks now = base::TimeTicks::Now();
@@ -194,23 +204,6 @@
 void FakeLocalFrame::SnapshotDocumentForViewTransition(
     SnapshotDocumentForViewTransitionCallback callback) {}
 
-void FakeLocalFrame::AddResourceTimingEntryForFailedSubframeNavigation(
-    const ::blink::FrameToken& subframe_token,
-    const GURL& initial_url,
-    ::base::TimeTicks start_time,
-    ::base::TimeTicks redirect_time,
-    ::base::TimeTicks request_start,
-    ::base::TimeTicks response_start,
-    uint32_t response_code,
-    const std::string& mime_type,
-    const ::net::LoadTimingInfo& load_timing_info,
-    ::net::HttpResponseInfo::ConnectionInfo connection_info,
-    const std::string& alpn_negotiated_protocol,
-    bool is_secure_transport,
-    bool is_validated,
-    const std::string& normalized_server_timing,
-    const ::network::URLLoaderCompletionStatus& completion_status) {}
-
 void FakeLocalFrame::BindFrameHostReceiver(
     mojo::ScopedInterfaceEndpointHandle handle) {
   receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index 8930e12..e732e63 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -8,8 +8,6 @@
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "net/http/http_response_info.h"
-#include "services/network/public/mojom/load_timing_info.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
@@ -67,6 +65,12 @@
   void ReportBlinkFeatureUsage(
       const std::vector<blink::mojom::WebFeature>&) override;
   void RenderFallbackContent() override;
+  void AddResourceTimingEntryFromNonNavigatedFrame(
+      blink::mojom::ResourceTimingInfoPtr timing,
+      blink::FrameOwnerElementType parent_frame_element_type) override;
+  void RenderFallbackContentWithResourceTiming(
+      blink::mojom::ResourceTimingInfoPtr,
+      const std::string& server_timing_value) override;
   void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) override;
   void MediaPlayerActionAt(const gfx::Point& location,
                            blink::mojom::MediaPlayerActionPtr action) override;
@@ -146,22 +150,6 @@
                          blink::mojom::TraverseCancelledReason reason) override;
   void SnapshotDocumentForViewTransition(
       SnapshotDocumentForViewTransitionCallback callback) override;
-  void AddResourceTimingEntryForFailedSubframeNavigation(
-      const ::blink::FrameToken& subframe_token,
-      const GURL& initial_url,
-      base::TimeTicks start_time,
-      base::TimeTicks redirect_time,
-      base::TimeTicks request_start,
-      base::TimeTicks response_start,
-      uint32_t response_code,
-      const std::string& mime_type,
-      const net::LoadTimingInfo& load_timing_info,
-      net::HttpResponseInfo::ConnectionInfo connection_info,
-      const std::string& alpn_negotiated_protocol,
-      bool is_secure_transport,
-      bool is_validated,
-      const std::string& normalized_server_timing,
-      const ::network::URLLoaderCompletionStatus& completion_status) override;
 
  private:
   void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/content/public/test/fake_remote_frame.cc b/content/public/test/fake_remote_frame.cc
index 04d8a077..9492218 100644
--- a/content/public/test/fake_remote_frame.cc
+++ b/content/public/test/fake_remote_frame.cc
@@ -63,6 +63,10 @@
 
 void FakeRemoteFrame::RenderFallbackContent() {}
 
+void FakeRemoteFrame::RenderFallbackContentWithResourceTiming(
+    blink::mojom::ResourceTimingInfoPtr,
+    const std::string& server_timing_value) {}
+
 void FakeRemoteFrame::AddResourceTimingFromChild(
     blink::mojom::ResourceTimingInfoPtr timing) {}
 
diff --git a/content/public/test/fake_remote_frame.h b/content/public/test/fake_remote_frame.h
index 1521517b..e8174cd2 100644
--- a/content/public/test/fake_remote_frame.h
+++ b/content/public/test/fake_remote_frame.h
@@ -64,6 +64,9 @@
       const base::UnguessableToken& embedding_token) override;
   void SetPageFocus(bool is_focused) override;
   void RenderFallbackContent() override;
+  void RenderFallbackContentWithResourceTiming(
+      blink::mojom::ResourceTimingInfoPtr,
+      const std::string& server_timing_value) override;
   void AddResourceTimingFromChild(
       blink::mojom::ResourceTimingInfoPtr timing) override;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 24fced83..0569890 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -944,8 +944,6 @@
       browser_navigation_timings.fetch_start;
 
   renderer_navigation_timings.input_start = input_start;
-  renderer_navigation_timings.parent_resource_timing_access =
-      browser_navigation_timings.parent_resource_timing_access;
 
   return renderer_navigation_timings;
 }
@@ -5759,7 +5757,7 @@
               : nullptr,
           info->impression, renderer_before_unload_start,
           renderer_before_unload_end, web_bundle_token_params,
-          initiator_activation_and_ad_status, info->is_container_initiated);
+          initiator_activation_and_ad_status);
 
   mojo::PendingAssociatedRemote<mojom::NavigationClient>
       navigation_client_remote;
diff --git a/content/test/content_unittests_bundle_data.filelist b/content/test/content_unittests_bundle_data.filelist
index 6943b774..65058f6 100644
--- a/content/test/content_unittests_bundle_data.filelist
+++ b/content/test/content_unittests_bundle_data.filelist
@@ -71,6 +71,7 @@
 //content/test/data/attribution_reporting/interop/event_level_trigger_priority.json
 //content/test/data/attribution_reporting/interop/event_report_window.json
 //content/test/data/attribution_reporting/interop/event_source.json
+//content/test/data/attribution_reporting/interop/event_source_trigger_priority.json
 //content/test/data/attribution_reporting/interop/expired_source.json
 //content/test/data/attribution_reporting/interop/most_recent_source.json
 //content/test/data/attribution_reporting/interop/rate_limit_max_attribution_reporting_endpoints.json
diff --git a/content/test/data/accessibility/html/custom-element-hidden-expected-blink.txt b/content/test/data/accessibility/html/custom-element-hidden-expected-blink.txt
index 9db06e2..f2f68f3 100644
--- a/content/test/data/accessibility/html/custom-element-hidden-expected-blink.txt
+++ b/content/test/data/accessibility/html/custom-element-hidden-expected-blink.txt
@@ -5,4 +5,7 @@
 ++++++genericContainer ignored invisible htmlTag='div'
 ++++++++genericContainer ignored invisible htmlTag='my-element'
 ++++++++++genericContainer ignored invisible htmlTag='div'
-++++++button htmlTag='button' name='Done'
+++++++++++++genericContainer ignored invisible htmlTag='slot'
+++++++++++++++genericContainer ignored invisible htmlTag='span'
+++++++++++++++++staticText ignored invisible name='Slot contents'
+++++++button htmlTag='button' name='Done'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/meter-expected-blink.txt b/content/test/data/accessibility/html/meter-expected-blink.txt
index 3396f991..6c2d34a 100644
--- a/content/test/data/accessibility/html/meter-expected-blink.txt
+++ b/content/test/data/accessibility/html/meter-expected-blink.txt
@@ -6,3 +6,5 @@
 ++++++++++genericContainer
 ++++++++++++genericContainer ignored
 ++++++++genericContainer ignored invisible
+++++++++++genericContainer ignored invisible
+++++++++++++staticText ignored invisible name='2 out of 10'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/popover-api-expected-blink.txt b/content/test/data/accessibility/html/popover-api-expected-blink.txt
index 483f1769..cc9bd623 100644
--- a/content/test/data/accessibility/html/popover-api-expected-blink.txt
+++ b/content/test/data/accessibility/html/popover-api-expected-blink.txt
@@ -10,6 +10,9 @@
 ++++++++genericContainer ignored invisible
 ++++++++++staticText ignored invisible name='Listbox role on ul'
 ++++++details ignored invisible
+++++++++genericContainer ignored invisible
+++++++++++disclosureTriangle ignored invisible
+++++++++++++staticText ignored invisible name='summary/details popover'
 ++++++button collapsed name='Button pointing to hidden popover'
 ++++++++staticText name='Button pointing to hidden popover'
 ++++++++++inlineTextBox name='Button pointing to hidden popover'
diff --git a/content/test/data/accessibility/html/selectmenu-expected-blink.txt b/content/test/data/accessibility/html/selectmenu-expected-blink.txt
index 065b897e..e542bb4 100644
--- a/content/test/data/accessibility/html/selectmenu-expected-blink.txt
+++ b/content/test/data/accessibility/html/selectmenu-expected-blink.txt
@@ -12,10 +12,14 @@
 ++++++++++++++genericContainer ignored
 ++++++++genericContainer ignored
 ++++++++++listBox ignored invisible
+++++++++++++genericContainer ignored invisible
+++++++++++++++listBoxOption focusable ignored invisible
+++++++++++++++listBoxOption focusable ignored invisible
+++++++++++++++listBoxOption focusable ignored invisible
 ++++++genericContainer
 ++++++++genericContainer ignored
 ++++++++++comboBoxMenuButton collapsed value='Option 1' haspopup=listbox
 ++++++++++++staticText name='Custom selectmenu button'
 ++++++++++++++inlineTextBox name='Custom selectmenu button'
 ++++++++genericContainer ignored
-++++++++++listBox ignored invisible
+++++++++++listBox ignored invisible
\ No newline at end of file
diff --git a/content/test/data/accessibility/regression/title-in-shadow-expected-blink.txt b/content/test/data/accessibility/regression/title-in-shadow-expected-blink.txt
index 099b17be..fd7f44e4 100644
--- a/content/test/data/accessibility/regression/title-in-shadow-expected-blink.txt
+++ b/content/test/data/accessibility/regression/title-in-shadow-expected-blink.txt
@@ -6,3 +6,4 @@
 ++++++++++genericContainer
 ++++++++++++genericContainer ignored
 ++++++++genericContainer ignored invisible
+++++++++++genericContainer ignored invisible
\ No newline at end of file
diff --git a/content/test/data/attribution_reporting/interop/aggregatable_contributions_creation.json b/content/test/data/attribution_reporting/interop/aggregatable_contributions_creation.json
index cce2ec7..1a5a331 100644
--- a/content/test/data/attribution_reporting/interop/aggregatable_contributions_creation.json
+++ b/content/test/data/attribution_reporting/interop/aggregatable_contributions_creation.json
@@ -18,7 +18,8 @@
               "aggregation_keys": {
                 "a": "0x1",
                 "b": "0x2",
-                "c": "0x4"
+                "c": "0x4",
+                "A": "0xffffffffffffffffffffffffffffffff"
               },
               "filter_data": {
                 "product": ["123", "456"],
@@ -66,11 +67,16 @@
                     "source_type": ["navigation"],
                     "campaign": ["example"]
                   }
+                },
+                {
+                  "source_keys": ["A"],
+                  "key_piece": "0xffffffffffffffffffffffffffffffff"
                 }
               ],
               "aggregatable_values": {
                 "a": 123,
-                "b": 456
+                "b": 456,
+                "A": 999
               }
             }
           }
@@ -213,6 +219,26 @@
             }
           }
         }]
+      },
+      // Should result in an aggregatable report with the key pieces defined in
+      // the source.
+      {
+        "timestamp": "1643235579000",
+        "registration_request": {
+          "attribution_src_url": "https://reporter.test/register-trigger",
+          "destination_origin": "https://destination.test"
+        },
+        "responses": [{
+          "url": "https://reporter.test/register-trigger",
+          "response": {
+            "Attribution-Reporting-Register-Trigger": {
+              "aggregatable_values": {
+                "a": 666,
+                "A": 333
+              }
+            }
+          }
+        }]
       }
     ]
   },
@@ -223,6 +249,10 @@
           "attribution_destination": "https://destination.test",
           "histograms": [
             {
+              "key": "0xffffffffffffffffffffffffffffffff",
+              "value": 999
+            },
+            {
               "key": "0x11",
               "value": 123
             },
@@ -268,6 +298,20 @@
         },
         "report_url": "https://reporter.test/.well-known/attribution-reporting/report-aggregate-attribution",
         "report_time": "1643239176000"
+      },
+      {
+        "payload": {
+          "attribution_destination": "https://destination.test",
+          "histograms": [ {
+             "key": "0xffffffffffffffffffffffffffffffff",
+             "value": 333
+          }, {
+             "key": "0x1",
+             "value": 666
+          } ]
+       },
+       "report_time": "1643239179000",
+       "report_url": "https://reporter.test/.well-known/attribution-reporting/report-aggregate-attribution"
       }
     ],
     "verbose_debug_reports": [
diff --git a/content/test/data/attribution_reporting/interop/event_source_trigger_priority.json b/content/test/data/attribution_reporting/interop/event_source_trigger_priority.json
new file mode 100644
index 0000000..bde0ccd
--- /dev/null
+++ b/content/test/data/attribution_reporting/interop/event_source_trigger_priority.json
@@ -0,0 +1,121 @@
+{
+  "description": "Trigger priority for event sources",
+  "input": {
+    "sources": [
+      {
+        "timestamp": "1643235573000",
+        "registration_request": {
+          "source_origin": "https://source.test",
+          "attribution_src_url": "https://reporter.test/register-source",
+          "source_type": "event"
+        },
+        "responses": [{
+          "url": "https://reporter.test/register-source",
+          "response": {
+            "Attribution-Reporting-Register-Source": {
+              "destination": "https://destination.test",
+              "source_event_id": "123"
+            }
+          }
+        }]
+      }
+    ],
+    "triggers": [
+      {
+        "timestamp": "1643235574000",
+        "registration_request": {
+          "attribution_src_url": "https://reporter.test/register-trigger",
+          "destination_origin": "https://destination.test"
+        },
+        "responses": [{
+          "url": "https://reporter.test/register-trigger",
+          "response": {
+            "Attribution-Reporting-Register-Trigger": {
+              "event_trigger_data": [
+                {
+                  "trigger_data": "0",
+                  "priority": "-1"
+                }
+              ]
+            }
+          }
+        }]
+      },
+      // Will replace the first report as its priority is higher.
+      {
+        "timestamp": "1643235575000",
+        "registration_request": {
+          "attribution_src_url": "https://reporter.test/register-trigger",
+          "destination_origin": "https://destination.test"
+        },
+        "responses": [{
+          "url": "https://reporter.test/register-trigger",
+          "response": {
+            "Attribution-Reporting-Register-Trigger": {
+              "event_trigger_data": [
+                {
+                  "trigger_data": "1"
+                }
+              ]
+            }
+          }
+        }]
+      },
+      // Will not replace the second report as its priority is not higher.
+      {
+        "timestamp": "1643235576000",
+        "registration_request": {
+          "attribution_src_url": "https://reporter.test/register-trigger",
+          "destination_origin": "https://destination.test"
+        },
+        "responses": [{
+          "url": "https://reporter.test/register-trigger",
+          "debug_permission": true,
+          "response": {
+            "Attribution-Reporting-Register-Trigger": {
+              "event_trigger_data": [
+                {
+                  "trigger_data": "0"
+                }
+              ],
+              "debug_reporting": true
+            }
+          }
+        }]
+      }
+    ]
+  },
+  "output": {
+    "event_level_results": [
+      {
+        "payload": {
+          "attribution_destination": "https://destination.test",
+          "randomized_trigger_rate": 0.0000025,
+          "scheduled_report_time": "1645831173",
+          "source_event_id": "123",
+          "source_type": "event",
+          "trigger_data": "1"
+        },
+        "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution",
+        "report_time": "1645831173000"
+      }
+    ],
+    "verbose_debug_reports": [
+      {
+        "payload": [ {
+          "body": {
+             "attribution_destination": "https://destination.test",
+             "randomized_trigger_rate": 0.0000025,
+             "scheduled_report_time": "1645831173",
+             "source_event_id": "123",
+             "source_type": "event",
+             "trigger_data": "0"
+          },
+          "type": "trigger-event-low-priority"
+       } ],
+       "report_time": "1643235576000",
+       "report_url": "https://reporter.test/.well-known/attribution-reporting/debug/verbose"
+      }
+    ]
+  }
+}
diff --git a/content/test/gpu/gpu_tests/context_lost_integration_test.py b/content/test/gpu/gpu_tests/context_lost_integration_test.py
index b4e889b..9b228ed 100644
--- a/content/test/gpu/gpu_tests/context_lost_integration_test.py
+++ b/content/test/gpu/gpu_tests/context_lost_integration_test.py
@@ -162,6 +162,8 @@
               'webgl.html?query=kill_after_notification'),
              ('ContextLost_WebGLContextLostOverlyLargeUniform',
               'webgl-overly-large-uniform.html'),
+             ('ContextLost_WebGLContextRestoredInHiddenTab',
+              'webgl.html?query=kill_after_notification'),
              ('ContextLost_WebGLBlockedAfterJSNavigation',
               'webgl-domain-blocking-page1.html'),
              ('ContextLost_WebGLUnblockedAfterUserInitiatedReload',
@@ -417,6 +419,33 @@
     # No reason to wait more than 10 seconds for this test to complete.
     self._WaitForTabAndCheckCompletion(timeout=10)
 
+  def _ContextLost_WebGLContextRestoredInHiddenTab(self, test_path: str
+                                                   ) -> None:
+    self.RestartBrowserIfNecessaryWithArgs([])
+    self._NavigateAndWaitForLoad(test_path)
+    tab = self.tab
+    if not tab.browser.supports_tab_control:
+      self.fail('Browser must support tab control')
+    # Make sure the tab got a WebGL context.
+    if tab.EvaluateJavaScript('window.domAutomationController._finished'):
+      # This means the test failed for some reason.
+      if tab.EvaluateJavaScript('window.domAutomationController._succeeded'):
+        self.fail('Initial page claimed to succeed early')
+      else:
+        self.fail('Initial page failed to get a WebGL context')
+    # Open a new tab occluding the one containing the WebGL context.
+    blank_tab = tab.browser.tabs.New()
+    blank_tab.Activate()
+    # Wait for 2 seconds so that the new tab becomes visible.
+    blank_tab.action_runner.Wait(2)
+    # Kill the GPU process.
+    tab.EvaluateJavaScript('chrome.gpuBenchmarking.crashGpuProcess()')
+    # Wait for the WebGL context to be restored and for the test to complete.
+    # This will fail cooperatively if the context wasn't restored properly, and
+    # will time out (and fail) if the context wasn't restored at all.
+    self._WaitForTabAndCheckCompletion(timeout=10)
+    self._RestartBrowser('must restart after tests that kill the GPU process')
+
   def _ContextLost_WebGLBlockedAfterJSNavigation(self, test_path: str) -> None:
     self.RestartBrowserIfNecessaryWithArgs([])
     self._NavigateAndWaitForLoad(test_path)
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index 56a2888..5be0119 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -84,6 +84,7 @@
 
 # Fuchsia cannot launch a new tab.
 [ fuchsia ] ContextLost_WebGLContextLostInHiddenTab [ Skip ]
+[ fuchsia ] ContextLost_WebGLContextRestoredInHiddenTab [ Skip ]
 
 # Webgpu not fully supported on Linux, Android, ChromeOS, and Fuchsia
 [ linux ] ContextLost_WebGPUContextLostFromGPUProcessExit [ Skip ]
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index d4e0576..69de66c 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -1323,8 +1323,7 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation,
-          false /* is_container_initiated */);
+              kDidNotStartWithTransientActivation);
   auto common_params = blink::CreateCommonNavigationParams();
   common_params->navigation_start = base::TimeTicks::Now();
   common_params->input_start = navigation_input_start_;
@@ -1532,20 +1531,21 @@
   params->method = request_ ? request_->common_params().method : "GET";
 
   if (failed_navigation) {
-    // Note: Error pages must commit in a unique origin. So it is left unset.
     params->url_is_unreachable = true;
+  } else if (same_document) {
+    params->should_update_history = true;
   } else {
-    if (same_document) {
-      params->origin = current_rfh->GetLastCommittedOrigin();
-      params->should_update_history = true;
-    } else {
-      // This mirrors the calculation in
-      // RenderFrameImpl::MakeDidCommitProvisionalLoadParams.
-      // TODO(https://crbug.com/1158101): Reconsider how we calculate
-      // should_update_history.
-      params->should_update_history = response_headers_->response_code() != 404;
-      params->origin = origin_.value_or(request_->GetOriginToCommit().value());
-    }
+    // TODO(https://crbug.com/1158101): Reconsider how we calculate
+    // should_update_history.
+    params->should_update_history = response_headers_->response_code() != 404;
+  }
+
+  // This mirrors the calculation in
+  // RenderFrameImpl::MakeDidCommitProvisionalLoadParams.
+  if (same_document) {
+    params->origin = current_rfh->GetLastCommittedOrigin();
+  } else {
+    params->origin = origin_.value_or(request_->GetOriginToCommit().value());
   }
 
   if (same_document) {
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 3cdfea02..0491d69 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -419,8 +419,7 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation,
-          false /* is_container_initiated */);
+              kDidNotStartWithTransientActivation);
   auto common_params = blink::CreateCommonNavigationParams();
   common_params->url = url;
   common_params->initiator_origin = GetLastCommittedOrigin();
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
index 8f97fba..9205714 100644
--- a/device/bluetooth/bluetooth_adapter_mac.h
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -205,10 +205,6 @@
       DiscoverySessionResultCallback callback) override;
   void StopScan(DiscoverySessionResultCallback callback) override;
 
-  // Start classic and/or low energy discovery sessions, according to the
-  // filter.  If a discovery session is already running the filter is updated.
-  bool StartDiscovery(BluetoothDiscoveryFilter* discovery_filter);
-
   void Initialize(base::OnceClosure callback) override;
   void InitForTest(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   void PollAdapter();
@@ -229,10 +225,6 @@
   // Updates |devices_| when there is a change to the CBCentralManager's state.
   void LowEnergyCentralManagerUpdatedState();
 
-  // Updates |advertisements_| when there is a change to the
-  // CBPeripheralManager's state.
-  void LowEnergyPeripheralManagerUpdatedState();
-
   // Updates |devices_| to include the currently paired devices and notifies
   // observers.
   void AddPairedDevices();
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index 0c4121f1..605bf70 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -536,31 +536,6 @@
                           UMABluetoothDiscoverySessionOutcome::SUCCESS);
 }
 
-bool BluetoothAdapterMac::StartDiscovery(
-    BluetoothDiscoveryFilter* discovery_filter) {
-  // Default to dual discovery if |discovery_filter| is NULL.  IOBluetooth seems
-  // allow starting low energy and classic discovery at once.
-  BluetoothTransport transport = BLUETOOTH_TRANSPORT_DUAL;
-  if (discovery_filter)
-    transport = discovery_filter->GetTransport();
-
-  if ((transport & BLUETOOTH_TRANSPORT_CLASSIC) &&
-      !classic_discovery_manager_->IsDiscovering()) {
-    // TODO(krstnmnlsn): If a classic discovery session is already running then
-    // we should update its filter. crbug.com/498056
-    if (!classic_discovery_manager_->StartDiscovery()) {
-      DVLOG(1) << "Failed to add a classic discovery session";
-      return false;
-    }
-  }
-  if (transport & BLUETOOTH_TRANSPORT_LE) {
-    // Begin a low energy discovery session or update it if one is already
-    // running.
-    low_energy_discovery_manager_->StartDiscovery(BluetoothDevice::UUIDList());
-  }
-  return true;
-}
-
 void BluetoothAdapterMac::Initialize(base::OnceClosure callback) {
   // Real initialization is deferred to LazyInitialize().
   ui_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
diff --git a/extensions/browser/api/declarative_net_request/global_rules_tracker.cc b/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
index 563a8cddd..f8ca439 100644
--- a/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
+++ b/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
@@ -22,14 +22,14 @@
 size_t CalculateAllocatedGlobalRuleCount(
     const ExtensionPrefs* extension_prefs,
     const ExtensionRegistry* extension_registry) {
-  std::unique_ptr<ExtensionSet> installed_extensions =
+  const ExtensionSet installed_extensions =
       extension_registry->GenerateInstalledExtensionsSet();
 
   // For each extension, fetch its allocated rules count and add it to
   // |allocated_global_rule_count_|.
   size_t allocated_rule_count;
   size_t allocated_global_rule_count = 0;
-  for (const auto& extension : *installed_extensions) {
+  for (const auto& extension : installed_extensions) {
     if (extension_prefs->GetDNRAllocatedGlobalRuleCount(
             extension->id(), &allocated_rule_count)) {
       allocated_global_rule_count += allocated_rule_count;
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc
index 3128c43b..e7e05cc2 100644
--- a/extensions/browser/extension_protocols.cc
+++ b/extensions/browser/extension_protocols.cc
@@ -606,7 +606,7 @@
     const std::string extension_id = request_.url.host();
     ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
     scoped_refptr<const Extension> extension =
-        registry->GenerateInstalledExtensionsSet()->GetByIDorGUID(extension_id);
+        registry->GenerateInstalledExtensionsSet().GetByIDorGUID(extension_id);
     const ExtensionSet& enabled_extensions = registry->enabled_extensions();
     const ProcessMap* process_map = ProcessMap::Get(browser_context_);
     bool incognito_enabled =
diff --git a/extensions/browser/extension_registry.cc b/extensions/browser/extension_registry.cc
index f142a403..c3197eb 100644
--- a/extensions/browser/extension_registry.cc
+++ b/extensions/browser/extension_registry.cc
@@ -20,24 +20,23 @@
   return ExtensionRegistryFactory::GetForBrowserContext(context);
 }
 
-std::unique_ptr<ExtensionSet>
-ExtensionRegistry::GenerateInstalledExtensionsSet() const {
+ExtensionSet ExtensionRegistry::GenerateInstalledExtensionsSet() const {
   return GenerateInstalledExtensionsSet(EVERYTHING);
 }
 
-std::unique_ptr<ExtensionSet> ExtensionRegistry::GenerateInstalledExtensionsSet(
+ExtensionSet ExtensionRegistry::GenerateInstalledExtensionsSet(
     int include_mask) const {
-  std::unique_ptr<ExtensionSet> installed_extensions(new ExtensionSet);
+  ExtensionSet installed_extensions;
   if (include_mask & IncludeFlag::ENABLED)
-    installed_extensions->InsertAll(enabled_extensions_);
+    installed_extensions.InsertAll(enabled_extensions_);
   if (include_mask & IncludeFlag::DISABLED)
-    installed_extensions->InsertAll(disabled_extensions_);
+    installed_extensions.InsertAll(disabled_extensions_);
   if (include_mask & IncludeFlag::TERMINATED)
-    installed_extensions->InsertAll(terminated_extensions_);
+    installed_extensions.InsertAll(terminated_extensions_);
   if (include_mask & IncludeFlag::BLOCKLISTED)
-    installed_extensions->InsertAll(blocklisted_extensions_);
+    installed_extensions.InsertAll(blocklisted_extensions_);
   if (include_mask & IncludeFlag::BLOCKED)
-    installed_extensions->InsertAll(blocked_extensions_);
+    installed_extensions.InsertAll(blocked_extensions_);
   return installed_extensions;
 }
 
@@ -85,7 +84,7 @@
                                                  const std::string& old_name) {
   CHECK(extension);
   DCHECK_EQ(is_update,
-            GenerateInstalledExtensionsSet()->Contains(extension->id()));
+            GenerateInstalledExtensionsSet().Contains(extension->id()));
   DCHECK_EQ(is_update, !old_name.empty());
   for (auto& observer : observers_)
     observer.OnExtensionWillBeInstalled(browser_context_, extension, is_update,
@@ -95,7 +94,7 @@
 void ExtensionRegistry::TriggerOnInstalled(const Extension* extension,
                                            bool is_update) {
   CHECK(extension);
-  DCHECK(GenerateInstalledExtensionsSet()->Contains(extension->id()));
+  DCHECK(GenerateInstalledExtensionsSet().Contains(extension->id()));
   for (auto& observer : observers_)
     observer.OnExtensionInstalled(browser_context_, extension, is_update);
 }
@@ -103,7 +102,7 @@
 void ExtensionRegistry::TriggerOnUninstalled(const Extension* extension,
                                              UninstallReason reason) {
   CHECK(extension);
-  DCHECK(!GenerateInstalledExtensionsSet()->Contains(extension->id()));
+  DCHECK(!GenerateInstalledExtensionsSet().Contains(extension->id()));
   for (auto& observer : observers_)
     observer.OnExtensionUninstalled(browser_context_, extension, reason);
 }
@@ -111,7 +110,7 @@
 void ExtensionRegistry::TriggerOnUninstallationDenied(
     const Extension* extension) {
   CHECK(extension);
-  DCHECK(GenerateInstalledExtensionsSet()->Contains(extension->id()));
+  DCHECK(GenerateInstalledExtensionsSet().Contains(extension->id()));
   for (auto& observer : observers_)
     observer.OnExtensionUninstallationDenied(browser_context_, extension);
 }
diff --git a/extensions/browser/extension_registry.h b/extensions/browser/extension_registry.h
index 15e8f2b..f4e3cdf 100644
--- a/extensions/browser/extension_registry.h
+++ b/extensions/browser/extension_registry.h
@@ -79,7 +79,7 @@
 
   // Returns the set of all installed extensions, regardless of state (enabled,
   // disabled, etc). Equivalent to GenerateInstalledExtensionSet(EVERYTHING).
-  std::unique_ptr<ExtensionSet> GenerateInstalledExtensionsSet() const;
+  ExtensionSet GenerateInstalledExtensionsSet() const;
 
   // Returns a set of all extensions in the subsets specified by |include_mask|.
   //  * enabled_extensions()     --> ExtensionRegistry::ENABLED
@@ -87,8 +87,7 @@
   //  * terminated_extensions()  --> ExtensionRegistry::TERMINATED
   //  * blocklisted_extensions() --> ExtensionRegistry::BLOCKLISTED
   //  * blocked_extensions()     --> ExtensionRegistry::BLOCKED
-  std::unique_ptr<ExtensionSet> GenerateInstalledExtensionsSet(
-      int include_mask) const;
+  ExtensionSet GenerateInstalledExtensionsSet(int include_mask) const;
 
   // Returns the current version of the extension with the given |id|, if
   // one exists.
diff --git a/extensions/browser/permissions_manager.cc b/extensions/browser/permissions_manager.cc
index 22cb518..c390e07 100644
--- a/extensions/browser/permissions_manager.cc
+++ b/extensions/browser/permissions_manager.cc
@@ -710,7 +710,7 @@
   // accurate.
   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
   auto all_extensions = registry->GenerateInstalledExtensionsSet();
-  for (const auto& extension : *all_extensions) {
+  for (const auto& extension : all_extensions) {
     UpdatePermissionsWithUserSettings(*extension, user_allowed_set);
   }
 
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index f799f27..cfbf2bb4 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -550,8 +550,6 @@
     "api/declarative_net_request/test_utils.h",
     "api/extension_action/action_info_test_util.cc",
     "api/extension_action/action_info_test_util.h",
-    "file_test_util.cc",
-    "file_test_util.h",
     "warnings_test_util.cc",
     "warnings_test_util.h",
   ]
diff --git a/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc b/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
index fd7f4ccc61..9d66616 100644
--- a/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
+++ b/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
@@ -100,7 +100,7 @@
       EXPECT_TRUE(base::CreateDirectory(rules_path.DirName()));
 
       // Persist an empty ruleset file.
-      EXPECT_EQ(0, base::WriteFile(rules_path, nullptr /*data*/, 0 /*size*/));
+      EXPECT_TRUE(base::WriteFile(rules_path, base::StringPiece()));
     }
 
     // Persist manifest file.
diff --git a/extensions/common/api/declarative_net_request/test_utils.cc b/extensions/common/api/declarative_net_request/test_utils.cc
index 75251ea..425ea1b 100644
--- a/extensions/common/api/declarative_net_request/test_utils.cc
+++ b/extensions/common/api/declarative_net_request/test_utils.cc
@@ -335,9 +335,8 @@
   // Persists a background script if needed.
   if (flags & ConfigFlag::kConfig_HasBackgroundScript) {
     std::string content = "chrome.test.sendMessage('ready');";
-    CHECK_EQ(static_cast<int>(content.length()),
-             base::WriteFile(extension_dir.Append(kBackgroundScriptFilepath),
-                             content.c_str(), content.length()));
+    CHECK(base::WriteFile(extension_dir.Append(kBackgroundScriptFilepath),
+                          content));
   }
 
   // Persist manifest file.
diff --git a/extensions/common/api/generated_externs_list.txt b/extensions/common/api/generated_externs_list.txt
index a5d7ca0..120a3c44 100644
--- a/extensions/common/api/generated_externs_list.txt
+++ b/extensions/common/api/generated_externs_list.txt
@@ -8,13 +8,10 @@
 clipboard.idl
 events.json
 extension_types.json
-management.json
 metrics_private.json
 metrics_private_individual_apis.json
-mime_handler_private.idl
 mojo_private.idl
 networking_private.idl
 runtime.json
-system_display.idl
 test.json
 virtual_keyboard_private.json
diff --git a/extensions/common/extension_l10n_util_unittest.cc b/extensions/common/extension_l10n_util_unittest.cc
index e5eea234..6908528 100644
--- a/extensions/common/extension_l10n_util_unittest.cc
+++ b/extensions/common/extension_l10n_util_unittest.cc
@@ -41,8 +41,7 @@
 
   base::FilePath messages_file = locale.Append(kMessagesFilename);
   std::string data = "{ \"name\":";
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(messages_file, data.c_str(), data.length()));
+  ASSERT_TRUE(base::WriteFile(messages_file, data));
 
   base::Value::Dict manifest;
   manifest.Set(keys::kDefaultLocale, "en");
@@ -95,9 +94,7 @@
   base::FilePath locale_1 = src_path.AppendASCII("sr");
   ASSERT_TRUE(base::CreateDirectory(locale_1));
   std::string data("whatever");
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(locale_1.Append(kMessagesFilename), data.c_str(),
-                            data.length()));
+  ASSERT_TRUE(base::WriteFile(locale_1.Append(kMessagesFilename), data));
   // Unsupported locale.
   ASSERT_TRUE(base::CreateDirectory(src_path.AppendASCII("xxx_yyy")));
 
@@ -202,8 +199,7 @@
 
   std::string data = "{ \"name\":";
   base::FilePath messages_file = locale.Append(kMessagesFilename);
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(messages_file, data.c_str(), data.length()));
+  ASSERT_TRUE(base::WriteFile(messages_file, data));
 
   std::string error;
   EXPECT_FALSE(extension_l10n_util::LoadMessageCatalogs(
@@ -229,16 +225,12 @@
   std::string data =
       "{ \"name\": { \"message\": \"something\" }, "
       "\"name\": { \"message\": \"something else\" } }";
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(locale_1.Append(kMessagesFilename), data.c_str(),
-                            data.length()));
+  ASSERT_TRUE(base::WriteFile(locale_1.Append(kMessagesFilename), data));
 
   base::FilePath locale_2 = src_path.AppendASCII("sr");
   ASSERT_TRUE(base::CreateDirectory(locale_2));
 
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(locale_2.Append(kMessagesFilename), data.c_str(),
-                            data.length()));
+  ASSERT_TRUE(base::WriteFile(locale_2.Append(kMessagesFilename), data));
 
   std::string error;
   // JSON parser hides duplicates. We are going to get only one key/value
@@ -265,10 +257,9 @@
   std::string data = "{ \"name\": { \"message\": \"something\" } }";
   std::string compressed_data;
   ASSERT_TRUE(compression::GzipCompress(data, &compressed_data));
-  ASSERT_EQ(static_cast<int>(compressed_data.length()),
-            base::WriteFile(locale.Append(kMessagesFilename)
-                                .AddExtension(FILE_PATH_LITERAL(".gz")),
-                            compressed_data.c_str(), compressed_data.length()));
+  ASSERT_TRUE(base::WriteFile(
+      locale.Append(kMessagesFilename).AddExtension(FILE_PATH_LITERAL(".gz")),
+      compressed_data));
 
   // Test that LoadMessageCatalogs fails with gzip_permission = kDisallow.
   std::string error;
diff --git a/extensions/common/extension_resource_unittest.cc b/extensions/common/extension_resource_unittest.cc
index 19e1fb9d..482fb1c 100644
--- a/extensions/common/extension_resource_unittest.cc
+++ b/extensions/common/extension_resource_unittest.cc
@@ -58,8 +58,8 @@
   ASSERT_TRUE(base::CreateDirectory(sub_dir));
   base::FilePath inner_file = inner_dir.AppendASCII("inner");
   base::FilePath outer_file = temp.GetPath().AppendASCII("outer");
-  ASSERT_EQ(1, base::WriteFile(outer_file, "X", 1));
-  ASSERT_EQ(1, base::WriteFile(inner_file, "X", 1));
+  ASSERT_TRUE(base::WriteFile(outer_file, "X"));
+  ASSERT_TRUE(base::WriteFile(inner_file, "X"));
   std::string extension_id = crx_file::id_util::GenerateId("test");
 
 #if BUILDFLAG(IS_POSIX)
@@ -126,8 +126,7 @@
   const char* filename = "res.ico";
   base::FilePath root_resource = temp.GetPath().AppendASCII(filename);
   std::string data = "some foo";
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(root_resource, data.c_str(), data.length()));
+  ASSERT_TRUE(base::WriteFile(root_resource, data));
 
   // Create l10n resources (for current locale and its parents).
   base::FilePath l10n_path = temp.GetPath().Append(kLocaleFolder);
@@ -141,9 +140,7 @@
     base::FilePath make_path;
     make_path = l10n_path.AppendASCII(locales[i]);
     ASSERT_TRUE(base::CreateDirectory(make_path));
-    ASSERT_EQ(static_cast<int>(data.length()),
-              base::WriteFile(make_path.AppendASCII(filename), data.c_str(),
-                              data.length()));
+    ASSERT_TRUE(base::WriteFile(make_path.AppendASCII(filename), data));
   }
 
   base::FilePath path;
diff --git a/extensions/common/extension_set.cc b/extensions/common/extension_set.cc
index 1a840d45..784fdfd7 100644
--- a/extensions/common/extension_set.cc
+++ b/extensions/common/extension_set.cc
@@ -28,7 +28,7 @@
   return ExtensionId();
 }
 
-ExtensionSet::const_iterator::const_iterator() {}
+ExtensionSet::const_iterator::const_iterator() = default;
 
 ExtensionSet::const_iterator::const_iterator(const const_iterator& other)
     : it_(other.it_) {
@@ -38,21 +38,15 @@
     : it_(it) {
 }
 
-ExtensionSet::const_iterator::~const_iterator() {}
+ExtensionSet::const_iterator::~const_iterator() = default;
 
-ExtensionSet::ExtensionSet() {
-}
+ExtensionSet::ExtensionSet() = default;
 
-ExtensionSet::~ExtensionSet() {
-}
+ExtensionSet::~ExtensionSet() = default;
 
-size_t ExtensionSet::size() const {
-  return extensions_.size();
-}
+ExtensionSet::ExtensionSet(ExtensionSet&&) = default;
 
-bool ExtensionSet::is_empty() const {
-  return extensions_.empty();
-}
+ExtensionSet& ExtensionSet::operator=(ExtensionSet&&) noexcept = default;
 
 bool ExtensionSet::Contains(const ExtensionId& extension_id) const {
   return extensions_.find(extension_id) != extensions_.end();
diff --git a/extensions/common/extension_set.h b/extensions/common/extension_set.h
index 30d5c079..b082c12d 100644
--- a/extensions/common/extension_set.h
+++ b/extensions/common/extension_set.h
@@ -68,12 +68,14 @@
   ExtensionSet();
 
   ExtensionSet(const ExtensionSet&) = delete;
+  ExtensionSet(ExtensionSet&&);
   ExtensionSet& operator=(const ExtensionSet&) = delete;
+  ExtensionSet& operator=(ExtensionSet&&) noexcept;
 
   ~ExtensionSet();
 
-  size_t size() const;
-  bool is_empty() const;
+  size_t size() const { return extensions_.size(); }
+  bool empty() const { return extensions_.empty(); }
 
   // Iteration support.
   const_iterator begin() const { return const_iterator(extensions_.begin()); }
diff --git a/extensions/common/file_test_util.cc b/extensions/common/file_test_util.cc
deleted file mode 100644
index b2a91672..0000000
--- a/extensions/common/file_test_util.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/common/file_test_util.h"
-#include "base/files/file_util.h"
-
-namespace extensions {
-namespace file_test_util {
-
-bool WriteFile(const base::FilePath& path, base::StringPiece content) {
-  return base::WriteFile(path, content.data(), content.size()) ==
-         static_cast<int>(content.size());
-}
-
-}  // namespace file_test_util
-}  // namespace extensions
diff --git a/extensions/common/file_test_util.h b/extensions/common/file_test_util.h
deleted file mode 100644
index bda2f49..0000000
--- a/extensions/common/file_test_util.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef EXTENSIONS_COMMON_FILE_TEST_UTIL_H_
-#define EXTENSIONS_COMMON_FILE_TEST_UTIL_H_
-
-#include "base/strings/string_piece.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace extensions {
-namespace file_test_util {
-
-// Writes |content| to |path|. Returns true if writing was successful,
-// verifying the number of bytes written equals the size of |content|.
-bool WriteFile(const base::FilePath& path, base::StringPiece content);
-
-}  // namespace file_test_util
-}  // namespace extensions
-
-#endif  // EXTENSIONS_COMMON_FILE_TEST_UTIL_H_
diff --git a/extensions/common/file_util_unittest.cc b/extensions/common/file_util_unittest.cc
index 1b13b5b..8107dc8 100644
--- a/extensions/common/file_util_unittest.cc
+++ b/extensions/common/file_util_unittest.cc
@@ -245,9 +245,7 @@
   ASSERT_TRUE(base::CreateDirectory(src_path));
 
   std::string data = "{ \"name\": { \"message\": \"foobar\" } }";
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(src_path.AppendASCII("some_file.txt"), data.c_str(),
-                            data.length()));
+  ASSERT_TRUE(base::WriteFile(src_path.AppendASCII("some_file.txt"), data));
   std::string error;
   EXPECT_TRUE(file_util::CheckForIllegalFilenames(temp.GetPath(), &error));
 }
@@ -307,9 +305,7 @@
   ASSERT_TRUE(base::CreateDirectory(src_path));
 
   std::string data = "{ \"name\": { \"message\": \"foobar\" } }";
-  ASSERT_EQ(static_cast<int>(data.length()),
-            base::WriteFile(src_path.AppendASCII("lpt1.txt"), data.c_str(),
-                            data.length()));
+  ASSERT_TRUE(base::WriteFile(src_path.AppendASCII("lpt1.txt"), data));
 
   std::string error;
   EXPECT_FALSE(
@@ -355,7 +351,7 @@
   std::string non_ascii_file = "\xC3\xA0\xC3\xA8\xC3\xB2.png";
   base::FilePath non_ascii_path =
       temp.GetPath().Append(base::FilePath::FromUTF8Unsafe(non_ascii_file));
-  base::WriteFile(non_ascii_path, "", 0);
+  base::WriteFile(non_ascii_path, "");
 
   std::string kManifest = base::StringPrintf(
       "{ \"name\": \"Test\", \"version\": \"1.0\", "
@@ -418,7 +414,7 @@
 
 // Private key, generated by Chrome specifically for this test, and
 // never used elsewhere.
-const char private_key[] =
+constexpr base::StringPiece private_key =
     "-----BEGIN PRIVATE KEY-----\n"
     "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKt02SR0FYaYy6fpW\n"
     "MAA+kU1BgK3d+OmmWfdr+JATIjhRkyeSF4lTd/71JQsyKqPzYkQPi3EeROWM+goTv\n"
@@ -443,20 +439,17 @@
   base::FilePath src_path = temp.GetPath().AppendASCII("some_dir");
   ASSERT_TRUE(base::CreateDirectory(src_path));
 
-  ASSERT_EQ(static_cast<int>(std::size(private_key)),
-            base::WriteFile(src_path.AppendASCII("a_key.pem"), private_key,
-                            std::size(private_key)));
-  ASSERT_EQ(static_cast<int>(std::size(private_key)),
-            base::WriteFile(src_path.AppendASCII("second_key.pem"), private_key,
-                            std::size(private_key)));
+  ASSERT_TRUE(base::WriteFile(src_path.AppendASCII("a_key.pem"), private_key));
+  ASSERT_TRUE(
+      base::WriteFile(src_path.AppendASCII("second_key.pem"), private_key));
   // Shouldn't find a key with a different extension.
-  ASSERT_EQ(static_cast<int>(std::size(private_key)),
-            base::WriteFile(src_path.AppendASCII("key.diff_ext"), private_key,
-                            std::size(private_key)));
+  ASSERT_TRUE(
+      base::WriteFile(src_path.AppendASCII("key.diff_ext"), private_key));
   // Shouldn't find a key that isn't parsable.
-  ASSERT_EQ(static_cast<int>(std::size(private_key)) - 30,
-            base::WriteFile(src_path.AppendASCII("unparsable_key.pem"),
-                            private_key, std::size(private_key) - 30));
+  base::StringPiece private_key_substring =
+      private_key.substr(0, private_key.size() - 30);
+  ASSERT_TRUE(base::WriteFile(src_path.AppendASCII("unparsable_key.pem"),
+                              private_key_substring));
   std::vector<base::FilePath> private_keys =
       file_util::FindPrivateKeyFiles(temp.GetPath());
   EXPECT_EQ(2U, private_keys.size());
@@ -480,12 +473,8 @@
       "  \"manifest_version\": 2,\n"
       "  \"description\": \"The first extension that I made.\"\n"
       "}\n";
-  ASSERT_EQ(static_cast<int>(strlen(manifest)),
-            base::WriteFile(ext_path.AppendASCII("manifest.json"), manifest,
-                            strlen(manifest)));
-  ASSERT_EQ(static_cast<int>(strlen(private_key)),
-            base::WriteFile(ext_path.AppendASCII("a_key.pem"), private_key,
-                            strlen(private_key)));
+  ASSERT_TRUE(base::WriteFile(ext_path.AppendASCII("manifest.json"), manifest));
+  ASSERT_TRUE(base::WriteFile(ext_path.AppendASCII("a_key.pem"), private_key));
 
   std::string error;
   scoped_refptr<Extension> extension(file_util::LoadExtension(
@@ -524,9 +513,7 @@
       "  \"manifest_version\": 2,\n"
       "  \"description\": \"The first extension that I made.\"\n"
       "}\n";
-  ASSERT_EQ(static_cast<int>(strlen(manifest)),
-            base::WriteFile(ext_path.AppendASCII(kCustomManifest), manifest,
-                            strlen(manifest)));
+  ASSERT_TRUE(base::WriteFile(ext_path.AppendASCII(kCustomManifest), manifest));
 
   std::string error;
   scoped_refptr<Extension> extension(file_util::LoadExtension(
diff --git a/extensions/common/image_util_unittest.cc b/extensions/common/image_util_unittest.cc
index 779783e..fa673aa 100644
--- a/extensions/common/image_util_unittest.cc
+++ b/extensions/common/image_util_unittest.cc
@@ -188,11 +188,7 @@
                                                      &bitmap));
   std::vector<unsigned char> output_data;
   ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output_data));
-  const int bytes_to_write = output_data.size();
-  ASSERT_EQ(bytes_to_write,
-            base::WriteFile(rendered_icon_path,
-                            reinterpret_cast<const char*>(&output_data[0]),
-                            bytes_to_write));
+  ASSERT_TRUE(base::WriteFile(rendered_icon_path, output_data));
 }
 
 }  // namespace
diff --git a/extensions/renderer/renderer_extension_registry.cc b/extensions/renderer/renderer_extension_registry.cc
index c4f94aa..5a64b5008 100644
--- a/extensions/renderer/renderer_extension_registry.cc
+++ b/extensions/renderer/renderer_extension_registry.cc
@@ -39,16 +39,6 @@
   return &extensions_;
 }
 
-size_t RendererExtensionRegistry::size() const {
-  base::AutoLock lock(lock_);
-  return extensions_.size();
-}
-
-bool RendererExtensionRegistry::is_empty() const {
-  base::AutoLock lock(lock_);
-  return extensions_.is_empty();
-}
-
 bool RendererExtensionRegistry::Contains(
     const std::string& extension_id) const {
   base::AutoLock lock(lock_);
diff --git a/extensions/renderer/renderer_extension_registry.h b/extensions/renderer/renderer_extension_registry.h
index 5e066b7..b17734d 100644
--- a/extensions/renderer/renderer_extension_registry.h
+++ b/extensions/renderer/renderer_extension_registry.h
@@ -42,12 +42,8 @@
   // TODO(annekao): remove or make thread-safe and callback-based.
   const ExtensionSet* GetMainThreadExtensionSet() const;
 
-  size_t size() const;
-  bool is_empty() const;
-
   // Forwards to the ExtensionSet methods by the same name.
   bool Contains(const std::string& id) const;
-  bool ContainsGUID(const std::string& guid) const;
   bool Insert(const scoped_refptr<const Extension>& extension);
   bool Remove(const std::string& id);
   std::string GetExtensionOrAppIDByURL(const GURL& url) const;
diff --git a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json b/infra/config/generated/builders/ci/android-rust-arm32-rel/properties.json
similarity index 91%
rename from infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
rename to infra/config/generated/builders/ci/android-rust-arm32-rel/properties.json
index 82266ff..a0da3cf 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-rust-arm32-rel/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "android-rust-arm32-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -39,13 +39,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm32-rel",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm32-rel",
           "group": "tryserver.chromium.rust"
         }
       ]
diff --git a/infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json b/infra/config/generated/builders/ci/android-rust-arm64-dbg/properties.json
similarity index 89%
rename from infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json
rename to infra/config/generated/builders/ci/android-rust-arm64-dbg/properties.json
index 4eed56b..a0dfdafa 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-rust-arm64-dbg/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-dbg",
+              "builder": "android-rust-arm64-dbg",
               "project": "chromium"
             },
             "builder_spec": {
@@ -22,7 +22,7 @@
                 "build_config": "Debug",
                 "config": "android",
                 "target_arch": "arm",
-                "target_bits": 32,
+                "target_bits": 64,
                 "target_platform": "android"
               },
               "legacy_gclient_config": {
@@ -39,13 +39,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-dbg",
+          "builder": "android-rust-arm64-dbg",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-dbg",
+          "builder": "android-rust-arm64-dbg",
           "group": "tryserver.chromium.rust"
         }
       ]
diff --git a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json b/infra/config/generated/builders/ci/android-rust-arm64-rel/properties.json
similarity index 89%
copy from infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/ci/android-rust-arm64-rel/properties.json
index 82266ff..36212748 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-rust-arm64-rel/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "android-rust-arm64-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -22,7 +22,7 @@
                 "build_config": "Release",
                 "config": "android",
                 "target_arch": "arm",
-                "target_bits": 32,
+                "target_bits": 64,
                 "target_platform": "android"
               },
               "legacy_gclient_config": {
@@ -39,13 +39,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm64-rel",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm64-rel",
           "group": "tryserver.chromium.rust"
         }
       ]
diff --git a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json b/infra/config/generated/builders/ci/mac-rust-x64-rel/properties.json
similarity index 70%
copy from infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/ci/mac-rust-x64-rel/properties.json
index 82266ff..bcf47e6 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/mac-rust-x64-rel/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "mac-rust-x64-rel",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Release",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,13 +33,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "mac-rust-x64-rel",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-rel",
+          "builder": "mac-rust-x64-rel",
           "group": "tryserver.chromium.rust"
         }
       ]
@@ -54,7 +48,8 @@
   "$build/reclient": {
     "instance": "rbe-chromium-trusted",
     "jobs": 250,
-    "metrics_project": "chromium-reclient-metrics"
+    "metrics_project": "chromium-reclient-metrics",
+    "scandeps_server": true
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json b/infra/config/generated/builders/ci/win-rust-x64-dbg/properties.json
similarity index 72%
copy from infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json
copy to infra/config/generated/builders/ci/win-rust-x64-dbg/properties.json
index 4eed56b..9136732 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json
+++ b/infra/config/generated/builders/ci/win-rust-x64-dbg/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-dbg",
+              "builder": "win-rust-x64-dbg",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Debug",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,13 +33,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-dbg",
+          "builder": "win-rust-x64-dbg",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-dbg",
+          "builder": "win-rust-x64-dbg",
           "group": "tryserver.chromium.rust"
         }
       ]
diff --git a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json b/infra/config/generated/builders/ci/win-rust-x64-rel/properties.json
similarity index 72%
copy from infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/ci/win-rust-x64-rel/properties.json
index 82266ff..d402bd3 100644
--- a/infra/config/generated/builders/ci/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/win-rust-x64-rel/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "win-rust-x64-rel",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Release",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,13 +33,13 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "win-rust-x64-rel",
           "project": "chromium"
         }
       ],
       "mirroring_builder_group_and_names": [
         {
-          "builder": "android-rust-arm-rel",
+          "builder": "win-rust-x64-rel",
           "group": "tryserver.chromium.rust"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json b/infra/config/generated/builders/try/android-rust-arm32-rel/properties.json
similarity index 93%
rename from infra/config/generated/builders/try/android-rust-arm-rel/properties.json
rename to infra/config/generated/builders/try/android-rust-arm32-rel/properties.json
index 0065d7c4..7e8ce639 100644
--- a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-rust-arm32-rel/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "android-rust-arm32-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -39,7 +39,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm32-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-dbg/properties.json b/infra/config/generated/builders/try/android-rust-arm64-dbg/properties.json
similarity index 91%
rename from infra/config/generated/builders/try/android-rust-arm-dbg/properties.json
rename to infra/config/generated/builders/try/android-rust-arm64-dbg/properties.json
index d3a71507..8676d069 100644
--- a/infra/config/generated/builders/try/android-rust-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-rust-arm64-dbg/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-dbg",
+              "builder": "android-rust-arm64-dbg",
               "project": "chromium"
             },
             "builder_spec": {
@@ -22,7 +22,7 @@
                 "build_config": "Debug",
                 "config": "android",
                 "target_arch": "arm",
-                "target_bits": 32,
+                "target_bits": 64,
                 "target_platform": "android"
               },
               "legacy_gclient_config": {
@@ -39,7 +39,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-dbg",
+          "builder": "android-rust-arm64-dbg",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json b/infra/config/generated/builders/try/android-rust-arm64-rel/properties.json
similarity index 91%
copy from infra/config/generated/builders/try/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/try/android-rust-arm64-rel/properties.json
index 0065d7c4..c3aa074 100644
--- a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-rust-arm64-rel/properties.json
@@ -6,7 +6,7 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "android-rust-arm64-rel",
               "project": "chromium"
             },
             "builder_spec": {
@@ -22,7 +22,7 @@
                 "build_config": "Release",
                 "config": "android",
                 "target_arch": "arm",
-                "target_bits": 32,
+                "target_bits": 64,
                 "target_platform": "android"
               },
               "legacy_gclient_config": {
@@ -39,7 +39,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "android-rust-arm64-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json b/infra/config/generated/builders/try/mac-rust-x64-rel/properties.json
similarity index 73%
copy from infra/config/generated/builders/try/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/try/mac-rust-x64-rel/properties.json
index 0065d7c4..3adaeb7 100644
--- a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/mac-rust-x64-rel/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "mac-rust-x64-rel",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Release",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,7 +33,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "mac-rust-x64-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-dbg/properties.json b/infra/config/generated/builders/try/win-rust-x64-dbg/properties.json
similarity index 73%
copy from infra/config/generated/builders/try/android-rust-arm-dbg/properties.json
copy to infra/config/generated/builders/try/win-rust-x64-dbg/properties.json
index d3a71507..519078c 100644
--- a/infra/config/generated/builders/try/android-rust-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/win-rust-x64-dbg/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-dbg",
+              "builder": "win-rust-x64-dbg",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Debug",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,7 +33,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-dbg",
+          "builder": "win-rust-x64-dbg",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json b/infra/config/generated/builders/try/win-rust-x64-rel/properties.json
similarity index 73%
copy from infra/config/generated/builders/try/android-rust-arm-rel/properties.json
copy to infra/config/generated/builders/try/win-rust-x64-rel/properties.json
index 0065d7c4..96a6151d 100644
--- a/infra/config/generated/builders/try/android-rust-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/win-rust-x64-rel/properties.json
@@ -6,29 +6,23 @@
           {
             "builder_id": {
               "bucket": "ci",
-              "builder": "android-rust-arm-rel",
+              "builder": "win-rust-x64-rel",
               "project": "chromium"
             },
             "builder_spec": {
               "builder_group": "chromium.rust",
               "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "base_config"
-              },
               "legacy_chromium_config": {
                 "apply_configs": [
-                  "android"
+                  "mb"
                 ],
                 "build_config": "Release",
-                "config": "android",
-                "target_arch": "arm",
-                "target_bits": 32,
-                "target_platform": "android"
+                "config": "chromium",
+                "target_bits": 64
               },
               "legacy_gclient_config": {
                 "apply_configs": [
-                  "use_rust",
-                  "android"
+                  "use_rust"
                 ],
                 "config": "chromium"
               }
@@ -39,7 +33,7 @@
       "builder_ids": [
         {
           "bucket": "ci",
-          "builder": "android-rust-arm-rel",
+          "builder": "win-rust-x64-rel",
           "project": "chromium"
         }
       ]
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index f2407a4..c594669 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -749,11 +749,15 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/android-rust-arm-dbg"
+        name: "chromium/try/android-rust-arm32-rel"
         includable_only: true
       }
       builders {
-        name: "chromium/try/android-rust-arm-rel"
+        name: "chromium/try/android-rust-arm64-dbg"
+        includable_only: true
+      }
+      builders {
+        name: "chromium/try/android-rust-arm64-rel"
         includable_only: true
       }
       builders {
@@ -3245,6 +3249,10 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/mac-rust-x64-rel"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/mac-swangle-chromium-try-x64"
         includable_only: true
       }
@@ -3704,6 +3712,14 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/win-rust-x64-dbg"
+        includable_only: true
+      }
+      builders {
+        name: "chromium/try/win-rust-x64-rel"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/win-swangle-chromium-try-x86"
         includable_only: true
       }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 23d1bf7..da7e523 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -27733,13 +27733,15 @@
       }
     }
     builders {
-      name: "android-rust-arm-dbg"
+      name: "android-rust-arm32-rel"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-rust-arm-dbg"
+      dimensions: "builderless:1"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
       dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -27757,7 +27759,7 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/ci/android-rust-arm-dbg/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/ci/android-rust-arm32-rel/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -27815,13 +27817,15 @@
       }
     }
     builders {
-      name: "android-rust-arm-rel"
+      name: "android-rust-arm64-dbg"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-rust-arm-rel"
+      dimensions: "builderless:1"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
       dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -27839,7 +27843,91 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/ci/android-rust-arm-rel/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/ci/android-rust-arm64-dbg/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "android-rust-arm64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/ci/android-rust-arm64-rel/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -32817,7 +32905,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:ios15-sdk-simulator"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "os:Mac-13"
       dimensions: "pool:luci.chromium.ci"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -32989,7 +33077,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:ios16-sdk-device"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "os:Mac-13"
       dimensions: "pool:luci.chromium.ci"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -33075,7 +33163,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:ios16-sdk-simulator"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "os:Mac-13"
       dimensions: "pool:luci.chromium.ci"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -38117,10 +38205,6 @@
         value: 100
       }
       experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 0
-      }
-      experiments {
         key: "luci.recipes.use_python3"
         value: 100
       }
@@ -38330,11 +38414,13 @@
     builders {
       name: "linux-rust-x64-dbg"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:linux-rust-x64-dbg"
+      dimensions: "builderless:1"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
       dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -38412,11 +38498,13 @@
     builders {
       name: "linux-rust-x64-rel"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:linux-rust-x64-rel"
+      dimensions: "builderless:1"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
       dimensions: "os:Ubuntu-18.04"
       dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
         cipd_version: "latest"
@@ -41677,6 +41765,88 @@
       }
     }
     builders {
+      name: "mac-rust-x64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:mac-rust-x64-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Mac-12"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/ci/mac-rust-x64-rel/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "mac-swangle-chromium-x64"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -45451,10 +45621,6 @@
         value: 100
       }
       experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 0
-      }
-      experiments {
         key: "luci.recipes.use_python3"
         value: 100
       }
@@ -45579,6 +45745,170 @@
       }
     }
     builders {
+      name: "win-rust-x64-dbg"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:win-rust-x64-dbg"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/ci/win-rust-x64-dbg/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "win-rust-x64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:win-rust-x64-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/ci/win-rust-x64-rel/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "win-swangle-chromium-x86"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -58792,9 +59122,9 @@
       }
     }
     builders {
-      name: "android-rust-arm-dbg"
+      name: "android-rust-arm32-rel"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-rust-arm-dbg"
+      dimensions: "builder:android-rust-arm32-rel"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-18.04"
@@ -58816,7 +59146,7 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/android-rust-arm-dbg/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/try/android-rust-arm32-rel/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -58881,9 +59211,9 @@
       }
     }
     builders {
-      name: "android-rust-arm-rel"
+      name: "android-rust-arm64-dbg"
       swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-rust-arm-rel"
+      dimensions: "builder:android-rust-arm64-dbg"
       dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Ubuntu-18.04"
@@ -58905,7 +59235,96 @@
         '    }'
         '  },'
         '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/android-rust-arm-rel/properties.json",'
+        '    "properties_file": "infra/config/generated/builders/try/android-rust-arm64-dbg/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "android-rust-arm64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:android-rust-arm64-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/try/android-rust-arm64-rel/properties.json",'
         '    "top_level_project": {'
         '      "ref": "refs/heads/main",'
         '      "repo": {'
@@ -61611,10 +62030,6 @@
         value: 100
       }
       experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 0
-      }
-      experiments {
         key: "luci.recipes.use_python3"
         value: 100
       }
@@ -69621,7 +70036,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:ios15-sdk-simulator"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "os:Mac-13"
       dimensions: "pool:luci.chromium.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -69805,7 +70220,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:ios16-sdk-simulator"
       dimensions: "cpu:x86-64"
-      dimensions: "os:Mac-12"
+      dimensions: "os:Mac-13"
       dimensions: "pool:luci.chromium.try"
       exe {
         cipd_package: "infra/chromium/bootstrapper/${platform}"
@@ -79692,6 +80107,95 @@
       description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a>."
     }
     builders {
+      name: "mac-rust-x64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:mac-rust-x64-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/try/mac-rust-x64-rel/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "mac-swangle-chromium-try-x64"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -84679,6 +85183,184 @@
       description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/win-rel\">win-rel</a>."
     }
     builders {
+      name: "win-rust-x64-dbg"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:win-rust-x64-dbg"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/try/win-rust-x64-dbg/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "win-rust-x64-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builder:win-rust-x64-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/try/win-rust-x64-rel/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.rust",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "win-swangle-chromium-try-x86"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 5890d0e..bf2c807 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -13995,13 +13995,18 @@
   refs: "regexp:refs/heads/main"
   manifest_name: "REVISION"
   builders {
-    name: "buildbucket/luci.chromium.ci/android-rust-arm-dbg"
-    category: "Android"
+    name: "buildbucket/luci.chromium.ci/android-rust-arm32-rel"
+    category: "Android 32bit"
+    short_name: "rel"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/android-rust-arm64-dbg"
+    category: "Android 64bit"
     short_name: "dbg"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/android-rust-arm-rel"
-    category: "Android"
+    name: "buildbucket/luci.chromium.ci/android-rust-arm64-rel"
+    category: "Android 64bit"
     short_name: "rel"
   }
   builders {
@@ -14014,6 +14019,21 @@
     category: "Linux"
     short_name: "rel"
   }
+  builders {
+    name: "buildbucket/luci.chromium.ci/mac-rust-x64-rel"
+    category: "Mac x64"
+    short_name: "rel"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/win-rust-x64-dbg"
+    category: "Windows x64"
+    short_name: "dbg"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/win-rust-x64-rel"
+    category: "Windows x64"
+    short_name: "rel"
+  }
   header {
     oncalls {
       name: "Chromium"
@@ -17250,10 +17270,13 @@
     name: "buildbucket/luci.chromium.try/android-pie-x86-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-rust-arm-dbg"
+    name: "buildbucket/luci.chromium.try/android-rust-arm32-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-rust-arm-rel"
+    name: "buildbucket/luci.chromium.try/android-rust-arm64-dbg"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.try/android-rust-arm64-rel"
   }
   builders {
     name: "buildbucket/luci.chromium.try/android-webview-10-x86-rel-tests"
@@ -17943,6 +17966,9 @@
     name: "buildbucket/luci.chromium.try/mac-rel-compilator"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/mac-rust-x64-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/mac-swangle-chromium-try-x64"
   }
   builders {
@@ -18108,6 +18134,12 @@
     name: "buildbucket/luci.chromium.try/win-rel-compilator"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/win-rust-x64-dbg"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.try/win-rust-x64-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/win-swangle-chromium-try-x86"
   }
   builders {
@@ -19180,10 +19212,13 @@
   id: "tryserver.chromium.rust"
   name: "tryserver.chromium.rust"
   builders {
-    name: "buildbucket/luci.chromium.try/android-rust-arm-dbg"
+    name: "buildbucket/luci.chromium.try/android-rust-arm32-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-rust-arm-rel"
+    name: "buildbucket/luci.chromium.try/android-rust-arm64-dbg"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.try/android-rust-arm64-rel"
   }
   builders {
     name: "buildbucket/luci.chromium.try/linux-rust-x64-dbg"
@@ -19194,6 +19229,15 @@
   builders {
     name: "buildbucket/luci.chromium.try/linux-rust-x64-rel-android-toolchain"
   }
+  builders {
+    name: "buildbucket/luci.chromium.try/mac-rust-x64-rel"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.try/win-rust-x64-dbg"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.try/win-rust-x64-rel"
+  }
   builder_view_only: true
 }
 consoles {
diff --git a/infra/config/generated/luci/luci-notify.cfg b/infra/config/generated/luci/luci-notify.cfg
index c604b6c3..0eae97a 100644
--- a/infra/config/generated/luci/luci-notify.cfg
+++ b/infra/config/generated/luci/luci-notify.cfg
@@ -2401,7 +2401,7 @@
   }
   builders {
     bucket: "ci"
-    name: "android-rust-arm-dbg"
+    name: "android-rust-arm32-rel"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
 }
@@ -2415,7 +2415,21 @@
   }
   builders {
     bucket: "ci"
-    name: "android-rust-arm-rel"
+    name: "android-rust-arm64-dbg"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+}
+notifiers {
+  notifications {
+    on_new_status: FAILURE
+    on_new_status: INFRA_FAILURE
+    email {
+      recipients: "chrome-rust-experiments+bots@google.com"
+    }
+  }
+  builders {
+    bucket: "ci"
+    name: "android-rust-arm64-rel"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
 }
@@ -3522,6 +3536,20 @@
 notifiers {
   notifications {
     on_new_status: FAILURE
+    on_new_status: INFRA_FAILURE
+    email {
+      recipients: "chrome-rust-experiments+bots@google.com"
+    }
+  }
+  builders {
+    bucket: "ci"
+    name: "mac-rust-x64-rel"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+}
+notifiers {
+  notifications {
+    on_new_status: FAILURE
     email {
       recipients: "chromium-component-mapping@google.com"
       recipients: "chanli@google.com"
@@ -3626,6 +3654,34 @@
 }
 notifiers {
   notifications {
+    on_new_status: FAILURE
+    on_new_status: INFRA_FAILURE
+    email {
+      recipients: "chrome-rust-experiments+bots@google.com"
+    }
+  }
+  builders {
+    bucket: "ci"
+    name: "win-rust-x64-dbg"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+}
+notifiers {
+  notifications {
+    on_new_status: FAILURE
+    on_new_status: INFRA_FAILURE
+    email {
+      recipients: "chrome-rust-experiments+bots@google.com"
+    }
+  }
+  builders {
+    bucket: "ci"
+    name: "win-rust-x64-rel"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+}
+notifiers {
+  notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
     email {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 8754528..2d5ed27 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -3823,21 +3823,30 @@
   }
 }
 job {
-  id: "android-rust-arm-dbg"
+  id: "android-rust-arm32-rel"
   realm: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "ci"
-    builder: "android-rust-arm-dbg"
+    builder: "android-rust-arm32-rel"
   }
 }
 job {
-  id: "android-rust-arm-rel"
+  id: "android-rust-arm64-dbg"
   realm: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
     bucket: "ci"
-    builder: "android-rust-arm-rel"
+    builder: "android-rust-arm64-dbg"
+  }
+}
+job {
+  id: "android-rust-arm64-rel"
+  realm: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "android-rust-arm64-rel"
   }
 }
 job {
@@ -5498,6 +5507,15 @@
   }
 }
 job {
+  id: "mac-rust-x64-rel"
+  realm: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "mac-rust-x64-rel"
+  }
+}
+job {
   id: "mac-swangle-chromium-x64"
   realm: "ci"
   buildbucket {
@@ -5923,6 +5941,24 @@
   }
 }
 job {
+  id: "win-rust-x64-dbg"
+  realm: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "win-rust-x64-dbg"
+  }
+}
+job {
+  id: "win-rust-x64-rel"
+  realm: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "win-rust-x64-rel"
+  }
+}
+job {
   id: "win-swangle-chromium-x86"
   realm: "ci"
   buildbucket {
@@ -6395,8 +6431,9 @@
   triggers: "android-pie-arm64-rel"
   triggers: "android-pie-arm64-wpt-rel-non-cq"
   triggers: "android-pie-x86-rel"
-  triggers: "android-rust-arm-dbg"
-  triggers: "android-rust-arm-rel"
+  triggers: "android-rust-arm32-rel"
+  triggers: "android-rust-arm64-dbg"
+  triggers: "android-rust-arm64-rel"
   triggers: "android-webview-pie-x86-wpt-fyi-rel"
   triggers: "android-x86-rel"
   triggers: "build-perf-android"
@@ -6515,6 +6552,7 @@
   triggers: "mac-hermetic-upgrade-rel"
   triggers: "mac-official"
   triggers: "mac-rel-cft"
+  triggers: "mac-rust-x64-rel"
   triggers: "mac-swangle-chromium-x64"
   triggers: "mac-updater-builder-arm64-dbg"
   triggers: "mac-updater-builder-arm64-rel"
@@ -6534,6 +6572,8 @@
   triggers: "win-official"
   triggers: "win-presubmit"
   triggers: "win-rel-cft"
+  triggers: "win-rust-x64-dbg"
+  triggers: "win-rust-x64-rel"
   triggers: "win-swangle-chromium-x86"
   triggers: "win-swangle-tot-swiftshader-x64"
   triggers: "win-swangle-tot-swiftshader-x86"
diff --git a/infra/config/subprojects/chromium/ci/checks.star b/infra/config/subprojects/chromium/ci/checks.star
index 55513d3..dd0400cb 100644
--- a/infra/config/subprojects/chromium/ci/checks.star
+++ b/infra/config/subprojects/chromium/ci/checks.star
@@ -28,9 +28,6 @@
         short_name = "linux",
     ),
     execution_timeout = ci.DEFAULT_EXECUTION_TIMEOUT,
-
-    # TODO(crbug.com/1370463): remove this.
-    omit_python2 = False,
     properties = {
         "$depot_tools/presubmit": {
             "runhooks": True,
@@ -56,9 +53,6 @@
         short_name = "win",
     ),
     execution_timeout = 6 * time.hour,
-
-    # TODO(crbug.com/1370463): remove this.
-    omit_python2 = False,
     properties = {
         "$depot_tools/presubmit": {
             "runhooks": True,
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star
index 90dc2bf0..1e90847c 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -2191,7 +2191,7 @@
         ),
         build_gs_bucket = "chromium-fyi-archive",
     ),
-    os = os.MAC_12,
+    os = os.MAC_DEFAULT,
     console_view_entry = [
         consoles.console_view_entry(
             category = "iOS|iOS15",
@@ -2216,7 +2216,7 @@
         ),
         build_gs_bucket = "chromium-fyi-archive",
     ),
-    os = os.MAC_12,
+    os = os.MAC_13,
     console_view_entry = [
         consoles.console_view_entry(
             category = "iOS|iOS15",
@@ -2270,7 +2270,7 @@
         ),
         build_gs_bucket = "chromium-fyi-archive",
     ),
-    os = os.MAC_DEFAULT,
+    os = os.MAC_13,
     console_view_entry = [
         consoles.console_view_entry(
             category = "iOS|iOS16",
@@ -2299,7 +2299,7 @@
         ),
         build_gs_bucket = "chromium-fyi-archive",
     ),
-    os = os.MAC_DEFAULT,
+    os = os.MAC_13,
     console_view_entry = consoles.console_view_entry(
         category = "iOS|iOS16",
         short_name = "sdk16",
diff --git a/infra/config/subprojects/chromium/ci/chromium.rust.star b/infra/config/subprojects/chromium/ci/chromium.rust.star
index 34ad45ca..25f5f0ec 100644
--- a/infra/config/subprojects/chromium/ci/chromium.rust.star
+++ b/infra/config/subprojects/chromium/ci/chromium.rust.star
@@ -12,7 +12,6 @@
     executable = ci.DEFAULT_EXECUTABLE,
     builder_group = "chromium.rust",
     pool = ci.DEFAULT_POOL,
-    builderless = False,
     cores = 8,
     os = os.LINUX_DEFAULT,
     execution_timeout = ci.DEFAULT_EXECUTION_TIMEOUT,
@@ -27,33 +26,7 @@
 )
 
 ci.builder(
-    name = "android-rust-arm-dbg",
-    builder_spec = builder_config.builder_spec(
-        gclient_config = builder_config.gclient_config(
-            config = "chromium",
-            apply_configs = [
-                "use_rust",
-                "android",
-            ],
-        ),
-        chromium_config = builder_config.chromium_config(
-            config = "android",
-            apply_configs = ["android"],
-            build_config = builder_config.build_config.DEBUG,
-            target_arch = builder_config.target_arch.ARM,
-            target_bits = 32,
-            target_platform = builder_config.target_platform.ANDROID,
-        ),
-        android_config = builder_config.android_config(config = "base_config"),
-    ),
-    console_view_entry = consoles.console_view_entry(
-        category = "Android",
-        short_name = "dbg",
-    ),
-)
-
-ci.builder(
-    name = "android-rust-arm-rel",
+    name = "android-rust-arm32-rel",
     builder_spec = builder_config.builder_spec(
         gclient_config = builder_config.gclient_config(
             config = "chromium",
@@ -73,7 +46,59 @@
         android_config = builder_config.android_config(config = "base_config"),
     ),
     console_view_entry = consoles.console_view_entry(
-        category = "Android",
+        category = "Android 32bit",
+        short_name = "rel",
+    ),
+)
+
+ci.builder(
+    name = "android-rust-arm64-dbg",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "use_rust",
+                "android",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "android",
+            apply_configs = ["android"],
+            build_config = builder_config.build_config.DEBUG,
+            target_arch = builder_config.target_arch.ARM,
+            target_bits = 64,
+            target_platform = builder_config.target_platform.ANDROID,
+        ),
+        android_config = builder_config.android_config(config = "base_config"),
+    ),
+    console_view_entry = consoles.console_view_entry(
+        category = "Android 64bit",
+        short_name = "dbg",
+    ),
+)
+
+ci.builder(
+    name = "android-rust-arm64-rel",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "use_rust",
+                "android",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "android",
+            apply_configs = ["android"],
+            build_config = builder_config.build_config.RELEASE,
+            target_arch = builder_config.target_arch.ARM,
+            target_bits = 64,
+            target_platform = builder_config.target_platform.ANDROID,
+        ),
+        android_config = builder_config.android_config(config = "base_config"),
+    ),
+    console_view_entry = consoles.console_view_entry(
+        category = "Android 64bit",
         short_name = "rel",
     ),
 )
@@ -117,3 +142,66 @@
         short_name = "rel",
     ),
 )
+
+ci.builder(
+    name = "mac-rust-x64-rel",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = ["use_rust"],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = ["mb"],
+            build_config = builder_config.build_config.RELEASE,
+            target_bits = 64,
+        ),
+    ),
+    os = os.MAC_DEFAULT,
+    console_view_entry = consoles.console_view_entry(
+        category = "Mac x64",
+        short_name = "rel",
+    ),
+)
+
+ci.builder(
+    name = "win-rust-x64-dbg",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = ["use_rust"],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = ["mb"],
+            build_config = builder_config.build_config.DEBUG,
+            target_bits = 64,
+        ),
+    ),
+    os = os.WINDOWS_ANY,
+    console_view_entry = consoles.console_view_entry(
+        category = "Windows x64",
+        short_name = "dbg",
+    ),
+)
+
+ci.builder(
+    name = "win-rust-x64-rel",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = ["use_rust"],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = ["mb"],
+            build_config = builder_config.build_config.RELEASE,
+            target_bits = 64,
+        ),
+    ),
+    os = os.WINDOWS_ANY,
+    console_view_entry = consoles.console_view_entry(
+        category = "Windows x64",
+        short_name = "rel",
+    ),
+)
diff --git a/infra/config/subprojects/chromium/try/presubmit.star b/infra/config/subprojects/chromium/try/presubmit.star
index bba04a6..1653a8d 100644
--- a/infra/config/subprojects/chromium/try/presubmit.star
+++ b/infra/config/subprojects/chromium/try/presubmit.star
@@ -128,9 +128,6 @@
     branch_selector = branches.selector.ALL_BRANCHES,
     executable = "recipe:presubmit",
     execution_timeout = 40 * time.minute,
-
-    # TODO(crbug.com/1366979): remove this.
-    omit_python2 = False,
     properties = {
         "$depot_tools/presubmit": {
             "runhooks": True,
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
index 2f9209b..a1971ba 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -489,7 +489,7 @@
 ios_builder(
     name = "ios15-sdk-simulator",
     mirrors = ["ci/ios15-sdk-simulator"],
-    os = os.MAC_12,
+    os = os.MAC_13,
 )
 
 ios_builder(
@@ -506,7 +506,7 @@
     mirrors = [
         "ci/ios16-sdk-simulator",
     ],
-    os = os.MAC_DEFAULT,
+    os = os.MAC_13,
     xcode = xcode.x14betabots,
 )
 
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.rust.star b/infra/config/subprojects/chromium/try/tryserver.chromium.rust.star
index 46e4ddf..a9d1d9d 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.rust.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.rust.star
@@ -25,13 +25,18 @@
 )
 
 try_.builder(
-    name = "android-rust-arm-dbg",
-    mirrors = ["ci/android-rust-arm-dbg"],
+    name = "android-rust-arm32-rel",
+    mirrors = ["ci/android-rust-arm32-rel"],
 )
 
 try_.builder(
-    name = "android-rust-arm-rel",
-    mirrors = ["ci/android-rust-arm-rel"],
+    name = "android-rust-arm64-dbg",
+    mirrors = ["ci/android-rust-arm64-dbg"],
+)
+
+try_.builder(
+    name = "android-rust-arm64-rel",
+    mirrors = ["ci/android-rust-arm64-rel"],
 )
 
 try_.builder(
@@ -40,11 +45,26 @@
 )
 
 try_.builder(
-    name = "linux-rust-x64-rel-android-toolchain",
-    mirrors = ["ci/linux-rust-x64-rel"],
+    name = "linux-rust-x64-dbg",
+    mirrors = ["ci/linux-rust-x64-dbg"],
 )
 
 try_.builder(
-    name = "linux-rust-x64-dbg",
-    mirrors = ["ci/linux-rust-x64-dbg"],
+    name = "win-rust-x64-rel",
+    mirrors = ["ci/win-rust-x64-rel"],
+)
+
+try_.builder(
+    name = "win-rust-x64-dbg",
+    mirrors = ["ci/win-rust-x64-dbg"],
+)
+
+try_.builder(
+    name = "mac-rust-x64-rel",
+    mirrors = ["ci/mac-rust-x64-rel"],
+)
+
+try_.builder(
+    name = "linux-rust-x64-rel-android-toolchain",
+    mirrors = ["ci/linux-rust-x64-rel"],
 )
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index fa03cda0..7d8c174f 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1388,6 +1388,9 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(kAddToHomeScreen,
                                     kAddToHomeScreenVariations,
                                     "IOSEditMenuPartialTranslate")},
+    {"policy-logs-page-ios", flag_descriptions::kPolicyLogsPageIOSName,
+     flag_descriptions::kPolicyLogsPageIOSDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(policy::features::kPolicyLogsPageIOS)},
     {"indicate-account-storage-error-in-account-cell",
      flag_descriptions::kIndicateAccountStorageErrorInAccountCellName,
      flag_descriptions::kIndicateAccountStorageErrorInAccountCellDescription,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index d09e4c8a..e97335d 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -745,6 +745,11 @@
     "Displays warning when user types or pastes a saved password into a "
     "phishing website.";
 
+const char kPolicyLogsPageIOSName[] = "Policy Logs Page on IOS";
+const char kPolicyLogsPageIOSDescription[] =
+    "Enable the new chrome://policy/logs page containing logs for debugging "
+    "policy related issues on IOS.";
+
 const char kPromosManagerUsesFETName[] = "Promos Manager using FET";
 const char kPromosManagerUsesFETDescription[] =
     "Migrates the Promos Manager to use the Feature Engagement Tracker as its "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 64efe23..79410e6 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -661,6 +661,10 @@
 extern const char kPasswordReuseDetectionName[];
 extern const char kPasswordReuseDetectionDescription[];
 
+// Title and description for the flag to enable chrome://policy/logs on iOS
+extern const char kPolicyLogsPageIOSName[];
+extern const char kPolicyLogsPageIOSDescription[];
+
 // Title and description for the flag to have the Promos Manager use the FET as
 // its impression tracking system.
 extern const char kPromosManagerUsesFETName[];
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm b/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm
index 64040f9..f020eaf 100644
--- a/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm
+++ b/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm
@@ -43,7 +43,7 @@
 constexpr base::TimeDelta kPromoTimeout = base::Seconds(45);
 
 bool PromoCanBeDisplayed() {
-  if (IsInBlueDotExperiment()) {
+  if (!AreDefaultBrowserPromosEnabled()) {
     return false;
   }
 
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_utils.h b/ios/chrome/browser/ui/default_promo/default_browser_utils.h
index 58ce82d..8b90928 100644
--- a/ios/chrome/browser/ui/default_promo/default_browser_utils.h
+++ b/ios/chrome/browser/ui/default_promo/default_browser_utils.h
@@ -77,12 +77,13 @@
 // description and "Learn More" text.
 bool IsInModifiedStringsGroup();
 
-// Returns true if the user is in the default browser blue dot experiment.
-bool IsInBlueDotExperiment();
+// Returns true if the user is not in the blue dot default browser experiment,
+// or if they are in the group with all DB promos enabled.
+bool AreDefaultBrowserPromosEnabled();
 
 // Returns true if the user is in the default browser blue dot experiment and in
-// the blue dot active/enabled group.
-bool IsInBlueDotExperimentEnabledGroup();
+// one of the blue dot active/enabled groups.
+bool IsBlueDotPromoEnabled();
 
 // Returns true if the user is in the CTA experiment in the open links group.
 bool IsInCTAOpenLinksGroup();
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_utils.mm b/ios/chrome/browser/ui/default_promo/default_browser_utils.mm
index a69a920..54b002dd 100644
--- a/ios/chrome/browser/ui/default_promo/default_browser_utils.mm
+++ b/ios/chrome/browser/ui/default_promo/default_browser_utils.mm
@@ -376,7 +376,7 @@
     const base::Feature& feature,
     feature_engagement::Tracker* tracker) {
   // TODO(crbug.com/1410229) clean-up experiment code when fully launched.
-  if (!IsInBlueDotExperimentEnabledGroup() || IsChromeLikelyDefaultBrowser()) {
+  if (!IsBlueDotPromoEnabled() || IsChromeLikelyDefaultBrowser()) {
     return false;
   }
 
@@ -415,14 +415,21 @@
   return !paramValue.empty();
 }
 
-bool IsInBlueDotExperiment() {
-  return base::FeatureList::IsEnabled(kDefaultBrowserBlueDotPromo);
-}
-
-bool IsInBlueDotExperimentEnabledGroup() {
+bool AreDefaultBrowserPromosEnabled() {
   if (base::FeatureList::IsEnabled(kDefaultBrowserBlueDotPromo)) {
     return kBlueDotPromoUserGroupParam.Get() ==
-           BlueDotPromoUserGroup::kOnlyBlueDotPromoEnabled;
+           BlueDotPromoUserGroup::kAllDBPromosEnabled;
+  }
+
+  return true;
+}
+
+bool IsBlueDotPromoEnabled() {
+  if (base::FeatureList::IsEnabled(kDefaultBrowserBlueDotPromo)) {
+    return kBlueDotPromoUserGroupParam.Get() ==
+               BlueDotPromoUserGroup::kOnlyBlueDotPromoEnabled ||
+           kBlueDotPromoUserGroupParam.Get() ==
+               BlueDotPromoUserGroup::kAllDBPromosEnabled;
   }
 
   return false;
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 521c925..5812f22 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -1153,7 +1153,7 @@
   // Don't show the default browser promo if the user is in the default browser
   // blue dot experiment.
   // TODO(crbug.com/1410229) clean-up experiment code when fully launched.
-  if (IsInBlueDotExperiment()) {
+  if (!AreDefaultBrowserPromosEnabled()) {
     return;
   }
 
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 5dd64513..3a379ea 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -11,6 +11,7 @@
 constexpr base::FeatureParam<BlueDotPromoUserGroup>::Option
     kBlueDotPromoUserGroupOptions[] = {
         {BlueDotPromoUserGroup::kAllDBPromosDisabled, "all-db-promos-disabled"},
+        {BlueDotPromoUserGroup::kAllDBPromosEnabled, "all-db-promos-enabled"},
         {BlueDotPromoUserGroup::kOnlyBlueDotPromoEnabled,
          "only-blue-dot-promo-enabled"}};
 
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index e14950b..ff0b1dc 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -17,6 +17,7 @@
 // default browser promos, which are already shipped.
 enum class BlueDotPromoUserGroup {
   kAllDBPromosDisabled,
+  kAllDBPromosEnabled,
   kOnlyBlueDotPromoEnabled,
 };
 extern const base::FeatureParam<BlueDotPromoUserGroup>
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 71f4de9..712d1326 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -1617,12 +1617,29 @@
     // The leaf cert is used as the key, because the chain provided by
     // `didFailProvisionalNavigation:` will differ (it is the server-supplied
     // chain), thus if intermediates were considered, the keys would mismatch.
+
+    // TODO(crbug.com/1418068): Remove after minimum version required is >=
+    // iOS 15.
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+    base::ScopedCFTypeRef<CFArrayRef> certificateChain(
+        SecTrustCopyCertificateChain(trust));
+    SecCertificateRef secCertificate =
+        base::mac::CFCastStrict<SecCertificateRef>(
+            CFArrayGetValueAtIndex(certificateChain, 0));
+    scoped_refptr<net::X509Certificate> leafCert =
+        net::x509_util::CreateX509CertificateFromSecCertificate(
+            base::ScopedCFTypeRef<SecCertificateRef>(
+                secCertificate, base::scoped_policy::RETAIN),
+            {});
+#else
     scoped_refptr<net::X509Certificate> leafCert =
         net::x509_util::CreateX509CertificateFromSecCertificate(
             base::ScopedCFTypeRef<SecCertificateRef>(
                 SecTrustGetCertificateAtIndex(trust, 0),
                 base::scoped_policy::RETAIN),
             {});
+#endif  // __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+
     if (leafCert) {
       bool is_recoverable =
           policy == web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR_UNDECIDED_BY_USER;
diff --git a/ios/web/security/crw_cert_verification_controller.mm b/ios/web/security/crw_cert_verification_controller.mm
index 66653a6..49766ce 100644
--- a/ios/web/security/crw_cert_verification_controller.mm
+++ b/ios/web/security/crw_cert_verification_controller.mm
@@ -228,12 +228,27 @@
   }
 
   // Check if user has decided to proceed with this bad cert.
+  // TODO(crbug.com/1418068): Remove after minimum version required is >=
+  // iOS 15.
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+  base::ScopedCFTypeRef<CFArrayRef> certificateChain(
+      SecTrustCopyCertificateChain(trust));
+  SecCertificateRef secCertificate = base::mac::CFCastStrict<SecCertificateRef>(
+      CFArrayGetValueAtIndex(certificateChain, 0));
+  scoped_refptr<net::X509Certificate> leafCert =
+      net::x509_util::CreateX509CertificateFromSecCertificate(
+          base::ScopedCFTypeRef<SecCertificateRef>(secCertificate,
+                                                   base::scoped_policy::RETAIN),
+          {});
+#else
   scoped_refptr<net::X509Certificate> leafCert =
       net::x509_util::CreateX509CertificateFromSecCertificate(
           base::ScopedCFTypeRef<SecCertificateRef>(
               SecTrustGetCertificateAtIndex(trust, 0),
               base::scoped_policy::RETAIN),
           {});
+#endif  // __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+
   if (!leafCert)
     return web::CERT_ACCEPT_POLICY_NON_RECOVERABLE_ERROR;
 
diff --git a/ios/web/security/wk_web_view_security_util.mm b/ios/web/security/wk_web_view_security_util.mm
index fd89204..ee69d02af 100644
--- a/ios/web/security/wk_web_view_security_util.mm
+++ b/ios/web/security/wk_web_view_security_util.mm
@@ -75,6 +75,25 @@
   }
 
   std::vector<base::ScopedCFTypeRef<SecCertificateRef>> intermediates;
+
+  // TODO(crbug.com/1418068): Remove after minimum version required is >=
+  // iOS 15.
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+  base::ScopedCFTypeRef<CFArrayRef> certificateChain(
+      SecTrustCopyCertificateChain(trust));
+  for (CFIndex i = 1; i < cert_count; i++) {
+    SecCertificateRef secCertificate =
+        base::mac::CFCastStrict<SecCertificateRef>(
+            CFArrayGetValueAtIndex(certificateChain, i));
+    intermediates.emplace_back(secCertificate, base::scoped_policy::RETAIN);
+  }
+  SecCertificateRef secCertificate = base::mac::CFCastStrict<SecCertificateRef>(
+      CFArrayGetValueAtIndex(certificateChain, 0));
+  return net::x509_util::CreateX509CertificateFromSecCertificate(
+      base::ScopedCFTypeRef<SecCertificateRef>(secCertificate,
+                                               base::scoped_policy::RETAIN),
+      intermediates);
+#else
   for (CFIndex i = 1; i < cert_count; i++) {
     intermediates.emplace_back(SecTrustGetCertificateAtIndex(trust, i),
                                base::scoped_policy::RETAIN);
@@ -83,6 +102,7 @@
       base::ScopedCFTypeRef<SecCertificateRef>(
           SecTrustGetCertificateAtIndex(trust, 0), base::scoped_policy::RETAIN),
       intermediates);
+#endif  // __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
 }
 
 base::ScopedCFTypeRef<SecTrustRef> CreateServerTrustFromChain(NSArray* certs,
diff --git a/ios/web/security/wk_web_view_security_util_unittest.mm b/ios/web/security/wk_web_view_security_util_unittest.mm
index c3e9c0c..ee51e8e 100644
--- a/ios/web/security/wk_web_view_security_util_unittest.mm
+++ b/ios/web/security/wk_web_view_security_util_unittest.mm
@@ -10,6 +10,7 @@
 #import <memory>
 
 #import "base/mac/bridging.h"
+#import "base/mac/foundation_util.h"
 #import "base/mac/scoped_cftyperef.h"
 #import "crypto/rsa_private_key.h"
 #import "net/cert/x509_certificate.h"
@@ -131,9 +132,22 @@
   EXPECT_EQ(static_cast<CFIndex>(chain.count),
             SecTrustGetCertificateCount(server_trust));
   [chain enumerateObjectsUsingBlock:^(id expected_cert, NSUInteger i, BOOL*) {
-    id actual_cert = static_cast<id>(SecTrustGetCertificateAtIndex(
-        server_trust.get(), static_cast<CFIndex>(i)));
-    EXPECT_EQ(expected_cert, actual_cert);
+    SecCertificateRef secCertificate;
+
+    // TODO(crbug.com/1418068): Remove after minimum version required is >=
+    // iOS 15.
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+    base::ScopedCFTypeRef<CFArrayRef> certificateChain(
+        SecTrustCopyCertificateChain(server_trust.get()));
+    secCertificate = base::mac::CFCastStrict<SecCertificateRef>(
+        CFArrayGetValueAtIndex(certificateChain, static_cast<CFIndex>(i)));
+#else
+    secCertificate = SecTrustGetCertificateAtIndex(
+                                                   server_trust.get(), static_cast<CFIndex>(i));
+#endif  // __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_15_0
+
+    id actual_cert = static_cast<id>((__bridge id)secCertificate);
+    EXPECT_NSEQ(expected_cert, actual_cert);
   }];
 
   // Verify policies.
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc
index 03e79f9..3dda656 100644
--- a/media/gpu/chromeos/video_decoder_pipeline.cc
+++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -1017,19 +1017,28 @@
   // Note that fourcc is specified in ImageProcessor's factory method.
   auto fourcc = image_processor->input_config().fourcc;
   auto size = image_processor->input_config().size;
-
+  const size_t kMinImageProcessorOutputFramePoolSize = 10;
   // We need to instantiate an ImageProcessor with a pool large enough to serve
-  // the Renderer pipeline, hence we use |estimated_num_buffers_for_renderer_|.
+  // the Renderer pipeline, it should be enough to use
+  // |estimated_num_buffers_for_renderer_|. Experimentally it is not enough for
+  // some devices that are using ImageProcessor (b/264212288), hence choose the
+  // max from |estimated_num_buffers_for_renderer_| and empirically choosen
+  // kMinImageProcessorOutputFramePoolSize.
+  // TODO(b/270990622): Add VD renderer buffer count parameter and plumb it back
+  // to clients
   //
   // TODO(b/203240043): Verify that if we're using the image processor for tiled
   // to linear transformation, that the created frame pool is of linear format.
   // TODO(b/203240043): Add CHECKs to verify that the image processor is being
   // created for only valid use cases. Writing to a linear output buffer, e.g.
+  const size_t num_buffers =
+      std::max<size_t>(estimated_num_buffers_for_renderer_,
+                       kMinImageProcessorOutputFramePoolSize);
   VLOGF(1) << "Initializing Image Processor frame pool with up to "
-           << estimated_num_buffers_for_renderer_ << " VideoFrames";
+           << num_buffers << " VideoFrames";
   auto status_or_image_processor = ImageProcessorWithPool::Create(
-      std::move(image_processor), main_frame_pool_.get(),
-      estimated_num_buffers_for_renderer_, use_protected, decoder_task_runner_);
+      std::move(image_processor), main_frame_pool_.get(), num_buffers,
+      use_protected, decoder_task_runner_);
   if (!status_or_image_processor.has_value()) {
     DVLOGF(2) << "Unable to create ImageProcessorWithPool.";
     return std::move(status_or_image_processor).error();
diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn
index 0927bad..fdb50e0 100644
--- a/mojo/core/BUILD.gn
+++ b/mojo/core/BUILD.gn
@@ -204,8 +204,6 @@
       sources += [
         "broker_win.cc",
         "channel_win.cc",
-        "platform_handle_security_util_win.cc",
-        "platform_handle_security_util_win.h",
       ]
     }
 
diff --git a/mojo/core/ipcz_driver/transport.cc b/mojo/core/ipcz_driver/transport.cc
index bd0ac88..ecb297f 100644
--- a/mojo/core/ipcz_driver/transport.cc
+++ b/mojo/core/ipcz_driver/transport.cc
@@ -29,7 +29,7 @@
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 #if BUILDFLAG(IS_WIN)
-#include "mojo/core/platform_handle_security_util_win.h"
+#include "mojo/public/cpp/platform/platform_handle_security_util_win.h"
 #endif
 
 namespace mojo::core::ipcz_driver {
diff --git a/mojo/core/platform_handle_in_transit.cc b/mojo/core/platform_handle_in_transit.cc
index 7b46a21a..b30b70e 100644
--- a/mojo/core/platform_handle_in_transit.cc
+++ b/mojo/core/platform_handle_in_transit.cc
@@ -17,7 +17,7 @@
 
 #include "base/win/nt_status.h"
 #include "base/win/scoped_handle.h"
-#include "mojo/core/platform_handle_security_util_win.h"
+#include "mojo/public/cpp/platform/platform_handle_security_util_win.h"
 #endif
 
 namespace mojo {
diff --git a/mojo/core/platform_handle_security_util_win.h b/mojo/core/platform_handle_security_util_win.h
deleted file mode 100644
index fcc5299..0000000
--- a/mojo/core/platform_handle_security_util_win.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_CORE_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
-#define MOJO_CORE_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
-
-#include "base/win/windows_types.h"
-
-namespace mojo::core {
-
-// This function DCHECKs if `handle` is to a writeable file that can be mapped
-// executable. If so, this is a security risk. Does nothing in non-DCHECK
-// builds.
-void DcheckIfFileHandleIsUnsafe(HANDLE handle);
-
-}  // namespace mojo::core
-
-#endif  // MOJO_CORE_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
diff --git a/mojo/public/cpp/platform/BUILD.gn b/mojo/public/cpp/platform/BUILD.gn
index 67b1547..a51ff31 100644
--- a/mojo/public/cpp/platform/BUILD.gn
+++ b/mojo/public/cpp/platform/BUILD.gn
@@ -28,6 +28,11 @@
     sources += [ "socket_utils_posix.cc" ]
   }
 
+  if (is_win) {
+    public += [ "platform_handle_security_util_win.h" ]
+    sources += [ "platform_handle_security_util_win.cc" ]
+  }
+
   public_deps = [
     "//base",
     "//mojo/public/c/system:headers",
diff --git a/mojo/core/platform_handle_security_util_win.cc b/mojo/public/cpp/platform/platform_handle_security_util_win.cc
similarity index 73%
rename from mojo/core/platform_handle_security_util_win.cc
rename to mojo/public/cpp/platform/platform_handle_security_util_win.cc
index 45d0f18..82a04bc 100644
--- a/mojo/core/platform_handle_security_util_win.cc
+++ b/mojo/public/cpp/platform/platform_handle_security_util_win.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 "mojo/core/platform_handle_security_util_win.h"
+#include "mojo/public/cpp/platform/platform_handle_security_util_win.h"
 
 #include <windows.h>
 #include <winternl.h>
@@ -12,16 +12,23 @@
 #include "base/debug/stack_trace.h"
 #include "base/feature_list.h"
 #include "base/features.h"
+#include "base/functional/callback_helpers.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_util.h"
 #include "base/win/nt_status.h"
 #include "base/win/scoped_handle.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace mojo::core {
+namespace mojo {
 
 namespace {
 
+FileHandleSecurityErrorCallback& GetErrorCallback() {
+  static base::NoDestructor<FileHandleSecurityErrorCallback> callback;
+  return *callback;
+}
+
 #if DCHECK_IS_ON()
 
 std::wstring GetPathFromHandle(HANDLE handle) {
@@ -99,13 +106,31 @@
       ::CreateFileW(path.c_str(), FILE_READ_DATA | FILE_EXECUTE,
                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                     nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
-  CHECK(!file_handle.is_valid())
-      << "Transfer of writable handle to executable "
-         "file to an untrusted process: "
-      << path
-      << ". Please use AddFlagsForPassingToUntrustedProcess or call "
-         "PreventExecuteMapping on the FilePath.";
+
+  // If the file cannot be opened with FILE_EXECUTE it means that it is safe.
+  if (!file_handle.is_valid()) {
+    return;
+  }
+
+  auto& error_callback = GetErrorCallback();
+  if (error_callback) {
+    bool handled = error_callback.Run();
+    if (handled) {
+      return;
+    }
+  }
+
+  DLOG(FATAL) << "Transfer of writable handle to executable file to an "
+                 "untrusted process: "
+              << path
+              << ". Please use AddFlagsForPassingToUntrustedProcess or call "
+                 "PreventExecuteMapping on the FilePath.";
 #endif  // DCHECK_IS_ON();
 }
 
-}  // namespace mojo::core
+void SetUnsafeFileHandleCallbackForTesting(
+    FileHandleSecurityErrorCallback callback) {
+  GetErrorCallback() = std::move(callback);
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_handle_security_util_win.h b/mojo/public/cpp/platform/platform_handle_security_util_win.h
new file mode 100644
index 0000000..b44602e1
--- /dev/null
+++ b/mojo/public/cpp/platform/platform_handle_security_util_win.h
@@ -0,0 +1,33 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
+#define MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
+
+#include "base/component_export.h"
+#include "base/functional/callback.h"
+#include "base/win/windows_types.h"
+
+namespace mojo {
+
+using FileHandleSecurityErrorCallback = base::RepeatingCallback<bool()>;
+
+// This function DCHECKs if `handle` is to a writeable file that can be mapped
+// executable. If so, this is a security risk. Does nothing in non-DCHECK
+// builds.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+void DcheckIfFileHandleIsUnsafe(HANDLE handle);
+
+// Sets a callback for testing that will be called before DCHECKing inside
+// DcheckIfFileHandleIsUnsafe because of an insecure handle. If the callback has
+// been set, and returns true, then the error has been successfully handled and
+// a DCHECK will not happen, otherwise DcheckIfFileHandleIsUnsafe will DCHECK as
+// normal.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+void SetUnsafeFileHandleCallbackForTesting(
+    FileHandleSecurityErrorCallback callback);
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_HANDLE_SECURITY_UTIL_WIN_H_
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 7bd4f6f..787b335 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1160,8 +1160,6 @@
       "android/network_change_notifier_factory_android.h",
       "android/network_library.cc",
       "android/network_library.h",
-      "android/radio_activity_tracker.cc",
-      "android/radio_activity_tracker.h",
       "android/traffic_stats.cc",
       "android/traffic_stats.h",
       "cert/cert_verify_proc_android.cc",
diff --git a/net/android/radio_activity_tracker.cc b/net/android/radio_activity_tracker.cc
deleted file mode 100644
index 13dc83a..0000000
--- a/net/android/radio_activity_tracker.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/android/radio_activity_tracker.h"
-
-#include "base/feature_list.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/no_destructor.h"
-#include "net/base/features.h"
-
-namespace net::android {
-
-namespace {
-
-// The minimum interval for recording possible radio wake-ups. It's unlikely
-// that radio state transitions happen in seconds.
-constexpr base::TimeDelta kMinimumRecordIntervalForPossibleWakeupTrigger =
-    base::Seconds(1);
-
-}  // namespace
-
-// static
-RadioActivityTracker& RadioActivityTracker::GetInstance() {
-  static base::NoDestructor<RadioActivityTracker> s_instance;
-  return *s_instance;
-}
-
-RadioActivityTracker::RadioActivityTracker() = default;
-
-bool RadioActivityTracker::ShouldRecordActivityForWakeupTrigger() {
-  if (!base::FeatureList::IsEnabled(features::kRecordRadioWakeupTrigger))
-    return false;
-
-  if (!IsRadioUtilsSupported())
-    return false;
-
-  base::TimeTicks now = base::TimeTicks::Now();
-
-  // Check recording interval first to reduce overheads of calling Android's
-  // platform APIs.
-  if (!last_check_time_.is_null() &&
-      now - last_check_time_ < kMinimumRecordIntervalForPossibleWakeupTrigger)
-    return false;
-
-  last_check_time_ = now;
-
-  bool should_record = ShouldRecordActivityForWakeupTriggerInternal();
-
-  // TODO(crbug.com/1232623): Use "Net." prefix instead of "Network."
-  base::UmaHistogramTimes(
-      "Network.Radio.PossibleWakeupTrigger.RadioUtilsOverhead",
-      base::TimeTicks::Now() - now);
-
-  return should_record;
-}
-
-bool RadioActivityTracker::IsRadioUtilsSupported() {
-  return base::android::RadioUtils::IsSupported() ||
-         radio_activity_override_for_testing_.has_value() ||
-         radio_type_override_for_testing_.has_value();
-}
-
-bool RadioActivityTracker::ShouldRecordActivityForWakeupTriggerInternal() {
-  base::android::RadioConnectionType radio_type =
-      radio_type_override_for_testing_.value_or(
-          base::android::RadioUtils::GetConnectionType());
-  if (radio_type != base::android::RadioConnectionType::kCell)
-    return false;
-
-  absl::optional<base::android::RadioDataActivity> radio_activity =
-      radio_activity_override_for_testing_.has_value()
-          ? radio_activity_override_for_testing_
-          : base::android::RadioUtils::GetCellDataActivity();
-
-  if (!radio_activity.has_value())
-    return false;
-
-  // When the last activity was dormant, don't treat this event as a wakeup
-  // trigger since there could be state transition delay and startup latency.
-  bool should_record =
-      *radio_activity == base::android::RadioDataActivity::kDormant &&
-      last_radio_data_activity_ != base::android::RadioDataActivity::kDormant;
-  last_radio_data_activity_ = *radio_activity;
-  return should_record;
-}
-
-}  // namespace net::android
diff --git a/net/android/radio_activity_tracker.h b/net/android/radio_activity_tracker.h
deleted file mode 100644
index cf342f4a..0000000
--- a/net/android/radio_activity_tracker.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_ANDROID_RADIO_ACTIVITY_TRACKER_H_
-#define NET_ANDROID_RADIO_ACTIVITY_TRACKER_H_
-
-#include "base/android/radio_utils.h"
-#include "base/no_destructor.h"
-#include "base/time/time.h"
-#include "net/base/net_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace net::android {
-
-// Tracks radio states and provides helper methods to record network activities
-// which may trigger power-consuming radio state changes like wake-ups.
-class NET_EXPORT RadioActivityTracker {
- public:
-  static RadioActivityTracker& GetInstance();
-
-  RadioActivityTracker(const RadioActivityTracker&) = delete;
-  RadioActivityTracker& operator=(const RadioActivityTracker&) = delete;
-  RadioActivityTracker(RadioActivityTracker&&) = delete;
-  RadioActivityTracker& operator=(RadioActivityTracker&&) = delete;
-
-  // Returns true when a network activity such as creating a network request and
-  // resolving a host name could trigger a radio wakeup.
-  // TODO(crbug.com/1232623): Consider optimizing this function. This function
-  // uses Android's platform APIs which add non-negligible overheads.
-  bool ShouldRecordActivityForWakeupTrigger();
-
-  // These override internal members for testing.
-  void OverrideRadioActivityForTesting(
-      absl::optional<base::android::RadioDataActivity> radio_activity) {
-    radio_activity_override_for_testing_ = radio_activity;
-  }
-  void OverrideRadioTypeForTesting(
-      absl::optional<base::android::RadioConnectionType> radio_type) {
-    radio_type_override_for_testing_ = radio_type;
-  }
-  void OverrideLastCheckTimeForTesting(base::TimeTicks last_check_time) {
-    last_check_time_ = last_check_time;
-  }
-
- private:
-  friend class base::NoDestructor<RadioActivityTracker>;
-  RadioActivityTracker();
-  ~RadioActivityTracker() = delete;
-
-  // Returns true when RadioUtils is available or any radio states are
-  // overridden for testing.
-  bool IsRadioUtilsSupported();
-
-  // Contains potentially expensive API calls. Factored out to measure
-  // overheads.
-  bool ShouldRecordActivityForWakeupTriggerInternal();
-
-  // Updated when ShouldRecordActivityForWakeupTrigger() is called.
-  base::android::RadioDataActivity last_radio_data_activity_ =
-      base::android::RadioDataActivity::kNone;
-  base::TimeTicks last_check_time_;
-
-  // Radio state overrides for testing.
-  absl::optional<base::android::RadioDataActivity>
-      radio_activity_override_for_testing_;
-  absl::optional<base::android::RadioConnectionType>
-      radio_type_override_for_testing_;
-};
-
-}  // namespace net::android
-
-#endif  // NET_ANDROID_RADIO_ACTIVITY_TRACKER_H_
diff --git a/net/base/features.cc b/net/base/features.cc
index 7c048f8..36ab7bb 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -251,10 +251,6 @@
              "NoncedPartitionedCookies",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kRecordRadioWakeupTrigger,
-             "RecordRadioWakeupTrigger",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kClampCookieExpiryTo400Days,
              "ClampCookieExpiryTo400Days",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/net/base/features.h b/net/base/features.h
index 7a5062b2d..e570b03d 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -309,10 +309,6 @@
 // frames.
 NET_EXPORT BASE_DECLARE_FEATURE(kNoncedPartitionedCookies);
 
-// Enable recording UMAs for network activities which can wake-up radio on
-// Android.
-NET_EXPORT BASE_DECLARE_FEATURE(kRecordRadioWakeupTrigger);
-
 // When enabled, cookies cannot have an expiry date further than 400 days in the
 // future.
 NET_EXPORT BASE_DECLARE_FEATURE(kClampCookieExpiryTo400Days);
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc
index d258486..34b6e19 100644
--- a/net/dns/host_resolver.cc
+++ b/net/dns/host_resolver.cc
@@ -515,7 +515,7 @@
 
 // static
 AddressList HostResolver::EndpointResultToAddressList(
-    const std::vector<HostResolverEndpointResult>& endpoints,
+    base::span<const HostResolverEndpointResult> endpoints,
     const std::set<std::string>& aliases) {
   AddressList list;
 
@@ -534,7 +534,7 @@
 
 // static
 std::vector<IPEndPoint> HostResolver::GetNonProtocolEndpoints(
-    const std::vector<HostResolverEndpointResult>& endpoints) {
+    base::span<const HostResolverEndpointResult> endpoints) {
   auto non_protocol_endpoint =
       base::ranges::find_if(endpoints, &EndpointResultIsNonProtocol);
   if (non_protocol_endpoint == endpoints.end())
@@ -542,6 +542,23 @@
   return non_protocol_endpoint->ip_endpoints;
 }
 
+// static
+bool HostResolver::AllProtocolEndpointsHaveEch(
+    base::span<const HostResolverEndpointResult> endpoints) {
+  bool has_svcb = false;
+  for (const auto& endpoint : endpoints) {
+    if (!endpoint.metadata.supported_protocol_alpns.empty()) {
+      has_svcb = true;
+      if (endpoint.metadata.ech_config_list.empty()) {
+        return false;  // There is a non-ECH SVCB/HTTPS route.
+      }
+    }
+  }
+  // Either there were no SVCB/HTTPS records (should be SVCB-optional), or there
+  // were and all supported ECH (should be SVCB-reliant).
+  return has_svcb;
+}
+
 HostResolver::HostResolver() = default;
 
 // static
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index cd98dd1..b538f751 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -13,6 +13,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/strings/string_piece.h"
 #include "base/values.h"
 #include "net/base/address_family.h"
@@ -513,12 +514,18 @@
   // TODO(crbug.com/1264933): Delete once `AddressList` usage is fully replaced
   // in `HostResolver` and results.
   static AddressList EndpointResultToAddressList(
-      const std::vector<HostResolverEndpointResult>& endpoints,
+      base::span<const HostResolverEndpointResult> endpoints,
       const std::set<std::string>& aliases);
 
-  // Utility to get the non protocol endpoints.
+  // Utility to get the non-protocol endpoints.
   static std::vector<IPEndPoint> GetNonProtocolEndpoints(
-      const std::vector<HostResolverEndpointResult>& endpoints);
+      base::span<const HostResolverEndpointResult> endpoints);
+
+  // Returns whether there is at least one protocol endpoint in `endpoints`, and
+  // all such endpoints have ECH parameters. This can be used to implement the
+  // guidance in section 10.1 of draft-ietf-dnsop-svcb-https-11.
+  static bool AllProtocolEndpointsHaveEch(
+      base::span<const HostResolverEndpointResult> endpoints);
 
  protected:
   HostResolver();
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index a84782cf..33d2b07 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -449,11 +449,13 @@
 
     DCHECK(quic_version_used_.IsKnown());
     IPEndPoint stale_address = endpoint_result_.ip_endpoints.front();
+    bool svcb_optional =
+        IsSvcbOptional(*fresh_resolve_host_request_->GetEndpointResults());
     for (const auto& candidate :
          *fresh_resolve_host_request_->GetEndpointResults()) {
       // TODO(https://crbug.com/1416963): Should other values also be checked
       // for consistency?
-      if (SelectQuicVersion(candidate) == quic_version_used_ &&
+      if (SelectQuicVersion(candidate, svcb_optional) == quic_version_used_ &&
           base::Contains(candidate.ip_endpoints, stale_address)) {
         return true;
       }
@@ -462,11 +464,27 @@
     return false;
   }
 
+  // Returns whether the client should be SVCB-optional when connecting to
+  // `results`.
+  bool IsSvcbOptional(
+      base::span<const HostResolverEndpointResult> results) const {
+    // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all
+    // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of
+    // draft-ietf-dnsop-svcb-https-11.
+    if (!factory_->ssl_config_service_->GetSSLContextConfig()
+             .EncryptedClientHelloEnabled()) {
+      return true;  // ECH is not supported for this request.
+    }
+
+    return !HostResolver::AllProtocolEndpointsHaveEch(results);
+  }
+
   // Returns the QUIC version that would be used with `endpoint_result`, or
   // `quic::ParsedQuicVersion::Unsupported()` if `endpoint_result` cannot be
   // used with QUIC.
   quic::ParsedQuicVersion SelectQuicVersion(
-      const HostResolverEndpointResult& endpoint_result) const {
+      const HostResolverEndpointResult& endpoint_result,
+      bool svcb_optional) const {
     // TODO(davidben): `require_dns_https_alpn_` only exists to be `DCHECK`ed
     // for consistency against `quic_version_`. Remove the parameter?
     DCHECK_EQ(require_dns_https_alpn_, !quic_version_.IsKnown());
@@ -474,12 +492,10 @@
     if (endpoint_result.metadata.supported_protocol_alpns.empty()) {
       // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB
       // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc,
-      // use it. Otherwise, `endpoint_result` is not eligible for QUIC.
-      //
-      // TODO(https://crbug.com/1287248): If all routes have ECH configs, and
-      // ECH is enabled, we should switch to a SVCB-reliant mode. See
-      // draft-ietf-dnsop-svcb-https-11, section 10.1.
-      return quic_version_;
+      // use it in SVCB-optional mode. Otherwise, `endpoint_result` is not
+      // eligible for QUIC.
+      return svcb_optional ? quic_version_
+                           : quic::ParsedQuicVersion::Unsupported();
     }
 
     // Otherwise, `endpoint_result` came from an HTTPS/SVCB record. We can use
@@ -933,9 +949,12 @@
 int QuicStreamFactory::Job::DoCreateSession() {
   // TODO(https://crbug.com/1416409): This logic only knows how to try one
   // endpoint result.
+  bool svcb_optional =
+      IsSvcbOptional(*resolve_host_request_->GetEndpointResults());
   bool found = false;
   for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) {
-    quic::ParsedQuicVersion version = SelectQuicVersion(candidate);
+    quic::ParsedQuicVersion version =
+        SelectQuicVersion(candidate, svcb_optional);
     if (version.IsKnown()) {
       found = true;
       quic_version_used_ = version;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index d9392191..543b6b3 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -15519,4 +15519,83 @@
   EXPECT_FALSE(config.ech_grease_enabled);
 }
 
+// Test that, when the server supports ECH, the connection should use
+// SVCB-reliant behavior.
+TEST_P(QuicStreamFactoryEchTest, EchSvcbReliant) {
+  // The HTTPS-RR route only advertises HTTP/2 and is therefore incompatible
+  // with QUIC. The fallback A/AAAA is compatible, but is ineligible in
+  // ECH-capable clients.
+  std::vector<HostResolverEndpointResult> endpoints(2);
+  endpoints[0].ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
+  endpoints[0].metadata.supported_protocol_alpns = {"h2"};
+  endpoints[0].metadata.ech_config_list = {1, 2, 3, 4};
+  endpoints[1].ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
+
+  host_resolver_ = std::make_unique<MockHostResolver>();
+  host_resolver_->rules()->AddRule(
+      scheme_host_port_.host(),
+      MockHostResolverBase::RuleResolver::RuleResult(std::move(endpoints)));
+
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  MockQuicData socket_data(version_);
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(
+                scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
+                SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
+                /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false,
+                /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
+                failed_on_default_network_callback_, callback_.callback()));
+  EXPECT_THAT(callback_.WaitForResult(),
+              IsError(ERR_DNS_NO_MATCHING_SUPPORTED_ALPN));
+}
+
+// Test that, when ECH is disabled, SVCB-reliant behavior doesn't trigger.
+TEST_P(QuicStreamFactoryEchTest, EchDisabledSvcbOptional) {
+  // The HTTPS-RR route only advertises HTTP/2 and is therefore incompatible
+  // with QUIC. The fallback A/AAAA is compatible, but is ineligible in
+  // ECH-capable clients.
+  std::vector<HostResolverEndpointResult> endpoints(2);
+  endpoints[0].ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
+  endpoints[0].metadata.supported_protocol_alpns = {"h2"};
+  endpoints[0].metadata.ech_config_list = {1, 2, 3, 4};
+  endpoints[1].ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
+
+  host_resolver_ = std::make_unique<MockHostResolver>();
+  host_resolver_->rules()->AddRule(
+      scheme_host_port_.host(),
+      MockHostResolverBase::RuleResolver::RuleResult(std::move(endpoints)));
+
+  // But this client is not ECH-capable, so the connection should succeed.
+  SSLContextConfig ssl_config;
+  ssl_config.ech_enabled = false;
+  ssl_config_service_.UpdateSSLConfigAndNotify(ssl_config);
+
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  MockQuicData socket_data(version_);
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(
+                scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
+                SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
+                /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false,
+                /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
+                failed_on_default_network_callback_, callback_.callback()));
+  EXPECT_THAT(callback_.WaitForResult(), IsOk());
+}
+
 }  // namespace net::test
diff --git a/net/socket/connect_job.h b/net/socket/connect_job.h
index 2650f15..35c0f499 100644
--- a/net/socket/connect_job.h
+++ b/net/socket/connect_job.h
@@ -274,7 +274,7 @@
   WebSocketEndpointLockManager* websocket_endpoint_lock_manager() {
     return common_connect_job_params_->websocket_endpoint_lock_manager;
   }
-  const CommonConnectJobParams* common_connect_job_params() {
+  const CommonConnectJobParams* common_connect_job_params() const {
     return common_connect_job_params_;
   }
 
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc
index 66e5727c..f4c62ce 100644
--- a/net/socket/transport_connect_job.cc
+++ b/net/socket/transport_connect_job.cc
@@ -511,25 +511,21 @@
   // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all routes
   // support ECH, disable the A/AAAA fallback. See Section 10.1 of
   // draft-ietf-dnsop-svcb-https-08.
+
   auto* scheme_host_port =
       absl::get_if<url::SchemeHostPort>(&params_->destination());
-  if (!base::FeatureList::IsEnabled(features::kEncryptedClientHello) ||
-      !scheme_host_port || scheme_host_port->scheme() != url::kHttpsScheme) {
+  if (!scheme_host_port || scheme_host_port->scheme() != url::kHttpsScheme) {
+    return true;  // This is not a SVCB-capable request at all.
+  }
+
+  if (!common_connect_job_params()->ssl_client_context ||
+      !common_connect_job_params()
+           ->ssl_client_context->config()
+           .EncryptedClientHelloEnabled()) {
     return true;  // ECH is not supported for this request.
   }
 
-  bool has_svcb = false;
-  for (const auto& result : results) {
-    if (!result.metadata.supported_protocol_alpns.empty()) {
-      has_svcb = true;
-      if (result.metadata.ech_config_list.empty()) {
-        return true;  // There is a non-ECH SVCB/HTTPS route.
-      }
-    }
-  }
-  // Either there were no SVCB/HTTPS records (should be SVCB-optional), or there
-  // were and all supported ECH (should be SVCB-reliant).
-  return !has_svcb;
+  return !HostResolver::AllProtocolEndpointsHaveEch(results);
 }
 
 bool TransportConnectJob::IsEndpointResultUsable(
diff --git a/net/socket/transport_connect_job_unittest.cc b/net/socket/transport_connect_job_unittest.cc
index 226e15f..01a8d706 100644
--- a/net/socket/transport_connect_job_unittest.cc
+++ b/net/socket/transport_connect_job_unittest.cc
@@ -12,20 +12,24 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "net/base/address_family.h"
-#include "net/base/address_list.h"
 #include "net/base/features.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
+#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/mock_cert_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/dns/public/secure_dns_policy.h"
+#include "net/http/transport_security_state.h"
 #include "net/log/net_log.h"
 #include "net/socket/connect_job_test_util.h"
 #include "net/socket/connection_attempts.h"
+#include "net/socket/ssl_client_socket.h"
 #include "net/socket/stream_socket.h"
 #include "net/socket/transport_client_socket_pool_test_util.h"
+#include "net/ssl/ssl_config_service.h"
+#include "net/ssl/test_ssl_config_service.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_with_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -52,18 +56,18 @@
         common_connect_job_params_(
             &client_socket_factory_,
             &host_resolver_,
-            nullptr /* http_auth_cache */,
-            nullptr /* http_auth_handler_factory */,
-            nullptr /* spdy_session_pool */,
-            nullptr /* quic_supported_versions */,
-            nullptr /* quic_stream_factory */,
-            nullptr /* proxy_delegate */,
-            nullptr /* http_user_agent_settings */,
-            nullptr /* ssl_client_context */,
-            nullptr /* socket_performance_watcher_factory */,
-            nullptr /* network_quality_estimator */,
+            /*http_auth_cache=*/nullptr,
+            /*http_auth_handler_factory=*/nullptr,
+            /*spdy_session_pool=*/nullptr,
+            /*quic_supported_versions=*/nullptr,
+            /*quic_stream_factory=*/nullptr,
+            /*proxy_delegate=*/nullptr,
+            /*http_user_agent_settings=*/nullptr,
+            &ssl_client_context_,
+            /*socket_performance_watcher_factory=*/nullptr,
+            /*network_quality_estimator=*/nullptr,
             NetLog::Get(),
-            nullptr /* websocket_endpoint_lock_manager */) {}
+            /*websocket_endpoint_lock_manager=*/nullptr) {}
 
   ~TransportConnectJobTest() override = default;
 
@@ -87,6 +91,16 @@
   MockHostResolver host_resolver_{/*default_result=*/MockHostResolverBase::
                                       RuleResolver::GetLocalhostResult()};
   MockTransportClientSocketFactory client_socket_factory_;
+  TestSSLConfigService ssl_config_service_{SSLContextConfig{}};
+  MockCertVerifier cert_verifier_;
+  TransportSecurityState transport_security_state_;
+  DefaultCTPolicyEnforcer ct_policy_enforcer_;
+  SSLClientContext ssl_client_context_{&ssl_config_service_,
+                                       &cert_verifier_,
+                                       &transport_security_state_,
+                                       &ct_policy_enforcer_,
+                                       /*ssl_client_session_cache=*/nullptr,
+                                       /*sct_auditing_delegate=*/nullptr};
   const CommonConnectJobParams common_connect_job_params_;
 };
 
@@ -915,8 +929,9 @@
   EXPECT_EQ(attempts[1].endpoint, IPEndPoint(ParseIP("2::"), 8442));
 }
 
-// SVCB-reliant mode should be disabled for ECH servers when ECH is disabled.
-TEST_F(TransportConnectJobTest, SvcbOptionalIfEchDisabled) {
+// SVCB-reliant mode should be disabled for ECH servers when ECH is disabled via
+// `base::Feature`.
+TEST_F(TransportConnectJobTest, SvcbOptionalIfEchDisabledFeature) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndDisableFeature(features::kEncryptedClientHello);
 
@@ -955,6 +970,51 @@
                                         /*expect_sync_result=*/false);
 }
 
+// SVCB-reliant mode should be disabled for ECH servers when ECH is disabled via
+// config.
+TEST_F(TransportConnectJobTest, SvcbOptionalIfEchDisabledConfig) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
+
+  SSLContextConfig config;
+  config.ech_enabled = false;
+  ssl_config_service_.UpdateSSLConfigAndNotify(config);
+
+  HostResolverEndpointResult endpoint1, endpoint2, endpoint3;
+  endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
+  endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
+  endpoint1.metadata.ech_config_list = {1, 2, 3, 4};
+  endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
+  endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
+  endpoint2.metadata.ech_config_list = {1, 2, 3, 4};
+  endpoint3.ip_endpoints = {IPEndPoint(ParseIP("3::"), 443)};
+  // `endpoint3` has no `supported_protocol_alpns` and is thus a fallback route.
+  host_resolver_.rules()->AddRule(
+      kHostName, MockHostResolverBase::RuleResolver::RuleResult(
+                     std::vector{endpoint1, endpoint2, endpoint3}));
+
+  // `TransportConnectJob` should try `endpoint3`.
+  MockTransportClientSocketFactory::Rule rules[] = {
+      MockTransportClientSocketFactory::Rule(
+          MockTransportClientSocketFactory::Type::kFailing,
+          std::vector{IPEndPoint(ParseIP("1::"), 8441)}),
+      MockTransportClientSocketFactory::Rule(
+          MockTransportClientSocketFactory::Type::kFailing,
+          std::vector{IPEndPoint(ParseIP("2::"), 8442)}),
+      MockTransportClientSocketFactory::Rule(
+          MockTransportClientSocketFactory::Type::kSynchronous,
+          std::vector{IPEndPoint(ParseIP("3::"), 443)}),
+  };
+  client_socket_factory_.SetRules(rules);
+
+  TestConnectJobDelegate test_delegate;
+  TransportConnectJob transport_connect_job(
+      DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
+      DefaultHttpsParams(), &test_delegate, /*net_log=*/nullptr);
+  test_delegate.StartJobExpectingResult(&transport_connect_job, OK,
+                                        /*expect_sync_result=*/false);
+}
+
 // SVCB-reliant mode should be disabled if not all SVCB/HTTPS records include
 // ECH.
 TEST_F(TransportConnectJobTest, SvcbOptionalIfEchInconsistent) {
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index 26b41bc..ed5ebbd 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -12,6 +12,8 @@
 import("//testing/test.gni")
 if (is_android) {
   import("//build/config/android/rules.gni")
+} else if (is_ios && use_blink) {
+  import("//build/config/ios/bundle_data_from_filelist.gni")
 }
 
 assert(enable_printing)
@@ -338,6 +340,13 @@
   }
 }
 
+if (is_ios && use_blink) {
+  bundle_data_from_filelist("pdf_metafile_cg_mac_unittest_bundle_data") {
+    testonly = true
+    filelist_name = "test/pdf_metafile_cg_mac_unittest_bundle_data.filelist"
+  }
+}
+
 test("printing_unittests") {
   sources = [
     "backend/print_backend_unittest.cc",
@@ -385,13 +394,17 @@
     ]
   }
 
-  if (is_mac) {
+  if (is_apple) {
     sources += [ "pdf_metafile_cg_mac_unittest.cc" ]
+  }
 
+  if (is_mac) {
     data = [
       "test/data/pdf_cg/",
       "../pdf/test/data/",
     ]
+  } else if (is_ios && use_blink) {
+    deps += [ ":pdf_metafile_cg_mac_unittest_bundle_data" ]
   }
 
   if (is_win) {
diff --git a/printing/test/OWNERS b/printing/test/OWNERS
new file mode 100644
index 0000000..2b3b88a
--- /dev/null
+++ b/printing/test/OWNERS
@@ -0,0 +1,2 @@
+# Anyone can update the unit test bundle data filelist.
+per-file pdf_metafile_cg_mac_unittest_bundle_data.filelist=*
diff --git a/printing/test/PRESUBMIT.py b/printing/test/PRESUBMIT.py
new file mode 100644
index 0000000..90af259
--- /dev/null
+++ b/printing/test/PRESUBMIT.py
@@ -0,0 +1,26 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit checks for printing/test
+
+See https://www.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+PRESUBMIT_VERSION = '2.0.0'
+
+USE_PYTHON3 = True
+
+def CheckChange(input_api, output_api):
+    import sys
+    old_sys_path = sys.path[:]
+    results = []
+    try:
+        sys.path.append(input_api.change.RepositoryRoot())
+        from build.ios import presubmit_support
+        results += presubmit_support.CheckBundleData(
+            input_api, output_api, 'pdf_metafile_cg_mac_unittest_bundle_data')
+    finally:
+        sys.path = old_sys_path
+    return results
diff --git a/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.filelist b/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.filelist
new file mode 100644
index 0000000..965c1fd
--- /dev/null
+++ b/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.filelist
@@ -0,0 +1,24 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# NOTE: this file is generated by build/ios/update_bundle_filelist.py
+#       If it requires updating, you should get a presubmit error with
+#       instructions on how to regenerate. Otherwise, do not edit.
+//printing/test/data/emf/test4.emf
+//printing/test/data/pdf_cg/render_autorotated_portrait_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_autorotated_rotated_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_autorotated_rotated_rectangles_expected.1.png
+//printing/test/data/pdf_cg/render_autorotated_rotated_rectangles_expected.2.png
+//printing/test/data/pdf_cg/render_autorotated_rotated_rectangles_expected.3.png
+//printing/test/data/pdf_cg/render_landscape_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_large_landscape_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_large_portrait_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_portrait_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_rotated_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_rotated_rectangles_expected.1.png
+//printing/test/data/pdf_cg/render_rotated_rectangles_expected.2.png
+//printing/test/data/pdf_cg/render_rotated_rectangles_expected.3.png
+//printing/test/data/pdf_cg/render_scaled_large_landscape_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_scaled_small_landscape_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_small_landscape_rectangles_expected.0.png
+//printing/test/data/pdf_cg/render_small_portrait_rectangles_expected.0.png
diff --git a/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.globlist b/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.globlist
new file mode 100644
index 0000000..c83a1670
--- /dev/null
+++ b/printing/test/pdf_metafile_cg_mac_unittest_bundle_data.globlist
@@ -0,0 +1,9 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# See build/ios/update_bundle_filelist.py for details on how .globlist
+# files are used to update their .filelist counterparts.
+
+//printing/test/data/**
+-//printing/test/data/pdf_cg/README.md
diff --git a/remoting/host/disconnect_window_chromeos.cc b/remoting/host/disconnect_window_chromeos.cc
index 3ce65b3..0f48114 100644
--- a/remoting/host/disconnect_window_chromeos.cc
+++ b/remoting/host/disconnect_window_chromeos.cc
@@ -32,18 +32,14 @@
 DisconnectWindowAura::DisconnectWindowAura() = default;
 
 DisconnectWindowAura::~DisconnectWindowAura() {
-  ash::Shell::Get()->system_tray_notifier()->NotifyScreenShareStop();
+  ash::Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStop();
 }
 
 void DisconnectWindowAura::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  // TODO(kelvinp): Clean up the NotifyScreenShareStart interface when we
-  // completely retire Hangout Remote Desktop v1.
-  std::u16string helper_name;
-  ash::Shell::Get()->system_tray_notifier()->NotifyScreenShareStart(
+  ash::Shell::Get()->system_tray_notifier()->NotifyRemotingScreenShareStart(
       base::BindRepeating(&ClientSessionControl::DisconnectSession,
-                          client_session_control, protocol::OK),
-      helper_name);
+                          client_session_control, protocol::OK));
 }
 
 }  // namespace
diff --git a/services/device/geolocation/geolocation_impl.cc b/services/device/geolocation/geolocation_impl.cc
index 24aa8af..7eeeb7e3 100644
--- a/services/device/geolocation/geolocation_impl.cc
+++ b/services/device/geolocation/geolocation_impl.cc
@@ -108,7 +108,6 @@
   DCHECK(context_);
 
   current_position_ = position;
-  current_position_.valid = ValidateGeoposition(position);
   has_position_to_report_ = true;
 
   if (!position_callback_.is_null())
diff --git a/services/device/geolocation/win/fake_geocoordinate_winrt.cc b/services/device/geolocation/win/fake_geocoordinate_winrt.cc
index 04b34804..f73d622 100644
--- a/services/device/geolocation/win/fake_geocoordinate_winrt.cc
+++ b/services/device/geolocation/win/fake_geocoordinate_winrt.cc
@@ -19,12 +19,31 @@
 FakeGeocoordinateData::FakeGeocoordinateData(const FakeGeocoordinateData& obj) =
     default;
 
+FakeGeopoint::FakeGeopoint(const FakeGeocoordinateData& position_data)
+    : position_data_(position_data) {}
+
+FakeGeopoint::~FakeGeopoint() = default;
+
+IFACEMETHODIMP FakeGeopoint::get_Position(
+    ABI::Windows::Devices::Geolocation::BasicGeoposition* value) {
+  value->Latitude = position_data_.latitude;
+  value->Longitude = position_data_.longitude;
+  value->Altitude = position_data_.altitude.value_or(0.0);
+  return S_OK;
+}
+
 FakeGeocoordinate::FakeGeocoordinate(
     std::unique_ptr<FakeGeocoordinateData> position_data)
     : position_data_(std::move(position_data)) {}
 
 FakeGeocoordinate::~FakeGeocoordinate() = default;
 
+IFACEMETHODIMP FakeGeocoordinate::get_Point(
+    ABI::Windows::Devices::Geolocation::IGeopoint** value) {
+  *value = Make<FakeGeopoint>(*position_data_).Detach();
+  return S_OK;
+}
+
 IFACEMETHODIMP FakeGeocoordinate::get_Latitude(DOUBLE* value) {
   *value = position_data_->latitude;
   return S_OK;
diff --git a/services/device/geolocation/win/fake_geocoordinate_winrt.h b/services/device/geolocation/win/fake_geocoordinate_winrt.h
index d160377..eb64ec3 100644
--- a/services/device/geolocation/win/fake_geocoordinate_winrt.h
+++ b/services/device/geolocation/win/fake_geocoordinate_winrt.h
@@ -26,11 +26,32 @@
   absl::optional<DOUBLE> speed;
 };
 
+class FakeGeopoint
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<
+              Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
+          ABI::Windows::Devices::Geolocation::IGeopoint> {
+ public:
+  explicit FakeGeopoint(const FakeGeocoordinateData& position_data);
+  FakeGeopoint(const FakeGeopoint&) = delete;
+  FakeGeopoint(FakeGeopoint&&) = delete;
+  FakeGeopoint& operator=(const FakeGeopoint&) = delete;
+  FakeGeopoint& operator=(FakeGeopoint&&) = delete;
+  ~FakeGeopoint() override;
+
+  IFACEMETHODIMP get_Position(
+      ABI::Windows::Devices::Geolocation::BasicGeoposition* value) override;
+
+ private:
+  const FakeGeocoordinateData position_data_;
+};
+
 class FakeGeocoordinate
     : public Microsoft::WRL::RuntimeClass<
           Microsoft::WRL::RuntimeClassFlags<
               Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
-          ABI::Windows::Devices::Geolocation::IGeocoordinate> {
+          ABI::Windows::Devices::Geolocation::IGeocoordinate,
+          ABI::Windows::Devices::Geolocation::IGeocoordinateWithPoint> {
  public:
   explicit FakeGeocoordinate(
       std::unique_ptr<FakeGeocoordinateData> position_data);
@@ -39,6 +60,8 @@
   FakeGeocoordinate& operator=(const FakeGeocoordinate&) = delete;
 
   ~FakeGeocoordinate() override;
+  IFACEMETHODIMP get_Point(
+      ABI::Windows::Devices::Geolocation::IGeopoint** point) override;
   IFACEMETHODIMP get_Latitude(DOUBLE* value) override;
   IFACEMETHODIMP get_Longitude(DOUBLE* value) override;
   IFACEMETHODIMP get_Altitude(
diff --git a/services/device/geolocation/win/location_provider_winrt.cc b/services/device/geolocation/win/location_provider_winrt.cc
index 81dff79..aa6ebca3 100644
--- a/services/device/geolocation/win/location_provider_winrt.cc
+++ b/services/device/geolocation/win/location_provider_winrt.cc
@@ -27,9 +27,12 @@
 using ABI::Windows::Devices::Enumeration::DeviceClass;
 using ABI::Windows::Devices::Enumeration::IDeviceAccessInformation;
 using ABI::Windows::Devices::Enumeration::IDeviceAccessInformationStatics;
+using ABI::Windows::Devices::Geolocation::BasicGeoposition;
 using ABI::Windows::Devices::Geolocation::Geolocator;
 using ABI::Windows::Devices::Geolocation::IGeocoordinate;
+using ABI::Windows::Devices::Geolocation::IGeocoordinateWithPoint;
 using ABI::Windows::Devices::Geolocation::IGeolocator;
+using ABI::Windows::Devices::Geolocation::IGeopoint;
 using ABI::Windows::Devices::Geolocation::IGeoposition;
 using ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs;
 using ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs;
@@ -113,6 +116,29 @@
            status == DeviceAccessStatus::DeviceAccessStatus_DeniedByUser);
 }
 
+absl::optional<BasicGeoposition> GetPositionFromCoordinate(
+    const ComPtr<IGeocoordinate>& coordinate) {
+  ComPtr<IGeocoordinateWithPoint> coordinate_with_point = nullptr;
+  const HRESULT query_result = coordinate.As(&coordinate_with_point);
+  if (FAILED(query_result) || !coordinate_with_point) {
+    return absl::nullopt;
+  }
+
+  ComPtr<IGeopoint> point = nullptr;
+  const HRESULT point_result = coordinate_with_point->get_Point(&point);
+  if (FAILED(point_result) || !point) {
+    return absl::nullopt;
+  }
+
+  BasicGeoposition position;
+  const HRESULT position_result = point->get_Position(&position);
+  if (FAILED(position_result)) {
+    return absl::nullopt;
+  }
+
+  return position;
+}
+
 }  // namespace
 
 // LocationProviderWinrt
@@ -253,7 +279,7 @@
     if (FAILED(hr)) {
       RecordUmaEvent(WindowsRTLocationRequestEvent::
                          WINDOWS_RT_LOCATION_CALLBACK_EVENT_FAILURE);
-      if (!last_position_.valid) {
+      if (!ValidateGeoposition(last_position_)) {
         HandleErrorCondition(
             mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE,
             "Unable to add a callback to retrieve position for Geolocation "
@@ -331,7 +357,7 @@
   if (FAILED(hr)) {
     RecordUmaEvent(WindowsRTLocationRequestEvent::
                        WINDOWS_RT_LOCATION_CALLBACK_EVENT_FAILURE);
-    if (!last_position_.valid) {
+    if (!ValidateGeoposition(last_position_)) {
       HandleErrorCondition(
           mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE,
           "Unable to get position from Geolocation API. HRESULT: " +
@@ -348,7 +374,6 @@
     return;
   }
 
-  location_data.valid = true;
   last_position_ = location_data;
 
   if (!position_received_) {
@@ -409,19 +434,21 @@
     return;
   }
 
-  location_data->latitude = GetOptionalDouble([&](DOUBLE* value) -> HRESULT {
-                              return coordinate->get_Latitude(value);
-                            }).value_or(device::mojom::kBadLatitudeLongitude);
-  location_data->longitude = GetOptionalDouble([&](DOUBLE* value) -> HRESULT {
-                               return coordinate->get_Longitude(value);
-                             }).value_or(device::mojom::kBadLatitudeLongitude);
+  const absl::optional<BasicGeoposition> position =
+      GetPositionFromCoordinate(coordinate);
+  if (position) {
+    location_data->latitude = position->Latitude;
+    location_data->longitude = position->Longitude;
+    location_data->altitude = position->Altitude;
+  } else {
+    location_data->latitude = device::mojom::kBadLatitudeLongitude;
+    location_data->longitude = device::mojom::kBadLatitudeLongitude;
+    location_data->altitude = device::mojom::kBadAltitude;
+  }
+
   location_data->accuracy = GetOptionalDouble([&](DOUBLE* value) -> HRESULT {
                               return coordinate->get_Accuracy(value);
                             }).value_or(device::mojom::kBadAccuracy);
-  location_data->altitude =
-      GetReferenceOptionalDouble([&](IReference<DOUBLE>** value) -> HRESULT {
-        return coordinate->get_Altitude(value);
-      }).value_or(device::mojom::kBadAltitude);
   location_data->altitude_accuracy =
       GetReferenceOptionalDouble([&](IReference<DOUBLE>** value) -> HRESULT {
         return coordinate->get_AltitudeAccuracy(value);
@@ -435,6 +462,11 @@
         return coordinate->get_Speed(value);
       }).value_or(device::mojom::kBadSpeed);
   location_data->timestamp = base::Time::Now();
+
+  // Overwrite the altitude if the accuracy is known to be bad.
+  if (location_data->altitude_accuracy == device::mojom::kBadAccuracy) {
+    location_data->altitude = device::mojom::kBadAltitude;
+  }
 }
 
 HRESULT LocationProviderWinrt::GetGeolocator(IGeolocator** geo_locator) {
diff --git a/services/device/public/cpp/test/scoped_geolocation_overrider.cc b/services/device/public/cpp/test/scoped_geolocation_overrider.cc
index 150d79e..c3a4bec 100644
--- a/services/device/public/cpp/test/scoped_geolocation_overrider.cc
+++ b/services/device/public/cpp/test/scoped_geolocation_overrider.cc
@@ -152,13 +152,7 @@
 
 ScopedGeolocationOverrider::FakeGeolocationContext::FakeGeolocationContext(
     mojom::GeopositionPtr position)
-    : position_(std::move(position)) {
-  if (position_) {
-    position_->valid = false;
-    if (ValidateGeoposition(*position_))
-      position_->valid = true;
-  }
-}
+    : position_(std::move(position)) {}
 
 ScopedGeolocationOverrider::FakeGeolocationContext::~FakeGeolocationContext() {}
 
@@ -169,10 +163,6 @@
   if (!position_)
     return;
 
-  position_->valid = false;
-  if (ValidateGeoposition(*position_))
-    position_->valid = true;
-
   for (auto& impl : impls_) {
     impl->UpdateLocation();
   }
@@ -214,10 +204,6 @@
   if (override_position_.is_null())
     return;
 
-  override_position_->valid = false;
-  if (ValidateGeoposition(*override_position_))
-    override_position_->valid = true;
-
   for (auto& impl : impls_) {
     impl->UpdateLocation();
   }
diff --git a/services/device/public/mojom/geoposition.mojom b/services/device/public/mojom/geoposition.mojom
index fcfbd39..5a94ce38 100644
--- a/services/device/public/mojom/geoposition.mojom
+++ b/services/device/public/mojom/geoposition.mojom
@@ -28,9 +28,6 @@
     LAST = POSITION_UNAVAILABLE
   };
 
-  // Whether this geoposition is valid.
-  bool valid;
-
   // These properties correspond to those of the JavaScript Position object
   // although their types may differ.
   // Latitude in decimal degrees north (WGS84 coordinate frame).
diff --git a/services/network/oblivious_http_request_handler.cc b/services/network/oblivious_http_request_handler.cc
index 9eecbafa..a9d8bba1 100644
--- a/services/network/oblivious_http_request_handler.cc
+++ b/services/network/oblivious_http_request_handler.cc
@@ -104,8 +104,7 @@
 std::string CreateAndSerializeBhttpMessage(
     const GURL& request_url,
     const std::string& method,
-    absl::optional<std::string> content_type,
-    absl::optional<std::string> content_data,
+    mojom::ObliviousHttpRequestBodyPtr request_body,
     net::HttpRequestHeaders::HeaderVector headers) {
   std::string host_port = request_url.host();
   if (request_url.has_port()) {
@@ -119,13 +118,14 @@
   // protections (according to the OHTTP spec).
   bhttp_request.AddHeaderField(
       {"Date", base::TimeFormatHTTP(base::Time::Now())});
-  if (content_data) {
-    DCHECK(content_type);
+  if (request_body && !request_body->content.empty()) {
+    DCHECK(!request_body->content_type.empty());
+    bhttp_request.AddHeaderField({net::HttpRequestHeaders::kContentType,
+                                  std::move(request_body->content_type)});
     bhttp_request.AddHeaderField(
-        {net::HttpRequestHeaders::kContentType, std::move(*content_type)});
-    bhttp_request.AddHeaderField({net::HttpRequestHeaders::kContentLength,
-                                  base::NumberToString(content_data->size())});
-    bhttp_request.set_body(std::move(*content_data));
+        {net::HttpRequestHeaders::kContentLength,
+         base::NumberToString(request_body->content.size())});
+    bhttp_request.set_body(std::move(request_body->content));
   }
   for (const auto& header : headers) {
     bhttp_request.AddHeaderField({header.key, header.value});
@@ -279,8 +279,7 @@
 
   std::string bhttp_payload = CreateAndSerializeBhttpMessage(
       state->request->resource_url, state->request->method,
-      std::move(state->request->request_body->content_type),
-      std::move(state->request->request_body->content),
+      std::move(state->request->request_body),
       std::move(headers.value_or(net::HttpRequestHeaders()).GetHeaderVector()));
 
   state->net_log.AddEvent(
diff --git a/services/network/oblivious_http_request_handler_unittest.cc b/services/network/oblivious_http_request_handler_unittest.cc
index ee3ebb60..33260fa5 100644
--- a/services/network/oblivious_http_request_handler_unittest.cc
+++ b/services/network/oblivious_http_request_handler_unittest.cc
@@ -195,6 +195,14 @@
 
   network::mojom::ObliviousHttpRequestPtr CreateRequest() {
     network::mojom::ObliviousHttpRequestPtr request =
+        CreateRequestWithoutBody();
+    request->request_body = network::mojom::ObliviousHttpRequestBody::New(
+        /*content=*/"test data", /*content_type=*/"application/testdata");
+    return request;
+  }
+
+  network::mojom::ObliviousHttpRequestPtr CreateRequestWithoutBody() {
+    network::mojom::ObliviousHttpRequestPtr request =
         network::mojom::ObliviousHttpRequest::New();
     request->relay_url = GURL(kRelayURL);
     request->key_config = CreateTestKeyConfig();
@@ -202,8 +210,6 @@
     request->method = net::HttpRequestHeaders::kGetMethod;
     request->traffic_annotation =
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
-    request->request_body = network::mojom::ObliviousHttpRequestBody::New(
-        /*content=*/"test data", /*content_type=*/"application/testdata");
     return request;
   }
 
@@ -231,6 +237,14 @@
     RespondToPendingRequest("");
     client.WaitForCall();
   }
+  // Empty body
+  {
+    TestOhttpClient client("", net::OK);
+    handler->StartRequest(CreateRequestWithoutBody(),
+                          client.CreatePendingRemote());
+    RespondToPendingRequest("");
+    client.WaitForCall();
+  }
 }
 
 TEST_F(TestObliviousHttpRequestHandler, TestInvalidArguments) {
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 1d504c05..5bb12238 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -728,10 +728,7 @@
     net::QuicSimpleTestServer::Start();
     net::URLRequestFailedJob::AddUrlHandler();
 
-    scoped_feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kAcceptCHFrame,
-                              net::features::kRecordRadioWakeupTrigger},
-        /*disabled_features=*/{});
+    scoped_feature_list_.InitAndEnableFeature(features::kAcceptCHFrame);
   }
   ~URLLoaderTest() override {
     net::URLRequestFilter::GetInstance()->ClearHandlers();
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 98c93b78..b4f1996 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1986,75 +1986,6 @@
       }
     ]
   },
-  "lacros-arm-generic-chrome": {
-    "additional_compile_targets": [
-      "chrome",
-      "linux_symbols",
-      "symupload",
-      "strip_lacros_files"
-    ],
-    "gtest_tests": [
-      {
-        "args": [
-          "--board=jacuzzi",
-          "--flash"
-        ],
-        "experiment_percentage": 100,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "lacros_all_tast_tests jacuzzi",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "jacuzzi",
-              "os": "ChromeOS",
-              "pool": "chrome.tests"
-            }
-          ],
-          "idempotent": false,
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "lacros_all_tast_tests",
-        "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/",
-        "trigger_script": {
-          "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
-        },
-        "variant_id": "jacuzzi"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "isolate_name": "chrome_sizes",
-        "merge": {
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "chrome_sizes",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-18.04",
-              "pool": "chrome.tests"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://chrome/test:chrome_sizes/"
-      }
-    ]
-  },
   "lacros-arm-generic-chrome-skylab": {
     "additional_compile_targets": [
       "chrome",
@@ -2154,37 +2085,6 @@
       }
     ]
   },
-  "lacros-arm64-generic-chrome": {
-    "additional_compile_targets": [
-      "chrome",
-      "linux_symbols",
-      "symupload",
-      "strip_lacros_files"
-    ],
-    "isolated_scripts": [
-      {
-        "isolate_name": "chrome_sizes",
-        "merge": {
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "chrome_sizes",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "pool": "chrome.tests"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://chrome/test:chrome_sizes/"
-      }
-    ]
-  },
   "lacros-arm64-generic-chrome-skylab": {
     "additional_compile_targets": [
       "chrome",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index d636da7f..f9479c0 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -18462,13 +18462,55 @@
     "isolated_scripts": [
       {
         "args": [
-          "--log-wptreport",
-          "--no-wpt-internal",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
           "14c18",
-          "--xctest"
+          "--xctest",
+          "--xcode-parallelization"
+        ],
+        "isolate_name": "ios_cwt_chromedriver_tests_module",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "ios_cwt_chromedriver_tests_module",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://ios/chrome/test/wpt:ios_cwt_chromedriver_tests_module/",
+        "variants": [
+          "SIM_IPHONE_X_16_2"
+        ]
+      },
+      {
+        "args": [
+          "--log-wptreport",
+          "--no-wpt-internal"
         ],
         "experiment_percentage": 100,
         "isolate_name": "wpt_tests_ios",
@@ -18499,12 +18541,6 @@
               "os": "Mac-12"
             }
           ],
-          "named_caches": [
-            {
-              "name": "xcode_ios_14c18",
-              "path": "Xcode.app"
-            }
-          ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 15
         },
@@ -18556,7 +18592,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18608,7 +18644,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18660,7 +18696,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18712,7 +18748,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18764,7 +18800,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18816,7 +18852,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18868,7 +18904,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18920,7 +18956,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -18972,7 +19008,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19024,7 +19060,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19076,7 +19112,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19128,7 +19164,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19180,7 +19216,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19232,7 +19268,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19284,7 +19320,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19336,7 +19372,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19388,7 +19424,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19440,7 +19476,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19492,7 +19528,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19544,7 +19580,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19596,7 +19632,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19648,7 +19684,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19700,7 +19736,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19752,7 +19788,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19804,7 +19840,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19856,7 +19892,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19908,7 +19944,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -19960,7 +19996,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20012,7 +20048,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20064,7 +20100,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20116,7 +20152,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20168,7 +20204,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20220,7 +20256,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20272,7 +20308,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20324,7 +20360,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20376,7 +20412,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20429,7 +20465,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20482,7 +20518,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20535,7 +20571,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20588,7 +20624,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20641,7 +20677,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20694,7 +20730,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20747,7 +20783,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20801,7 +20837,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20855,7 +20891,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20909,7 +20945,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -20963,7 +20999,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21017,7 +21053,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21071,7 +21107,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21125,7 +21161,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21179,7 +21215,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21233,7 +21269,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21287,7 +21323,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21341,7 +21377,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21395,7 +21431,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21449,7 +21485,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21503,7 +21539,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21557,7 +21593,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21611,7 +21647,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21665,7 +21701,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21719,7 +21755,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21772,7 +21808,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21825,7 +21861,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21878,7 +21914,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21931,7 +21967,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -21984,7 +22020,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22037,7 +22073,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22091,7 +22127,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22145,7 +22181,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22199,7 +22235,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22253,7 +22289,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22307,7 +22343,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22360,7 +22396,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22412,7 +22448,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22464,7 +22500,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22516,7 +22552,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22568,7 +22604,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22620,7 +22656,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22672,7 +22708,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22724,7 +22760,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22777,7 +22813,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22831,7 +22867,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22885,7 +22921,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22939,7 +22975,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -22993,7 +23029,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23047,7 +23083,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23100,7 +23136,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23152,7 +23188,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23204,7 +23240,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23257,7 +23293,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23310,7 +23346,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23362,7 +23398,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23415,7 +23451,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23468,7 +23504,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23521,7 +23557,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23574,7 +23610,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23627,7 +23663,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23680,7 +23716,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23732,7 +23768,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23784,7 +23820,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23836,7 +23872,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23888,7 +23924,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23940,7 +23976,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -23992,7 +24028,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24044,7 +24080,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24096,7 +24132,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24148,7 +24184,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24200,7 +24236,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24253,7 +24289,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24306,7 +24342,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24359,7 +24395,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24412,7 +24448,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24465,7 +24501,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24518,7 +24554,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24570,7 +24606,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24622,7 +24658,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24674,7 +24710,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24726,7 +24762,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24778,7 +24814,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24830,7 +24866,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24882,7 +24918,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24934,7 +24970,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -24986,7 +25022,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25038,7 +25074,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25090,7 +25126,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25142,7 +25178,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25194,7 +25230,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25246,7 +25282,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25298,7 +25334,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25350,7 +25386,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25402,7 +25438,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25454,7 +25490,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25506,7 +25542,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25558,7 +25594,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25610,7 +25646,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25662,7 +25698,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25714,7 +25750,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25766,7 +25802,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25818,7 +25854,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25870,7 +25906,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25922,7 +25958,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -25974,7 +26010,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26026,7 +26062,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26078,7 +26114,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26130,7 +26166,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26182,7 +26218,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26234,7 +26270,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26286,7 +26322,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26338,7 +26374,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26390,7 +26426,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26442,7 +26478,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26494,7 +26530,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26546,7 +26582,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26598,7 +26634,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26650,7 +26686,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26702,7 +26738,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26754,7 +26790,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26806,7 +26842,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26858,7 +26894,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26910,7 +26946,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -26962,7 +26998,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27014,7 +27050,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27073,7 +27109,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27125,7 +27161,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27177,7 +27213,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27229,7 +27265,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27281,7 +27317,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27333,7 +27369,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27385,7 +27421,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27437,7 +27473,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27489,7 +27525,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27541,7 +27577,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27593,7 +27629,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27645,7 +27681,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27697,7 +27733,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27749,7 +27785,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27801,7 +27837,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27853,7 +27889,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27905,7 +27941,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -27957,7 +27993,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28012,7 +28048,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28067,7 +28103,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28122,7 +28158,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28177,7 +28213,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28232,7 +28268,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28287,7 +28323,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28343,7 +28379,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28399,7 +28435,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28455,7 +28491,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28511,7 +28547,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28567,7 +28603,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28623,7 +28659,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28679,7 +28715,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28735,7 +28771,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28791,7 +28827,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28847,7 +28883,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28903,7 +28939,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -28959,7 +28995,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29015,7 +29051,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29071,7 +29107,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29126,7 +29162,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29181,7 +29217,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29236,7 +29272,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29291,7 +29327,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29346,7 +29382,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29402,7 +29438,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29458,7 +29494,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29514,7 +29550,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29570,7 +29606,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29623,7 +29659,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29675,7 +29711,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29727,7 +29763,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29779,7 +29815,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29834,7 +29870,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29890,7 +29926,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -29946,7 +29982,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30002,7 +30038,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30058,7 +30094,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30111,7 +30147,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30164,7 +30200,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30216,7 +30252,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30269,7 +30305,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30324,7 +30360,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30379,7 +30415,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30434,7 +30470,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30489,7 +30525,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30544,7 +30580,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30597,7 +30633,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30650,7 +30686,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30702,7 +30738,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30754,7 +30790,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30806,7 +30842,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30858,7 +30894,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30910,7 +30946,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -30965,7 +31001,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31020,7 +31056,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31075,7 +31111,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31130,7 +31166,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31182,7 +31218,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31234,7 +31270,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31286,7 +31322,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31338,7 +31374,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31390,7 +31426,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31442,7 +31478,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31494,7 +31530,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31546,7 +31582,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31598,7 +31634,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31650,7 +31686,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31702,7 +31738,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31754,7 +31790,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31806,7 +31842,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31858,7 +31894,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31910,7 +31946,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -31962,7 +31998,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32014,7 +32050,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32066,7 +32102,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32118,7 +32154,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32170,7 +32206,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32222,7 +32258,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32274,7 +32310,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32326,7 +32362,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32378,7 +32414,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32444,8 +32480,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32499,8 +32534,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32554,8 +32588,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32609,8 +32642,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32664,8 +32696,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32719,8 +32750,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32774,8 +32804,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32829,8 +32858,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32884,8 +32912,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32939,8 +32966,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -32994,8 +33020,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33049,8 +33074,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33104,8 +33128,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33159,8 +33182,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33214,8 +33236,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33269,8 +33290,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33324,8 +33344,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33379,8 +33398,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33434,8 +33452,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33489,8 +33506,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33544,8 +33560,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33599,8 +33614,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33654,8 +33668,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33709,8 +33722,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33764,8 +33776,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33819,8 +33830,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33874,8 +33884,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33929,8 +33938,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -33984,8 +33992,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34039,8 +34046,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34094,8 +34100,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34149,8 +34154,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34204,8 +34208,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34262,8 +34265,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34320,8 +34322,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34378,8 +34379,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34436,8 +34436,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34494,8 +34493,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34552,8 +34550,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34610,8 +34607,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34668,8 +34664,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34726,8 +34721,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34784,8 +34778,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34842,8 +34835,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34900,8 +34892,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -34959,8 +34950,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35018,8 +35008,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35077,8 +35066,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35136,8 +35124,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35195,8 +35182,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35254,8 +35240,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35313,8 +35298,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35372,8 +35356,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35431,8 +35414,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35490,8 +35472,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35549,8 +35530,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35608,8 +35588,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35667,8 +35646,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35726,8 +35704,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35785,8 +35762,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35844,8 +35820,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35903,8 +35878,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -35962,8 +35936,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36021,8 +35994,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36080,8 +36052,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36139,8 +36110,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36198,8 +36168,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36257,8 +36226,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36316,8 +36284,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36375,8 +36342,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36434,8 +36400,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36493,8 +36458,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36552,8 +36516,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36611,8 +36574,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36670,8 +36632,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36729,8 +36690,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36788,8 +36748,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36847,8 +36806,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36905,8 +36863,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -36963,8 +36920,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37021,8 +36977,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37079,8 +37034,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37137,8 +37091,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37195,8 +37148,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37253,8 +37205,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37311,8 +37262,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37369,8 +37319,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37427,8 +37376,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37485,8 +37433,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37544,8 +37491,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37603,8 +37549,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37662,8 +37607,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37721,8 +37665,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37780,8 +37723,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37839,8 +37781,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37898,8 +37839,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -37957,8 +37897,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38016,8 +37955,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38075,8 +38013,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38131,8 +38068,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38186,8 +38122,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38241,8 +38176,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38296,8 +38230,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38351,8 +38284,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38409,8 +38341,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38468,8 +38399,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38527,8 +38457,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38586,8 +38515,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38645,8 +38573,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38704,8 +38631,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38763,8 +38689,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38822,8 +38747,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38881,8 +38805,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38940,8 +38863,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -38999,8 +38921,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39055,8 +38976,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39110,8 +39030,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39165,8 +39084,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39221,8 +39139,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39277,8 +39194,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39333,8 +39249,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39388,8 +39303,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39444,8 +39358,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39500,8 +39413,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39556,8 +39468,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39611,8 +39522,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39666,8 +39576,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39724,8 +39633,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39782,8 +39690,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39840,8 +39747,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39898,8 +39804,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -39956,8 +39861,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40014,8 +39918,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40072,8 +39975,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40130,8 +40032,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40188,8 +40089,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40246,8 +40146,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40304,8 +40203,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40360,8 +40258,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40416,8 +40313,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40471,8 +40367,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40526,8 +40421,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40581,8 +40475,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40636,8 +40529,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40691,8 +40583,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40746,8 +40637,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40801,8 +40691,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40856,8 +40745,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40914,8 +40802,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -40972,8 +40859,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41030,8 +40916,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41088,8 +40973,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41146,8 +41030,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41204,8 +41087,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41262,8 +41144,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41320,8 +41201,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41378,8 +41258,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41436,8 +41315,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41494,8 +41372,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41549,8 +41426,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41604,8 +41480,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41659,8 +41534,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41714,8 +41588,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41769,8 +41642,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41824,8 +41696,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41879,8 +41750,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41934,8 +41804,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -41989,8 +41858,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42044,8 +41912,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42099,8 +41966,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42154,8 +42020,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42209,8 +42074,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42264,8 +42128,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42319,8 +42182,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42374,8 +42236,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42429,8 +42290,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42484,8 +42344,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42539,8 +42398,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42594,8 +42452,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42649,8 +42506,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42704,8 +42560,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42759,8 +42614,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42814,8 +42668,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42869,8 +42722,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42924,8 +42776,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -42979,8 +42830,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43034,8 +42884,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43089,8 +42938,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43144,8 +42992,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43199,8 +43046,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43254,8 +43100,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43309,8 +43154,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43364,8 +43208,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43419,8 +43262,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43474,8 +43316,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
@@ -43529,8 +43370,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "mac_model": "Macmini8,1",
-              "os": "Mac-12"
+              "os": "Mac-13"
             }
           ],
           "named_caches": [
diff --git a/testing/buildbot/chromium.rust.json b/testing/buildbot/chromium.rust.json
index e5db7dc..012e46b 100644
--- a/testing/buildbot/chromium.rust.json
+++ b/testing/buildbot/chromium.rust.json
@@ -1,7 +1,7 @@
 {
   "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {},
   "AAAAA2 See generate_buildbot_json.py to make changes": {},
-  "android-rust-arm-dbg": {
+  "android-rust-arm32-rel": {
     "additional_compile_targets": [
       "mojo_rust",
       "rust_build_tests"
@@ -101,7 +101,107 @@
       }
     ]
   },
-  "android-rust-arm-rel": {
+  "android-rust-arm64-dbg": {
+    "additional_compile_targets": [
+      "mojo_rust",
+      "rust_build_tests"
+    ],
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_unittests",
+        "test_id_prefix": "ninja://base:base_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gnrt_unittests",
+        "test_id_prefix": "ninja://tools/crates/gnrt:gnrt_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "rust_gtest_interop_unittests",
+        "test_id_prefix": "ninja://testing/rust_gtest_interop:rust_gtest_interop_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_cpp_including_rust_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_cpp_including_rust_unittests",
+        "test_id_prefix": "ninja://build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_serde_json_lenient",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "PQ3A.190801.002",
+              "device_os_flavor": "google"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_serde_json_lenient",
+        "test_id_prefix": "ninja://build/rust/tests/test_serde_json_lenient:test_serde_json_lenient/"
+      }
+    ]
+  },
+  "android-rust-arm64-rel": {
     "additional_compile_targets": [
       "mojo_rust",
       "rust_build_tests"
@@ -611,5 +711,605 @@
         "test_id_prefix": "ninja://mojo/public/rust:mojo_rust_tests/"
       }
     ]
+  },
+  "mac-rust-x64-rel": {
+    "additional_compile_targets": [
+      "gnrt_unittests",
+      "mojo_rust",
+      "mojo_rust_tests",
+      "rust_build_tests"
+    ],
+    "gtest_tests": [
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_unittests",
+        "test_id_prefix": "ninja://base:base_unittests/"
+      },
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gnrt_unittests",
+        "test_id_prefix": "ninja://tools/crates/gnrt:gnrt_unittests/"
+      },
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "rust_gtest_interop_unittests",
+        "test_id_prefix": "ninja://testing/rust_gtest_interop:rust_gtest_interop_unittests/"
+      },
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_cpp_including_rust_unittests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_cpp_including_rust_unittests",
+        "test_id_prefix": "ninja://build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests/"
+      },
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_serde_json_lenient",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_serde_json_lenient",
+        "test_id_prefix": "ninja://build/rust/tests/test_serde_json_lenient:test_serde_json_lenient/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "isolate_name": "build_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "build_rust_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "build_rust_tests",
+        "test_id_prefix": "ninja://build/rust/tests:build_rust_tests/"
+      },
+      {
+        "args": [
+          "--out-dir",
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "14c18",
+          "--xctest"
+        ],
+        "isolate_name": "mojo_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "mojo_rust_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/mac_toolchain/${platform}",
+              "location": ".",
+              "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Mac-12"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "xcode_ios_14c18",
+              "path": "Xcode.app"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_rust_tests",
+        "test_id_prefix": "ninja://mojo/public/rust:mojo_rust_tests/"
+      }
+    ]
+  },
+  "win-rust-x64-dbg": {
+    "additional_compile_targets": [
+      "gnrt_unittests",
+      "mojo_rust",
+      "mojo_rust_tests",
+      "rust_build_tests"
+    ],
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_unittests",
+        "test_id_prefix": "ninja://base:base_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gnrt_unittests",
+        "test_id_prefix": "ninja://tools/crates/gnrt:gnrt_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "rust_gtest_interop_unittests",
+        "test_id_prefix": "ninja://testing/rust_gtest_interop:rust_gtest_interop_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_cpp_including_rust_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_cpp_including_rust_unittests",
+        "test_id_prefix": "ninja://build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_serde_json_lenient",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_serde_json_lenient",
+        "test_id_prefix": "ninja://build/rust/tests/test_serde_json_lenient:test_serde_json_lenient/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "build_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "build_rust_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "build_rust_tests",
+        "test_id_prefix": "ninja://build/rust/tests:build_rust_tests/"
+      },
+      {
+        "isolate_name": "mojo_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "mojo_rust_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_rust_tests",
+        "test_id_prefix": "ninja://mojo/public/rust:mojo_rust_tests/"
+      }
+    ]
+  },
+  "win-rust-x64-rel": {
+    "additional_compile_targets": [
+      "gnrt_unittests",
+      "mojo_rust",
+      "mojo_rust_tests",
+      "rust_build_tests"
+    ],
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_unittests",
+        "test_id_prefix": "ninja://base:base_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gnrt_unittests",
+        "test_id_prefix": "ninja://tools/crates/gnrt:gnrt_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "rust_gtest_interop_unittests",
+        "test_id_prefix": "ninja://testing/rust_gtest_interop:rust_gtest_interop_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_cpp_including_rust_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_cpp_including_rust_unittests",
+        "test_id_prefix": "ninja://build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "test_serde_json_lenient",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "test_serde_json_lenient",
+        "test_id_prefix": "ninja://build/rust/tests/test_serde_json_lenient:test_serde_json_lenient/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "build_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "build_rust_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "build_rust_tests",
+        "test_id_prefix": "ninja://build/rust/tests:build_rust_tests/"
+      },
+      {
+        "isolate_name": "mojo_rust_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "mojo_rust_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "os": "Windows-10"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_rust_tests",
+        "test_id_prefix": "ninja://mojo/public/rust:mojo_rust_tests/"
+      }
+    ]
   }
 }
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 41d7e5d..a229aec 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -53,6 +53,7 @@
   testonly = true
 
   data = [
+    "//testing/buildbot/filters/cft.official.browser_tests.filter",
     "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter",
     "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter",
     "//testing/buildbot/filters/code_coverage.browser_tests.filter",
diff --git a/testing/buildbot/filters/cft.official.browser_tests.filter b/testing/buildbot/filters/cft.official.browser_tests.filter
new file mode 100644
index 0000000..1304213
--- /dev/null
+++ b/testing/buildbot/filters/cft.official.browser_tests.filter
@@ -0,0 +1,6 @@
+# crbug/1419576: Positive filter to only run Chrome for Testing info bar tests
+# on the Chrome for Testing official builders.
+#
+# These builders do not require any other test because they can leverage test
+# coverage from the Chrome official builders.
+ChromeForTestingInfoBarTest.*
\ No newline at end of file
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index fa31eb85..45d8353 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -549,6 +549,10 @@
     "label": "//ios/chrome/test/wpt:wpt_tests_ios",
     "type": "generated_script",
   },
+  "ios_cwt_chromedriver_tests_module": {
+    "label": "//ios/chrome/test/wpt:ios_cwt_chromedriver_tests_module",
+    "type": "generated_script",
+  },
   "chrome/browser/media/router": {
     "label": "//chrome/browser/media/router:router",
     "type": "additional_compile_target",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index c049de43..044be44 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1579,16 +1579,6 @@
           ],
         },
       },
-      'lacros-arm-generic-chrome': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'cpu': 'x86-64',
-              'os': 'Ubuntu-18.04',
-            },
-          ],
-        },
-      },
       'lacros-arm-generic-chrome-skylab': {
         'swarming': {
           'dimension_sets': [
@@ -2761,9 +2751,6 @@
   },
   'lacros_all_tast_tests jacuzzi': {
     'modifications': {
-      'lacros-arm-generic-chrome': {
-        'experiment_percentage': 100,
-      },
       'lacros-arm-generic-rel': {
         'ci_only': True,
       },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 090e12ba..5b36b00 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -5520,6 +5520,17 @@
     },
 
     'wpt_tests_ios': {
+      'ios_cwt_chromedriver_tests_module': {
+        'mixins': [
+          'out_dir_arg',
+          'xcode_14_main',
+          'xctest',
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_X_16_2',
+        ]
+      },
       'wpt_tests_ios': {
         'args': [
           '--log-wptreport',
@@ -7259,14 +7270,6 @@
       },
     },
 
-    'lacros_device_arm_tests': {
-      'lacros_all_tast_tests': {
-        'variants': [
-          'LACROS_JACUZZI',
-        ],
-      },
-    },
-
     'lacros_device_arm_tests_rel': {
       'lacros_all_tast_tests': {
         'variants': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 5092634..2052a58 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -237,24 +237,6 @@
         },
         'os_type': 'chromeos',
       },
-      'lacros-arm-generic-chrome': {
-        'additional_compile_targets': [
-          'chrome',
-          'linux_symbols',
-          'symupload',
-          'strip_lacros_files'
-        ],
-        'mixins': [
-          'chrome-swarming-pool',
-        ],
-        'test_suites': {
-          'gtest_tests': 'lacros_device_arm_tests',
-          'isolated_scripts': 'chrome_sizes',
-        },
-        'os_type': 'chromeos',
-      },
-      # TODO(crbug.com/1286898): Merge this to lacros-amd64-generic-chrome
-      # once it's proven to be stable and easy to debug.
       'lacros-arm-generic-chrome-skylab': {
         'additional_compile_targets': [
           'chrome',
@@ -271,21 +253,6 @@
         },
         'os_type': 'chromeos',
       },
-      'lacros-arm64-generic-chrome': {
-        'additional_compile_targets': [
-          'chrome',
-          'linux_symbols',
-          'symupload',
-          'strip_lacros_files'
-        ],
-        'mixins': [
-          'chrome-swarming-pool',
-        ],
-        'test_suites': {
-          'isolated_scripts': 'chrome_sizes',
-        },
-        'os_type': 'chromeos',
-      },
       'lacros-arm64-generic-chrome-skylab': {
         'additional_compile_targets': [
           'chrome',
@@ -3321,9 +3288,6 @@
           'has_native_resultdb_integration',
           'mac_12_x64',
           'mac_toolchain',
-          'out_dir_arg',
-          'xcode_14_main',
-          'xctest',
         ],
         'test_suites': {
           'isolated_scripts': 'wpt_tests_ios',
@@ -3335,7 +3299,7 @@
         ],
         'mixins': [
           'has_native_resultdb_integration',
-          'mac_12_x64',
+          'mac_13_x64',
           'mac_toolchain',
           'out_dir_arg',
           'xcode_14_main',
@@ -3348,7 +3312,7 @@
         ],
         'mixins': [
           'has_native_resultdb_integration',
-          'mac_12_x64',
+          'mac_13_x64',
           'mac_toolchain',
           'out_dir_arg',
           'xcode_14_main',
@@ -3366,7 +3330,7 @@
         ],
         'mixins': [
           'has_native_resultdb_integration',
-          'mac_12_x64',
+          'mac_13_x64',
           'mac_toolchain',
           'out_dir_arg',
           'xcode_14_beta',
@@ -3389,7 +3353,7 @@
         ],
         'mixins': [
           'has_native_resultdb_integration',
-          'mac_12_t2_x64',
+          'mac_13_x64',
           'mac_toolchain',
           'out_dir_arg',
           'xcode_14_beta',
@@ -5540,7 +5504,7 @@
     'name': 'chromium.rust',
     'mixins': ['chromium-tester-service-account'],
     'machines': {
-      'android-rust-arm-dbg': {
+      'android-rust-arm32-rel': {
         'additional_compile_targets': [
           'mojo_rust',
           'rust_build_tests',
@@ -5553,7 +5517,20 @@
           # TODO(https://crbug.com/1260120): Cover `rust_native_tests` here.
         },
       },
-      'android-rust-arm-rel': {
+      'android-rust-arm64-dbg': {
+        'additional_compile_targets': [
+          'mojo_rust',
+          'rust_build_tests',
+        ],
+        'mixins': [ 'pie_fleet' ],
+        'test_suites': {
+          'gtest_tests': 'rust_gtests',
+          # Currently `can_build_rust_unit_tests` is false on Android (because
+          # we need to construct an APK instead of compile an exe).
+          # TODO(https://crbug.com/1260120): Cover `rust_native_tests` here.
+        },
+      },
+      'android-rust-arm64-rel': {
         'additional_compile_targets': [
           'mojo_rust',
           'rust_build_tests',
@@ -5611,7 +5588,58 @@
           'isolated_scripts': 'rust_native_tests',
         },
       },
-
+      'mac-rust-x64-rel' : {
+        'additional_compile_targets': [
+          'gnrt_unittests',
+          'mojo_rust',
+          'mojo_rust_tests',
+          'rust_build_tests',
+        ],
+        'mixins': [
+          'has_native_resultdb_integration',
+          'mac_12_x64',
+          'mac_toolchain',
+          'out_dir_arg',
+          'xcode_14_main',
+          'xctest',
+        ],
+        'test_suites': {
+          'gtest_tests': 'rust_gtests',
+          'isolated_scripts': 'rust_native_tests',
+        },
+      },
+      'win-rust-x64-dbg' : {
+        'additional_compile_targets': [
+          'gnrt_unittests',
+          'mojo_rust',
+          'mojo_rust_tests',
+          'rust_build_tests',
+        ],
+        'mixins': [
+          'win10-any',
+          'x86-64',
+        ],
+        'test_suites': {
+          'gtest_tests': 'rust_gtests',
+          'isolated_scripts': 'rust_native_tests',
+        },
+      },
+      'win-rust-x64-rel' : {
+        'additional_compile_targets': [
+          'gnrt_unittests',
+          'mojo_rust',
+          'mojo_rust_tests',
+          'rust_build_tests',
+        ],
+        'mixins': [
+          'win10-any',
+          'x86-64',
+        ],
+        'test_suites': {
+          'gtest_tests': 'rust_gtests',
+          'isolated_scripts': 'rust_native_tests',
+        },
+      },
     },
   },
   {
diff --git a/testing/scripts/run_finch_smoke_tests_android.py b/testing/scripts/run_finch_smoke_tests_android.py
index 667df7a..af08419 100755
--- a/testing/scripts/run_finch_smoke_tests_android.py
+++ b/testing/scripts/run_finch_smoke_tests_android.py
@@ -62,6 +62,7 @@
 from blinkpy.web_tests.models import test_failures
 from blinkpy.web_tests.port.android import (
     ANDROID_WEBLAYER, ANDROID_WEBVIEW, CHROME_ANDROID)
+from blinkpy.w3c.wpt_results_processor import WPTResultsProcessor
 
 from devil import devil_env
 from devil.android import apk_helper
@@ -128,6 +129,7 @@
     self.layout_test_results_subdir = 'layout-test-results'
     self._device = device
     self.parse_args()
+    self.port.set_option_default('target', self.options.target)
     self._browser_apk_helper = apk_helper.ToHelper(self.options.browser_apk)
 
     self.browser_package_name = self._browser_apk_helper.GetPackageName()
@@ -322,6 +324,10 @@
   def wpt_output(self):
       return self.options.isolated_script_test_output
 
+  @property
+  def _raw_log_path(self):
+    return self.fs.join(self.output_directory, 'finch-smoke-raw-events.log')
+
   def __enter__(self):
     self._device.EnableRoot()
     # Run below commands to ensure that the device can download a seed
@@ -391,24 +397,19 @@
           'run',
       ]
 
-  def process_and_upload_results(self):
-    command = [
-        self.select_python_executable(),
-        os.path.join(BLINK_TOOLS, 'wpt_process_results.py'),
-        '--target',
-        self.options.target,
-        '--web-tests-dir',
-        BLINK_WEB_TESTS,
-        '--artifacts-dir',
-        os.path.join(os.path.dirname(self.wpt_output),
-                      self.layout_test_results_subdir),
-        '--wpt-results',
-        self.wpt_output,
-    ]
-    if self.options.verbose:
-        command.append('--verbose')
-
-    return common.run_command(command)
+  def process_and_upload_results(self, test_name_prefix):
+    processor = WPTResultsProcessor(
+        self.host.filesystem,
+        self.port,
+        artifacts_dir=os.path.join(os.path.dirname(self.wpt_output),
+                                   self.layout_test_results_subdir),
+        test_name_prefix=test_name_prefix)
+    processor.recreate_artifacts_dir()
+    with self.fs.open_text_file_for_reading(self._raw_log_path) as raw_logs:
+        for event in map(json.loads, raw_logs):
+            if event.get('action') != 'shutdown':
+                processor.process_event(event)
+    processor.process_results_json(self.wpt_output)
 
   def wpt_rest_args(self, unknown_args):
     rest_args = list(self._wpt_run_args)
@@ -419,6 +420,7 @@
         '--tests=%s' % self.wpt_root_dir,
         '--metadata=%s' % self.wpt_root_dir,
         '--mojojs-path=%s' % self.mojo_js_directory,
+        '--log-raw=%s' % self._raw_log_path,
     ])
 
     if self.options.default_exclude:
@@ -665,7 +667,7 @@
     # If wpt tests are not run then the file path stored in self.wpt_output
     # was not created. That is why this check exists.
     if os.path.exists(self.wpt_output):
-      self.process_and_upload_results()
+      self.process_and_upload_results(test_run_variation)
 
       with open(self.wpt_output, 'r') as test_harness_results:
         test_harness_results_dict = json.load(test_harness_results)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c015389a..c98e377 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2729,24 +2729,6 @@
             ]
         }
     ],
-    "ChromeOSQsRevampExperiments": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_Dogfood",
-                    "params": {
-                        "launch_stage": "dogfood"
-                    },
-                    "enable_features": [
-                        "QsRevamp"
-                    ]
-                }
-            ]
-        }
-    ],
     "ChromeOSRawPSIMetrics": [
         {
             "platforms": [
@@ -9859,6 +9841,21 @@
             ]
         }
     ],
+    "QsRevampStudy": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "QsRevamp"
+                    ]
+                }
+            ]
+        }
+    ],
     "QueryTiles": [
         {
             "platforms": [
@@ -14255,6 +14252,21 @@
             ]
         }
     ],
+    "WindowLayoutMenu": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "WindowLayoutMenu"
+                    ]
+                }
+            ]
+        }
+    ],
     "ZeroCopyTabCaptureStudyMac": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 4090846d..d90a7547 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -346,10 +346,6 @@
 const char kPrerender2MemoryAcceptablePercentOfSystemMemoryParamName[] =
     "acceptable_percent_of_system_memory";
 
-BASE_FEATURE(kPrerender2InBackground,
-             "Prerender2InBackground",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kPrerender2InNewTab,
              "Prerender2InNewTab",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index c32cdd35..b9f90f5 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -233,7 +233,6 @@
     "platform/web_policy_container.h",
     "platform/web_prescient_networking.h",
     "platform/web_private_ptr.h",
-    "platform/web_request_peer.h",
     "platform/web_runtime_features.h",
     "platform/web_scoped_page_pauser.h",
     "platform/web_scroll_anchor_data.h",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 03613db..734fb63 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -176,9 +176,6 @@
 // pages will not be prerendered even when kPrerender2 is enabled.
 BLINK_COMMON_EXPORT extern const char
     kPrerender2MemoryAcceptablePercentOfSystemMemoryParamName[];
-// Enables to keep prerenderings alive in the background when their visibility
-// state changes to HIDDEN.
-BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kPrerender2InBackground);
 // Enables to run prerendering for new tabs (e.g., target="_blank").
 // See https://crbug.com/1350676.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kPrerender2InNewTab);
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index bbd52a7..57f4dcef 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -13,10 +13,7 @@
 import "services/network/public/mojom/content_security_policy.mojom";
 import "services/network/public/mojom/cross_origin_opener_policy.mojom";
 import "services/network/public/mojom/fetch_api.mojom";
-import "services/network/public/mojom/load_timing_info.mojom";
-import "services/network/public/mojom/network_types.mojom";
 import "services/network/public/mojom/source_location.mojom";
-import "services/network/public/mojom/url_loader_completion_status.mojom";
 import "skia/public/mojom/skcolor.mojom";
 import "third_party/blink/public/mojom/blob/blob.mojom";
 import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
@@ -688,6 +685,22 @@
       => (mojo_base.mojom.String16 content, uint32 start_offset,
           uint32 end_offset);
 
+  // Report ResourceTiming information about cancelled navigation in iframe
+  // initiated from this document. This is required to prevent revealing
+  // information about the status codes to the parent frame. (See crbug.com/1346924)
+  //
+  // Example of cancelled navigations:
+  // - 204 - No Content
+  // - 205 - Reset Content
+  // - Extension blocking navigation (e.g. Ad blocker)
+  // - etc
+  //
+  // |parent_frame_element_type| is used on the blink side to determine the
+  // 'initiator_type' of the entry.
+  AddResourceTimingEntryFromNonNavigatedFrame(
+    ResourceTimingInfo timing,
+    blink.mojom.FrameOwnerElementType parent_frame_element_type);
+
   // Creates an intervention report in the frame with contents |id| and
   // |message|, returns once the report has been queued. |id| identifies the
   // intervention that occurred. |message| is a human-readable string that
@@ -769,6 +782,13 @@
   // network error.
   RenderFallbackContent();
 
+  // Sent to this frame in parent frame's process to render fallback contents.
+  // This is only used for <object> elements that failed a navigation with an
+  // HTTP error.
+  RenderFallbackContentWithResourceTiming(
+      ResourceTimingInfo timing,
+      string server_timing_value);
+
   // Instructs the frame to invoke the beforeunload event handler.
   //
   // The closure callback is invoked to acknowledge the browser that
@@ -963,27 +983,6 @@
   // See https://drafts.csswg.org/css-view-transitions-1/ for details.
   SnapshotDocumentForViewTransition() => (
       blink.mojom.ViewTransitionState view_transition_state);
-
-  // Allows the browser to add a resource timing entry for a subframe
-  // navigation that has failed before committing - a non-ok object navigation
-  // or a no-content response (204/205).
-  AddResourceTimingEntryForFailedSubframeNavigation(
-    blink.mojom.FrameToken subframe_token,
-    url.mojom.Url initial_url,
-    mojo_base.mojom.TimeTicks start_time,
-    mojo_base.mojom.TimeTicks redirect_time,
-    mojo_base.mojom.TimeTicks request_start,
-    mojo_base.mojom.TimeTicks response_start,
-    uint32 response_code,
-    string mime_type,
-    network.mojom.LoadTimingInfo load_timing_info,
-    network.mojom.ConnectionInfo connection_info,
-    string alpn_negotiated_protocol,
-    bool is_secure_transport,
-    bool is_validated,
-    string normalized_server_timing,
-    network.mojom.URLLoaderCompletionStatus completion_status
-  );
 };
 
 // Also implemented in Blink, this interface defines frame-specific methods
diff --git a/third_party/blink/public/mojom/frame/remote_frame.mojom b/third_party/blink/public/mojom/frame/remote_frame.mojom
index dcea8cc..c6d96107 100644
--- a/third_party/blink/public/mojom/frame/remote_frame.mojom
+++ b/third_party/blink/public/mojom/frame/remote_frame.mojom
@@ -120,12 +120,6 @@
   // The navigation initiator's user activation and ad status.
   blink.mojom.NavigationInitiatorActivationAndAdStatus
       initiator_activation_and_ad_status;
-
-  // Whether this navigation was container initiated (e.g. iframe changed src).
-  // Only container-initiated navigations report a resource-timing entry.
-  // Note: when relying on this in the browser process, also make sure to check
-  // that this comes from the renderer process of the parent frame.
-  bool is_container_initiated = false;
 };
 
 // Implemented in Browser, this interface defines frame-specific methods that
@@ -331,6 +325,13 @@
   // network error).
   RenderFallbackContent();
 
+  // Sent to this frame in parent frame's process to render fallback contents.
+  // This is only used for <object> elements that failed a navigation with an
+  // HTTP error.
+  RenderFallbackContentWithResourceTiming(
+      ResourceTimingInfo timing,
+      string server_timing_value);
+
   // Sent to the remote frame placeholder in the parent process so that
   // resource timing information can be added to the parent frame.
   AddResourceTimingFromChild(ResourceTimingInfo timing);
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom
index f81865be..f8cf8ce 100644
--- a/third_party/blink/public/mojom/navigation/navigation_params.mojom
+++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -157,16 +157,6 @@
   // The navigation initiator's user activation and ad status.
   blink.mojom.NavigationInitiatorActivationAndAdStatus
       initiator_activation_and_ad_status;
-
-  // Whether this navigation was container initiated (e.g. iframe changed src).
-  // This is currently partially specified in
-  // https://html.spec.whatwg.org/#create-navigation-params-by-fetching
-  // "If sourceSnapshotParams's fetch client is navigable's container document's
-  // relevant settings object, then set request's initiator type to navigable's
-  // container's local name." This means that only container initiated
-  // navigations should create a resource timing entry.
-  // TODO(https://github.com/whatwg/html/issues/8846): clarify this further.
-  bool is_container_initiated = false;
 };
 
 // Provided by the browser or the renderer -------------------------------------
@@ -282,21 +272,6 @@
 
 // Provided by the browser -----------------------------------------------------
 
-// Only container-initiated navigations report resource timing to the parent.
-// See https://github.com/whatwg/fetch/pull/1579
-enum ParentResourceTimingAccess {
-  kDoNotReport,
-
-  // See https://fetch.spec.whatwg.org/#response-has-cross-origin-redirects
-  // Whether response info (status code, content-type) can be exposed to
-  // resource timing. True for CORS same-origin subresource responses and for
-  // same-origin navigations without cross-origin redirects.
-  // TODO(https://github.com/whatwg/fetch/issues/1602) clarify the spec around
-  // this.
-  kReportWithoutResponseDetails,
-  kReportWithResponseDetails
-};
-
 // Timings collected in the browser during navigation for the
 // Navigation Timing API. Sent to Blink in CommitNavigationParams when
 // the navigation is ready to be committed.
@@ -304,8 +279,6 @@
   mojo_base.mojom.TimeTicks redirect_start;
   mojo_base.mojom.TimeTicks redirect_end;
   mojo_base.mojom.TimeTicks fetch_start;
-
-  ParentResourceTimingAccess parent_resource_timing_access = ParentResourceTimingAccess.kDoNotReport;
 };
 
 // Sent with CommitNavigationParams and should only be set for main-frame
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index f6923df..f38d2942 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3783,7 +3783,7 @@
   kPrivateNetworkAccessFetchedSubFrame = 4442,
   kPrivateNetworkAccessFetchedTopFrame = 4443,
   kDisableThirdPartyStoragePartitioning = 4444,
-  kServiceWorkerFetchHandlerUpdateAfterInitialization = 4445,
+  kServiceWorkerFetchHandlerAddedAfterInitialization = 4445,
   kObsoleteCreateImageBitmapImageOrientationNone = 4446,
   kWindowManagementPermissionDescriptorUsed = 4447,
   kWindowPlacementPermissionDescriptorUsed = 4448,
@@ -3806,8 +3806,8 @@
   kPopoverTypeManual = 4465,
   kPopoverTypeInvalid = 4466,
   kCSSAnchorPositioning = 4467,
-  kServiceWorkerAddHandlerAfterInitialization = 4468,
-  kServiceWorkerSetAttributeHandlerAfterInitialization = 4469,
+  kServiceWorkerEventHandlerAddedAfterInitialization = 4468,
+  kServiceWorkerEventHandlerModifiedAfterInitialization = 4469,
   kAuthorizationCrossOrigin = 4470,
   kCSSColorMixFunction = 4471,
   kCSSColorColorSpecifiedSpace = 4472,
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 87b97a7..4dfaca0 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -191,10 +191,6 @@
 
   // The initiator frame's LocalDOMWindow's has_storage_access state.
   bool has_storage_access = false;
-  // Whether this navigation was initiated by the container, e.g. iframe changed
-  // src. Only container-initiated navigation report resource timing to the
-  // parent.
-  bool is_container_initiated = false;
 };
 
 // This structure holds all information provided by the embedder that is
@@ -538,10 +534,6 @@
 
   // Whether the document should be loaded with the has_storage_access bit set.
   bool has_storage_access = false;
-  // Whether this navigation should report resource timing to the parent,
-  // and if so, whether it should expose/hide response details.
-  mojom::ParentResourceTimingAccess parent_resource_timing_access =
-      mojom::ParentResourceTimingAccess::kDoNotReport;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/web/web_navigation_timings.h b/third_party/blink/public/web/web_navigation_timings.h
index dc713ca..6f0a079 100644
--- a/third_party/blink/public/web/web_navigation_timings.h
+++ b/third_party/blink/public/web/web_navigation_timings.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_NAVIGATION_TIMINGS_H_
 
 #include "base/time/time.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
 
 namespace blink {
 
@@ -16,7 +15,6 @@
   base::TimeTicks redirect_start;
   base::TimeTicks redirect_end;
   base::TimeTicks fetch_start;
-  blink::mojom::ParentResourceTimingAccess parent_resource_timing_access;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 69a6a3ac..157d143 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1783,8 +1783,6 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_delay_node.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_delegated_ink_trail_presenter.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_delegated_ink_trail_presenter.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_info.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_info.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_quota.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_deprecated_storage_quota.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dev_tools_host.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index b115589..9ce6517 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -638,14 +638,12 @@
           "//third_party/blink/renderer/modules/push_messaging/service_worker_global_scope_push.idl",
           "//third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.idl",
           "//third_party/blink/renderer/modules/quota/deprecated_storage_callbacks.idl",
-          "//third_party/blink/renderer/modules/quota/deprecated_storage_info.idl",
           "//third_party/blink/renderer/modules/quota/deprecated_storage_quota.idl",
           "//third_party/blink/renderer/modules/quota/dom_error.idl",
           "//third_party/blink/renderer/modules/quota/navigator_storage_quota.idl",
           "//third_party/blink/renderer/modules/quota/storage_estimate.idl",
           "//third_party/blink/renderer/modules/quota/storage_manager.idl",
           "//third_party/blink/renderer/modules/quota/storage_usage_details.idl",
-          "//third_party/blink/renderer/modules/quota/window_quota.idl",
           "//third_party/blink/renderer/modules/quota/worker_navigator_storage_quota.idl",
           "//third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl",
           "//third_party/blink/renderer/modules/remoteplayback/remote_playback.idl",
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl
index d07a413e..64d12394 100644
--- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl
+++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl
@@ -133,8 +133,11 @@
 
 mojom::blink::RuntimeFeatureStateController*
   RuntimeFeatureStateOverrideContext::GetOrBindRuntimeFeatureStateController(){
+  // TODO(https://crbug.com/1410817): add support for workers/non-frames that
+  // are enabling origin trials to send their information to the browser too.
   if(!runtime_feature_state_controller_remote_.is_bound()){
-    Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
+    CHECK(execution_context_->IsWindow());
+    execution_context_->GetBrowserInterfaceBroker().GetInterface(
       runtime_feature_state_controller_remote_.BindNewPipeAndPassReceiver(execution_context_->GetTaskRunner(TaskType::kInternalDefault)));
   }
   return runtime_feature_state_controller_remote_.get();
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS
index c8ea315e..586ef27 100644
--- a/third_party/blink/renderer/core/DEPS
+++ b/third_party/blink/renderer/core/DEPS
@@ -76,7 +76,6 @@
     "+services/network/public/cpp/request_destination.h",
     "+services/network/public/cpp/request_mode.h",
     "+services/network/public/cpp/resource_request.h",
-    "+services/network/public/cpp/url_loader_completion_status.h",
     "+services/network/public/cpp/web_sandbox_flags.h",
     "+services/service_manager/public",
     "+skia/public/mojom",
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc
index 5a60c1ce..4ffcd14 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -614,6 +614,34 @@
   return CSSMathExpressionNumericLiteral::Create(value, unit_type);
 }
 
+CSSMathExpressionNode*
+CSSMathExpressionOperation::CreateSignRelatedFunctionSimplified(
+    Operands&& operands,
+    CSSValueID function_id) {
+  if (!RuntimeEnabledFeatures::CSSSignRelatedFunctionsEnabled() ||
+      operands[0]->ResolvedUnitType() ==
+          CSSPrimitiveValue::UnitType::kUnknown) {
+    return nullptr;
+  }
+
+  const double value = operands[0]->DoubleValue();
+
+  switch (function_id) {
+    case CSSValueID::kAbs:
+      return CSSMathExpressionNumericLiteral::Create(
+          std::abs(value), operands[0]->ResolvedUnitType());
+    case CSSValueID::kSign: {
+      const double signum =
+          (value == 0 || std::isnan(value)) ? value : ((value > 0) ? 1 : -1);
+      return CSSMathExpressionNumericLiteral::Create(
+          signum, CSSPrimitiveValue::UnitType::kNumber);
+    };
+    default:
+      NOTREACHED();
+      return nullptr;
+  }
+}
+
 // static
 CSSMathExpressionNode*
 CSSMathExpressionOperation::CreateArithmeticOperationSimplified(
@@ -1418,6 +1446,9 @@
       case CSSValueID::kAtan:
       case CSSValueID::kAtan2:
         return RuntimeEnabledFeatures::CSSTrigonometricFunctionsEnabled();
+      case CSSValueID::kAbs:
+      case CSSValueID::kSign:
+        return RuntimeEnabledFeatures::CSSSignRelatedFunctionsEnabled();
       case CSSValueID::kAnchor:
       case CSSValueID::kAnchorSize:
         return RuntimeEnabledFeatures::CSSAnchorPositioningEnabled();
@@ -1542,6 +1573,12 @@
         max_argument_count = 2;
         min_argument_count = 2;
         break;
+      case CSSValueID::kAbs:
+      case CSSValueID::kSign:
+        DCHECK(RuntimeEnabledFeatures::CSSSignRelatedFunctionsEnabled());
+        max_argument_count = 1;
+        min_argument_count = 1;
+        break;
       // TODO(crbug.com/1284199): Support other math functions.
       default:
         break;
@@ -1593,6 +1630,15 @@
         return CSSMathExpressionOperation::
             CreateTrigonometricFunctionSimplified(std::move(nodes),
                                                   function_id);
+      case CSSValueID::kAbs:
+      case CSSValueID::kSign:
+        // TODO(seokho): Relative and Percent values cannot be evaluated at the
+        // parsing time. So we should implement cannot be simplified value
+        // using CalculationExpressionNode
+        DCHECK(RuntimeEnabledFeatures::CSSSignRelatedFunctionsEnabled());
+        return CSSMathExpressionOperation::CreateSignRelatedFunctionSimplified(
+            std::move(nodes), function_id);
+
       // TODO(crbug.com/1284199): Support other math functions.
       default:
         return nullptr;
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h
index 74ec44ee..9914e11c 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.h
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -254,6 +254,10 @@
       const CSSMathExpressionNode* right_side,
       CSSMathOperator op);
 
+  static CSSMathExpressionNode* CreateSignRelatedFunctionSimplified(
+      Operands&& operands,
+      CSSValueID function_id);
+
   CSSMathExpressionOperation(const CSSMathExpressionNode* left_side,
                              const CSSMathExpressionNode* right_side,
                              CSSMathOperator op,
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
index 5a40509..e359a39 100644
--- a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
+++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
@@ -40,7 +40,9 @@
   // At this point, we know that value is in a small range,
   // so we can use a simple cast instead of ClampTo<int>.
   int int_value = static_cast<int>(value);
-  if (value != int_value) {
+  // To handle negative zero, detect signed zero
+  // https://en.wikipedia.org/wiki/Signed_zero
+  if (value != int_value || (value == 0 && std::signbit(value))) {
     return MakeGarbageCollected<CSSNumericLiteralValue>(value, type);
   }
 
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5
index 2906596e3..4152694 100644
--- a/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -1387,6 +1387,10 @@
     "atan2",
     "acos",
 
+    // Sign related functions
+    "sign",
+    "abs",
+
     //<calc-constant>
     //https://drafts.csswg.org/css-values/#calc-syntax
     "infinity",
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index e582f9a..6b2a16e 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -3485,6 +3485,45 @@
   return image_value;
 }
 
+static CSSImageSetOptionValue* ConsumeImageSetOption(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    ConsumeGeneratedImagePolicy generated_image_policy) {
+  CSSValue* image = nullptr;
+  AtomicString url_value = (RuntimeEnabledFeatures::CSSImageSetEnabled()
+                                ? ConsumeUrlOrStringAsStringView(range, context)
+                                : ConsumeUrlAsStringView(range, context))
+                               .ToAtomicString();
+  if (!url_value.IsNull()) {
+    image = CreateCSSImageValueWithReferrer(url_value, context);
+  } else {
+    if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) {
+      return nullptr;
+    }
+
+    image = ConsumeGeneratedImage(range, context);
+    if (!image) {
+      return nullptr;
+    }
+  }
+
+  CSSNumericLiteralValue* resolution = nullptr;
+  if (range.Peek().GetType() == kDimensionToken ||
+      !RuntimeEnabledFeatures::CSSImageSetEnabled()) {
+    if (range.Peek().GetUnitType() != CSSPrimitiveValue::UnitType::kX &&
+        !RuntimeEnabledFeatures::CSSImageSetEnabled()) {
+      return nullptr;
+    }
+
+    resolution = ConsumeResolution(range);
+    if (!resolution || resolution->GetDoubleValue() <= 0.0) {
+      return nullptr;
+    }
+  }
+
+  return MakeGarbageCollected<CSSImageSetOptionValue>(image, resolution);
+}
+
 static CSSValue* ConsumeImageSet(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
@@ -3494,44 +3533,14 @@
   CSSParserTokenRange args = ConsumeFunction(range_copy);
 
   auto* image_set = MakeGarbageCollected<CSSImageSetValue>();
-
   do {
-    CSSValue* image = nullptr;
-
-    AtomicString url_value =
-        (RuntimeEnabledFeatures::CSSImageSetEnabled()
-             ? ConsumeUrlOrStringAsStringView(args, context)
-             : ConsumeUrlAsStringView(args, context))
-            .ToAtomicString();
-    if (!url_value.IsNull()) {
-      image = CreateCSSImageValueWithReferrer(url_value, context);
-    } else {
-      if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) {
-        return nullptr;
-      }
-
-      image = ConsumeGeneratedImage(args, context);
-      if (image == nullptr) {
-        return nullptr;
-      }
+    auto* image_set_option =
+        ConsumeImageSetOption(args, context, generated_image_policy);
+    if (!image_set_option) {
+      return nullptr;
     }
 
-    CSSNumericLiteralValue* resolution = nullptr;
-    if (args.Peek().GetType() == kDimensionToken ||
-        !RuntimeEnabledFeatures::CSSImageSetEnabled()) {
-      if (args.Peek().GetUnitType() != CSSPrimitiveValue::UnitType::kX &&
-          !RuntimeEnabledFeatures::CSSImageSetEnabled()) {
-        return nullptr;
-      }
-
-      resolution = ConsumeResolution(args);
-      if (resolution == nullptr || resolution->GetDoubleValue() <= 0.0) {
-        return nullptr;
-      }
-    }
-
-    image_set->Append(
-        *MakeGarbageCollected<CSSImageSetOptionValue>(image, resolution));
+    image_set->Append(*image_set_option);
   } while (ConsumeCommaIncludingWhitespace(args));
 
   if (!args.AtEnd()) {
@@ -3553,6 +3562,7 @@
   }
 
   range = range_copy;
+
   return image_set;
 }
 
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index d5757118..21debf5a 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -86,6 +86,7 @@
 #include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
 
 namespace blink {
 
@@ -2157,6 +2158,10 @@
   }
 
   editor.RespondToChangedContents(new_selection.Base());
+
+  if (auto* rc = GetDocument().GetResourceCoordinator()) {
+    rc->SetHadUserEdits();
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
index 22bf66c..b211523 100644
--- a/third_party/blink/renderer/core/frame/frame.cc
+++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -342,6 +342,17 @@
       HTMLObjectElement::ErrorEventPolicy::kDispatch);
 }
 
+void Frame::RenderFallbackContentWithResourceTiming(
+    mojom::blink::ResourceTimingInfoPtr timing,
+    const String& server_timing_value) {
+  auto* local_dom_window = To<LocalDOMWindow>(Parent()->DomWindow());
+  DOMWindowPerformance::performance(*local_dom_window)
+      ->AddResourceTimingWithUnparsedServerTiming(
+          std::move(timing), server_timing_value,
+          html_names::kObjectTag.LocalName());
+  RenderFallbackContent();
+}
+
 bool Frame::IsInFencedFrameTree() const {
   DCHECK(!IsDetached());
   if (!features::IsFencedFramesEnabled())
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h
index 5cfb8cd..df85fa1 100644
--- a/third_party/blink/renderer/core/frame/frame.h
+++ b/third_party/blink/renderer/core/frame/frame.h
@@ -481,6 +481,9 @@
   void ClearUserActivationInFrameTree();
 
   void RenderFallbackContent();
+  void RenderFallbackContentWithResourceTiming(
+      mojom::blink::ResourceTimingInfoPtr timing,
+      const String& server_timing_values);
 
   // Only implemented for LocalFrames.
   virtual void ActivateHistoryUserActivationState() {}
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index e26eebb..919ac436 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -229,6 +229,28 @@
 
 namespace {
 
+const AtomicString& ConvertElementTypeToInitiatorType(
+    blink::FrameOwnerElementType frame_owner_elem_type) {
+  switch (frame_owner_elem_type) {
+    case blink::FrameOwnerElementType::kFrame:
+      return blink::html_names::kFrameTag.LocalName();
+    case blink::FrameOwnerElementType::kIframe:
+      return blink::html_names::kIFrameTag.LocalName();
+    case blink::FrameOwnerElementType::kObject:
+      return blink::html_names::kObjectTag.LocalName();
+    case blink::FrameOwnerElementType::kFencedframe:
+      return blink::html_names::kFencedframeTag.LocalName();
+    case blink::FrameOwnerElementType::kEmbed:
+      return blink::html_names::kEmbedTag.LocalName();
+    case blink::FrameOwnerElementType::kPortal:
+      return blink::html_names::kPortalTag.LocalName();
+    case blink::FrameOwnerElementType::kNone:
+      NOTREACHED();
+  }
+  NOTREACHED();
+  return blink::html_names::kFrameTag.LocalName();
+}
+
 // Maintain a global (statically-allocated) hash map indexed by the the result
 // of hashing the |frame_token| passed on creation of a LocalFrame object.
 using LocalFramesByTokenMap = HeapHashMap<uint64_t, WeakMember<LocalFrame>>;
@@ -727,6 +749,15 @@
   return local_root.clip_path_paint_image_generator_.Get();
 }
 
+void LocalFrame::AddResourceTimingEntryFromNonNavigatedFrame(
+    mojom::blink::ResourceTimingInfoPtr timing,
+    blink::FrameOwnerElementType initiator_type) {
+  auto* local_dom_window = DomWindow();
+  DOMWindowPerformance::performance(*local_dom_window)
+      ->AddResourceTiming(std::move(timing),
+                          ConvertElementTypeToInitiatorType(initiator_type));
+}
+
 const SecurityContext* LocalFrame::GetSecurityContext() const {
   return DomWindow() ? &DomWindow()->GetSecurityContext() : nullptr;
 }
@@ -2353,15 +2384,11 @@
 }
 
 void LocalFrame::UpdateBackForwardCacheDisablingFeatures(
-    uint64_t features_mask,
-    const BFCacheBlockingFeatureAndLocations&
-        non_sticky_features_and_js_locations,
-    const BFCacheBlockingFeatureAndLocations&
-        sticky_features_and_js_locations) {
+    BlockingDetails details) {
   // TODO(crbug.com/1366675): Add two Vectors to argument of
   // DidChangeBackForwardCacheDisablingFeatures
   GetBackForwardCacheControllerHostRemote()
-      .DidChangeBackForwardCacheDisablingFeatures(features_mask);
+      .DidChangeBackForwardCacheDisablingFeatures(details.feature_mask);
 }
 
 const base::UnguessableToken& LocalFrame::GetAgentClusterId() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index bd10cad9..ff71639 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -293,6 +293,10 @@
   BoxShadowPaintImageGenerator* GetBoxShadowPaintImageGenerator();
   ClipPathPaintImageGenerator* GetClipPathPaintImageGenerator();
 
+  void AddResourceTimingEntryFromNonNavigatedFrame(
+      mojom::blink::ResourceTimingInfoPtr timing,
+      blink::FrameOwnerElementType initiator_type);
+
   // A local root is the root of a connected subtree that contains only
   // LocalFrames. The local root is responsible for coordinating input, layout,
   // et cetera for that subtree of frames.
@@ -904,11 +908,7 @@
   ukm::SourceId GetUkmSourceId() override;
   void UpdateTaskTime(base::TimeDelta time) override;
   void UpdateBackForwardCacheDisablingFeatures(
-      uint64_t features_mask,
-      const BFCacheBlockingFeatureAndLocations&
-          non_sticky_features_and_js_locations,
-      const BFCacheBlockingFeatureAndLocations&
-          sticky_features_and_js_locations) override;
+      BlockingDetails details) override;
   const base::UnguessableToken& GetAgentClusterId() const override;
 
   // Activates the user activation states of this frame and all its ancestors.
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 2e876bb..553afb5 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -187,8 +187,7 @@
       const LocalFrameToken* initiator_frame_token,
       std::unique_ptr<SourceLocation> source_location,
       mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>
-          initiator_policy_container_handle,
-      bool is_container_initiated) = 0;
+          initiator_policy_container_handle) = 0;
 
   virtual void DispatchWillSendSubmitEvent(HTMLFormElement*) = 0;
 
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 3e43e9d7..c4a59332 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
@@ -526,8 +526,7 @@
     const LocalFrameToken* initiator_frame_token,
     std::unique_ptr<SourceLocation> source_location,
     mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>
-        initiator_policy_container_keep_alive_handle,
-    bool is_container_initiated) {
+        initiator_policy_container_keep_alive_handle) {
   if (!web_frame_->Client())
     return;
 
@@ -686,7 +685,6 @@
                                                     .GetSandboxFlags();
 
   navigation_info->href_translate = href_translate;
-  navigation_info->is_container_initiated = is_container_initiated;
 
   web_frame_->Client()->BeginNavigation(std::move(navigation_info));
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
index fc56200..5d2c642 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -138,8 +138,7 @@
       const LocalFrameToken* initiator_frame_token,
       std::unique_ptr<SourceLocation> source_location,
       mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>
-          initiator_policy_container_keep_alive_handle,
-      bool is_container_initiated) override;
+          initiator_policy_container_keep_alive_handle) override;
   void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
   void DidStartLoading() override;
   void DidStopLoading() override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index fe43461..238edb9c5 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -10,8 +10,6 @@
 #include "build/build_config.h"
 #include "components/power_scheduler/power_mode.h"
 #include "components/power_scheduler/power_mode_arbiter.h"
-#include "services/network/public/cpp/url_loader_completion_status.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/chrome_debug_urls.h"
@@ -69,7 +67,6 @@
 #include "third_party/blink/renderer/core/script/classic_script.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h"
 #include "third_party/blink/renderer/platform/widget/frame_widget.h"
 
 #if BUILDFLAG(IS_MAC)
@@ -670,6 +667,20 @@
   frame_->RenderFallbackContent();
 }
 
+void LocalFrameMojoHandler::RenderFallbackContentWithResourceTiming(
+    mojom::blink::ResourceTimingInfoPtr timing,
+    const String& server_timing_value) {
+  frame_->RenderFallbackContentWithResourceTiming(std::move(timing),
+                                                  server_timing_value);
+}
+
+void LocalFrameMojoHandler::AddResourceTimingEntryFromNonNavigatedFrame(
+    mojom::blink::ResourceTimingInfoPtr timing,
+    blink::FrameOwnerElementType parent_frame_owner_element_type) {
+  frame_->AddResourceTimingEntryFromNonNavigatedFrame(
+      std::move(timing), parent_frame_owner_element_type);
+}
+
 void LocalFrameMojoHandler::BeforeUnload(bool is_reload,
                                          BeforeUnloadCallback callback) {
   base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
@@ -1345,51 +1356,6 @@
   BeforeUnload(is_reload, std::move(callback));
 }
 
-void LocalFrameMojoHandler::AddResourceTimingEntryForFailedSubframeNavigation(
-    const FrameToken& subframe_token,
-    const KURL& initial_url,
-    base::TimeTicks start_time,
-    base::TimeTicks redirect_time,
-    base::TimeTicks request_start,
-    base::TimeTicks response_start,
-    uint32_t response_code,
-    const WTF::String& mime_type,
-    network::mojom::blink::LoadTimingInfoPtr load_timing_info,
-    net::HttpResponseInfo::ConnectionInfo connection_info,
-    const WTF::String& alpn_negotiated_protocol,
-    bool is_secure_transport,
-    bool is_validated,
-    const WTF::String& normalized_server_timing,
-    const network::URLLoaderCompletionStatus& completion_status) {
-  Frame* subframe = Frame::ResolveFrame(subframe_token);
-  if (!subframe || !subframe->Owner()) {
-    return;
-  }
-
-  ResourceResponse response;
-  response.SetAlpnNegotiatedProtocol(AtomicString(alpn_negotiated_protocol));
-  response.SetConnectionInfo(connection_info);
-  response.SetConnectionReused(load_timing_info->socket_reused);
-  response.SetTimingAllowPassed(true);
-  response.SetIsValidated(is_validated);
-  response.SetDecodedBodyLength(completion_status.decoded_body_length);
-  response.SetEncodedBodyLength(completion_status.encoded_body_length);
-  response.SetEncodedDataLength(completion_status.encoded_data_length);
-  response.SetHttpStatusCode(response_code);
-  if (!normalized_server_timing.empty()) {
-    response.SetHttpHeaderField("Server-Timing",
-                                AtomicString(normalized_server_timing));
-  }
-
-  mojom::blink::ResourceTimingInfoPtr info =
-      CreateResourceTimingInfo(start_time, initial_url, &response);
-  info->response_end = completion_status.completion_time;
-  info->last_redirect_end_time = redirect_time;
-  info->is_secure_transport = is_secure_transport;
-  info->timing = std::move(load_timing_info);
-  subframe->Owner()->AddResourceTiming(std::move(info));
-}
-
 void LocalFrameMojoHandler::RequestFullscreenVideoElement() {
   // Find the first video element of the frame.
   for (auto* child = frame_->GetDocument()->documentElement(); child;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
index a31557c9..9e4185a5 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -19,7 +19,6 @@
 #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_remote.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 #if BUILDFLAG(IS_MAC)
 #include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h"
@@ -119,6 +118,12 @@
   void SaveImageAt(const gfx::Point& window_point) final;
   void ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature>&) final;
   void RenderFallbackContent() final;
+  void RenderFallbackContentWithResourceTiming(
+      mojom::blink::ResourceTimingInfoPtr timing,
+      const String& server_timing_values) final;
+  void AddResourceTimingEntryFromNonNavigatedFrame(
+      mojom::blink::ResourceTimingInfoPtr timing,
+      blink::FrameOwnerElementType parent_frame_owner_element_type) final;
   void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) final;
   void MediaPlayerActionAt(
       const gfx::Point& window_point,
@@ -202,23 +207,6 @@
   void SnapshotDocumentForViewTransition(
       SnapshotDocumentForViewTransitionCallback callback) final;
 
-  void AddResourceTimingEntryForFailedSubframeNavigation(
-      const FrameToken& subframe_token,
-      const KURL& initial_url,
-      base::TimeTicks start_time,
-      base::TimeTicks redirect_time,
-      base::TimeTicks request_start,
-      base::TimeTicks response_start,
-      uint32_t response_code,
-      const WTF::String& mime_type,
-      network::mojom::blink::LoadTimingInfoPtr load_timing_info,
-      net::HttpResponseInfo::ConnectionInfo connection_info,
-      const WTF::String& alpn_negotiated_protocol,
-      bool is_secure_transport,
-      bool is_validated,
-      const WTF::String& normalized_server_timing,
-      const ::network::URLLoaderCompletionStatus& completion_status) final;
-
   // blink::mojom::LocalMainFrame overrides:
   void AnimateDoubleTapZoom(const gfx::Point& point,
                             const gfx::Rect& rect) override;
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index b8546a7a..a5c5ed7 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -304,7 +304,6 @@
       GetNavigationInitiatorActivationAndAdStatus(request.HasUserGesture(),
                                                   is_ad_script_in_stack);
 
-  params->is_container_initiated = frame_request.IsContainerInitiated();
   GetRemoteFrameHostRemote().OpenURL(std::move(params));
 }
 
@@ -410,11 +409,25 @@
   Frame::RenderFallbackContent();
 }
 
+void RemoteFrame::RenderFallbackContentWithResourceTiming(
+    mojom::blink::ResourceTimingInfoPtr timing,
+    const String& server_timing_value) {
+  Frame::RenderFallbackContentWithResourceTiming(std::move(timing),
+                                                 server_timing_value);
+}
+
 void RemoteFrame::AddResourceTimingFromChild(
     mojom::blink::ResourceTimingInfoPtr timing) {
   HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner());
   DCHECK(owner_element);
-  owner_element->AddResourceTiming(std::move(timing));
+
+  if (!owner_element->HasPendingFallbackTimingInfo()) {
+    return;
+  }
+
+  DOMWindowPerformance::performance(*owner_element->GetDocument().domWindow())
+      ->AddResourceTiming(std::move(timing), owner_element->localName());
+  owner_element->DidReportResourceTiming();
 }
 
 void RemoteFrame::DidStartLoading() {
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h
index eedd7f6..6c1aaec 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -182,6 +182,9 @@
       const base::UnguessableToken& embedding_token) override;
   void SetPageFocus(bool is_focused) override;
   void RenderFallbackContent() override;
+  void RenderFallbackContentWithResourceTiming(
+      mojom::blink::ResourceTimingInfoPtr timing,
+      const String& server_timing_values) final;
   void ScrollRectToVisible(
       const gfx::RectF& rect_to_scroll,
       mojom::blink::ScrollIntoViewParamsPtr params) override;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.cc
index e5ea049..3cc05ff 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.cc
+++ b/third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.cc
@@ -26,7 +26,9 @@
 
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
+#include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -319,8 +321,22 @@
 
 bool HTMLFormControlElementWithState::ShouldSaveAndRestoreFormControlState()
     const {
-  // We don't save/restore control state in a form with autocomplete=off.
-  return isConnected() && ShouldAutocomplete();
+  if (!isConnected()) {
+    return false;
+  }
+  // TODO(crbug.com/1419161): remove this after M113 has been stable for a bit.
+  if (RuntimeEnabledFeatures::
+          FormControlRestoreStateIfAutocompleteOffEnabled()) {
+    return ShouldAutocomplete();
+  }
+  if (Form() && !Form()->ShouldAutocomplete()) {
+    return false;
+  }
+  if (EqualIgnoringASCIICase(FastGetAttribute(html_names::kAutocompleteAttr),
+                             "off")) {
+    return false;
+  }
+  return true;
 }
 
 void HTMLFormControlElementWithState::DispatchInputEvent() {
diff --git a/third_party/blink/renderer/core/html/html_frame_element_base.cc b/third_party/blink/renderer/core/html/html_frame_element_base.cc
index ca9855c..d8df68e 100644
--- a/third_party/blink/renderer/core/html/html_frame_element_base.cc
+++ b/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -93,6 +93,7 @@
 
   KURL url = GetDocument().CompleteURL(url_);
 
+  WillPerformContainerInitiatedNavigation(url);
   // There is no (easy) way to tell if |url_| is relative at this point. That
   // is determined in the KURL constructor. If we fail to create an absolute
   // URL at this point, *and* the base URL is a data URL, assume |url_| was
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index 3f5cdaf..0edf7c8 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -482,7 +482,7 @@
 void HTMLFrameOwnerElement::AddResourceTiming(
     mojom::blink::ResourceTimingInfoPtr info) {
   // Resource timing info should only be reported if the subframe is attached.
-  DCHECK(ContentFrame());
+  DCHECK(ContentFrame() && ContentFrame()->IsLocalFrame());
 
   // Make sure we don't double-report, e.g. in the case of restored iframes.
   if (!HasPendingFallbackTimingInfo()) {
@@ -512,6 +512,17 @@
   fallback_timing_info_.reset();
 }
 
+void HTMLFrameOwnerElement::WillPerformContainerInitiatedNavigation(
+    const KURL& url) {
+  if (!url.ProtocolIsInHTTPFamily() &&
+      !url.ProtocolIs(url::kUuidInPackageScheme)) {
+    return;
+  }
+
+  fallback_timing_info_ = CreateResourceTimingInfo(base::TimeTicks::Now(), url,
+                                                   /*response=*/nullptr);
+}
+
 // This will report fallback timing only if the "real" resource timing had not
 // been previously reported: e.g. a cross-origin iframe without TAO.
 void HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded() {
@@ -693,15 +704,6 @@
     bool replace_current_item) {
   TRACE_EVENT0("navigation", "HTMLFrameOwnerElement::LoadOrRedirectSubframe");
 
-  // If the subframe navigation is aborted or TAO fails, we report a "fallback"
-  // entry that starts at navigation and ends at load/error event.
-  if (url.ProtocolIsInHTTPFamily() ||
-      url.ProtocolIs(url::kUuidInPackageScheme)) {
-    fallback_timing_info_ =
-        CreateResourceTimingInfo(base::TimeTicks::Now(), url,
-                                 /*response=*/nullptr);
-  }
-
   // Update the |should_lazy_load_children_| value according to the "loading"
   // attribute immediately, so that it still gets respected even if the "src"
   // attribute gets parsed in ParseAttribute() before the "loading" attribute
@@ -728,7 +730,6 @@
 
   if (ContentFrame()) {
     FrameLoadRequest frame_load_request(GetDocument().domWindow(), request);
-    frame_load_request.SetIsContainerInitiated(true);
     frame_load_request.SetClientRedirectReason(
         ClientNavigationReason::kFrameNavigation);
     WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
@@ -789,7 +790,6 @@
   }
 
   FrameLoadRequest frame_load_request(GetDocument().domWindow(), request);
-  frame_load_request.SetIsContainerInitiated(true);
   child_frame->Loader().StartNavigation(frame_load_request, child_load_type);
 
   return true;
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h
index 55d4d6f5..ca27f17 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -124,6 +124,8 @@
   void DidReportResourceTiming();
   bool HasPendingFallbackTimingInfo() const;
 
+  void WillPerformContainerInitiatedNavigation(const KURL&);
+
   // For unit tests, manually trigger the UpdateContainerPolicy method.
   void UpdateContainerPolicyForTests() { UpdateContainerPolicy(); }
 
@@ -189,7 +191,6 @@
   // based on the frame attributes.
   virtual network::mojom::blink::TrustTokenParamsPtr ConstructTrustTokenParams()
       const;
-  void ReportFallbackResourceTimingIfNeeded();
 
  protected:
   bool is_swapping_frames() const { return is_swapping_frames_; }
@@ -236,6 +237,7 @@
       bool is_loading_attr_lazy,
       AutomaticLazyLoadReason auto_lazy_load_reason);
 
+  void ReportFallbackResourceTimingIfNeeded();
   // Check if the frame should be lazy-loaded and apply when conditions are
   // passed. Return true when lazy-load is applied.
   bool LazyLoadIfPossible(const KURL&,
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc
index 111fdc2..9072e8b 100644
--- a/third_party/blink/renderer/core/html/html_plugin_element.cc
+++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -631,6 +631,8 @@
       DCHECK(OwnedEmbeddedContentView());
     }
 
+    WillPerformContainerInitiatedNavigation(completed_url);
+
     // If the plugin element already contains a subframe,
     // loadOrRedirectSubframe will re-use it. Otherwise, it will create a
     // new frame and set it as the LayoutEmbeddedContent's EmbeddedContentView,
@@ -708,7 +710,6 @@
 }
 
 void HTMLPlugInElement::DispatchErrorEvent() {
-  ReportFallbackResourceTimingIfNeeded();
   if (IsA<PluginDocument>(GetDocument()) && GetDocument().LocalOwner()) {
     GetDocument().LocalOwner()->DispatchEvent(
         *Event::Create(event_type_names::kError));
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni
index 0da4edb..3f5526c 100644
--- a/third_party/blink/renderer/core/layout/build.gni
+++ b/third_party/blink/renderer/core/layout/build.gni
@@ -440,6 +440,8 @@
   "ng/inline/ng_offset_mapping.h",
   "ng/inline/ng_offset_mapping_builder.cc",
   "ng/inline/ng_offset_mapping_builder.h",
+  "ng/inline/ng_paragraph_line_breaker.cc",
+  "ng/inline/ng_paragraph_line_breaker.h",
   "ng/inline/ng_physical_line_box_fragment.cc",
   "ng/inline/ng_physical_line_box_fragment.h",
   "ng/inline/ng_ruby_utils.cc",
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.cc
index 895cc41..6510b77 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.cc
@@ -17,6 +17,7 @@
  public:
   NGFragmentItemsBuilder items_builder_;
   absl::optional<NGInlineLayoutStateStack> box_states_;
+  absl::optional<LayoutUnit> optional_layout_unit;
   void* pointers[3];
   unsigned number;
   HeapVector<Member<const NGBlockBreakToken>> propagated_float_break_tokens_;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
index 482dd774..eb44af5 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h
@@ -62,6 +62,13 @@
   void ClearPropagatedBreakTokens();
   void PropagateBreakToken(const NGBlockBreakToken*);
 
+  const absl::optional<LayoutUnit>& BalancedAvailableWidth() const {
+    return balanced_available_width_;
+  }
+  void SetBalancedAvailableWidth(absl::optional<LayoutUnit> value) {
+    balanced_available_width_ = value;
+  }
+
  private:
   NGBoxFragmentBuilder* container_builder_ = nullptr;
   NGFragmentItemsBuilder items_builder_;
@@ -75,6 +82,9 @@
   unsigned item_index_ = 0;
 
   HeapVector<Member<const NGBlockBreakToken>> propagated_float_break_tokens_;
+
+  // Used by `NGParagraphLineBreaker`.
+  absl::optional<LayoutUnit> balanced_available_width_;
 };
 
 inline NGLogicalLineItems&
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
index a2f2bc20..381d3df 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -72,6 +72,9 @@
   const char* NGInlineItemTypeToString(int val) const;
 
   NGTextType TextType() const { return static_cast<NGTextType>(text_type_); }
+  bool IsForcedLineBreak() const {
+    return TextType() == NGTextType::kForcedLineBreak;
+  }
   void SetTextType(NGTextType text_type) {
     text_type_ = static_cast<unsigned>(text_type);
   }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index d98f6aa..9709484 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
@@ -45,27 +46,50 @@
 
 namespace blink {
 
+namespace {
+
+inline bool ShouldInitiateBalancing(
+    const NGInlineBreakToken* break_token,
+    const LayoutOpportunityVector& opportunities) {
+  // Block-fragmented boxes are not supported.
+  if (break_token) {
+    return false;
+  }
+  // All lines should have the same available widths. No floats etc.
+  if (opportunities.size() != 1) {
+    return false;
+  }
+  const NGLayoutOpportunity& opportunity = opportunities.front();
+  // Bisection needs a positive available width.
+  if (opportunity.rect.InlineSize() <= LayoutUnit() ||
+      // Block-fragmented boxes are not supported.
+      opportunity.rect.BlockEndOffset() != LayoutUnit::Max() ||
+      // Shape exclusions are not supported.
+      opportunity.HasShapeExclusions()) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm(
     NGInlineNode inline_node,
     const NGConstraintSpace& space,
     const NGInlineBreakToken* break_token,
     const NGColumnSpannerPath* column_spanner_path,
     NGInlineChildLayoutContext* context)
-    : NGLayoutAlgorithm(
-          inline_node,
-          inline_node.GetDocument()
-              .GetStyleResolver()
-              .CreateAnonymousStyleWithDisplay(inline_node.Style(),
-                                               EDisplay::kBlock),
-          space,
-          // Use LTR direction since inline layout handles bidi by itself and
-          // lays out in visual order.
-          TextDirection::kLtr,
-          break_token),
+    : NGLayoutAlgorithm(inline_node,
+                        &inline_node.Style(),
+                        space,
+                        // Use LTR direction since inline layout handles bidi by
+                        // itself and lays out in visual order.
+                        TextDirection::kLtr,
+                        break_token),
       box_states_(nullptr),
       context_(context),
       column_spanner_path_(column_spanner_path),
-      baseline_type_(container_builder_.Style().GetFontBaseline()),
+      baseline_type_(inline_node.Style().GetFontBaseline()),
       quirks_mode_(inline_node.GetDocument().InLineHeightQuirksMode()) {
   DCHECK(context);
 }
@@ -1238,6 +1262,10 @@
   NGLogicalLineItems* const line_box = items_builder->AcquireLogicalLineItems();
   DCHECK(line_box);
 
+  const bool initiate_balancing =
+      Style().TextWrap() == ETextWrap::kBalance &&
+      ShouldInitiateBalancing(break_token, opportunities) &&
+      !column_spanner_path_;
   bool is_line_created = false;
   LayoutUnit line_block_size;
   LayoutUnit block_delta;
@@ -1272,6 +1300,22 @@
         opportunity.ComputeLineLayoutOpportunity(ConstraintSpace(),
                                                  line_block_size, block_delta);
 
+    if (initiate_balancing) {
+      // `ShouldInitiateBalancing` should have checked these conditions.
+      DCHECK(!context_->BalancedAvailableWidth());
+      DCHECK_GT(line_opportunity.AvailableInlineSize(), LayoutUnit());
+      DCHECK_EQ(opportunity.rect.BlockEndOffset(), LayoutUnit::Max());
+      DCHECK(!opportunity.HasShapeExclusions());
+      context_->SetBalancedAvailableWidth(
+          NGParagraphLineBreaker::AttemptParagraphBalancing(
+              Node(), ConstraintSpace(), line_opportunity));
+    }
+    if (const absl::optional<LayoutUnit>& balanced_available_width =
+            context_->BalancedAvailableWidth()) {
+      NGParagraphLineBreaker::PrepareForNextLine(*balanced_available_width,
+                                                 &line_opportunity);
+    }
+
     STACK_UNINITIALIZED NGLineInfo line_info;
     NGLineBreaker line_breaker(
         Node(), NGLineBreakerMode::kContent, ConstraintSpace(),
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc
new file mode 100644
index 0000000..82264bd
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.cc
@@ -0,0 +1,184 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.h"
+
+#include <numeric>
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_info.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
+
+namespace blink {
+
+namespace {
+
+// Max number of lines to balance.
+static constexpr wtf_size_t kMaxLinesToBalance = 4;
+
+struct LineBreakResult {
+  LayoutUnit width;
+};
+
+struct LineBreakResults {
+  STACK_ALLOCATED();
+
+ public:
+  LineBreakResults(const NGInlineNode& node, const NGConstraintSpace& space)
+      : node_(node), space_(space) {}
+
+  wtf_size_t size() const { return lines_.size(); }
+  LayoutUnit LineWidthSum() const {
+    return std::accumulate(lines_.begin(), lines_.end(), LayoutUnit(),
+                           [](LayoutUnit acc, const LineBreakResult& item) {
+                             return acc + item.width;
+                           });
+  }
+
+  void clear() { lines_.clear(); }
+
+  bool BreakLines(const LayoutUnit available_width, wtf_size_t max_lines) {
+    DCHECK(lines_.empty());
+    const NGInlineBreakToken* break_token = nullptr;
+    const NGLineLayoutOpportunity line_opportunity(available_width);
+    NGPositionedFloatVector leading_floats;
+    NGExclusionSpace exclusion_space;
+    for (;;) {
+      STACK_UNINITIALIZED NGLineInfo line_info;
+      NGLineBreaker line_breaker(
+          node_, NGLineBreakerMode::kContent, space_, line_opportunity,
+          leading_floats,
+          /* handled_leading_floats_index */ 0, break_token,
+          /* column_spanner_path_ */ nullptr, &exclusion_space);
+      line_breaker.NextLine(&line_info);
+      // Bisecting can't find the desired value if the paragraph has forced line
+      // breaks.
+      DCHECK(!line_info.HasForcedBreak());
+      if (line_info.HasOverflow()) {
+        return false;  // Don't balance if there are overflowing lines.
+      }
+      break_token = line_breaker.CreateBreakToken(line_info);
+      lines_.push_back(LineBreakResult{line_info.Width()});
+      DCHECK_LE(lines_.size(), kMaxLinesToBalance);
+      if (!break_token) {
+        return true;
+      }
+      if (!--max_lines) {
+        return false;  // Didn't fit into `max_lines`.
+      }
+    }
+  }
+
+  LayoutUnit BisectAvailableWidth(const LayoutUnit max_available_width,
+                                  const LayoutUnit min_available_width,
+                                  const LayoutUnit epsilon,
+                                  const wtf_size_t num_lines) {
+    DCHECK_GT(epsilon, LayoutUnit());  // 0 may cause an infinite loop
+    DCHECK_GT(num_lines, 0u);
+    DCHECK_EQ(size(), 0u);
+    LayoutUnit upper = max_available_width;
+    LayoutUnit lower = min_available_width;
+    while (lower + epsilon < upper) {
+      const LayoutUnit middle = (upper + lower) / 2;
+      if (!BreakLines(middle, num_lines)) {
+        lower = middle;
+      } else {
+        DCHECK_LE(size(), num_lines);
+        upper = middle;
+      }
+      clear();
+    }
+    DCHECK_GE(upper, min_available_width);
+    DCHECK_LE(upper, max_available_width);
+    return upper;
+  }
+
+ private:
+  const NGInlineNode node_;
+  const NGConstraintSpace& space_;
+  Vector<LineBreakResult, kMaxLinesToBalance> lines_;
+};
+
+// Estimate the number of lines using the `ch` unit (the space width) without
+// running the line breaker.
+wtf_size_t EstimateNumLines(const String& text_content,
+                            const SimpleFontData* font,
+                            LayoutUnit available_width) {
+  const float space_width = font->SpaceWidth();
+  const wtf_size_t num_line_chars = available_width / space_width;
+  return (text_content.length() + num_line_chars - 1) / num_line_chars;
+}
+
+}  // namespace
+
+// static
+absl::optional<LayoutUnit> NGParagraphLineBreaker::AttemptParagraphBalancing(
+    const NGInlineNode& node,
+    const NGConstraintSpace& space,
+    const NGLineLayoutOpportunity& line_opportunity) {
+  const NGInlineItemsData& items_data = node.ItemsData(
+      /* use_first_line_style */ false);
+  // Bisecting can't balance if there were floating objects, block-in-inline, or
+  // forced line breaks.
+  for (const NGInlineItem& item : items_data.items) {
+    if (item.IsForcedLineBreak() || item.Type() == NGInlineItem::kFloating ||
+        item.Type() == NGInlineItem::kBlockInInline) {
+      return absl::nullopt;
+    }
+  }
+
+  // Estimate the number of lines to see if the text is too long to balance.
+  // Because this is an estimate, allow it to be `kMaxLinesToBalance * 2`.
+  const ComputedStyle& block_style = node.Style();
+  const wtf_size_t estimated_num_lines = EstimateNumLines(
+      items_data.text_content, block_style.GetFont().PrimaryFont(),
+      line_opportunity.AvailableInlineSize());
+  if (estimated_num_lines > kMaxLinesToBalance * 2) {
+    return absl::nullopt;
+  }
+
+  const LayoutUnit available_width = line_opportunity.AvailableInlineSize();
+  LineBreakResults normal_lines(node, space);
+  if (!normal_lines.BreakLines(available_width, kMaxLinesToBalance)) {
+    return absl::nullopt;
+  }
+  const wtf_size_t num_lines = normal_lines.size();
+  DCHECK_LE(num_lines, kMaxLinesToBalance);
+  if (num_lines <= 1) {
+    return absl::nullopt;  // Balancing not needed for single line paragraphs.
+  }
+
+  // The bisect less than 1 pixel is worthless, so ignore. Use CSS pixels
+  // instead of device pixels to make the algorithm consistent across different
+  // zoom levels, but make sure it's not zero to avoid infinite loop.
+  const LayoutUnit epsilon =
+      LayoutUnit::FromFloatCeil(block_style.EffectiveZoom());
+
+  // Find the desired available width by bisecting the maximum available width
+  // that produces `num_lines`.
+  LineBreakResults balanced_lines(node, space);
+  // Start the bisect with the minimum value at the average line width, with 20%
+  // buffer for potential edge cases.
+  const LayoutUnit avg_line_width = normal_lines.LineWidthSum() / num_lines;
+  const LayoutUnit min_available_width =
+      LayoutUnit::FromFloatRound(avg_line_width * .8f);
+  return balanced_lines.BisectAvailableWidth(
+      available_width, min_available_width, epsilon, num_lines);
+}
+
+// static
+void NGParagraphLineBreaker::PrepareForNextLine(
+    LayoutUnit balanced_available_width,
+    NGLineLayoutOpportunity* line_opportunity) {
+  DCHECK_GE(line_opportunity->line_right_offset,
+            line_opportunity->line_left_offset);
+  DCHECK_EQ(line_opportunity->line_left_offset,
+            line_opportunity->float_line_left_offset);
+  DCHECK_EQ(line_opportunity->line_right_offset,
+            line_opportunity->float_line_right_offset);
+  line_opportunity->line_right_offset =
+      line_opportunity->line_left_offset + balanced_available_width;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.h
new file mode 100644
index 0000000..35eecec1
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_paragraph_line_breaker.h
@@ -0,0 +1,32 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PARAGRAPH_LINE_BREAKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PARAGRAPH_LINE_BREAKER_H_
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class NGConstraintSpace;
+class NGInlineNode;
+struct NGLineLayoutOpportunity;
+
+class CORE_EXPORT NGParagraphLineBreaker {
+ public:
+  static absl::optional<LayoutUnit> AttemptParagraphBalancing(
+      const NGInlineNode& node,
+      const NGConstraintSpace& space,
+      const NGLineLayoutOpportunity& line_opportunity);
+
+  static void PrepareForNextLine(LayoutUnit balanced_available_width,
+                                 NGLineLayoutOpportunity* line_opportunity);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PARAGRAPH_LINE_BREAKER_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
index 741e4a6..94fc0415 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
@@ -30,12 +30,6 @@
   void SetStyleVariant(NGStyleVariant style_variant) {
     style_variant_ = style_variant;
   }
-  void SetStyle(scoped_refptr<const ComputedStyle> style,
-                NGStyleVariant style_variant) {
-    DCHECK(style);
-    style_ = std::move(style);
-    style_variant_ = style_variant;
-  }
 
   WritingDirectionMode GetWritingDirection() const {
     return writing_direction_;
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 4308beef..01c27839 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -289,6 +289,7 @@
   CommitReason commit_reason;
   uint64_t main_resource_identifier;
   mojom::blink::ResourceTimingInfoPtr resource_timing_info_for_parent;
+  base::TimeTicks last_redirect_end_time;
   WebScopedVirtualTimePauser virtual_time_pauser;
   Member<PrefetchedSignedExchangeManager> prefetched_signed_exchange_manager;
   ukm::SourceId ukm_source_id;
@@ -313,7 +314,6 @@
   absl::optional<FencedFrame::RedactedFencedFrameProperties>
       fenced_frame_properties;
   bool has_storage_access;
-  mojom::blink::ParentResourceTimingAccess parent_resource_timing_access;
 };
 
 // Asserts size of DocumentLoader, so that whenever a new attribute is added to
@@ -513,8 +513,7 @@
       reduced_accept_language_(params_->reduced_accept_language),
       navigation_delivery_type_(params_->navigation_delivery_type),
       view_transition_state_(std::move(params_->view_transition_state)),
-      has_storage_access_(params_->has_storage_access),
-      parent_resource_timing_access_(params_->parent_resource_timing_access) {
+      has_storage_access_(params_->has_storage_access) {
   DCHECK(frame_);
   DCHECK(params_);
 
@@ -534,8 +533,6 @@
   document_policy_ = CreateDocumentPolicy();
 
   WebNavigationTimings& timings = params_->navigation_timings;
-  parent_resource_timing_access_ = timings.parent_resource_timing_access;
-
   if (!timings.input_start.is_null())
     document_load_timing_.SetInputStart(timings.input_start);
   if (timings.navigation_start.is_null()) {
@@ -1102,7 +1099,6 @@
     const absl::optional<WebURLError>& error) {
   TRACE_EVENT0("loading", "DocumentLoader::BodyLoadingFinished");
 
-  DCHECK(frame_);
   if (!error) {
     GetFrameLoader().Progress().CompleteProgress(main_resource_identifier_);
     probe::DidFinishLoading(
@@ -1250,6 +1246,10 @@
       probe::ToCoreProbeSink(GetFrame()), main_resource_identifier_, this,
       url_after_redirect, http_method_, http_body_.get());
 
+  if (ResourceLoadTiming* timing = redirect_response.GetResourceLoadTiming()) {
+    redirect_end_time_ = timing->ReceiveHeadersEnd();
+  }
+
   DCHECK(!GetTiming().FetchStart().is_null());
   GetTiming().AddRedirect(url_before_redirect, url_after_redirect);
 }
@@ -2626,32 +2626,27 @@
 
   if (response_.ShouldPopulateResourceTiming() ||
       is_error_page_for_failed_navigation_) {
-    // We only report resource timing info to the parent if:
-    // 1. The navigation is container-initiated (e.g. iframe changed src)
-    // 2. TAO passed.
-    if (parent_resource_timing_access_ !=
-            mojom::blink::ParentResourceTimingAccess::kDoNotReport &&
-        response_.TimingAllowPassed()) {
-      ResourceResponse response_for_parent(response_);
-      if (parent_resource_timing_access_ ==
-          mojom::blink::ParentResourceTimingAccess::
-              kReportWithoutResponseDetails) {
-        response_for_parent.SetType(network::mojom::FetchResponseType::kOpaque);
-      }
-
-      DCHECK(frame_->Owner());
-      DCHECK(GetRequestorOrigin());
+    // We only report resource timing to the parent if:
+    // 1. We have a parent (owner)
+    // 2. Timing Allow Passed - otherwise we report fallback timing.
+    // 3. It's an external navigation (kWebNavigationTypeOther)
+    // TODO (crbug.com/1410705): Using navigation_type_ for this covers
+    // most cases but might still have very rare racy edge cases, such as
+    // extension or window.open with target cancelling an ongoing navigation
+    // and start a new navigation to the same URL.
+    if (frame_->Owner() && response_.TimingAllowPassed() &&
+        navigation_type_ == WebNavigationType::kWebNavigationTypeOther) {
       resource_timing_info_for_parent_ = CreateResourceTimingInfo(
-          GetTiming().NavigationStart(), original_url_, &response_for_parent);
-
+          GetTiming().NavigationStart(), original_url_, &response_);
+      if (!is_same_origin_initiator ||
+          document_load_timing_.HasCrossOriginRedirect()) {
+        resource_timing_info_for_parent_->content_type = g_empty_string;
+        resource_timing_info_for_parent_->response_status = 0;
+      }
       resource_timing_info_for_parent_->last_redirect_end_time =
-          document_load_timing_.RedirectEnd();
+          redirect_end_time_;
     }
 
-    // TimingAllowPassed only applies to resource
-    // timing reporting. Navigation timing is always same-origin with the
-    // document that holds to the timing entry, as navigation timing represents
-    // the timing of that document itself.
     response_.SetTimingAllowPassed(true);
     mojom::blink::ResourceTimingInfoPtr navigation_timing_info =
         CreateResourceTimingInfo(base::TimeTicks(),
@@ -2659,9 +2654,8 @@
                                      ? pre_redirect_url_for_failed_navigations_
                                      : url_,
                                  &response_);
-    navigation_timing_info->last_redirect_end_time =
-        document_load_timing_.RedirectEnd();
-
+    navigation_timing_info->last_redirect_end_time = redirect_end_time_;
+    DCHECK(frame_);
     DCHECK(frame_->DomWindow());
     DOMWindowPerformance::performance(*frame_->DomWindow())
         ->CreateNavigationTimingInstance(std::move(navigation_timing_info));
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index 11e3bce..b790d8d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -49,8 +49,6 @@
 #include "third_party/blink/public/mojom/loader/content_security_notifier.mojom-blink.h"
 #include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-blink.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
 #include "third_party/blink/public/mojom/page/page.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
@@ -760,6 +758,7 @@
   CommitReason commit_reason_ = CommitReason::kRegular;
   uint64_t main_resource_identifier_ = 0;
   mojom::blink::ResourceTimingInfoPtr resource_timing_info_for_parent_;
+  base::TimeTicks redirect_end_time_;
   WebScopedVirtualTimePauser virtual_time_pauser_;
   Member<PrefetchedSignedExchangeManager> prefetched_signed_exchange_manager_;
   ukm::SourceId ukm_source_id_;
@@ -823,10 +822,6 @@
   // Indicates whether the document should be loaded with its has_storage_access
   // bit set.
   const bool has_storage_access_;
-
-  // Only container-initiated navigations (e.g. iframe change src) report
-  // their resource timing to the parent.
-  mojom::blink::ParentResourceTimingAccess parent_resource_timing_access_;
 };
 
 DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc
index 3047062..1547749 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -121,8 +121,7 @@
     const absl::optional<Impression>&,
     const LocalFrameToken* initiator_frame_token,
     std::unique_ptr<SourceLocation>,
-    mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>,
-    bool is_container_initiated) {}
+    mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>) {}
 
 void EmptyLocalFrameClient::DispatchWillSendSubmitEvent(HTMLFormElement*) {}
 
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 9e34e80..84e9886 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -308,8 +308,8 @@
       const absl::optional<Impression>&,
       const LocalFrameToken* initiator_frame_token,
       std::unique_ptr<SourceLocation>,
-      mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>,
-      bool is_container_initiated) override;
+      mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>)
+      override;
 
   void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
 
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h
index 8d28e63..5282d87 100644
--- a/third_party/blink/renderer/core/loader/frame_load_request.h
+++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -84,10 +84,6 @@
     return client_navigation_reason_;
   }
 
-  void SetIsContainerInitiated(bool value) { is_container_initiated_ = value; }
-
-  bool IsContainerInitiated() const { return is_container_initiated_; }
-
   NavigationPolicy GetNavigationPolicy() const { return navigation_policy_; }
   void SetNavigationPolicy(NavigationPolicy navigation_policy) {
     navigation_policy_ = navigation_policy;
@@ -244,10 +240,6 @@
 
   mojom::blink::ForceHistoryPush force_history_push_ =
       mojom::blink::ForceHistoryPush::kNo;
-
-  // Only container-initiated navigations (e.g. iframe change src) report a
-  // resource timing entry to the parent.
-  bool is_container_initiated_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 939b5977b..8bad0fba 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -852,8 +852,7 @@
       request.GetInputStartTime(), request.HrefTranslate().GetString(),
       request.Impression(), request.GetInitiatorFrameToken(),
       request.TakeSourceLocation(),
-      request.TakeInitiatorPolicyContainerKeepAliveHandle(),
-      request.IsContainerInitiated());
+      request.TakeInitiatorPolicyContainerKeepAliveHandle());
 }
 
 static void FillStaticResponseIfNeeded(WebNavigationParams* params,
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index 566be66..2501f4f 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -549,6 +549,8 @@
       restricted.push_back(OriginTrialFeature::kFencedFrames);
     if (!base::FeatureList::IsEnabled(features::kSharedStorageAPI))
       restricted.push_back(OriginTrialFeature::kSharedStorageAPI);
+    if (!base::FeatureList::IsEnabled(features::kFencedFramesAPIChanges))
+      restricted.push_back(OriginTrialFeature::kFencedFramesAPIChanges);
     return restricted;
   }
 
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc b/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
index 4d8b617b..2944ee7 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc
@@ -749,13 +749,25 @@
       "    height: 100px;"
       "    background-image: url(\"data:image/svg+xml,"
       "      <svg xmlns='http://www.w3.org/2000/svg' width='100' height='300'>"
+      "        <g mask='url(does_not_exist)'>"
+      "          <circle cx='25' cy='50' r='10' fill='red'/>"
+      "        </g>"
       "        <g transform='translate(50, 50)'>"
       "          <circle cx='0' cy='0' r='10' fill='red'/>"
       "        </g>"
+      "        <g filter='blur(1px)'>"
+      "          <circle cx='75' cy='50' r='10' fill='red'/>"
+      "        </g>"
       "        <circle cx='50' cy='150' r='10' fill='green'/>"
+      "        <g mask='url(does_not_exist)'>"
+      "          <circle cx='25' cy='250' r='10' fill='red'/>"
+      "        </g>"
       "        <g transform='translate(50, 250)'>"
       "          <circle cx='0' cy='0' r='10' fill='red'/>"
       "        </g>"
+      "        <g filter='blur(1px)'>"
+      "          <circle cx='75' cy='250' r='10' fill='red'/>"
+      "        </g>"
       "      </svg>\");"
       "    background-position-y: -100px;"
       "    background-repeat: no-repeat;"
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index f5d79e56..f8cd29c 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -709,6 +709,17 @@
   resource_timing_secondary_buffer_.push_back(entry);
 }
 
+void Performance::AddResourceTimingWithUnparsedServerTiming(
+    mojom::blink::ResourceTimingInfoPtr info,
+    const String& server_timing_value,
+    const AtomicString& initiator_type) {
+  if (info->allow_timing_details) {
+    info->server_timing =
+        ParseServerTimingFromHeaderValueToMojo(server_timing_value);
+  }
+  AddResourceTiming(std::move(info), initiator_type);
+}
+
 // Called after loadEventEnd happens.
 void Performance::NotifyNavigationTimingToObservers() {
   if (navigation_timing_)
diff --git a/third_party/blink/renderer/core/timing/performance.h b/third_party/blink/renderer/core/timing/performance.h
index 4ab16f2..8909564f 100644
--- a/third_party/blink/renderer/core/timing/performance.h
+++ b/third_party/blink/renderer/core/timing/performance.h
@@ -200,6 +200,11 @@
   void AddResourceTiming(mojom::blink::ResourceTimingInfoPtr,
                          const AtomicString& initiator_type);
 
+  void AddResourceTimingWithUnparsedServerTiming(
+      mojom::blink::ResourceTimingInfoPtr,
+      const String& server_timing_value,
+      const AtomicString& initiator_type);
+
   void NotifyNavigationTimingToObservers();
 
   void AddFirstPaintTiming(base::TimeTicks start_time,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
index ccf478d8..f01a983c 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -479,11 +479,7 @@
 }
 
 void DedicatedWorkerGlobalScope::UpdateBackForwardCacheDisablingFeatures(
-    uint64_t features_mask,
-    const BFCacheBlockingFeatureAndLocations&
-        non_sticky_features_and_js_locations,
-    const BFCacheBlockingFeatureAndLocations&
-        sticky_features_and_js_locations) {
+    BlockingDetails details) {
   // `back_forward_cache_controller_host_` might not be bound when non-
   // PlzDedicatedWorker is used. Non-PlzDedicatedWorker will be removed in near
   // future.
@@ -494,7 +490,7 @@
   }
 
   back_forward_cache_controller_host_
-      ->DidChangeBackForwardCacheDisablingFeatures(features_mask);
+      ->DidChangeBackForwardCacheDisablingFeatures(details.feature_mask);
 }
 
 void DedicatedWorkerGlobalScope::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
index a84db7b6..44759288 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -128,11 +128,7 @@
 
   // Implements scheduler::WorkerScheduler::Delegate.
   void UpdateBackForwardCacheDisablingFeatures(
-      uint64_t features_mask,
-      const BFCacheBlockingFeatureAndLocations&
-          non_sticky_features_and_js_locations,
-      const BFCacheBlockingFeatureAndLocations&
-          sticky_features_and_js_locations) override;
+      BlockingDetails details) override;
   // Implements BackForwardCacheLoaderHelperImpl::Delegate.
   void EvictFromBackForwardCache(
       mojom::blink::RendererEvictionReason reason) override;
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
index 038fb4b..2a270d76 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
@@ -88,11 +88,7 @@
 
   // scheduler::WorkerScheduler::Delegate
   void UpdateBackForwardCacheDisablingFeatures(
-      uint64_t features_mask,
-      const BFCacheBlockingFeatureAndLocations&
-          non_sticky_features_and_js_locations,
-      const BFCacheBlockingFeatureAndLocations&
-          sticky_features_and_js_locations) override {}
+      BlockingDetails details) override {}
 
   // BackForwardCacheLoaderHelperImpl::Delegate
   void EvictFromBackForwardCache(
diff --git a/third_party/blink/renderer/modules/accessibility/OWNERS b/third_party/blink/renderer/modules/accessibility/OWNERS
index ff1d239b..077a5c59 100644
--- a/third_party/blink/renderer/modules/accessibility/OWNERS
+++ b/third_party/blink/renderer/modules/accessibility/OWNERS
@@ -1,6 +1,13 @@
+# General reviewers:
 aleventhal@chromium.org
 benjamin.beaudry@microsoft.com
 dlibby@microsoft.com
 dtseng@chromium.org
 kschmi@microsoft.com
 nektar@chromium.org
+# For changes that are pure code refactoring or DOM/layout integration:
+# (if downstream platform a11y API support is affected, please add another
+# owner from the main list above, so that a11y specialist knowledge is
+# represented):
+chrishtr@chromium.org
+szager@chromium.org
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 972d38c..dabb235 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -3177,18 +3177,9 @@
     if (auto* select_menu = HTMLSelectMenuElement::OwnerSelectMenu(node)) {
       DCHECK(RuntimeEnabledFeatures::HTMLSelectMenuElementEnabled());
       if (HTMLOptionElement* selected = select_menu->selectedOption()) {
-        // TODO(accessibility) Because these <option> elements can contain
-        // anything, we need to create an AXObject for the selected option, and
-        // use ax_selected_option->ComputedName(). However, for now, the
-        // AXObject is not created because AXObject::IsRelevantSlotElement()
-        // returns false for the invisible slot parent. Also, strangely,
-        // selected->innerText()/GetInnerTextWithoutUpdate() are returning "".
-        // See the following content_browsertest:
-        // All/DumpAccessibilityTreeTest.AccessibilitySelectMenu/blink.
-        // TODO(crbug.com/1401767): DCHECK fails with synchronous serialization.
-        DCHECK(selected->firstChild())
-            << "There is a selected option but it has no DOM children.";
-        return selected->textContent();
+        if (selected->firstChild()) {
+          return selected->textContent();
+        }
       }
       return String();
     }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index c3b58733..9a8e056 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -519,12 +519,6 @@
       return true;
   }
 
-  if (const HTMLSlotElement* slot =
-          ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
-    if (!AXObjectCacheImpl::IsRelevantSlotElement(*slot))
-      return true;
-  }
-
   // <optgroup> is irrelevant inside of a <select> menulist.
   if (auto* opt_group = DynamicTo<HTMLOptGroupElement>(node)) {
     if (auto* select = opt_group->OwnerSelectElement()) {
@@ -1133,57 +1127,6 @@
 }
 
 // static
-bool AXObjectCacheImpl::IsRelevantSlotElement(const HTMLSlotElement& slot) {
-  // A <slot> descendant of a node that is still in the DOM but no longer
-  // rendered will return true for Node::isConnected() and false for
-  // AXObject::IsDetached(). But from the perspective of platform ATs, this
-  // subtree is not connected and is detached unless it is canvas fallback
-  // content. In order to detect this condition, we look to the first non-slot
-  // parent. If it has a layout object, the <slot>'s contents are rendered.
-  // If it doesn't, but it's in the canvas subtree, those contents should be
-  // treated as canvas fallback content.
-  //
-  // The alternative way to determine whether the <slot> is still relevant for
-  // rendering is to iterate FlatTreeTraversal::Parent until you get to the last
-  // parent, and see if it's a document. If it is not a document, then it is not
-  // relevant. This seems much slower than just checking GetLayoutObject() as it
-  // needs to iterate the parent chain. However, checking GetLayoutObject()
-  // could produce null in the case of something that is
-  // content-visibility:auto. This means that any slotted content inside
-  // content-visibility:auto may be removed from the AX tree depending on
-  // whether it was recently rendered.
-  //
-  // TODO(accessibility) This fails for the web test
-  // detach-locked-slot-children-crash.html with --force-renderer-accessibility.
-  // See web_tests/FlagExpectations/force-renderer-accessibility.
-  // There should be a better way to accomplish this.
-  // Could a new function be added to the slot element?
-  const Node* parent = LayoutTreeBuilderTraversal::Parent(slot);
-  if (const HTMLSlotElement* parent_slot =
-          ToHTMLSlotElementIfSupportsAssignmentOrNull(parent)) {
-    return AXObjectCacheImpl::IsRelevantSlotElement(*parent_slot);
-  }
-
-  if (parent && parent->GetLayoutObject())
-    return true;
-
-  const Element* parent_element = DynamicTo<Element>(parent);
-  if (!parent_element)
-    return false;
-
-  // Authors can include elements as "Fallback content" inside a <canvas> in
-  // order to provide an alternative means to interact with the canvas using
-  // a screen reader. Those should always be included.
-  if (parent_element->IsInCanvasSubtree())
-    return true;
-
-  // LayoutObject::CreateObject() will not create an object for elements
-  // with display:contents. If we do not include a <slot> for that reason,
-  // any descendants will be not be included in the accessibility tree.
-  return parent_element->HasDisplayContentsStyle();
-}
-
-// static
 bool AXObjectCacheImpl::IsRelevantPseudoElement(const Node& node) {
   DCHECK(node.IsPseudoElement());
   if (!node.GetLayoutObject())
@@ -3672,18 +3615,6 @@
     return nullptr;
   }
 
-  // A <slot> descendant of a node that is still in the DOM but no longer
-  // rendered will return true for Node::isConnected() and false for
-  // AXObject::IsDetached(). But from the perspective of platform ATs, this
-  // subtree is not connected and is detached.
-  // TODO(accessibility): The relevance check probably applies to all nodes
-  // not just slot elements.
-  if (const HTMLSlotElement* slot =
-          ToHTMLSlotElementIfSupportsAssignmentOrNull(obj->GetNode())) {
-    if (!AXObjectCacheImpl::IsRelevantSlotElement(*slot))
-      return nullptr;
-  }
-
   // Ensure still in tree.
   if (obj->IsMissingParent()) {
     // TODO(accessibility) Only needed because of <select> size changes.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index bd7f0c571..9c2cb17 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -423,7 +423,6 @@
   static bool IsRelevantPseudoElement(const Node& node);
   static bool IsRelevantPseudoElementDescendant(
       const LayoutObject& layout_object);
-  static bool IsRelevantSlotElement(const HTMLSlotElement& slot);
 
   bool HasBeenDisposed() { return has_been_disposed_; }
 
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc
index f1872ed..962df1c 100644
--- a/third_party/blink/renderer/modules/geolocation/geolocation.cc
+++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -99,6 +99,12 @@
   }
 }
 
+bool ValidateGeoposition(const device::mojom::blink::Geoposition& position) {
+  return position.latitude >= -90. && position.latitude <= 90. &&
+         position.longitude >= -180. && position.longitude <= 180. &&
+         position.accuracy >= 0. && !position.timestamp.is_null();
+}
+
 }  // namespace
 
 // static
@@ -496,7 +502,7 @@
 void Geolocation::OnPositionUpdated(
     device::mojom::blink::GeopositionPtr position) {
   disconnected_geolocation_ = false;
-  if (position->valid) {
+  if (ValidateGeoposition(*position)) {
     last_position_ = CreateGeoposition(*position);
     PositionChanged();
   } else {
diff --git a/third_party/blink/renderer/modules/ml/webnn/features.gni b/third_party/blink/renderer/modules/ml/webnn/features.gni
index e188952..ec24336 100644
--- a/third_party/blink/renderer/modules/ml/webnn/features.gni
+++ b/third_party/blink/renderer/modules/ml/webnn/features.gni
@@ -5,7 +5,7 @@
 import("//build/config/chrome_build.gni")
 declare_args() {
   # This enables building WebNN with XNNPACK. Currently only available for
-  # Windows on x64 or x86.
+  # Windows and Linux on x64 or x86.
   build_webnn_with_xnnpack =
-      is_win && (current_cpu == "x64" || current_cpu == "x86")
+      (is_linux || is_win) && (current_cpu == "x64" || current_cpu == "x86")
 }
diff --git a/third_party/blink/renderer/modules/quota/BUILD.gn b/third_party/blink/renderer/modules/quota/BUILD.gn
index 57319dc..012cf1b 100644
--- a/third_party/blink/renderer/modules/quota/BUILD.gn
+++ b/third_party/blink/renderer/modules/quota/BUILD.gn
@@ -6,14 +6,10 @@
 
 blink_modules_sources("quota") {
   sources = [
-    "deprecated_storage_info.cc",
-    "deprecated_storage_info.h",
     "deprecated_storage_quota.cc",
     "deprecated_storage_quota.h",
     "dom_error.cc",
     "dom_error.h",
-    "dom_window_quota.cc",
-    "dom_window_quota.h",
     "navigator_storage_quota.cc",
     "navigator_storage_quota.h",
     "quota_utils.cc",
diff --git a/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc b/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc
deleted file mode 100644
index c823419..0000000
--- a/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/quota/deprecated_storage_info.h"
-
-#include "base/location.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/deprecation/deprecation.h"
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/modules/quota/deprecated_storage_quota.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-
-namespace blink {
-
-DeprecatedStorageInfo::DeprecatedStorageInfo() = default;
-
-void DeprecatedStorageInfo::queryUsageAndQuota(
-    ScriptState* script_state,
-    int storage_type,
-    V8StorageUsageCallback* success_callback,
-    V8StorageErrorCallback* error_callback) {
-  // The BlinkIDL definition for queryUsageAndQuota() already has a [Measure]
-  // attribute, so the kQuotaRead use counter must be explicitly updated.
-  UseCounter::Count(ExecutionContext::From(script_state),
-                    WebFeature::kQuotaRead);
-  // Dispatching the request to DeprecatedStorageQuota, as this interface is
-  // deprecated in favor of DeprecatedStorageQuota.
-  DeprecatedStorageQuota* storage_quota =
-      GetStorageQuota(storage_type, ExecutionContext::From(script_state));
-  if (!storage_quota) {
-    // Unknown storage type is requested.
-    DeprecatedStorageQuota::EnqueueStorageErrorCallback(
-        script_state, error_callback, DOMExceptionCode::kNotSupportedError);
-    return;
-  }
-  storage_quota->queryUsageAndQuota(script_state, success_callback,
-                                    error_callback);
-}
-
-void DeprecatedStorageInfo::requestQuota(
-    ScriptState* script_state,
-    int storage_type,
-    uint64_t new_quota_in_bytes,
-    V8StorageQuotaCallback* success_callback,
-    V8StorageErrorCallback* error_callback) {
-  // The BlinkIDL definition for requestQuota() already has a [Measure]
-  // attribute, so the kQuotaRead use counter must be explicitly updated.
-  UseCounter::Count(ExecutionContext::From(script_state),
-                    WebFeature::kQuotaRead);
-  // Dispatching the request to DeprecatedStorageQuota, as this interface is
-  // deprecated in favor of DeprecatedStorageQuota.
-  DeprecatedStorageQuota* storage_quota =
-      GetStorageQuota(storage_type, ExecutionContext::From(script_state));
-  if (!storage_quota) {
-    // Unknown storage type is requested.
-    DeprecatedStorageQuota::EnqueueStorageErrorCallback(
-        script_state, error_callback, DOMExceptionCode::kNotSupportedError);
-    return;
-  }
-  storage_quota->requestQuota(script_state, new_quota_in_bytes,
-                              success_callback, error_callback);
-}
-
-DeprecatedStorageQuota* DeprecatedStorageInfo::GetStorageQuota(
-    int storage_type,
-    ExecutionContext* execution_context) {
-  if (storage_type == kPersistent) {
-    // Show deprecation message and record usage for persistent storage type.
-    Deprecation::CountDeprecation(execution_context,
-                                  WebFeature::kPersistentQuotaType);
-  }
-  // As of crbug.com/1233525 kPersistent quota type is deprecated.
-  // Ignore `storage_type` and always return `temporary_storage_`.
-  if (!temporary_storage_) {
-    temporary_storage_ =
-        MakeGarbageCollected<DeprecatedStorageQuota>(execution_context);
-  }
-  return temporary_storage_.Get();
-}
-
-void DeprecatedStorageInfo::Trace(Visitor* visitor) const {
-  visitor->Trace(temporary_storage_);
-  ScriptWrappable::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/quota/deprecated_storage_info.h b/third_party/blink/renderer/modules/quota/deprecated_storage_info.h
deleted file mode 100644
index 6492ae5d..0000000
--- a/third_party/blink/renderer/modules/quota/deprecated_storage_info.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DEPRECATED_STORAGE_INFO_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DEPRECATED_STORAGE_INFO_H_
-
-#include "third_party/blink/renderer/modules/quota/deprecated_storage_quota.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class ScriptState;
-class V8StorageErrorCallback;
-class V8StorageQuotaCallback;
-class V8StorageUsageCallback;
-
-class DeprecatedStorageInfo final : public ScriptWrappable {
-  DEFINE_WRAPPERTYPEINFO();
-
- public:
-  enum {
-    kTemporary,
-    kPersistent,
-  };
-
-  DeprecatedStorageInfo();
-
-  void queryUsageAndQuota(ScriptState*,
-                          int storage_type,
-                          V8StorageUsageCallback* = nullptr,
-                          V8StorageErrorCallback* = nullptr);
-
-  void requestQuota(ScriptState*,
-                    int storage_type,
-                    uint64_t new_quota_in_bytes,
-                    V8StorageQuotaCallback* = nullptr,
-                    V8StorageErrorCallback* = nullptr);
-
-  void Trace(Visitor*) const override;
-
- private:
-  DeprecatedStorageQuota* GetStorageQuota(int storage_type,
-                                          ExecutionContext* execution_context);
-
-  mutable Member<DeprecatedStorageQuota> temporary_storage_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DEPRECATED_STORAGE_INFO_H_
diff --git a/third_party/blink/renderer/modules/quota/deprecated_storage_info.idl b/third_party/blink/renderer/modules/quota/deprecated_storage_info.idl
deleted file mode 100644
index 976f60af..0000000
--- a/third_party/blink/renderer/modules/quota/deprecated_storage_info.idl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-[
-    LegacyNoInterfaceObject,
-    RuntimeEnabled=PrefixedStorageInfo
-] interface DeprecatedStorageInfo {
-    // As of crbug.com/1233525, PERSISTENT quota type is deprecated and
-    // `storageType` parameter will be ignored.
-    const unsigned short TEMPORARY = 0;
-    const unsigned short PERSISTENT = 1;
-
-    // TODO(crbug.com/841185): |usageCallback| and |errorCallback| are not
-    // nullable in the spec.
-    [Measure, CallWith=ScriptState] void queryUsageAndQuota(unsigned short storageType, optional StorageUsageCallback? usageCallback, optional StorageErrorCallback? errorCallback);
-    // TODO(crbug.com/841185): |quotaCallback| and |errorCallback| are not
-    // nullable in the spec.
-    [Measure, CallWith=ScriptState] void requestQuota(unsigned short storageType, unsigned long long newQuotaInBytes, optional StorageQuotaCallback? quotaCallback, optional StorageErrorCallback? errorCallback);
-};
diff --git a/third_party/blink/renderer/modules/quota/dom_window_quota.cc b/third_party/blink/renderer/modules/quota/dom_window_quota.cc
deleted file mode 100644
index 255715c..0000000
--- a/third_party/blink/renderer/modules/quota/dom_window_quota.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/quota/dom_window_quota.h"
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/modules/quota/deprecated_storage_info.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-DOMWindowQuota::DOMWindowQuota(LocalDOMWindow& window)
-    : Supplement<LocalDOMWindow>(window) {}
-
-const char DOMWindowQuota::kSupplementName[] = "DOMWindowQuota";
-
-// static
-DOMWindowQuota& DOMWindowQuota::From(LocalDOMWindow& window) {
-  DOMWindowQuota* supplement =
-      Supplement<LocalDOMWindow>::From<DOMWindowQuota>(window);
-  if (!supplement) {
-    supplement = MakeGarbageCollected<DOMWindowQuota>(window);
-    ProvideTo(window, supplement);
-  }
-  return *supplement;
-}
-
-// static
-DeprecatedStorageInfo* DOMWindowQuota::webkitStorageInfo(
-    LocalDOMWindow& window) {
-  return DOMWindowQuota::From(window).webkitStorageInfo();
-}
-
-DeprecatedStorageInfo* DOMWindowQuota::webkitStorageInfo() const {
-  if (!storage_info_)
-    storage_info_ = MakeGarbageCollected<DeprecatedStorageInfo>();
-
-  // Record metrics for usage in third-party contexts.
-  GetSupplementable()->CountUseOnlyInCrossSiteIframe(
-      WebFeature::kPrefixedStorageInfoThirdPartyContext);
-
-  return storage_info_.Get();
-}
-
-void DOMWindowQuota::Trace(Visitor* visitor) const {
-  visitor->Trace(storage_info_);
-  Supplement<LocalDOMWindow>::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/quota/dom_window_quota.h b/third_party/blink/renderer/modules/quota/dom_window_quota.h
deleted file mode 100644
index ca4197b..0000000
--- a/third_party/blink/renderer/modules/quota/dom_window_quota.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DOM_WINDOW_QUOTA_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DOM_WINDOW_QUOTA_H_
-
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-class DeprecatedStorageInfo;
-class LocalDOMWindow;
-
-class DOMWindowQuota final : public GarbageCollected<DOMWindowQuota>,
-                             public Supplement<LocalDOMWindow> {
- public:
-  static const char kSupplementName[];
-
-  explicit DOMWindowQuota(LocalDOMWindow&);
-
-  static DOMWindowQuota& From(LocalDOMWindow&);
-  static DeprecatedStorageInfo* webkitStorageInfo(LocalDOMWindow&);
-  DeprecatedStorageInfo* webkitStorageInfo() const;
-
-  void Trace(Visitor*) const override;
-
- private:
-  mutable Member<DeprecatedStorageInfo> storage_info_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DOM_WINDOW_QUOTA_H_
diff --git a/third_party/blink/renderer/modules/quota/window_quota.idl b/third_party/blink/renderer/modules/quota/window_quota.idl
deleted file mode 100644
index 645a1c2..0000000
--- a/third_party/blink/renderer/modules/quota/window_quota.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-[
-    ImplementedAs=DOMWindowQuota
-] partial interface Window {
-    [RuntimeEnabled=PrefixedStorageInfo] readonly attribute DeprecatedStorageInfo webkitStorageInfo;
-};
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 4d2fe95..e068d77 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -692,11 +692,10 @@
     // Count the update of fetch handlers after the initial evaluation.
     if (event_type == event_type_names::kFetch) {
       UseCounter::Count(
-          this,
-          WebFeature::kServiceWorkerFetchHandlerUpdateAfterInitialization);
+          this, WebFeature::kServiceWorkerFetchHandlerAddedAfterInitialization);
     }
-    UseCounter::Count(this,
-                      WebFeature::kServiceWorkerAddHandlerAfterInitialization);
+    UseCounter::Count(
+        this, WebFeature::kServiceWorkerEventHandlerAddedAfterInitialization);
   }
   return WorkerGlobalScope::AddEventListenerInternal(event_type, listener,
                                                      options);
@@ -2660,7 +2659,8 @@
           WebFeature::kServiceWorkerFetchHandlerModifiedAfterInitialization);
     }
     UseCounter::Count(
-        this, WebFeature::kServiceWorkerSetAttributeHandlerAfterInitialization);
+        this,
+        WebFeature::kServiceWorkerEventHandlerModifiedAfterInitialization);
   }
   return WorkerGlobalScope::SetAttributeEventListener(event_type, listener);
 }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index c40a2523..c48603cf 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -773,6 +773,19 @@
     const auto& chunk_state = chunk.properties;
     bool switched_to_chunk_state = false;
 
+    if (additional_cull_rect) {
+      // `SwitchToChunkState` will also update `chunk_to_layer_mapper_`'s chunk
+      // but we need to explicitly switch the state ahead of time to ensure the
+      // call to `chunk_to_layer_mapper_.MapVisualRect` uses the correct state.
+      chunk_to_layer_mapper_.SwitchToChunk(chunk);
+      gfx::Rect chunk_visual_rect =
+          chunk_to_layer_mapper_.MapVisualRect(chunk.drawable_bounds);
+      if (additional_cull_rect &&
+          !additional_cull_rect->Intersects(chunk_visual_rect)) {
+        continue;
+      }
+    }
+
     for (const auto& item : it.DisplayItems()) {
       PaintRecord record;
       if (auto* scrollbar = DynamicTo<ScrollbarDisplayItem>(item))
@@ -793,11 +806,9 @@
         continue;
       }
 
-      // `SwitchToChunkState` will also update `chunk_to_layer_mapper_`'s chunk
-      // but we need to explicitly switch the state ahead of time to ensure the
-      // call to `chunk_to_layer_mapper_.MapVisualRect` uses the correct state.
       if (!switched_to_chunk_state) {
-        chunk_to_layer_mapper_.SwitchToChunk(chunk);
+        SwitchToChunkState(chunk);
+        switched_to_chunk_state = true;
       }
 
       gfx::Rect visual_rect =
@@ -807,11 +818,6 @@
         continue;
       }
 
-      if (!switched_to_chunk_state) {
-        SwitchToChunkState(chunk);
-        switched_to_chunk_state = true;
-      }
-
       result_.StartPaint();
       if (!record.empty()) {
         push<cc::DrawRecordOp>(std::move(record));
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
index fbf5c36..90b60298 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
@@ -61,6 +61,16 @@
   had_form_interaction_ = true;
 }
 
+void DocumentResourceCoordinator::SetHadUserEdits() {
+  // Only send this signal for the first interaction as it doesn't get cleared
+  // for the lifetime of the frame and it's inefficient to send this message
+  // for every keystroke.
+  if (!had_user_edits_) {
+    service_->SetHadUserEdits();
+  }
+  had_user_edits_ = true;
+}
+
 void DocumentResourceCoordinator::OnFirstContentfulPaint(
     base::TimeDelta time_since_navigation_start) {
   service_->OnFirstContentfulPaint(time_since_navigation_start);
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
index a48ef44..5417c044 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
@@ -39,6 +39,7 @@
   void SetIsAdFrame(bool is_ad_frame);
   void OnNonPersistentNotificationCreated();
   void SetHadFormInteraction();
+  void SetHadUserEdits();
   void OnFirstContentfulPaint(base::TimeDelta time_since_navigation_start);
   void OnWebMemoryMeasurementRequested(
       WebMemoryMeasurementMode mode,
@@ -51,6 +52,7 @@
       service_;
 
   bool had_form_interaction_ = false;
+  bool had_user_edits_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn
index 5eef33a1..5a2d30a 100644
--- a/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -135,6 +135,7 @@
     "fetch/url_loader/navigation_body_loader.h",
     "fetch/url_loader/request_conversion.cc",
     "fetch/url_loader/request_conversion.h",
+    "fetch/url_loader/resource_request_client.h",
     "fetch/url_loader/resource_request_sender.cc",
     "fetch/url_loader/resource_request_sender.h",
     "fetch/url_loader/sync_load_context.cc",
diff --git a/third_party/blink/renderer/platform/loader/README.md b/third_party/blink/renderer/platform/loader/README.md
index a51255a..3f2e8d1 100644
--- a/third_party/blink/renderer/platform/loader/README.md
+++ b/third_party/blink/renderer/platform/loader/README.md
@@ -14,7 +14,7 @@
 
 - blink::MojoURLLoaderClient
 - blink::ResponseBodyLoader
-- blink::WebRequestPeer implementations
+- blink::ResourceRequestClient implementations
 - blink::ThrottlingURLLoader implementations
 - blink::BackForwardCacheLoaderHelper implementations
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc
index 29ea11dd..f06d6d7f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc
@@ -20,8 +20,6 @@
 
 namespace blink {
 
-namespace {
-
 Vector<mojom::blink::ServerTimingInfoPtr>
 ParseServerTimingFromHeaderValueToMojo(const String& value) {
   std::unique_ptr<ServerTimingHeaderVector> headers =
@@ -35,8 +33,6 @@
   return result;
 }
 
-}  // namespace
-
 mojom::blink::ResourceTimingInfoPtr CreateResourceTimingInfo(
     base::TimeTicks start_time,
     const KURL& initial_url,
@@ -85,11 +81,11 @@
     }
   }
 
-  bool allow_response_details = response->IsCorsSameOrigin();
+  bool passes_cors = response->IsCorsSameOrigin();
 
   info->content_type = g_empty_string;
 
-  if (allow_response_details) {
+  if (passes_cors) {
     info->response_status = response->HttpStatusCode();
     if (!response->HttpContentType().IsNull()) {
       info->content_type = response->HttpContentType();
@@ -98,7 +94,7 @@
 
   bool expose_body_sizes =
       RuntimeEnabledFeatures::ResourceTimingUseCORSForBodySizesEnabled()
-          ? allow_response_details
+          ? passes_cors
           : info->allow_timing_details;
 
   if (expose_body_sizes && response) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h
index bcae05dc..51382262 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h
@@ -17,6 +17,9 @@
 class KURL;
 class ResourceResponse;
 
+BLINK_PLATFORM_EXPORT WTF::Vector<mojom::blink::ServerTimingInfoPtr>
+ParseServerTimingFromHeaderValueToMojo(const String& value);
+
 BLINK_PLATFORM_EXPORT mojom::blink::ResourceTimingInfoPtr
 CreateResourceTimingInfo(base::TimeTicks start_time,
                          const KURL& initial_url,
diff --git a/third_party/blink/public/platform/web_request_peer.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h
similarity index 81%
rename from third_party/blink/public/platform/web_request_peer.h
rename to third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h
index 572dd4d..dd052968 100644
--- a/third_party/blink/public/platform/web_request_peer.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_REQUEST_PEER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_REQUEST_PEER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_RESOURCE_REQUEST_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_RESOURCE_REQUEST_CLIENT_H_
 
 #include <stdint.h>
 
 #include <string>
 #include <vector>
 
-#include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "mojo/public/cpp/base/big_buffer.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 
 namespace net {
 struct RedirectInfo;
@@ -27,15 +27,11 @@
 
 namespace blink {
 
-// This is implemented by our custom resource loader within content. The Peer
-// and it's bridge should have identical lifetimes as they represent each end of
-// a communication channel.
-//
 // These callbacks mirror net::URLRequest::Delegate and the order and
 // conditions in which they will be called are identical. See url_request.h
 // for more information.
-class BLINK_PLATFORM_EXPORT WebRequestPeer
-    : public base::RefCounted<WebRequestPeer> {
+class BLINK_PLATFORM_EXPORT ResourceRequestClient
+    : public WTF::RefCounted<ResourceRequestClient> {
  public:
   // Called as upload progress is made.
   // note: only for requests with upload progress enabled.
@@ -78,11 +74,11 @@
   virtual void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) = 0;
 
-  virtual ~WebRequestPeer() = default;
+  virtual ~ResourceRequestClient() = default;
 
-  friend class base::RefCounted<WebRequestPeer>;
+  friend class WTF::RefCounted<ResourceRequestClient>;
 };
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_REQUEST_PEER_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_RESOURCE_REQUEST_CLIENT_H_
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc
index 005dbb74..b87a934 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc
@@ -40,13 +40,13 @@
 #include "third_party/blink/public/mojom/navigation/renderer_eviction_reason.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
-#include "third_party/blink/public/platform/web_request_peer.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_request_util.h"
 #include "third_party/blink/renderer/platform/back_forward_cache_utils.h"
 #include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
@@ -145,7 +145,7 @@
     const Vector<String>& cors_exempt_header_list,
     base::WaitableEvent* terminate_sync_load_event,
     mojo::PendingRemote<mojom::blink::BlobRegistry> download_to_blob_registry,
-    scoped_refptr<WebRequestPeer> peer,
+    scoped_refptr<ResourceRequestClient> client,
     std::unique_ptr<ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper) {
   CheckSchemeForReferrerPolicy(*request);
@@ -190,7 +190,7 @@
 
   while (context_for_redirect) {
     DCHECK(response->redirect_info);
-    bool follow_redirect = peer->OnReceivedRedirect(
+    bool follow_redirect = client->OnReceivedRedirect(
         *response->redirect_info, response->head.Clone(),
         nullptr /* removed_headers */);
     redirect_or_response_event.Reset();
@@ -213,7 +213,7 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     uint32_t loader_options,
     const Vector<String>& cors_exempt_header_list,
-    scoped_refptr<WebRequestPeer> peer,
+    scoped_refptr<ResourceRequestClient> client,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
     std::unique_ptr<ResourceLoadInfoNotifierWrapper>
@@ -238,7 +238,7 @@
   // Compute a unique request_id for this renderer process.
   int request_id = GenerateRequestId();
   request_info_ = std::make_unique<PendingRequestInfo>(
-      std::move(peer), request->destination, KURL(request->url),
+      std::move(client), request->destination, KURL(request->url),
       std::move(resource_load_info_notifier_wrapper));
 
   request_info_->resource_load_info_notifier_wrapper
@@ -246,7 +246,7 @@
           request_id, request->url, request->method, request->referrer,
           request_info_->request_destination, request->priority);
 
-  auto client = std::make_unique<MojoURLLoaderClient>(
+  auto url_loader_client = std::make_unique<MojoURLLoaderClient>(
       this, loading_task_runner, url_loader_factory->BypassRedirectChecks(),
       request->url, back_forward_cache_loader_helper);
 
@@ -258,8 +258,8 @@
   std::unique_ptr<ThrottlingURLLoader> url_loader =
       ThrottlingURLLoader::CreateLoaderAndStart(
           std::move(url_loader_factory), throttles.ReleaseVector(), request_id,
-          loader_options, request.get(), client.get(), traffic_annotation,
-          std::move(loading_task_runner),
+          loader_options, request.get(), url_loader_client.get(),
+          traffic_annotation, std::move(loading_task_runner),
           absl::make_optional(std_cors_exempt_header_list));
 
   // The request may be canceled by `ThrottlingURLLoader::CreateAndStart()`, in
@@ -271,7 +271,7 @@
   }
 
   request_info_->url_loader = std::move(url_loader);
-  request_info_->url_loader_client = std::move(client);
+  request_info_->url_loader_client = std::move(url_loader_client);
 
   return request_id;
 }
@@ -329,18 +329,18 @@
   request_info_->url_loader_client.reset();
 
   // Always delete the `request_info_` asyncly so that cancelling the request
-  // doesn't delete the request context which the `request_info_->peer` points
+  // doesn't delete the request context which the `request_info_->client` points
   // to while its response is still being handled.
   task_runner->DeleteSoon(FROM_HERE, request_info_.release());
 }
 
 ResourceRequestSender::PendingRequestInfo::PendingRequestInfo(
-    scoped_refptr<WebRequestPeer> peer,
+    scoped_refptr<ResourceRequestClient> client,
     network::mojom::RequestDestination request_destination,
     const KURL& request_url,
     std::unique_ptr<ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper)
-    : peer(std::move(peer)),
+    : client(std::move(client)),
       request_destination(request_destination),
       url(request_url),
       response_url(request_url),
@@ -382,8 +382,8 @@
   }
 
   // TODO(yhirano): Consider using int64_t in
-  // WebRequestPeer::OnTransferSizeUpdated.
-  request_info_->peer->OnTransferSizeUpdated(transfer_size_diff);
+  // ResourceRequestClient::OnTransferSizeUpdated.
+  request_info_->client->OnTransferSizeUpdated(transfer_size_diff);
   if (!request_info_) {
     return;
   }
@@ -396,7 +396,7 @@
     return;
   }
 
-  request_info_->peer->OnUploadProgress(position, size);
+  request_info_->client->OnUploadProgress(position, size);
 }
 
 void ResourceRequestSender::OnReceivedResponse(
@@ -420,8 +420,8 @@
   }
   request_info_->load_timing_info = response_head->load_timing;
 
-  request_info_->peer->OnReceivedResponse(response_head.Clone(),
-                                          response_arrival);
+  request_info_->client->OnReceivedResponse(response_head.Clone(),
+                                            response_arrival);
   if (!request_info_) {
     return;
   }
@@ -437,7 +437,7 @@
   }
 
   if (data.size()) {
-    request_info_->peer->OnReceivedCachedMetadata(std::move(data));
+    request_info_->client->OnReceivedCachedMetadata(std::move(data));
   }
 }
 
@@ -476,7 +476,7 @@
         request_info_->local_response_start - remote_response_start);
   }
   std::vector<std::string> removed_headers;
-  if (request_info_->peer->OnReceivedRedirect(
+  if (request_info_->client->OnReceivedRedirect(
           redirect_info, response_head.Clone(), &removed_headers)) {
     // Double-check if the request is still around. The call above could
     // potentially remove it.
@@ -511,7 +511,7 @@
   if (!request_info_) {
     return;
   }
-  request_info_->peer->OnStartLoadingResponseBody(std::move(body));
+  request_info_->client->OnStartLoadingResponseBody(std::move(body));
 }
 
 void ResourceRequestSender::OnRequestComplete(
@@ -526,7 +526,7 @@
   request_info_->resource_load_info_notifier_wrapper
       ->NotifyResourceLoadCompleted(status);
 
-  WebRequestPeer* peer = request_info_->peer.get();
+  ResourceRequestClient* client = request_info_->client.get();
 
   network::URLLoaderCompletionStatus renderer_status(status);
   if (status.completion_time.is_null()) {
@@ -565,10 +565,10 @@
   // The request ID will be removed from our pending list in the destructor.
   // Normally, dispatching this message causes the reference-counted request to
   // die immediately.
-  // TODO(kinuko): Revisit here. This probably needs to call request_info_->peer
-  // but the past attempt to change it seems to have caused crashes.
-  // (crbug.com/547047)
-  peer->OnCompletedRequest(renderer_status);
+  // TODO(kinuko): Revisit here. This probably needs to call
+  // request_info_->client but the past attempt to change it seems to have
+  // caused crashes. (crbug.com/547047)
+  client->OnCompletedRequest(renderer_status);
 }
 
 base::TimeTicks ResourceRequestSender::ToLocalURLResponseHead(
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h
index 9e5b4d2..d329811 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h
@@ -52,7 +52,7 @@
 class ResourceLoadInfoNotifierWrapper;
 class ThrottlingURLLoader;
 class MojoURLLoaderClient;
-class WebRequestPeer;
+class ResourceRequestClient;
 struct SyncLoadResponse;
 
 // This class creates a PendingRequestInfo object and handles sending a resource
@@ -88,13 +88,13 @@
       const Vector<String>& cors_exempt_header_list,
       base::WaitableEvent* terminate_sync_load_event,
       mojo::PendingRemote<mojom::blink::BlobRegistry> download_to_blob_registry,
-      scoped_refptr<WebRequestPeer> peer,
+      scoped_refptr<ResourceRequestClient> client,
       std::unique_ptr<ResourceLoadInfoNotifierWrapper>
           resource_load_info_notifier_wrapper);
 
   // Call this method to initiate the request. If this method succeeds, then
-  // the peer's methods will be called asynchronously to report various events.
-  // Returns the request id. |url_loader_factory| must be non-null.
+  // the client's methods will be called asynchronously to report various
+  // events. Returns the request id. |url_loader_factory| must be non-null.
   //
   // You need to pass a non-null |loading_task_runner| to specify task queue to
   // execute loading tasks on.
@@ -104,7 +104,7 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
       const Vector<String>& cors_exempt_header_list,
-      scoped_refptr<WebRequestPeer> peer,
+      scoped_refptr<ResourceRequestClient> client,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
       std::unique_ptr<ResourceLoadInfoNotifierWrapper>
@@ -160,7 +160,7 @@
   friend class URLResponseBodyConsumer;
 
   struct PendingRequestInfo {
-    PendingRequestInfo(scoped_refptr<WebRequestPeer> peer,
+    PendingRequestInfo(scoped_refptr<ResourceRequestClient> client,
                        network::mojom::RequestDestination request_destination,
                        const KURL& request_url,
                        std::unique_ptr<ResourceLoadInfoNotifierWrapper>
@@ -168,7 +168,7 @@
 
     ~PendingRequestInfo();
 
-    scoped_refptr<WebRequestPeer> peer;
+    scoped_refptr<ResourceRequestClient> client;
     network::mojom::RequestDestination request_destination;
     LoaderFreezeMode freeze_mode = LoaderFreezeMode::kNone;
     // Original requested url.
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender_unittest.cc
index 58f2c3b..344fd61 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender_unittest.cc
@@ -33,9 +33,9 @@
 #include "third_party/blink/public/common/loader/referrer_utils.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_request_peer.h"
 #include "third_party/blink/public/platform/web_url_request_extra_data.h"
 #include "third_party/blink/public/platform/web_url_request_util.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "url/gurl.h"
 
@@ -65,12 +65,13 @@
 
 }  // namespace
 
-// A mock WebRequestPeer to receive messages from the ResourceRequestSender.
-class MockRequestPeer : public WebRequestPeer {
+// A mock ResourceRequestClient to receive messages from the
+// ResourceRequestSender.
+class MockRequestClient : public ResourceRequestClient {
  public:
-  MockRequestPeer() = default;
+  MockRequestClient() = default;
 
-  // WebRequestPeer overrides:
+  // ResourceRequestClient overrides:
   void OnUploadProgress(uint64_t position, uint64_t size) override {}
   bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
                           network::mojom::URLResponseHeadPtr head,
@@ -166,11 +167,11 @@
   ResourceRequestSender* sender() { return resource_request_sender_.get(); }
 
   void StartAsync(std::unique_ptr<network::ResourceRequest> request,
-                  scoped_refptr<WebRequestPeer> peer) {
+                  scoped_refptr<ResourceRequestClient> client) {
     sender()->SendAsync(
         std::move(request), scheduler::GetSingleThreadTaskRunnerForTesting(),
         TRAFFIC_ANNOTATION_FOR_TESTS, false,
-        /*cors_exempt_header_list=*/Vector<String>(), std::move(peer),
+        /*cors_exempt_header_list=*/Vector<String>(), std::move(client),
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         std::make_unique<ResourceLoadInfoNotifierWrapper>(
@@ -186,7 +187,7 @@
   ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
   std::unique_ptr<ResourceRequestSender> resource_request_sender_;
 
-  scoped_refptr<MockRequestPeer> mock_peer_;
+  scoped_refptr<MockRequestClient> mock_client_;
 };
 
 // Tests the generation of unique request ids.
@@ -203,7 +204,7 @@
  public:
   void PerformTest(network::mojom::URLResponseHeadPtr response_head) {
     std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
-    StartAsync(std::move(request), mock_peer_);
+    StartAsync(std::move(request), mock_client_);
 
     ASSERT_EQ(1u, loader_and_clients_.size());
     mojo::Remote<network::mojom::URLLoaderClient> client(
@@ -271,8 +272,8 @@
                    base::TimeTicks completion_time,
                    base::TimeDelta delay) {
     std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
-    mock_peer_ = base::MakeRefCounted<MockRequestPeer>();
-    StartAsync(std::move(request), mock_peer_);
+    mock_client_ = base::MakeRefCounted<MockRequestClient>();
+    StartAsync(std::move(request), mock_client_);
 
     ASSERT_EQ(1u, loader_and_clients_.size());
     mojo::Remote<network::mojom::URLLoaderClient> client(
@@ -309,12 +310,12 @@
   }
 
   base::TimeTicks request_start() const {
-    EXPECT_TRUE(mock_peer_->received_response());
-    return mock_peer_->last_load_timing().request_start;
+    EXPECT_TRUE(mock_client_->received_response());
+    return mock_client_->last_load_timing().request_start;
   }
   base::TimeTicks completion_time() const {
-    EXPECT_TRUE(mock_peer_->complete());
-    return mock_peer_->completion_status().completion_time;
+    EXPECT_TRUE(mock_client_->complete());
+    return mock_client_->completion_status().completion_time;
   }
 };
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
index 756672b..b41f7a9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
@@ -111,10 +111,10 @@
     const Vector<String>& cors_exempt_header_list,
     std::unique_ptr<ResourceLoadInfoNotifierWrapper>
         resource_load_info_notifier_wrapper) {
-  scoped_refptr<SyncLoadContext> context(new SyncLoadContext(
+  scoped_refptr<SyncLoadContext> context(base::AdoptRef(new SyncLoadContext(
       request.get(), std::move(pending_url_loader_factory), response,
       context_for_redirect, redirect_or_response_event, abort_event, timeout,
-      std::move(download_to_blob_registry), loading_task_runner));
+      std::move(download_to_blob_registry), loading_task_runner)));
   context->resource_request_sender_->SendAsync(
       std::move(request), std::move(loading_task_runner), traffic_annotation,
       loader_options, cors_exempt_header_list, context,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
index 2abe4ab..91a6d40 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
@@ -15,9 +15,9 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
 #include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_request_peer.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h"
 
 namespace base {
@@ -41,7 +41,7 @@
 //   2) kBlob: body is received on a data pipe passed on
 //      OnStartLoadingResponseBody(), and wraps the data pipe with a
 //      SerializedBlobPtr.
-class BLINK_PLATFORM_EXPORT SyncLoadContext : public WebRequestPeer {
+class BLINK_PLATFORM_EXPORT SyncLoadContext : public ResourceRequestClient {
  public:
   // Begins a new asynchronous request on whatever sequence this method is
   // called on. |completed_event| will be signalled when the request is complete
@@ -94,7 +94,7 @@
       base::TimeDelta timeout,
       mojo::PendingRemote<mojom::blink::BlobRegistry> download_to_blob_registry,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-  // WebRequestPeer implementation:
+  // ResourceRequestClient implementation:
   void OnUploadProgress(uint64_t position, uint64_t size) override;
   bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
                           network::mojom::URLResponseHeadPtr head,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
index a4b21ee..a312de2 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
@@ -74,17 +74,17 @@
 
 class MockResourceRequestSender : public ResourceRequestSender {
  public:
-  void CreatePendingRequest(scoped_refptr<WebRequestPeer> peer) {
-    peer_ = std::move(peer);
+  void CreatePendingRequest(scoped_refptr<ResourceRequestClient> client) {
+    client_ = std::move(client);
   }
 
   void DeletePendingRequest(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
-    peer_.reset();
+    client_.reset();
   }
 
  private:
-  scoped_refptr<WebRequestPeer> peer_;
+  scoped_refptr<ResourceRequestClient> client_;
 };
 
 }  // namespace
@@ -128,17 +128,16 @@
       base::WaitableEvent* redirect_or_response_event,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
     DCHECK(task_runner->BelongsToCurrentThread());
-    auto* context = new SyncLoadContext(
+    auto context = base::AdoptRef(new SyncLoadContext(
         request, std::make_unique<MockPendingSharedURLLoaderFactory>(),
         response, context_for_redirect, redirect_or_response_event,
         nullptr /* terminate_sync_load_event */,
         base::Seconds(60) /* timeout */,
-        mojo::NullRemote() /* download_to_blob_registry */, task_runner);
+        mojo::NullRemote() /* download_to_blob_registry */, task_runner));
 
     auto mock_resource_request_sender =
         std::make_unique<MockResourceRequestSender>();
-    mock_resource_request_sender->CreatePendingRequest(
-        base::WrapRefCounted(context));
+    mock_resource_request_sender->CreatePendingRequest(context);
     context->resource_request_sender_ = std::move(mock_resource_request_sender);
 
     // Simulate the response.
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc
index ca85f48..9c5f9bb 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc
@@ -68,7 +68,6 @@
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
 #include "third_party/blink/public/platform/resource_request_blocked_reason.h"
 #include "third_party/blink/public/platform/url_conversion.h"
-#include "third_party/blink/public/platform/web_request_peer.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_error.h"
@@ -79,6 +78,7 @@
 #include "third_party/blink/public/web/web_security_policy.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/loader/fetch/back_forward_cache_loader_helper.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_client.h"
@@ -97,7 +97,7 @@
 // This inner class exists since the URLLoader may be deleted while inside a
 // call to URLLoaderClient. Refcounting is to keep the context from being
 // deleted if it may have work to do after calling into the client.
-class URLLoader::Context : public WebRequestPeer {
+class URLLoader::Context : public ResourceRequestClient {
  public:
   Context(URLLoader* loader,
           const Vector<String>& cors_exempt_header_list,
@@ -131,7 +131,7 @@
              std::unique_ptr<ResourceLoadInfoNotifierWrapper>
                  resource_load_info_notifier_wrapper);
 
-  // WebRequestPeer overrides:
+  // ResourceRequestClient overrides:
   void OnUploadProgress(uint64_t position, uint64_t size) override;
   bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
                           network::mojom::URLResponseHeadPtr head,
@@ -494,14 +494,15 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     mojo::PendingRemote<mojom::blink::KeepAliveHandle> keep_alive_handle,
     BackForwardCacheLoaderHelper* back_forward_cache_loader_helper)
-    : context_(new Context(this,
-                           cors_exempt_header_list,
-                           terminate_sync_load_event,
-                           std::move(freezable_task_runner),
-                           std::move(unfreezable_task_runner),
-                           std::move(url_loader_factory),
-                           std::move(keep_alive_handle),
-                           back_forward_cache_loader_helper)) {}
+    : context_(
+          base::MakeRefCounted<Context>(this,
+                                        cors_exempt_header_list,
+                                        terminate_sync_load_event,
+                                        std::move(freezable_task_runner),
+                                        std::move(unfreezable_task_runner),
+                                        std::move(url_loader_factory),
+                                        std::move(keep_alive_handle),
+                                        back_forward_cache_loader_helper)) {}
 
 URLLoader::URLLoader() = default;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_unittest.cc
index 0d37b00..c4c317e5 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader_unittest.cc
@@ -39,7 +39,6 @@
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_data.h"
-#include "third_party/blink/public/platform/web_request_peer.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_error.h"
@@ -49,6 +48,7 @@
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/renderer/platform/loader/fetch/loader_freeze_mode.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_response.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.h"
@@ -85,7 +85,7 @@
       const Vector<String>& cors_exempt_header_list,
       base::WaitableEvent* terminate_sync_load_event,
       mojo::PendingRemote<mojom::blink::BlobRegistry> download_to_blob_registry,
-      scoped_refptr<WebRequestPeer> peer,
+      scoped_refptr<ResourceRequestClient> resource_request_client,
       std::unique_ptr<ResourceLoadInfoNotifierWrapper>
           resource_load_info_notifier_wrapper) override {
     *response = std::move(sync_load_response_);
@@ -97,17 +97,17 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
       const Vector<String>& cors_exempt_header_list,
-      scoped_refptr<WebRequestPeer> peer,
+      scoped_refptr<ResourceRequestClient> resource_request_client,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       WebVector<std::unique_ptr<URLLoaderThrottle>> throttles,
       std::unique_ptr<ResourceLoadInfoNotifierWrapper>
           resource_load_info_notifier_wrapper,
       BackForwardCacheLoaderHelper* back_forward_cache_loader_helper) override {
-    EXPECT_FALSE(peer_);
+    EXPECT_FALSE(resource_request_client_);
     if (sync_load_response_.head->encoded_body_length) {
       EXPECT_TRUE(loader_options & network::mojom::kURLLoadOptionSynchronous);
     }
-    peer_ = std::move(peer);
+    resource_request_client_ = std::move(resource_request_client);
     return 1;
   }
 
@@ -116,10 +116,12 @@
     EXPECT_FALSE(canceled_);
     canceled_ = true;
 
-    task_runner->ReleaseSoon(FROM_HERE, std::move(peer_));
+    task_runner->ReleaseSoon(FROM_HERE, std::move(resource_request_client_));
   }
 
-  WebRequestPeer* peer() { return peer_.get(); }
+  ResourceRequestClient* resource_request_client() {
+    return resource_request_client_.get();
+  }
 
   bool canceled() { return canceled_; }
 
@@ -131,7 +133,7 @@
   }
 
  private:
-  scoped_refptr<WebRequestPeer> peer_;
+  scoped_refptr<ResourceRequestClient> resource_request_client_;
   bool canceled_ = false;
   LoaderFreezeMode freeze_mode_ = LoaderFreezeMode::kNone;
   SyncLoadResponse sync_load_response_;
@@ -332,7 +334,7 @@
         std::make_unique<ResourceLoadInfoNotifierWrapper>(
             /*resource_load_info_notifier=*/nullptr),
         client());
-    ASSERT_TRUE(peer());
+    ASSERT_TRUE(resource_request_client());
   }
 
   void DoReceiveRedirect() {
@@ -344,9 +346,9 @@
     redirect_info.new_site_for_cookies =
         net::SiteForCookies::FromUrl(GURL(kTestURL));
     std::vector<std::string> removed_headers;
-    peer()->OnReceivedRedirect(redirect_info,
-                               network::mojom::URLResponseHead::New(),
-                               &removed_headers);
+    resource_request_client()->OnReceivedRedirect(
+        redirect_info, network::mojom::URLResponseHead::New(),
+        &removed_headers);
     EXPECT_TRUE(client()->did_receive_redirect());
   }
 
@@ -358,14 +360,15 @@
     redirect_info.new_url = GURL(kTestHTTPSURL);
     redirect_info.new_site_for_cookies =
         net::SiteForCookies::FromUrl(GURL(kTestHTTPSURL));
-    peer()->OnReceivedRedirect(redirect_info,
-                               network::mojom::URLResponseHead::New(), nullptr);
+    resource_request_client()->OnReceivedRedirect(
+        redirect_info, network::mojom::URLResponseHead::New(), nullptr);
     EXPECT_TRUE(client()->did_receive_redirect());
   }
 
   void DoReceiveResponse() {
     EXPECT_FALSE(client()->did_receive_response());
-    peer()->OnReceivedResponse(network::mojom::URLResponseHead::New());
+    resource_request_client()->OnReceivedResponse(
+        network::mojom::URLResponseHead::New());
     EXPECT_TRUE(client()->did_receive_response());
   }
 
@@ -373,7 +376,8 @@
     mojo::ScopedDataPipeConsumerHandle handle_to_pass;
     MojoResult rv = mojo::CreateDataPipe(nullptr, body_handle_, handle_to_pass);
     ASSERT_EQ(MOJO_RESULT_OK, rv);
-    peer()->OnStartLoadingResponseBody(std::move(handle_to_pass));
+    resource_request_client()->OnStartLoadingResponseBody(
+        std::move(handle_to_pass));
   }
 
   void DoCompleteRequest() {
@@ -385,7 +389,7 @@
     status.encoded_data_length = std::size(kTestData);
     status.encoded_body_length = std::size(kTestData);
     status.decoded_body_length = std::size(kTestData);
-    peer()->OnCompletedRequest(status);
+    resource_request_client()->OnCompletedRequest(status);
     EXPECT_TRUE(client()->did_finish());
     // There should be no error.
     EXPECT_FALSE(client()->error());
@@ -400,7 +404,7 @@
     status.encoded_data_length = std::size(kTestData);
     status.encoded_body_length = std::size(kTestData);
     status.decoded_body_length = std::size(kTestData);
-    peer()->OnCompletedRequest(status);
+    resource_request_client()->OnCompletedRequest(status);
     EXPECT_FALSE(client()->did_finish());
     ASSERT_TRUE(client()->error());
     EXPECT_EQ(net::ERR_FAILED, client()->error()->reason());
@@ -408,7 +412,9 @@
 
   TestURLLoaderClient* client() { return client_.get(); }
   MockResourceRequestSender* sender() { return sender_; }
-  WebRequestPeer* peer() { return sender_->peer(); }
+  ResourceRequestClient* resource_request_client() {
+    return sender_->resource_request_client();
+  }
 
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 70d9703..2a425c5a 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1024,6 +1024,10 @@
       base_feature: "none",
     },
     {
+      name: "CSSSignRelatedFunctions",
+      status: "test",
+    },
+    {
       // Support for CSS ::spelling-error, ::grammar-error, and the
       // spelling-error and grammar-error values in text-decoration-line.
       //
@@ -1677,6 +1681,13 @@
       base_feature: "none",
     },
     {
+      // TODO(crbug.com/1419161): Remove this feature after M113 has been stable
+      // for a few weeks or more. This is a kill switch that, when enabled, goes
+      // back to the old behavior, which was to restore the state for <input>
+      // and <select> even when they had `autocomplete=off`.
+      name: "FormControlRestoreStateIfAutocompleteOff",
+    },
+    {
       name: "FormControlsVerticalWritingModeSupport",
       status: "experimental",
     },
@@ -2551,13 +2562,6 @@
       status: "experimental",
       base_feature: "none",
     },
-    // TODO(crbug/695586): This flag is being used to deprecate support for
-    // legacy quota API window.webkitStorageInfo.
-    {
-      name: "PrefixedStorageInfo",
-      public: true,
-      base_feature_status: "disabled",
-    },
     // This feature is deprecated and we are evangelizing affected sites.
     // See https://crbug.com/346236 for current status.
     {
diff --git a/third_party/blink/renderer/platform/scheduler/common/back_forward_cache_disabling_feature_tracker.cc b/third_party/blink/renderer/platform/scheduler/common/back_forward_cache_disabling_feature_tracker.cc
index bb099c5..1637742 100644
--- a/third_party/blink/renderer/platform/scheduler/common/back_forward_cache_disabling_feature_tracker.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/back_forward_cache_disabling_feature_tracker.cc
@@ -167,9 +167,10 @@
   if (mask == last_uploaded_bfcache_disabling_features_)
     return;
   last_uploaded_bfcache_disabling_features_ = mask;
-  delegate_->UpdateBackForwardCacheDisablingFeatures(
+  FrameOrWorkerScheduler::Delegate::BlockingDetails details(
       mask, non_sticky_features_and_js_locations_,
       sticky_features_and_js_locations_);
+  delegate_->UpdateBackForwardCacheDisablingFeatures(details);
 }
 
 }  // namespace scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 10072958..fa1204eb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -193,15 +193,51 @@
   const base::UnguessableToken& GetAgentClusterId() const override {
     return base::UnguessableToken::Null();
   }
-  MOCK_METHOD(void,
-              UpdateBackForwardCacheDisablingFeatures,
-              (uint64_t,
-               const BFCacheBlockingFeatureAndLocations&,
-               const BFCacheBlockingFeatureAndLocations&));
+  MOCK_METHOD(void, UpdateBackForwardCacheDisablingFeatures, (BlockingDetails));
 
   int update_task_time_calls_ = 0;
 };
 
+MATCHER(BlockingDetailsHasCCNS, "Blocking details has CCNS.") {
+  bool mask_has_ccns =
+      (arg.feature_mask == (1 << static_cast<uint64_t>(
+                                SchedulingPolicy::Feature::
+                                    kMainResourceHasCacheControlNoStore)) |
+       (1 << static_cast<uint64_t>(
+            SchedulingPolicy::Feature::kMainResourceHasCacheControlNoCache)));
+  bool vector_empty = arg.non_sticky_features_and_js_locations.empty();
+  bool vector_has_ccns =
+      arg.sticky_features_and_js_locations.Contains(
+          FeatureAndJSLocationBlockingBFCache(
+              SchedulingPolicy::Feature::kMainResourceHasCacheControlNoStore,
+              nullptr)) &&
+      arg.sticky_features_and_js_locations.Contains(
+          FeatureAndJSLocationBlockingBFCache(
+              SchedulingPolicy::Feature::kMainResourceHasCacheControlNoCache,
+              nullptr));
+  return mask_has_ccns && vector_empty && vector_has_ccns;
+}
+
+MATCHER_P(BlockingDetailsHasWebSocket,
+          handle,
+          "BlockingDetails has WebSocket.") {
+  bool mask_has_web_socket =
+      (arg.feature_mask ==
+       (1 << static_cast<size_t>(SchedulingPolicy::Feature::kWebSocket)));
+  bool handle_has_web_socket =
+      (handle->GetFeatureAndJSLocationBlockingBFCache() ==
+       FeatureAndJSLocationBlockingBFCache(
+           SchedulingPolicy::Feature::kWebSocket, nullptr));
+  bool vector_empty = arg.sticky_features_and_js_locations.empty();
+  return mask_has_web_socket && handle_has_web_socket && vector_empty;
+}
+
+MATCHER(BlockingDetailsIsEmpty, "BlockingDetails is empty.") {
+  bool non_sticky_vector_empty =
+      arg.non_sticky_features_and_js_locations.empty();
+  bool sticky_vector_empty = arg.sticky_features_and_js_locations.empty();
+  return non_sticky_vector_empty && sticky_vector_empty;
+}
 class FrameSchedulerImplTest : public testing::Test {
  public:
   FrameSchedulerImplTest()
@@ -2114,25 +2150,8 @@
                     {SchedulingPolicy::DisableBackForwardCache()});
                 // Ensure that the feature upload is delayed.
                 testing::Mock::VerifyAndClearExpectations(delegate);
-                EXPECT_CALL(
-                    *delegate,
-                    UpdateBackForwardCacheDisablingFeatures(
-                        (1 << static_cast<size_t>(
-                             SchedulingPolicy::Feature::
-                                 kMainResourceHasCacheControlNoStore)) |
-                            (1 << static_cast<size_t>(
-                                 SchedulingPolicy::Feature::
-                                     kMainResourceHasCacheControlNoCache)),
-                        BFCacheBlockingFeatureAndLocations(),
-                        BFCacheBlockingFeatureAndLocations(
-                            {FeatureAndJSLocationBlockingBFCache(
-                                 SchedulingPolicy::Feature::
-                                     kMainResourceHasCacheControlNoStore,
-                                 nullptr),
-                             FeatureAndJSLocationBlockingBFCache(
-                                 SchedulingPolicy::Feature::
-                                     kMainResourceHasCacheControlNoCache,
-                                 nullptr)})));
+                EXPECT_CALL(*delegate, UpdateBackForwardCacheDisablingFeatures(
+                                           BlockingDetailsHasCCNS()));
               },
               frame_scheduler_.get(), frame_scheduler_delegate_.get()));
 
@@ -2159,15 +2178,9 @@
                  FeatureHandle* feature_handle) {
                 // Ensure that the feature upload is delayed.
                 testing::Mock::VerifyAndClearExpectations(delegate);
-                EXPECT_CALL(
-                    *delegate,
-                    UpdateBackForwardCacheDisablingFeatures(
-                        (1 << static_cast<size_t>(
-                             SchedulingPolicy::Feature::kWebSocket)),
-                        BFCacheBlockingFeatureAndLocations(
-                            {feature_handle
-                                 ->GetFeatureAndJSLocationBlockingBFCache()}),
-                        BFCacheBlockingFeatureAndLocations()));
+                EXPECT_CALL(*delegate,
+                            UpdateBackForwardCacheDisablingFeatures(
+                                BlockingDetailsHasWebSocket(feature_handle)));
               },
               frame_scheduler_.get(), frame_scheduler_delegate_.get(),
               &feature_handle));
@@ -2183,11 +2196,9 @@
                        // Ensure that we don't upload the features for frame
                        // destruction.
                        testing::Mock::VerifyAndClearExpectations(delegate);
-                       EXPECT_CALL(
-                           *delegate,
-                           UpdateBackForwardCacheDisablingFeatures(
-                               testing::_, BFCacheBlockingFeatureAndLocations(),
-                               BFCacheBlockingFeatureAndLocations()))
+                       EXPECT_CALL(*delegate,
+                                   UpdateBackForwardCacheDisablingFeatures(
+                                       BlockingDetailsIsEmpty()))
                            .Times(0);
                      },
                      frame_scheduler_.get(), frame_scheduler_delegate_.get(),
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
index f3defc8..f0bfb28 100644
--- a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
@@ -97,18 +97,27 @@
    public:
     using BFCacheBlockingFeatureAndLocations =
         FrameOrWorkerScheduler::BFCacheBlockingFeatureAndLocations;
+
+    struct BlockingDetails {
+      // TODO(crbug.com/1366675): Remove features_mask.
+      uint64_t feature_mask;
+      const BFCacheBlockingFeatureAndLocations&
+          non_sticky_features_and_js_locations;
+      const BFCacheBlockingFeatureAndLocations&
+          sticky_features_and_js_locations;
+      BlockingDetails(uint64_t mask,
+                      BFCacheBlockingFeatureAndLocations& non_sticky,
+                      BFCacheBlockingFeatureAndLocations& sticky)
+          : feature_mask(mask),
+            non_sticky_features_and_js_locations(non_sticky),
+            sticky_features_and_js_locations(sticky) {}
+    };
     virtual ~Delegate() = default;
 
     // Notifies that the list of active blocking features for this worker has
     // changed when a blocking feature and its JS location are registered or
     // removed.
-    // TODO(crbug.com/1366675): Remove features_mask
-    virtual void UpdateBackForwardCacheDisablingFeatures(
-        uint64_t features_mask,
-        const BFCacheBlockingFeatureAndLocations&
-            non_sticky_features_and_js_locations,
-        const BFCacheBlockingFeatureAndLocations&
-            sticky_features_and_js_locations) = 0;
+    virtual void UpdateBackForwardCacheDisablingFeatures(BlockingDetails) = 0;
   };
 
   virtual ~FrameOrWorkerScheduler();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl_unittest.cc
index 10b9e6c..adcecde 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl_unittest.cc
@@ -347,13 +347,29 @@
 
 class WorkerSchedulerDelegateForTesting : public WorkerScheduler::Delegate {
  public:
-  MOCK_METHOD(void,
-              UpdateBackForwardCacheDisablingFeatures,
-              (uint64_t,
-               const BFCacheBlockingFeatureAndLocations&,
-               const BFCacheBlockingFeatureAndLocations&));
+  MOCK_METHOD(void, UpdateBackForwardCacheDisablingFeatures, (BlockingDetails));
 };
 
+MATCHER(BlockingDetailsHasCCNS, "Compares two blocking details.") {
+  bool mask_has_ccns =
+      (arg.feature_mask == (1 << static_cast<uint64_t>(
+                                SchedulingPolicy::Feature::
+                                    kMainResourceHasCacheControlNoStore)) |
+       (1 << static_cast<uint64_t>(
+            SchedulingPolicy::Feature::kMainResourceHasCacheControlNoCache)));
+  bool vector_empty = arg.non_sticky_features_and_js_locations.empty();
+  bool vector_has_ccns =
+      arg.sticky_features_and_js_locations.Contains(
+          FeatureAndJSLocationBlockingBFCache(
+              SchedulingPolicy::Feature::kMainResourceHasCacheControlNoStore,
+              nullptr)) &&
+      arg.sticky_features_and_js_locations.Contains(
+          FeatureAndJSLocationBlockingBFCache(
+              SchedulingPolicy::Feature::kMainResourceHasCacheControlNoCache,
+              nullptr));
+  return mask_has_ccns && vector_empty && vector_has_ccns;
+}
+
 // Confirms that the feature usage in a dedicated worker is uploaded to
 // somewhere (the browser side in the actual implementation) via a delegate.
 TEST_F(WorkerSchedulerImplTest, FeatureUpload) {
@@ -379,25 +395,9 @@
                                kMainResourceHasCacheControlNoCache,
                            {SchedulingPolicy::DisableBackForwardCache()});
                        testing::Mock::VerifyAndClearExpectations(delegate);
-                       EXPECT_CALL(
-                           *delegate,
-                           UpdateBackForwardCacheDisablingFeatures(
-                               (1 << static_cast<uint64_t>(
-                                    SchedulingPolicy::Feature::
-                                        kMainResourceHasCacheControlNoStore)) |
-                                   (1 << static_cast<uint64_t>(
-                                        SchedulingPolicy::Feature::
-                                            kMainResourceHasCacheControlNoCache)),
-                               BFCacheBlockingFeatureAndLocations(),
-                               BFCacheBlockingFeatureAndLocations(
-                                   {FeatureAndJSLocationBlockingBFCache(
-                                        SchedulingPolicy::Feature::
-                                            kMainResourceHasCacheControlNoStore,
-                                        nullptr),
-                                    FeatureAndJSLocationBlockingBFCache(
-                                        SchedulingPolicy::Feature::
-                                            kMainResourceHasCacheControlNoCache,
-                                        nullptr)})));
+                       EXPECT_CALL(*delegate,
+                                   UpdateBackForwardCacheDisablingFeatures(
+                                       BlockingDetailsHasCCNS()));
                      },
                      worker_scheduler_.get(), delegate.get()));
 
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
index 9f38e19..e154cc06 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -469,12 +469,7 @@
 
   void UpdateTaskTime(base::TimeDelta time) override {}
 
-  void UpdateBackForwardCacheDisablingFeatures(
-      uint64_t features_mask,
-      const BFCacheBlockingFeatureAndLocations&
-          non_sticky_features_and_js_locations,
-      const BFCacheBlockingFeatureAndLocations&
-          sticky_features_and_js_locations) override {}
+  void UpdateBackForwardCacheDisablingFeatures(BlockingDetails) override {}
 
   const base::UnguessableToken& GetAgentClusterId() const override {
     return base::UnguessableToken::Null();
diff --git a/third_party/blink/tools/BUILD.gn b/third_party/blink/tools/BUILD.gn
index 19aefd6c..cb7b879 100644
--- a/third_party/blink/tools/BUILD.gn
+++ b/third_party/blink/tools/BUILD.gn
@@ -12,9 +12,7 @@
     # WPT tooling
     "//third_party/wpt_tools/",
 
-    # Include blinkpy tools for setting up expectations and uploading results to
-    # ResultDB.
-    "//third_party/blink/tools/wpt_process_results.py",
+    # Include blinkpy tools for uploading results to ResultDB.
     "//third_party/blink/tools/blinkpy/",
 
     # Imported by some code in blinkpy.
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
index ff93640..deb4064 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
@@ -3,25 +3,39 @@
 # found in the LICENSE file.
 """Process WPT results for upload to ResultDB."""
 
-import argparse
 import base64
+import collections
+import contextlib
 import json
 import logging
-import optparse
-from typing import List
+import queue
+import threading
+from typing import (
+    Any,
+    Dict,
+    Iterator,
+    List,
+    NamedTuple,
+    Optional,
+    Set,
+    TypedDict,
+)
+from urllib.parse import urlsplit
 
 import mozinfo
 
 from blinkpy.common import path_finder
 from blinkpy.common.html_diff import html_diff
-from blinkpy.common.system.log_utils import configure_logging
+from blinkpy.common.memoized import memoized
+from blinkpy.common.system.filesystem import FileSystem
 from blinkpy.common.unified_diff import unified_diff
+from blinkpy.web_tests.port.base import Port
 from blinkpy.web_tests.models import test_failures
 from blinkpy.web_tests.models.typ_types import (
     Artifacts,
     Result,
-    ResultType,
     ResultSinkReporter,
+    ResultType,
 )
 
 path_finder.bootstrap_wpt_imports()
@@ -32,9 +46,132 @@
 _log = logging.getLogger(__name__)
 
 
-def _remove_query_params(test_name):
-    index = test_name.rfind('?')
-    return test_name if index == -1 else test_name[:index]
+class WPTResult(Result):
+    """A container for a wptrunner test result.
+
+    This class extends the typ `Result` type with wptrunner-specific
+    functionality:
+     1. Maps more specific wptrunner statuses to web test ones (which are then
+        mapped to ResultDB ones within typ).
+     2. Handles subtests. See below for an explanation of status priority.
+     3. Format (sub)test statuses and messages into WPT metadata or logs.
+    """
+
+    _wptrunner_to_chromium_statuses = {
+        'OK': ResultType.Pass,
+        'PASS': ResultType.Pass,
+        'FAIL': ResultType.Failure,
+        'ERROR': ResultType.Failure,
+        'PRECONDITION_FAILED': ResultType.Failure,
+        'TIMEOUT': ResultType.Timeout,
+        'EXTERNAL-TIMEOUT': ResultType.Timeout,
+        'CRASH': ResultType.Crash,
+        'INTERNAL-ERROR': ResultType.Crash,
+        'SKIP': ResultType.Skip,
+        'NOTRUN': ResultType.Skip,
+    }
+
+    _status_priority = [
+        # Sorted from least to most "interesting" statuses. A status is more
+        # "interesting" when it indicates the test did not run to completion.
+        ResultType.Pass,
+        ResultType.Failure,
+        ResultType.Skip,
+        ResultType.Timeout,
+        ResultType.Crash,
+    ]
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.messages = []
+        self._test_section = wptnode.DataNode(_test_basename(self.name))
+
+    def _add_expected_status(self, section: wptnode.DataNode, status: str):
+        expectation = wptnode.KeyValueNode('expected')
+        expectation.append(wptnode.ValueNode(status))
+        section.append(expectation)
+
+    def _maybe_set_statuses(self, status: str, expected: Set[str]):
+        """Set this result's actual/expected statuses.
+
+        A `testharness.js` test may have subtests with their own statuses and
+        expectations, in addition to the test-level harness status/expectation.
+        As a result, there isn't a singular status to report to ResultDB.
+
+        This method resolves this conflict by reporting the most "interesting"
+        status among all tests/subtests. Given two statuses with the same
+        priority, tiebreak by favoring the unexpected status, followed by the
+        latest status. The order tiebreaker ensures a test-level status
+        overrides a subtest-level status when they have the same priority.
+        """
+        actual = self._wptrunner_to_chromium_statuses[status]
+        expected = {
+            self._wptrunner_to_chromium_statuses[status]
+            for status in expected
+        }
+        unexpected = actual not in expected
+        priority = (self._status_priority.index(actual), unexpected)
+        # pylint: disable=access-member-before-definition
+        # `actual` and `unexpected` are set in `Result`'s constructor.
+        if priority >= (self._status_priority.index(
+                self.actual), self.unexpected):
+            self.actual, self.expected = actual, expected
+            self.unexpected = unexpected
+
+    def update_from_subtest(self,
+                            subtest: str,
+                            status: str,
+                            expected: Set[str],
+                            message: Optional[str] = None):
+        if message:
+            self.messages.append('%s: %s\n' % (subtest, message))
+        subtest_section = wptnode.DataNode(subtest)
+        self._add_expected_status(subtest_section, status)
+        self._test_section.append(subtest_section)
+        # Tentatively promote "interesting" statuses to the test level.
+        self._maybe_set_statuses(status, expected)
+
+    def update_from_test(self,
+                         status: str,
+                         expected: Set[str],
+                         message: Optional[str] = None):
+        if message:
+            self.messages.insert(0, 'Harness: %s\n' % message)
+        self._add_expected_status(self._test_section, status)
+        self._maybe_set_statuses(status, expected)
+
+    @property
+    def actual_metadata(self):
+        return wptmanifest.serialize(self._test_section)
+
+
+def _test_basename(test_id: str) -> str:
+    # The test "basename" is test path + query string + fragment
+    path_parts = urlsplit(test_id).path.rsplit('/', maxsplit=1)
+    if len(path_parts) == 1:
+        return test_id
+    return test_id[len(path_parts[0]) + 1:]
+
+
+class Event(NamedTuple):
+    action: str
+    time: int
+    thread: str
+    pid: int
+    source: str
+
+
+class EventProcessingError(ValueError):
+    """Non-fatal exception raised when an event cannot be processed.
+
+    Examples of bad inputs:
+      * Events delivered out-of-order (e.g., `test_end` before `test_start`).
+      * Referencing a test that doesn't exist.
+    """
+
+
+class StreamShutdown(Exception):
+    """Exception to halt event processing."""
 
 
 def update_with_static_expectations(test_or_subtest: ManifestItem):
@@ -74,96 +211,66 @@
         update_with_static_expectations(child_item)
 
 
+class ReftestScreenshot(TypedDict):
+    """A screenshot of either a test page or one of its references.
+
+    If the URL matches the test page, the screenshot is for the page under test.
+    """
+    url: str
+    screenshot: str
+
+
 class WPTResultsProcessor:
+    # Executables that wptrunner can start and whose output should go into the
+    # crash log.
+    _executables = [
+        'chromedriver',
+        'logcat',
+        'content_shell',
+    ]
+
     def __init__(self,
-                 host,
-                 port=None,
-                 web_tests_dir='',
-                 artifacts_dir='',
-                 results_dir='',
-                 sink=None):
-        self.host = host
-        self.fs = self.host.filesystem
-        self.port = port or self.host.port_factory.get()
-        self.web_tests_dir = web_tests_dir
+                 fs: FileSystem,
+                 port: Port,
+                 artifacts_dir: str = '',
+                 sink: Optional[ResultSinkReporter] = None,
+                 test_name_prefix: str = ''):
+        self.fs = fs
+        self.port = port
         self.artifacts_dir = artifacts_dir
-        self.results_dir = results_dir
         self.sink = sink or ResultSinkReporter()
+        # This prefix does not actually exist on disk and only affects how the
+        # results are reported.
+        if test_name_prefix and not test_name_prefix.endswith('/'):
+            test_name_prefix += '/'
+        self.test_name_prefix = test_name_prefix
         self.wpt_manifest = self.port.wpt_manifest('external/wpt')
         self.internal_manifest = self.port.wpt_manifest('wpt_internal')
         self.path_finder = path_finder.PathFinder(self.fs)
-        # Provide placeholder properties until the wptreport is processed.
+        # Provide placeholder properties until the `suite_start` events are
+        # processed.
         self.run_info = dict(mozinfo.info)
 
-    @classmethod
-    def from_options(cls, host, options):
-        logging_level = logging.DEBUG if options.verbose else logging.INFO
-        configure_logging(logging_level=logging_level, include_time=True)
+        self._iteration: int = 0
+        self._results: Dict[str, WPTResult] = {}
+        self._leaves: Dict[str, Dict[str, Any]] = collections.defaultdict(dict)
+        self._crash_log: List[str] = []
+        self._event_handlers = {
+            'suite_start': self.suite_start,
+            'test_start': self.test_start,
+            'test_status': self.test_status,
+            'test_end': self.test_end,
+            'suite_end': self.suite_end,
+            'shutdown': self.shutdown,
+            'process_output': self.process_output,
+        }
+        self.has_regressions: bool = False
 
-        port_options = optparse.Values()
-        # The factory will read the configuration ("Debug" or "Release")
-        # automatically from //src/<target>.
-        port_options.ensure_value('configuration', None)
-        port_options.ensure_value('target', options.target)
-        port_options.ensure_value('manifest_update', False)
-
-        port = host.port_factory.get(options=port_options)
-
-        results_dir = host.filesystem.dirname(options.wpt_results)
-        return WPTResultsProcessor(host, port, options.web_tests_dir,
-                                   options.artifacts_dir, results_dir)
-
-    def main(self, options):
-        self._recreate_artifacts_dir()
-        if options.wpt_report:
-            self.process_wpt_report(options.wpt_report)
-        else:
-            _log.debug('No wpt report to process')
-        self.process_wpt_results(options.wpt_results)
-        self._copy_results_viewer()
-
-    @classmethod
-    def parse_args(cls, argv=None):
-        parser = argparse.ArgumentParser(description=__doc__)
-        parser.add_argument(
-            '-v',
-            '--verbose',
-            action='store_true',
-            help='log extra details helpful for debugging',
-        )
-        parser.add_argument(
-            '-t',
-            '--target',
-            default='Release',
-            help='target build subdirectory under //out',
-        )
-        parser.add_argument(
-            '--web-tests-dir',
-            required=True,
-            help='path to the web tests root',
-        )
-        parser.add_argument(
-            '--artifacts-dir',
-            required=True,
-            help='path to a directory to write artifacts to',
-        )
-        parser.add_argument(
-            '--wpt-results',
-            required=True,
-            help=('path to the JSON test results file '
-                  '(created with `wpt run --log-chromium=...`)'),
-        )
-        parser.add_argument(
-            '--wpt-report',
-            help=('path to the wptreport file '
-                  '(created with `wpt run --log-wptreport=...`)'),
-        )
-        return parser.parse_args(argv)
-
-    def _recreate_artifacts_dir(self):
+    def recreate_artifacts_dir(self):
         if self.fs.exists(self.artifacts_dir):
             self.fs.rmtree(self.artifacts_dir)
         self.fs.maybe_make_directory(self.artifacts_dir)
+        self._copy_results_viewer()
         _log.info('Recreated artifacts directory (%s)', self.artifacts_dir)
 
     def _copy_results_viewer(self):
@@ -177,12 +284,12 @@
                 _log.info('Copied results viewer (%s -> %s)', source,
                           destination)
 
-    def process_wpt_results(self,
-                            raw_results_path,
-                            full_results_json=None,
-                            full_results_jsonp=None,
-                            failing_results_jsonp=None):
-        """Postprocess the results generated by wptrunner.
+    def process_results_json(self,
+                             raw_results_path,
+                             full_results_json=None,
+                             full_results_jsonp=None,
+                             failing_results_jsonp=None):
+        """Postprocess the results JSON generated by wptrunner.
 
         Arguments:
             raw_results_path (str): Path to a JSON results file, which contains
@@ -217,13 +324,8 @@
             num_passes = results['num_failures_by_type']['PASS']
             results['num_passes'] = num_passes
 
-        test_names = self._update_tests_trie(
-            results['tests'],
-            delim=results['path_delimiter'],
-            # This prefix does not actually exist on disk and only affects
-            # how the results are reported.
-            test_name_prefix=metadata.get('test_name_prefix', ''))
-        _log.info('Extracted artifacts for %d tests', len(test_names))
+        self._update_tests_trie(results['tests'],
+                                delim=results.get('path_delimiter', '/'))
 
         results['num_regressions'] = self._count_regressions(results['tests'])
 
@@ -244,11 +346,177 @@
             json.dump(results, dest)
             dest.write(');')
 
+    @contextlib.contextmanager
+    def stream_results(self,
+                       timeout: float = 3) -> Iterator[queue.SimpleQueue]:
+        """Asynchronously handle wptrunner test results.
+
+        This context manager starts and cleans up a worker thread to write
+        artifacts to disk and, in LUCI, report results to ResultSink.
+
+        Yields:
+            A queue that the caller should put `mozlog` events into. The worker
+            will consume events from the queue.
+
+        Raises:
+            TimeoutError: If the worker thread fails to join within the given
+                timeout. This probably indicates the event queue was backlogged
+                before this manager exited; a well-behaved caller should avoid
+                this.
+        """
+        self.recreate_artifacts_dir()
+        events = queue.SimpleQueue()
+        worker = threading.Thread(target=self._consume_events,
+                                  args=(events, ),
+                                  name='results-stream-worker',
+                                  daemon=True)
+        worker.start()
+        try:
+            yield events
+        finally:
+            # Send a shutdown event, if one has not been sent already, to tell
+            # the worker to exit.
+            events.put({'action': 'shutdown'}, timeout=timeout)
+            worker.join(timeout=timeout)
+
+    def _consume_events(self, events: queue.SimpleQueue):
+        while True:
+            event = events.get()
+            try:
+                self.process_event(event)
+            except StreamShutdown:
+                _log.info('Stopping results stream worker thread.')
+                return
+            except EventProcessingError as error:
+                _log.error('Unable to process event %r: %s', event, error)
+
+    def process_event(self, raw_event: Dict[str, Any]):
+        raw_event = dict(raw_event)
+        event = Event(raw_event.pop('action'), raw_event.pop('time'),
+                      raw_event.pop('thread'), raw_event.pop('pid'),
+                      raw_event.pop('source'))
+        test = raw_event.pop('test', None)
+        if test:
+            raw_event['test'] = test[1:] if test.startswith('/') else test
+        status = raw_event.get('status')
+        if status:
+            expected = {raw_event.get('expected', status)}
+            expected.update(raw_event.pop('known_intermittent', []))
+            raw_event['expected'] = expected
+        handler = self._event_handlers.get(event.action)
+        if handler:
+            handler(event, **raw_event)
+        elif event.action != 'log':
+            _log.warning(
+                "%r event received, but not handled (event: %r, "
+                'extra: %r)', event.action, event, raw_event)
+
+    def suite_start(self,
+                    event: Event,
+                    run_info: Optional[Dict[str, Any]] = None,
+                    **_):
+        if run_info:
+            self.run_info.update(run_info)
+
+    def suite_end(self, event: Event, **_):
+        self._iteration += 1
+
+    def test_start(self, event: Event, test: str, **_):
+        self._results[test] = WPTResult(
+            test,
+            # Placeholder status that has the lowest priority possible.
+            actual=ResultType.Pass,
+            unexpected=False,
+            started=event.time,
+            took=0,
+            worker=0,
+            file_path=self._file_path_for_test(test),
+            pid=event.pid)
+
+    @memoized
+    def _file_path_for_test(self, test: str) -> str:
+        if test.startswith('wpt_internal/'):
+            prefix = 'wpt_internal'
+            path_from_test_root = self.internal_manifest.file_path_for_test_url(
+                test[len('wpt_internal/'):])
+        else:
+            prefix = self.path_finder.wpt_prefix()
+            path_from_test_root = self.wpt_manifest.file_path_for_test_url(
+                test)
+        if not path_from_test_root:
+            raise EventProcessingError(
+                'Test ID %r does not exist in the manifest' % test)
+        return self.path_finder.path_from_web_tests(prefix,
+                                                    path_from_test_root)
+
+    def test_status(self,
+                    event: Event,
+                    test: str,
+                    subtest: str,
+                    status: str,
+                    expected: Set[str],
+                    message: Optional[str] = None,
+                    **_):
+        result = self._results.get(test)
+        if not result:
+            raise EventProcessingError('Test not started: %s' % test)
+        result.update_from_subtest(subtest, status, expected, message)
+
+    def test_end(self,
+                 event: Event,
+                 test: str,
+                 status: str,
+                 expected: Set[str],
+                 message: Optional[str] = None,
+                 extra: Optional[Dict[str, Any]] = None,
+                 **_):
+        result = self._results.pop(test, None)
+        if not result:
+            raise EventProcessingError('Test not started: %s' % test)
+        result.took = max(0, event.time - result.started) / 1000
+        result.update_from_test(status, expected, message)
+        result.artifacts = self._extract_artifacts(result, extra).artifacts
+        if result.unexpected:
+            if (self.run_info.get('sanitizer_enabled')
+                    and result.actual == ResultType.Failure):
+                # `--enable-sanitizer` is equivalent to running every test as a
+                # crashtest. It suffices for a crashtest to not suffer a timeout
+                # or low-level crash to pass:
+                #   https://web-platform-tests.org/writing-tests/crashtest.html
+                result.actual = ResultType.Pass
+                result.unexpected = False
+            if result.actual not in {ResultType.Pass, ResultType.Skip}:
+                self.has_regressions = True
+        self.sink.report_individual_test_result(
+            test_name_prefix=self.test_name_prefix,
+            result=result,
+            artifact_output_dir=self.fs.dirname(self.artifacts_dir),
+            expectations=None,
+            test_file_location=result.file_path)
+        _log.debug(
+            'Reported result for %s, iteration %d (actual: %s, '
+            'expected: %s, artifacts: %s)', result.name, self._iteration,
+            result.actual, ', '.join(sorted(result.expected)), ', '.join(
+                sorted(result.artifacts)) if result.artifacts else '<none>')
+
+    def shutdown(self, event: Event, **_):
+        if self._results:
+            _log.warning('Some tests have unreported results:')
+            for test in sorted(self._results):
+                _log.warning('  %s', test)
+        raise StreamShutdown
+
+    def process_output(self, event: Event, command: str, data: Any, **_):
+        if not any(executable in command for executable in self._executables):
+            return
+        if not isinstance(data, str):
+            data = json.dumps(data, sort_keys=True)
+        self._crash_log.append(data + '\n')
+
     def _update_tests_trie(self,
                            current_node,
                            current_path: str = '',
-                           delim: str = '/',
-                           test_name_prefix: str = '') -> List[str]:
+                           delim: str = '/'):
         """Recursively update the test results trie.
 
         The JSON results represent tests as the leaves of a trie (nested
@@ -263,33 +531,20 @@
                 name at a leaf node. An empty path represents the WPT root URL.
             delim: Delimiter between components in test names. In practice, the
                 value is the POSIX directory separator.
-            test_name_prefix: Test name prefix to prepend to the generated
-                path when uploading results.
-
-        Returns:
-            A list of test names found.
         """
-        if test_name_prefix and not test_name_prefix.endswith(delim):
-            test_name_prefix += delim
         if 'actual' in current_node:
             # Leaf node detected.
-            self._add_result_to_sink(current_node, current_path,
-                                     test_name_prefix)
-            return [current_path]
+            current_node.update(self._leaves.get(current_path, {}))
         else:
-            test_names = []
             for component, child_node in current_node.items():
                 if current_path:
                     child_path = current_path + delim + component
                 else:
                     # At the web test root, do not include a leading slash.
                     child_path = component
-                test_names.extend(
-                    self._update_tests_trie(child_node, child_path, delim,
-                                            test_name_prefix))
-            return test_names
+                self._update_tests_trie(child_node, child_path, delim)
 
-    def _read_expected_metadata(self, test_name):
+    def _read_expected_metadata(self, test_name: str, file_path: str):
         """Try to locate the expected output of this test, if it exists.
 
         The expected output of a test is checked in to the source tree beside
@@ -300,31 +555,26 @@
             ValueError: If the expected metadata was unreadable or unparsable.
         """
         if self.path_finder.is_wpt_internal_path(test_name):
-            test_file_subpath = self.internal_manifest.file_path_for_test_url(
-                test_name[len('wpt_internal/'):])
             metadata_root = self.path_finder.path_from_web_tests(
                 'wpt_internal')
         else:
             # TODO(crbug.com/1299650): Support virtual tests and metadata fallback.
-            test_file_subpath = self.wpt_manifest.file_path_for_test_url(
-                test_name)
             metadata_root = self.path_finder.path_from_web_tests(
                 'external', 'wpt')
-        if not test_file_subpath:
-            raise ValueError('test ID did not resolve to a file')
+        test_file_subpath = self.fs.relpath(file_path, metadata_root)
         manifest = manifestexpected.get_manifest(metadata_root,
                                                  test_file_subpath,
                                                  self.run_info)
         if not manifest:
-            raise ValueError('unable to read ".ini" file from disk')
-        test_manifest = manifest.get_test(test_name.rpartition('/')[-1])
+            raise FileNotFoundError
+        test_manifest = manifest.get_test(_test_basename(test_name))
         if not test_manifest:
             raise ValueError('test ID does not exist')
         update_with_static_expectations(test_manifest)
         return wptmanifest.serialize(test_manifest.node)
 
     def _write_text_results(self, test_name: str, artifacts: Artifacts,
-                            actual_text: str):
+                            actual_text: str, file_path: str):
         """Write actual, expected, and diff text outputs to disk, if possible.
 
         If the expected output (WPT metadata) is missing, this method will not
@@ -345,9 +595,13 @@
                                  write_as_text=True)
 
         try:
-            expected_text = self._read_expected_metadata(test_name)
+            expected_text = self._read_expected_metadata(test_name, file_path)
+        except FileNotFoundError:
+            _log.debug('".ini" file for "%s" does not exist.', file_path)
+            return
         except (ValueError, KeyError, wptmanifest.parser.ParseError) as error:
-            _log.error('Unable to read metadata for %s: %s', test_name, error)
+            _log.warning('Unable to parse metadata for %s: %s', test_name,
+                         error)
             return
         expected_subpath = self.port.output_filename(
             test_name, test_failures.FILENAME_SUFFIX_EXPECTED, '.txt')
@@ -378,16 +632,14 @@
                                  write_as_text=True)
 
     def _write_screenshots(self, test_name: str, artifacts: Artifacts,
-                           screenshots: List[str]):
+                           screenshots: List[ReftestScreenshot]):
         """Write actual, expected, and diff screenshots to disk, if possible.
 
         Arguments:
             test_name: Web test name (a path).
             artifacts: Artifact manager.
             screenshots: Each element represents a screenshot of either the test
-                result or one of its references and has the format
-                `<url>:<base64-encoded PNG>`. If `<url>` matches the test name,
-                that screenshot is of the page under test.
+                result or one of its references.
 
         Returns:
             The diff stats if the screenshots are different.
@@ -397,13 +649,15 @@
         expected_image_bytes = b''
 
         for screenshot in screenshots:
-            url, printable_image = screenshot.rsplit(':', 1)
-
+            if not isinstance(screenshot, dict):
+                # Skip the relation string, like '!=' or '=='.
+                continue
             # The URL produced by wptrunner will have a leading "/", which we
             # trim away for easier comparison to the WPT name below.
+            url = screenshot['url']
             if url.startswith('/'):
                 url = url[1:]
-            image_bytes = base64.b64decode(printable_image.strip())
+            image_bytes = base64.b64decode(screenshot['screenshot'].strip())
 
             screenshot_key = 'expected_image'
             file_suffix = test_failures.FILENAME_SUFFIX_EXPECTED
@@ -441,106 +695,47 @@
                                  log_subpath,
                                  ''.join(lines),
                                  write_as_text=True)
+        lines.clear()
 
-    def _add_result_to_sink(self, node, test_name, test_name_prefix=''):
-        """Add test results to the result sink."""
-        actual_statuses = node['actual'].split()
-        flaky = len(set(actual_statuses)) > 1
-        expected = set(node['expected'].split())
-        durations = node.get('times') or [0] * len(actual_statuses)
-        artifacts = self._extract_artifacts(test_name, node)
+    def _extract_artifacts(self, result: WPTResult, extra) -> Artifacts:
+        # Ensure `artifacts_base_dir` (i.e., `layout-test-results`) is prepended
+        # to `full_results_jsonp.js` paths so that `results.html` can correctly
+        # fetch artifacts.
+        artifacts = Artifacts(self.fs.dirname(self.artifacts_dir),
+                              self.sink.host,
+                              iteration=self._iteration,
+                              artifacts_base_dir=self.fs.basename(
+                                  self.artifacts_dir))
+        leaf = self._leaves[result.name]
+        if result.actual != ResultType.Pass:
+            self._write_text_results(result.name, artifacts,
+                                     result.actual_metadata, result.file_path)
+            screenshots = (extra or {}).get('reftest_screenshots') or []
+            if screenshots:
+                diff_stats = self._write_screenshots(result.name, artifacts,
+                                                     screenshots)
+                leaf['image_diff_stats'] = diff_stats
 
-        if self.path_finder.is_wpt_internal_path(test_name):
-            test_path = self.fs.join(self.web_tests_dir,
-                                     _remove_query_params(test_name))
-        else:
-            test_path = self.fs.join(self.web_tests_dir, 'external', 'wpt',
-                                     _remove_query_params(test_name))
-
-        for iteration, (actual,
-                        duration) in enumerate(zip(actual_statuses,
-                                                   durations)):
-            if (self.run_info.get('sanitizer_enabled')
-                    and actual == ResultType.Failure):
-                # `--enable-sanitizer` is equivalent to running every test as a
-                # crashtest. It suffices for a crashtest to not suffer a timeout
-                # or low-level crash to pass:
-                #   https://web-platform-tests.org/writing-tests/crashtest.html
-                actual = ResultType.Pass
-            result = Result(
-                name=test_name,
-                actual=actual,
-                started=(self.host.time() - duration),
-                took=duration,
-                worker=0,
-                # The expected statuses here are actually the web test/wptrunner
-                # ones, unlike `actual`, which is a ResultDB status.
-                expected=expected,
-                unexpected=(actual not in expected),
-                flaky=flaky,
-                # TODO(crbug/1314847): wptrunner merges output from all runs
-                # together. Until it outputs per-test-run artifacts instead, we
-                # just upload the artifacts on the first result. No need to
-                # upload the same artifacts multiple times.
-                artifacts=(artifacts.artifacts if iteration == 0 else {}),
-            )
-            self.sink.report_individual_test_result(
-                test_name_prefix=test_name_prefix,
-                result=result,
-                artifact_output_dir=self.results_dir,
-                expectations=None,
-                test_file_location=test_path)
-
-    def _extract_artifacts(self, test_name: str, node) -> Artifacts:
-        artifact_contents = node.get('artifacts') or {}
-        nonflaky_pass = node['actual'] == 'PASS'
-        # TODO(crbug.com/1314847): Reenable the overwrite check after the bug is
-        # fixed by removing `repeat_tests=True`.
-        artifacts = Artifacts(output_dir=self.results_dir,
-                              host=self.sink.host,
-                              artifacts_base_dir=self.fs.relpath(
-                                  self.artifacts_dir, self.results_dir),
-                              repeat_tests=True)
-
-        artifact_contents.pop('wpt_actual_status', None)
-        artifact_contents.pop('wpt_subtest_failure', None)
-
-        actual_metadata = artifact_contents.pop('wpt_actual_metadata', None)
-        if not nonflaky_pass and actual_metadata:
-            self._write_text_results(test_name, artifacts,
-                                     '\n'.join(actual_metadata))
-        screenshots = artifact_contents.pop('screenshots', None)
-        if screenshots:
-            diff_stats = self._write_screenshots(test_name, artifacts,
-                                                 screenshots)
-            if diff_stats:
-                node['image_diff_stats'] = diff_stats
-
-        log_lines = artifact_contents.pop('wpt_log', None)
-        if log_lines:
-            self._write_log(test_name, artifacts, 'stderr',
-                            test_failures.FILENAME_SUFFIX_STDERR, log_lines)
-            # Required by `blinkpy/web_tests/results.html` to show as stderr.
-            node['has_stderr'] = True
-        crash_log_lines = artifact_contents.pop('wpt_crash_log', None)
-        if crash_log_lines:
-            self._write_log(test_name, artifacts, 'crash_log',
+        if result.messages:
+            self._write_log(result.name, artifacts, 'stderr',
+                            test_failures.FILENAME_SUFFIX_STDERR,
+                            result.messages)
+            # Required by blinkpy/web_tests/results.html to show stderr.
+            leaf['has_stderr'] = True
+        if self._crash_log:
+            self._write_log(result.name, artifacts, 'crash_log',
                             test_failures.FILENAME_SUFFIX_CRASH_LOG,
-                            crash_log_lines)
+                            self._crash_log)
 
-        # Write back the map with paths to files, not the contents of the files
-        # themselves.
-        node['artifacts'] = artifacts.artifacts
-        _log.debug(
-            'Extracted artifacts for %s: %s', test_name, ', '.join(
-                artifacts.artifacts) if artifacts.artifacts else '(none)')
+        artifacts_across_retries = leaf.setdefault('artifacts', {})
+        for artifact_id, paths in artifacts.artifacts.items():
+            artifacts_across_retries.setdefault(artifact_id, []).extend(paths)
         return artifacts
 
     def _count_regressions(self, current_node) -> int:
         """Recursively count number of regressions from test results trie."""
         if current_node.get('actual'):
             return int(current_node.get('is_regression', 0))
-
         return sum(map(self._count_regressions, current_node.values()))
 
     def _trim_to_regressions(self, current_node):
@@ -575,7 +770,6 @@
             report['results'] = self._compact_wpt_results(report['results'])
         with self.fs.open_text_file_for_writing(artifact_path) as report_file:
             json.dump(report, report_file, separators=(',', ':'))
-        self.run_info.update(report['run_info'])
         _log.info('Processed wpt report (%s -> %s)', report_path,
                   artifact_path)
         self.sink.report_invocation_level_artifacts({
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py
index 948744bb..90da4977 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py
@@ -6,60 +6,29 @@
 import json
 import re
 import textwrap
+from unittest import mock
 
 from blinkpy.common.host_mock import MockHost as BlinkMockHost
 from blinkpy.common.path_finder import PathFinder
 from blinkpy.common.system.log_testing import LoggingTestCase
 from blinkpy.web_tests.port.factory_mock import MockPortFactory
 from blinkpy.w3c.wpt_manifest import BASE_MANIFEST_NAME
-from blinkpy.w3c.wpt_results_processor import WPTResultsProcessor
-
-# The path where the output of a wpt run was written. This is the file that
-# gets processed by WPTResultsProcessor.
-OUTPUT_JSON_FILENAME = "out.json"
-
-
-class MockResultSink(object):
-    def __init__(self, host):
-        self.sink_requests = []
-        self.invocation_level_artifacts = {}
-        self.host = host
-
-    def report_individual_test_result(self, test_name_prefix, result,
-                                      artifact_output_dir, expectations,
-                                      test_file_location):
-        assert not expectations, 'expectation parameter should always be None'
-        self.sink_requests.append({
-            'test_name_prefix': test_name_prefix,
-            'test_path': test_file_location,
-            'result': {
-                'name': result.name,
-                'actual': result.actual,
-                'expected': result.expected,
-                'unexpected': result.unexpected,
-                'took': result.took,
-                'flaky': result.flaky,
-                'artifacts': result.artifacts,
-            },
-        })
-
-    def report_invocation_level_artifacts(self, artifacts):
-        self.invocation_level_artifacts.update(artifacts)
+from blinkpy.w3c.wpt_results_processor import (
+    EventProcessingError,
+    StreamShutdown,
+    WPTResultsProcessor,
+)
 
 
 class WPTResultsProcessorTest(LoggingTestCase):
     def setUp(self):
-        super(WPTResultsProcessorTest, self).setUp()
+        super().setUp()
 
         self.host = BlinkMockHost()
         self.host.port_factory = MockPortFactory(self.host)
         self.fs = self.host.filesystem
         self.path_finder = PathFinder(self.fs)
         port = self.host.port_factory.get()
-        # `MockFileSystem` and `TestPort` use different web test directory
-        # placements to test nonstandard layouts. That is not a goal of this
-        # test case, so we settle on the former for consistency.
-        port.web_tests_dir = self.path_finder.web_tests_dir
 
         # Create a testing manifest containing any test files that we
         # might interact with.
@@ -78,19 +47,34 @@
                             'd933fd981d4a33ba82fb2b000234859bdda1494e',
                             [None, {}]
                         ],
-                        'crash.html': [
+                        'timeout.html': [
                             'd933fd981d4a33ba82fb2b000234859bdda1494e',
                             [None, {}]
                         ],
                         'variant.html': [
                             'b8db5972284d1ac6bbda0da81621d9bca5d04ee7',
-                            ['variant.html?foo=bar', {}],
+                            ['variant.html?foo=bar/abc', {}],
                             ['variant.html?foo=baz', {}],
                         ],
+                    },
+                },
+            }))
+        self.fs.write_text_file(
+            self.path_finder.path_from_web_tests('wpt_internal',
+                                                 'MANIFEST.json'),
+            json.dumps({
+                'items': {
+                    'reftest': {
+                        'reftest.html': [
+                            'c3f2fb6f436da59d43aeda0a7e8a018084557033',
+                            [None, [['reftest-ref.html', '==']], {}],
+                        ],
+                    },
+                    'testharness': {
                         'dir': {
                             'multiglob.https.any.js': [
                                 'd6498c3e388e0c637830fa080cca78b0ab0e5305',
-                                ['dir/multiglob.https.any.window.html', {}],
+                                ['dir/multiglob.https.any.html', {}],
                                 ['dir/multiglob.https.any.worker.html', {}],
                             ],
                         },
@@ -136,313 +120,607 @@
         }
 
         self.processor = WPTResultsProcessor(
-            self.host,
-            port=port,
-            web_tests_dir=port.web_tests_dir(),
+            self.fs,
+            port,
             artifacts_dir=self.fs.join('/mock-checkout', 'out', 'Default',
                                        'layout-test-results'),
-            results_dir=self.fs.join('/mock-checkout', 'out', 'Default'),
-            sink=MockResultSink(port.typ_host()))
+            sink=mock.Mock())
+        self.processor.sink.host = port.typ_host()
 
-    def _create_json_output(self, json_dict):
-        """Writing some json output for processing."""
-        self.fs.write_text_file(OUTPUT_JSON_FILENAME, json.dumps(json_dict))
+    def _event(self, **fields):
+        self.processor.process_event({
+            'pid': 16000,
+            'thread': 'TestRunner',
+            'source': 'web-platform-tests',
+            'time': 1000,
+            **fields
+        })
 
-    def _load_json_output(self, filename=OUTPUT_JSON_FILENAME):
-        """Loads the json output after post-processing."""
-        return json.loads(self.fs.read_text_file(filename))
+    def test_report_expected_pass(self):
+        self._event(action='test_start', time=1000, test='/reftest.html')
+        self._event(action='test_end',
+                    time=3000,
+                    test='/reftest.html',
+                    status='PASS')
 
-    def test_result_sink_for_test_expected_result(self):
-        json_dict = {
-            'tests': {
-                'fail': {
-                    'test.html?variant1': {
-                        'expected': 'PASS FAIL',
-                        'actual': 'FAIL',
-                        'artifacts': {
-                            'wpt_actual_status': ['OK'],
-                            'wpt_actual_metadata': ['test.html actual text'],
-                        },
-                    },
-                },
-                'wpt_internal': {
-                    'fail': {
-                        'test.html?variant1': {
-                            'expected': 'PASS FAIL',
-                            'actual': 'FAIL',
-                            'artifacts': {
-                                'wpt_actual_status': ['OK'],
-                                'wpt_actual_metadata':
-                                ['test.html actual text'],
-                            },
-                        },
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
+        report_mock = self.processor.sink.report_individual_test_result
+        report_mock.assert_called_once_with(
+            test_name_prefix='',
+            result=mock.ANY,
+            artifact_output_dir=self.fs.join('/mock-checkout', 'out',
+                                             'Default'),
+            expectations=None,
+            test_file_location=self.path_finder.path_from_web_tests(
+                'external', 'wpt', 'reftest.html'))
 
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        test_name = self.fs.join('fail', 'test.html?variant1')
-        test_abs_path = self.fs.join(self.processor.web_tests_dir, 'external',
-                                     'wpt', 'fail', 'test.html')
-        path_from_out_dir = self.fs.join('layout-test-results', 'fail',
-                                         'test_variant1-actual.txt')
-        internal_test_name = self.fs.join('wpt_internal', 'fail',
-                                          'test.html?variant1')
-        internal_test_abs_path = self.fs.join(self.processor.web_tests_dir,
-                                              'wpt_internal', 'fail',
-                                              'test.html')
-        internal_path_from_out_dir = self.fs.join('layout-test-results',
-                                                  'wpt_internal', 'fail',
-                                                  'test_variant1-actual.txt')
+        result = report_mock.call_args.kwargs['result']
+        self.assertEqual(result.name, 'reftest.html')
+        self.assertEqual(result.actual, 'PASS')
+        self.assertEqual(result.expected, {'PASS'})
+        self.assertFalse(result.unexpected)
+        self.assertAlmostEqual(result.took, 2)
+        self.assertEqual(result.artifacts, {})
+        self.assertFalse(self.processor.has_regressions)
+
+    def test_report_unexpected_fail(self):
+        self._event(action='test_start',
+                    time=1000,
+                    test='/wpt_internal/reftest.html')
+        self._event(action='test_end',
+                    time=1500,
+                    test='/wpt_internal/reftest.html',
+                    status='FAIL',
+                    expected='PASS',
+                    known_intermittent=['TIMEOUT'])
+
+        report_mock = self.processor.sink.report_individual_test_result
+        report_mock.assert_called_once_with(
+            test_name_prefix='',
+            result=mock.ANY,
+            artifact_output_dir=self.fs.join('/mock-checkout', 'out',
+                                             'Default'),
+            expectations=None,
+            test_file_location=self.path_finder.path_from_web_tests(
+                'wpt_internal', 'reftest.html'))
+
+        result = report_mock.call_args.kwargs['result']
+        self.assertEqual(result.name, 'wpt_internal/reftest.html')
+        self.assertEqual(result.actual, 'FAIL')
+        self.assertEqual(result.expected, {'PASS', 'TIMEOUT'})
+        self.assertTrue(result.unexpected)
+        self.assertAlmostEqual(result.took, 0.5)
         self.assertEqual(
-            self.processor.sink.sink_requests, [{
-                'test_name_prefix': '',
-                'test_path': test_abs_path,
-                'result': {
-                    'name': test_name,
-                    'actual': 'FAIL',
-                    'expected': {'PASS', 'FAIL'},
-                    'unexpected': False,
-                    'took': 0,
-                    'flaky': False,
-                    'artifacts': {
-                        'actual_text': [path_from_out_dir],
-                    },
-                },
-            }, {
-                'test_name_prefix': '',
-                'test_path': internal_test_abs_path,
-                'result': {
-                    'name': internal_test_name,
-                    'actual': 'FAIL',
-                    'expected': {'PASS', 'FAIL'},
-                    'unexpected': False,
-                    'took': 0,
-                    'flaky': False,
-                    'artifacts': {
-                        'actual_text': [internal_path_from_out_dir],
-                    },
-                },
-            }])
+            result.artifacts, {
+                'actual_text': [
+                    self.fs.join('layout-test-results', 'wpt_internal',
+                                 'reftest-actual.txt'),
+                ],
+            })
+        self.assertTrue(self.processor.has_regressions)
 
-    def test_result_sink_for_test_variant(self):
-        json_dict = {
-            'tests': {
-                'fail': {
-                    'test.html?variant1': {
-                        'expected': 'TIMEOUT',
-                        'actual': 'TIMEOUT',
-                        'artifacts': {
-                            'wpt_actual_status': ['TIMEOUT'],
-                            'wpt_actual_metadata': ['test.html actual text'],
-                        },
-                        'time': 1000,
-                        'times': [1000],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
+    def test_report_pass_on_retry(self):
+        self._event(action='suite_start', time=0)
+        self._event(action='test_start',
+                    test='/variant.html?foo=bar/abc',
+                    time=1000)
+        self._event(action='test_end',
+                    test='/variant.html?foo=bar/abc',
+                    time=2000,
+                    status='ERROR',
+                    expected='OK')
+        self._event(action='suite_end', time=3000)
+        self._event(action='suite_start', time=4000)
+        self._event(action='test_start',
+                    test='/variant.html?foo=bar/abc',
+                    time=5000)
+        self._event(action='test_status',
+                    test='/variant.html?foo=bar/abc',
+                    time=5500,
+                    status='PASS',
+                    subtest='subtest',
+                    message="subtest")
+        self._event(action='test_end',
+                    test='/variant.html?foo=bar/abc',
+                    time=6000,
+                    status='OK')
+        self._event(action='suite_end', time=7000)
 
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        test_name = self.fs.join('fail', 'test.html?variant1')
-        test_abs_path = self.fs.join(self.processor.web_tests_dir, 'external',
-                                     'wpt', 'fail', 'test.html')
-        path_from_out_dir = self.fs.join('layout-test-results', 'fail',
-                                         'test_variant1-actual.txt')
-        self.assertEqual(self.processor.sink.sink_requests,
-                         [{
-                             'test_name_prefix': '',
-                             'test_path': test_abs_path,
-                             'result': {
-                                 'name': test_name,
-                                 'actual': 'TIMEOUT',
-                                 'expected': {'TIMEOUT'},
-                                 'unexpected': False,
-                                 'took': 1000,
-                                 'flaky': False,
-                                 'artifacts': {
-                                     'actual_text': [path_from_out_dir],
-                                 },
-                             },
-                         }])
+        report_mock = self.processor.sink.report_individual_test_result
+        report_mock.assert_has_calls([
+            mock.call(test_name_prefix='',
+                      result=mock.ANY,
+                      artifact_output_dir=self.fs.join('/mock-checkout', 'out',
+                                                       'Default'),
+                      expectations=None,
+                      test_file_location=self.path_finder.path_from_web_tests(
+                          'external', 'wpt', 'variant.html')),
+        ] * 2)
 
-    def test_result_sink_with_prefix_through_metadata(self):
-        """Verify that the sink uploads results with a test name prefix.
+        fail, ok = [
+            call.kwargs['result'] for call in report_mock.call_args_list
+        ]
+        self.assertEqual(fail.name, 'variant.html?foo=bar/abc')
+        self.assertEqual(fail.actual, 'FAIL')
+        self.assertEqual(fail.expected, {'PASS'})
+        self.assertTrue(fail.unexpected)
+        self.assertEqual(ok.name, 'variant.html?foo=bar/abc')
+        self.assertEqual(ok.actual, 'PASS')
+        self.assertEqual(ok.expected, {'PASS'})
+        self.assertFalse(ok.unexpected)
+        self.assertEqual(
+            ok.artifacts, {
+                'stderr': [
+                    self.fs.join('layout-test-results', 'retry_1',
+                                 'variant_foo=bar_abc-stderr.txt'),
+                ],
+            })
 
-        The JSON results format allows passing arbitrary key-value data through
-        the "metadata" field. Some test runners include a "test_name_prefix"
-        metadata key that should be prepended to each test path in the trie.
+    def test_report_expected_subtest_fail(self):
+        """Subtest failures should be promoted to the test level.
 
-        See Also:
-            https://source.chromium.org/chromium/_/chromium/catapult.git/+/0c6b8d6722cc0e4a35b51d5104374b8cf9cc264e:third_party/typ/typ/runner.py;l=243-244
+        The subtest failure should override the test-level harness OK.
         """
-        self._create_json_output({
-            'tests': {
-                'fail': {
-                    'test.html': {
-                        'expected': 'PASS',
-                        'actual': 'FAIL',
-                        'artifacts': {
-                            'wpt_actual_status': ['OK'],
-                            'wpt_actual_metadata': ['test.html actual text'],
-                        },
-                    },
-                },
-            },
-            'path_delimiter': '/',
-            'metadata': {
-                'test_name_prefix': 'with_finch_seed',
-            },
-        })
+        self._event(action='test_start', test='/test.html')
+        self._event(action='test_status',
+                    test='/test.html',
+                    subtest='fail',
+                    status='FAIL')
+        self._event(action='test_end', test='/test.html', status='OK')
 
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        test_name = self.fs.join('fail', 'test.html')
-        test_abs_path = self.fs.join(self.processor.web_tests_dir, 'external',
-                                     'wpt', 'fail', 'test.html')
-        path_from_out_dir = self.fs.join('layout-test-results', 'fail',
-                                         'test-actual.txt')
-        self.assertEqual(self.processor.sink.sink_requests,
-                         [{
-                             'test_name_prefix': 'with_finch_seed/',
-                             'test_path': test_abs_path,
-                             'result': {
-                                 'name': test_name,
-                                 'actual': 'FAIL',
-                                 'expected': {'PASS'},
-                                 'unexpected': True,
-                                 'took': 0,
-                                 'flaky': False,
-                                 'artifacts': {
-                                     'actual_text': [path_from_out_dir],
-                                 },
-                             },
-                         }])
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'test.html')
+        self.assertEqual(result.actual, 'FAIL')
+        self.assertEqual(result.expected, {'FAIL'})
+        self.assertFalse(result.unexpected)
 
-    def test_result_sink_with_sanitizer(self):
-        self._create_json_output({
-            'tests': {
-                'fail': {
-                    'test.html': {
-                        'expected': 'PASS',
-                        'actual': 'FAIL',
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        })
-        self.processor.run_info['sanitizer_enabled'] = True
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        (request, ) = self.processor.sink.sink_requests
-        self.assertEqual(request['result']['actual'], 'PASS')
-        self.assertEqual(request['result']['expected'], {'PASS'})
-        self.assertEqual(request['result']['unexpected'], False)
+    def test_report_unexpected_subtest_fail(self):
+        self._event(action='test_start', test='/test.html')
+        self._event(action='test_status',
+                    test='/test.html',
+                    subtest='pass before',
+                    status='PASS')
+        self._event(action='test_status',
+                    test='/test.html',
+                    subtest='unexpected fail',
+                    status='FAIL',
+                    expected='PASS')
+        self._event(action='test_status',
+                    test='/test.html',
+                    subtest='expected fail',
+                    status='FAIL')
+        self._event(action='test_status',
+                    test='/test.html',
+                    subtest='unexpected pass after',
+                    status='PASS',
+                    expected='FAIL')
+        self._event(action='test_end', test='/test.html', status='OK')
 
-    def test_result_sink_for_multiple_runs(self):
-        json_dict = {
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'test.html')
+        self.assertEqual(result.actual, 'FAIL')
+        self.assertEqual(result.expected, {'PASS'})
+        self.assertTrue(result.unexpected)
+
+    def test_report_unexpected_timeout(self):
+        """NOTRUN should not be promoted to the test level."""
+        self._event(action='test_start', test='/timeout.html')
+        self._event(action='test_status',
+                    test='/timeout.html',
+                    subtest='timeout',
+                    status='TIMEOUT',
+                    expected='PASS')
+        self._event(action='test_status',
+                    test='/timeout.html',
+                    subtest='notrun',
+                    status='NOTRUN',
+                    expected='PASS')
+        self._event(action='test_end',
+                    test='/timeout.html',
+                    status='TIMEOUT',
+                    expected='OK')
+
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'timeout.html')
+        self.assertEqual(result.actual, 'TIMEOUT')
+        self.assertEqual(result.expected, {'PASS'})
+        self.assertTrue(result.unexpected)
+
+    def test_report_expected_timeout_with_unexpected_fails(self):
+        """Timeouts are always reported, even with subtest failures.
+
+        We want to surface when the harness fails to run to completion, even if
+        the failure to complete is expected. Timeouts/crashes need to be fixed
+        before the failed assertions.
+        """
+        self._event(action='test_start', test='/timeout.html')
+        self._event(action='test_status',
+                    test='/timeout.html',
+                    subtest='unexpected fail',
+                    status='FAIL',
+                    expected='PASS')
+        self._event(action='test_status',
+                    test='/timeout.html',
+                    subtest='timeout',
+                    status='TIMEOUT')
+        self._event(action='test_end', test='/timeout.html', status='TIMEOUT')
+
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'timeout.html')
+        self.assertEqual(result.actual, 'TIMEOUT')
+        self.assertEqual(result.expected, {'TIMEOUT'})
+        self.assertFalse(result.unexpected)
+
+    def test_report_sanitizer_fail(self):
+        self._event(action='suite_start', run_info={'sanitizer_enabled': True})
+        self._event(action='test_start', test='/reftest.html')
+        self._event(action='test_end',
+                    test='/reftest.html',
+                    status='FAIL',
+                    expected='PASS')
+        self._event(action='suite_end')
+
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'reftest.html')
+        self.assertEqual(result.actual, 'PASS')
+        self.assertEqual(result.expected, {'PASS'})
+        self.assertFalse(result.unexpected)
+
+    def test_report_skip(self):
+        self._event(action='test_start', test='/reftest.html')
+        self._event(action='test_end', test='/reftest.html', status='SKIP')
+
+        result = self.processor.sink.report_individual_test_result.call_args.kwargs[
+            'result']
+        self.assertEqual(result.name, 'reftest.html')
+        self.assertEqual(result.actual, 'SKIP')
+        self.assertEqual(result.expected, {'SKIP'})
+        self.assertFalse(result.unexpected)
+
+    def test_extract_text(self):
+        # There are multiple variants (test parameterizations) in the same
+        # metadata file. The processor should extract the relevant section as
+        # the expected text and generate diffs.
+        self.fs.write_text_file(
+            self.path_finder.path_from_wpt_tests('variant.html.ini'),
+            textwrap.dedent("""\
+                [variant.html?foo=bar/abc]
+                  expected: OK
+
+                [variant.html?foo=baz]
+                  expected: FAIL
+                """))
+        with self.fs.patch_builtins():
+            self._event(action='test_start', test='/variant.html?foo=baz')
+            self._event(action='test_end',
+                        test='/variant.html?foo=baz',
+                        status='CRASH',
+                        expected='FAIL')
+
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results',
+                             'variant_foo=baz-actual.txt')),
+            textwrap.dedent("""\
+                [variant.html?foo=baz]
+                  expected: CRASH
+                """))
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results',
+                             'variant_foo=baz-expected.txt')),
+            textwrap.dedent("""\
+                [variant.html?foo=baz]
+                  expected: FAIL
+                """))
+        diff_lines = self.fs.read_text_file(
+            self.fs.join('/mock-checkout', 'out', 'Default',
+                         'layout-test-results',
+                         'variant_foo=baz-diff.txt')).splitlines()
+        self.assertIn('-  expected: FAIL', diff_lines)
+        self.assertIn('+  expected: CRASH', diff_lines)
+        pretty_diff = self.fs.read_text_file(
+            self.fs.join('/mock-checkout', 'out', 'Default',
+                         'layout-test-results',
+                         'variant_foo=baz-pretty-diff.html'))
+        self.assertIn('expected: FAIL', pretty_diff)
+        self.assertIn('expected: CRASH', pretty_diff)
+
+    def test_extract_text_multiglobal(self):
+        # Similar to a test with variants, the processor should extract the
+        # correct section from a metadata file with multiple.
+        self.fs.write_text_file(
+            self.path_finder.path_from_web_tests('wpt_internal', 'dir',
+                                                 'multiglob.https.any.js.ini'),
+            textwrap.dedent("""\
+                [multiglob.https.any.worker.html]
+                  [subtest]
+                    expected: FAIL
+
+                [multiglob.https.any.html]
+                  expected: OK
+                """))
+        with self.fs.patch_builtins():
+            self._event(
+                action='test_start',
+                test='/wpt_internal/dir/multiglob.https.any.worker.html')
+            self._event(
+                action='test_end',
+                test='/wpt_internal/dir/multiglob.https.any.worker.html',
+                status='CRASH',
+                expected='OK')
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'wpt_internal', 'dir',
+                             'multiglob.https.any.worker-expected.txt')),
+            textwrap.dedent("""\
+                [multiglob.https.any.worker.html]
+                  [subtest]
+                    expected: FAIL
+                """))
+
+    def test_extract_text_with_conditions(self):
+        """Evaluate expectations with the latest `suite_start`'s `run_info`."""
+        self.fs.write_text_file(
+            self.path_finder.path_from_wpt_tests('test.html.ini'),
+            textwrap.dedent("""\
+                [test.html]
+                  expected:
+                    if flag_specific != "fake-flag": FAIL
+                    TIMEOUT
+                """))
+        with self.fs.patch_builtins():
+            self._event(action='suite_start',
+                        run_info={'flag_specific': 'fake-flag'})
+            self._event(action='test_start', test='/test.html')
+            self._event(action='test_end',
+                        test='/test.html',
+                        status='FAIL',
+                        expected='OK')
+            self._event(action='suite_end')
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'test-expected.txt')),
+            textwrap.dedent("""\
+                [test.html]
+                  expected: TIMEOUT
+                """))
+
+    def test_extract_text_with_invalid_metadata(self):
+        self.fs.write_text_file(
+            self.path_finder.path_from_wpt_tests('test.html.ini'),
+            textwrap.dedent("""\
+                [test.html
+                """))
+        with self.fs.patch_builtins():
+            self._event(action='test_start', test='/test.html')
+            self._event(action='test_end',
+                        test='/test.html',
+                        status='CRASH',
+                        expected='OK')
+        self.assertTrue(
+            self.fs.exists(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'test-actual.txt')))
+        self.assertFalse(
+            self.fs.exists(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'test-expected.txt')))
+        self.assertLog([
+            'WARNING: Unable to parse metadata for test.html: EOL in heading:  line 1\n',
+        ])
+
+    def test_extract_screenshots(self):
+        self._event(action='test_start', test='/reftest.html')
+        self._event(action='test_end',
+                    test='/reftest.html',
+                    status='FAIL',
+                    expected='PASS',
+                    extra={
+                        'reftest_screenshots': [{
+                            'url': '/reftest.html',
+                            'screenshot': 'abcd',
+                        }, {
+                            'url': '/reftest-ref.html',
+                            'screenshot': 'bcde',
+                        }],
+                    })
+        self.assertEqual(
+            self.fs.read_binary_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'reftest-actual.png')),
+            base64.b64decode('abcd'))
+        self.assertEqual(
+            self.fs.read_binary_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'reftest-expected.png')),
+            base64.b64decode('bcde'))
+        self.assertEqual(
+            self.fs.read_binary_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'reftest-diff.png')),
+            '\n'.join([
+                '< bcde',
+                '---',
+                '> abcd',
+            ]))
+
+    def test_no_diff_artifacts_on_pass(self):
+        self.fs.write_text_file(
+            self.path_finder.path_from_wpt_tests('test.html.ini'),
+            textwrap.dedent("""\
+                [test.html]
+                  expected: OK
+                """))
+        with self.fs.patch_builtins():
+            self._event(action='test_start', test='/test.html')
+            self._event(action='test_end', test='/test.html', status='OK')
+            self._event(action='test_start', test='/reftest.html')
+            self._event(action='test_end',
+                        test='/reftest.html',
+                        status='PASS',
+                        extra={
+                            'reftest_screenshots': [{
+                                'url': '/reftest.html',
+                                'screenshot': 'abcd',
+                            }, {
+                                'url': '/reftest-ref.html',
+                                'screenshot': 'bcde'
+                            }],
+                        })
+        for filename in (
+                'test-expected.txt',
+                'test-actual.txt',
+                'test-diff.txt',
+                'test-pretty-diff.html',
+                'reftest-expected.png',
+                'reftest-actual.png',
+                'reftest-diff.png',
+        ):
+            self.assertFalse(
+                self.fs.exists(
+                    self.fs.join('/mock-checkout', 'out', 'Default',
+                                 'layout-test-results', filename)))
+
+    def test_extract_logs(self):
+        self._event(action='process_output',
+                    command='content_shell --run-web-tests',
+                    data='[ERROR] Log this line')
+        self._event(action='process_output',
+                    command='git rev-parse HEAD',
+                    data='[ERROR] Do not log this line')
+        self._event(action='test_start', test='/test.html')
+        self._event(action='test_status',
+                    test='/test.html',
+                    status='PASS',
+                    subtest='subtest',
+                    message='assert_eq(a, b)')
+        self._event(action='test_end',
+                    test='/test.html',
+                    status='OK',
+                    message='Test ran to completion.')
+
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'test-stderr.txt')),
+            textwrap.dedent("""\
+                Harness: Test ran to completion.
+                subtest: assert_eq(a, b)
+                """))
+        self.assertEqual(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'test-crash-log.txt')),
+            textwrap.dedent("""\
+                [ERROR] Log this line
+                """))
+
+    def test_unknown_event(self):
+        self._event(action='unknown', time=1000)
+        message, = self.logMessages()
+        self.assertRegex(message,
+                         "WARNING: 'unknown' event received, but not handled")
+
+    def test_unknown_test(self):
+        with self.assertRaises(EventProcessingError):
+            self._event(action='test_start',
+                        test='/does-not-exist-in-manifest.html')
+
+    def test_unstarted_test(self):
+        with self.assertRaises(EventProcessingError):
+            self._event(action='test_end', test='/reftest.html', status='PASS')
+
+    def test_shutdown(self):
+        with self.assertRaises(StreamShutdown):
+            self._event(action='shutdown')
+
+    def test_shutdown_with_unreported_tests(self):
+        self._event(action='test_start', test='/test.html')
+        with self.assertRaises(StreamShutdown):
+            self._event(action='shutdown')
+        self.assertLog([
+            'WARNING: Some tests have unreported results:\n',
+            'WARNING:   test.html\n',
+        ])
+
+    def test_process_json(self):
+        """Ensure that various JSONs are written to the correct locations."""
+        diff_stats = {'maxDifference': 100, 'maxPixels': 3}
+        with mock.patch.object(self.processor.port,
+                               'diff_image',
+                               return_value=(..., diff_stats, ...)):
+            for _ in range(2):
+                self._event(action='suite_start')
+                self._event(action='test_start', test='/test.html')
+                self._event(action='test_status',
+                            test='/test.html',
+                            status='FAIL',
+                            expected='PASS',
+                            subtest='subtest',
+                            message='assert_eq(a, b)')
+                self._event(action='test_end',
+                            test='/test.html',
+                            status='OK',
+                            extra={
+                                'reftest_screenshots': [{
+                                    'url': '/test.html',
+                                    'screenshot': 'abcd',
+                                }]
+                            })
+                self._event(action='suite_end')
+
+        results_json = {
             'tests': {
-                'fail': {
-                    'test.html': {
-                        'expected': 'PASS',
-                        'actual': 'PASS FAIL',
-                        'times': [2, 3],
-                        'artifacts': {},
+                'test.html': {
+                    'expected': 'PASS',
+                    'actual': 'FAIL FAIL',
+                    'artifacts': {
+                        'wpt_actual_status': ['ERROR'],
                     },
+                    'is_unexpected': True,
+                    'is_regression': True,
                 },
             },
             'path_delimiter': '/',
         }
-        self._create_json_output(json_dict)
+        full_json_path = self.fs.join('/mock-checkout', 'out', 'Default',
+                                      'layout-test-results',
+                                      'raw_wpt_output.json')
+        self.fs.write_text_file(full_json_path, json.dumps(results_json))
 
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        test_name = self.fs.join('fail', 'test.html')
-        test_abs_path = self.fs.join(self.processor.web_tests_dir, 'external',
-                                     'wpt', 'fail', 'test.html')
-        self.assertEqual(self.processor.sink.sink_requests,
-                         [{
-                             'test_name_prefix': '',
-                             'test_path': test_abs_path,
-                             'result': {
-                                 'name': test_name,
-                                 'actual': 'PASS',
-                                 'expected': {'PASS'},
-                                 'unexpected': False,
-                                 'took': 2,
-                                 'flaky': True,
-                                 'artifacts': {},
-                             },
-                         }, {
-                             'test_name_prefix': '',
-                             'test_path': test_abs_path,
-                             'result': {
-                                 'name': test_name,
-                                 'actual': 'FAIL',
-                                 'expected': {'PASS'},
-                                 'unexpected': True,
-                                 'took': 3,
-                                 'flaky': True,
-                                 'artifacts': {},
-                             },
-                         }])
+        self.processor.process_results_json(full_json_path)
+        full_json = json.loads(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'full_results.json')))
+        unexpected_fail = full_json['tests']['test.html']
+        self.assertEqual(unexpected_fail['has_stderr'], True)
+        self.assertEqual(unexpected_fail['artifacts']['stderr'], [
+            self.fs.join('layout-test-results', 'test-stderr.txt'),
+            self.fs.join('layout-test-results', 'retry_1', 'test-stderr.txt'),
+        ])
+        self.assertEqual(unexpected_fail['image_diff_stats'], diff_stats)
 
-    def test_result_sink_artifacts(self):
-        json_dict = {
+    def test_trim_json_to_regressions(self):
+        results_json = {
             'tests': {
-                'fail': {
-                    'test.html': {
-                        'expected': 'PASS',
-                        'actual': 'FAIL',
-                        'artifacts': {
-                            'wpt_actual_status': ['OK'],
-                            'wpt_actual_metadata': ['test.html actual text'],
-                        },
+                'test.html': {
+                    'expected': 'PASS',
+                    'actual': 'PASS',
+                    'artifacts': {
+                        'wpt_actual_status': ['OK'],
                     },
                 },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        test_abs_path = self.fs.join(self.processor.web_tests_dir, 'external',
-                                     'wpt', 'fail', 'test.html')
-        path_from_out_dir = self.fs.join('layout-test-results', 'fail',
-                                         'test-actual.txt')
-        self.assertEqual(self.processor.sink.sink_requests,
-                         [{
-                             'test_name_prefix': '',
-                             'test_path': test_abs_path,
-                             'result': {
-                                 'name': self.fs.join('fail', 'test.html'),
-                                 'actual': 'FAIL',
-                                 'expected': {'PASS'},
-                                 'unexpected': True,
-                                 'took': 0,
-                                 'flaky': False,
-                                 'artifacts': {
-                                     'actual_text': [path_from_out_dir],
-                                 },
-                             },
-                         }])
-
-    def test_write_jsons(self):
-        # Ensure that various JSONs are written to the correct location.
-        json_dict = {
-            'tests': {
-                'pass': {
-                    'test.html': {
-                        'expected': 'PASS',
-                        'actual': 'PASS',
-                        'artifacts': {
-                            'wpt_actual_status': ['OK'],
-                        },
-                    },
-                },
-                'unexpected_pass.html': {
+                'variant.html?foo=bar/abc': {
                     'expected': 'FAIL',
                     'actual': 'PASS',
                     'artifacts': {
@@ -450,7 +728,7 @@
                     },
                     'is_unexpected': True,
                 },
-                'fail.html': {
+                'variant.html?foo=baz': {
                     'expected': 'PASS',
                     'actual': 'FAIL',
                     'artifacts': {
@@ -462,488 +740,28 @@
             },
             'path_delimiter': '/',
         }
-        self._create_json_output(json_dict)
+        full_json_path = self.fs.join('/mock-checkout', 'out', 'Default',
+                                      'layout-test-results',
+                                      'raw_wpt_output.json')
+        self.fs.write_text_file(full_json_path, json.dumps(results_json))
 
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        # The correctness of the output JSON is verified by other tests.
-        written_files = self.fs.written_files
-        artifact_path = self.fs.join(self.processor.artifacts_dir,
-                                     'full_results.json')
-        self.assertEqual(written_files[OUTPUT_JSON_FILENAME],
-                         written_files[artifact_path])
+        self.processor.process_results_json(full_json_path)
 
-        # Verify JSONP
-        artifact_path = self.fs.join(self.processor.artifacts_dir,
-                                     'full_results_jsonp.js')
-        full_results_jsonp = self.fs.read_text_file(artifact_path)
-        match = re.match(r'ADD_FULL_RESULTS\((.*)\);$', full_results_jsonp)
-        self.assertIsNotNone(match)
-        self.assertEqual(match.group(1),
-                         self.fs.read_text_file(OUTPUT_JSON_FILENAME))
-
-        artifact_path = self.fs.join(self.processor.artifacts_dir,
-                                     'failing_results.json')
-        failing_results_jsonp = self.fs.read_text_file(artifact_path)
-        match = re.match(r'ADD_RESULTS\((.*)\);$', failing_results_jsonp)
-        self.assertIsNotNone(match)
-        failing_results = json.loads(match.group(1))
-        # Verify filtering of failing_results.json
-        self.assertIn('fail.html', failing_results['tests'])
-        # We shouldn't have unexpected passes or empty dirs after filtering.
-        self.assertNotIn('unexpected_pass.html', failing_results['tests'])
-        self.assertNotIn('pass', failing_results['tests'])
-
-    def test_write_text_outputs(self):
-        # Ensure that text outputs are written to the correct location.
-
-        # We only generate an actual.txt if our actual wasn't PASS, so in this
-        # case we shouldn't write anything.
-        json_dict = {
-            'tests': {
-                'test.html': {
-                    'expected': 'PASS',
-                    'actual': 'PASS',
-                    'artifacts': {
-                        'wpt_actual_status': ['OK'],
-                        'wpt_actual_metadata': ['test.html actual text'],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        written_files = self.fs.written_files
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        actual_path = self.fs.join(artifacts_subdir, 'test-actual.txt')
-        diff_path = self.fs.join(artifacts_subdir, 'test-diff.txt')
-        pretty_diff_path = self.fs.join(artifacts_subdir,
-                                        'test-pretty-diff.html')
-        self.assertNotIn(actual_path, written_files)
-        self.assertNotIn(diff_path, written_files)
-        self.assertNotIn(pretty_diff_path, written_files)
-
-        # Now we change the outcome to be a FAIL, which should generate an
-        # actual.txt
-        json_dict['tests']['test.html']['actual'] = 'FAIL'
-        self._create_json_output(json_dict)
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        self.assertEqual('test.html actual text',
-                         self.fs.read_text_file(actual_path))
-        # Ensure the artifact in the json was replaced with the location of
-        # the newly-created file.
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['test.html']
-        path_from_out_dir = self.fs.join('layout-test-results',
-                                         'test-actual.txt')
-        self.assertNotIn('wpt_actual_metadata', test_node['artifacts'])
-        self.assertEqual([path_from_out_dir],
-                         test_node['artifacts']['actual_text'])
-        self.assertIn(actual_path, written_files)
-        self.assertNotIn(diff_path, written_files)
-        self.assertNotIn(pretty_diff_path, written_files)
-
-    def test_write_log_artifact(self):
-        # Ensure that crash log artifacts are written to the correct location.
-        json_dict = {
-            'tests': {
-                'test.html': {
-                    'expected': 'PASS',
-                    'actual': 'FAIL',
-                    'artifacts': {
-                        'wpt_actual_status': ['ERROR'],
-                        'wpt_log': ['test.html exceptions'],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        stderr_path = self.fs.join(artifacts_subdir, 'test-stderr.txt')
-        self.assertEqual('test.html exceptions',
-                         self.fs.read_text_file(stderr_path))
-
-        # Ensure the artifact in the json was replaced with the location of
-        # the newly-created file.
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['test.html']
-        self.assertNotIn('wpt_log', test_node['artifacts'])
-        path_from_out_dir = self.fs.join('layout-test-results',
-                                         'test-stderr.txt')
-        self.assertEqual([path_from_out_dir], test_node['artifacts']['stderr'])
-        self.assertTrue(test_node['has_stderr'])
-
-    def test_write_crashlog_artifact(self):
-        # Ensure that crash log artifacts are written to the correct location.
-        json_dict = {
-            'tests': {
-                'test.html': {
-                    'expected': 'PASS',
-                    'actual': 'CRASH',
-                    'artifacts': {
-                        'wpt_actual_status': ['CRASH'],
-                        'wpt_crash_log': ['test.html crashed!'],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        crash_log_path = self.fs.join(artifacts_subdir, 'test-crash-log.txt')
-        self.assertEqual('test.html crashed!',
-                         self.fs.read_text_file(crash_log_path))
-
-        # Ensure the artifact in the json was replaced with the location of
-        # the newly-created file.
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['test.html']
-        path_from_out_dir = self.fs.join('layout-test-results',
-                                         'test-crash-log.txt')
-        self.assertNotIn('wpt_crash_log', test_node['artifacts'])
-        self.assertEqual([path_from_out_dir],
-                         test_node['artifacts']['crash_log'])
-
-    def test_write_screenshot_artifacts(self):
-        # Ensure that screenshots are written to the correct filenames and
-        # their bytes are base64 decoded. The image diff should also be created.
-        json_dict = {
-            'tests': {
-                'reftest.html': {
-                    'expected': 'PASS',
-                    'actual': 'PASS',
-                    'artifacts': {
-                        'wpt_actual_status': ['PASS'],
-                        'screenshots': [
-                            'reftest.html:abcd',
-                            'reftest-ref.html:bcde',
-                        ],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-
-        self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        actual_path = self.fs.join(artifacts_subdir, 'reftest-actual.png')
-        self.assertEqual(base64.b64decode('abcd'),
-                         self.fs.read_binary_file(actual_path))
-        expected_path = self.fs.join(artifacts_subdir, 'reftest-expected.png')
-        self.assertEqual(base64.b64decode('bcde'),
-                         self.fs.read_binary_file(expected_path))
-        diff_path = self.fs.join(artifacts_subdir, 'reftest-diff.png')
-        self.assertEqual('\n'.join([
-            '< bcde',
-            '---',
-            '> abcd',
-        ]), self.fs.read_binary_file(diff_path))
-
-        # Ensure the artifacts in the json were replaced with the location of
-        # the newly-created files.
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['reftest.html']
-        path_from_out_dir_base = self.fs.join('layout-test-results')
-        self.assertNotIn('screenshots', test_node['artifacts'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'reftest-actual.png')],
-            test_node['artifacts']['actual_image'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'reftest-expected.png')],
-            test_node['artifacts']['expected_image'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'reftest-diff.png')],
-            test_node['artifacts']['image_diff'])
-        self.assertEqual({
-            'maxDifference': 100,
-            'maxPixels': 3
-        }, test_node['image_diff_stats'])
-
-    def test_copy_expected_output(self):
-        # Check that an -expected.txt file is created from a checked-in metadata
-        # ini file if it exists for a test
-        json_dict = {
-            'tests': {
-                'test.html': {
-                    'expected': 'PASS',
-                    'actual': 'FAIL',
-                    'artifacts': {
-                        'wpt_actual_status': ['OK'],
-                        'wpt_actual_metadata': [
-                            '[test.html]\n  expected: OK\n',
-                            '  [Assert something]\n    expected: CRASH\n',
-                        ],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-        # Also create a checked-in metadata file for this test
-        checked_in_metadata = textwrap.dedent("""\
-            [test.html]
-              expected:
-                if flag_specific != "highdpi": OK
-              [Assert something]
-                expected:
-                  if flag_specific != "highdpi": PASS
-                  [FAIL, TIMEOUT]
-            """)
-        self.fs.write_text_file(
-            self.fs.join(self.processor.web_tests_dir, 'external', 'wpt',
-                         'test.html.ini'), checked_in_metadata)
-
-        self.processor.run_info['flag_specific'] = 'highdpi'
-        with self.fs.patch_builtins():
-            self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        actual_path = self.fs.join(artifacts_subdir, 'test-actual.txt')
-        self.assertEqual(
-            textwrap.dedent("""\
-                [test.html]
-                  expected: OK
-
-                  [Assert something]
-                    expected: CRASH
-                """), self.fs.read_text_file(actual_path))
-
-        # The checked-in metadata file gets renamed from .ini to -expected.txt.
-        # Any conditions are also evaluated against the test run's properties.
-        expected_path = self.fs.join(artifacts_subdir, 'test-expected.txt')
-        self.assertEqual(
-            textwrap.dedent("""\
-                [test.html]
-                  [Assert something]
-                    expected: [FAIL, TIMEOUT]
-                """), self.fs.read_text_file(expected_path))
-
-        # Ensure the artifacts in the json were replaced with the locations of
-        # the newly-created files.
-        path_from_out_dir_base = self.fs.join('layout-test-results')
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['test.html']
-        self.assertNotIn('wpt_actual_metadata', test_node['artifacts'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'test-actual.txt')],
-            test_node['artifacts']['actual_text'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'test-expected.txt')],
-            test_node['artifacts']['expected_text'])
-
-        # Ensure that a diff was also generated. There should be both additions
-        # and deletions for this test since we have expected output. We don't
-        # validate the entire diff files to avoid checking line numbers/markup.
-        diff_lines = self.fs.read_text_file(
-            self.fs.join(artifacts_subdir, 'test-diff.txt')).splitlines()
-        self.assertIn('-    expected: [FAIL, TIMEOUT]', diff_lines)
-        self.assertIn('+    expected: CRASH', diff_lines)
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'test-diff.txt')],
-            test_node['artifacts']['text_diff'])
-
-        pretty_diff_contents = self.fs.read_text_file(
-            self.fs.join(artifacts_subdir, 'test-pretty-diff.html'))
-        self.assertIn('expected: [FAIL, TIMEOUT]', pretty_diff_contents)
-        self.assertIn('expected: CRASH', pretty_diff_contents)
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'test-pretty-diff.html')],
-            test_node['artifacts']['pretty_text_diff'])
-
-    def test_invalid_checked_in_metadata(self):
-        """Verify the processor handles a syntactically invalid metadata file:
-          * The tool does not crash.
-          * The actual text is created, but the expected text and diffs are not.
-        """
-        json_dict = {
-            'tests': {
-                'test.html': {
-                    'expected': 'PASS',
-                    'actual': 'FAIL',
-                    'artifacts': {
-                        'wpt_actual_status': ['OK'],
-                        'wpt_actual_metadata': [
-                            '[test.html]\n  expected: OK\n',
-                            '  [Assert something]\n    expected: CRASH\n',
-                        ],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-        # Also create a checked-in metadata file for this test
-        self.fs.write_text_file(
-            self.fs.join(self.processor.web_tests_dir, 'external', 'wpt',
-                         'test.html.ini'),
-            textwrap.dedent("""\
-                [test.html]
-                  [bracket is not matched
-                """))
-
-        with self.fs.patch_builtins():
-            self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-
-        path_from_out_dir_base = self.fs.join('layout-test-results')
-        updated_json = self._load_json_output()
-        test_node = updated_json['tests']['test.html']
-        self.assertNotIn('wpt_actual_metadata', test_node['artifacts'])
-        self.assertNotIn('expected_text', test_node['artifacts'])
-        self.assertNotIn('text_diff', test_node['artifacts'])
-        self.assertNotIn('pretty_text_diff', test_node['artifacts'])
-        self.assertEqual(
-            [self.fs.join(path_from_out_dir_base, 'test-actual.txt')],
-            test_node['artifacts']['actual_text'])
-
-    def test_expected_output_for_variant(self):
-        # Check that an -expected.txt file is created from a checked-in metadata
-        # ini file for a variant test. Variants are a little different because
-        # we have to use the manifest to map a test name to the test file, and
-        # determine the associated metadata from the test file.
-        # Check that an -expected.txt file is created from a checked-in metadata
-        # ini file if it exists for a test
-        json_dict = {
-            'tests': {
-                'variant.html?foo=bar': {
-                    'expected': 'PASS',
-                    'actual': 'FAIL',
-                    'artifacts': {
-                        'wpt_actual_status': ['OK'],
-                        'wpt_actual_metadata': [
-                            '[variant.html?foo=bar]\n  expected: OK\n',
-                        ],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-        # Also create a checked-in metadata file for this test. This filename
-        # matches the test *file* name, not the test ID. The checked-in file
-        # contains expectations for all variants.
-        self.fs.write_text_file(
-            self.fs.join(self.processor.web_tests_dir, 'external', 'wpt',
-                         'variant.html.ini'),
-            textwrap.dedent("""\
-                [variant.html?foo=bar]
-                  expected: OK
-
-                [variant.html?foo=baz]
-                  expected: TIMEOUT
-                """))
-        with self.fs.patch_builtins():
-            self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        variant_metadata = textwrap.dedent("""\
-            [variant.html?foo=bar]
-              expected: OK
-            """)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        actual_path = self.fs.join(artifacts_subdir,
-                                   'variant_foo=bar-actual.txt')
-        self.assertEqual(variant_metadata, self.fs.read_text_file(actual_path))
-        # The checked-in metadata file gets renamed from .ini to -expected.txt
-        expected_path = self.fs.join(artifacts_subdir,
-                                     'variant_foo=bar-expected.txt')
-        # Exclude the `foo=baz` variant from the expected text.
-        self.assertEqual(variant_metadata,
-                         self.fs.read_text_file(expected_path))
-
-        # Ensure the artifacts in the json were replaced with the locations of
-        # the newly-created files.
-        updated_json = self._load_json_output()
-        test_node_parent = updated_json['tests']
-        test_node = test_node_parent['variant.html?foo=bar']
-        path_from_out_dir_base = self.fs.join('layout-test-results')
-        actual_path = self.fs.join(path_from_out_dir_base,
-                                   'variant_foo=bar-actual.txt')
-        expected_path = self.fs.join(path_from_out_dir_base,
-                                     'variant_foo=bar-expected.txt')
-        self.assertNotIn('wpt_actual_metadata', test_node['artifacts'])
-        self.assertEqual([actual_path], test_node['artifacts']['actual_text'])
-        self.assertEqual([expected_path],
-                         test_node['artifacts']['expected_text'])
-
-    def test_expected_output_for_multiglob(self):
-        # Check that an -expected.txt file is created from a checked-in metadata
-        # ini file for a multiglobal test. Multi-globals are a little different
-        # because we have to use the manifest to map a test name to the test
-        # file, and determine the associated metadata from the test file.
-        #
-        # Also note that the "dir" is both a directory and a part of the test
-        # name, so the path delimiter remains a / (ie: dir/multiglob) even on
-        # Windows.
-        json_dict = {
-            'tests': {
-                'dir/multiglob.https.any.worker.html': {
-                    'expected': 'PASS',
-                    'actual': 'FAIL',
-                    'artifacts': {
-                        'wpt_actual_status': ['OK'],
-                        'wpt_actual_metadata': [
-                            '[multiglob.https.any.worker.html]\n'
-                            '  expected: OK\n',
-                        ],
-                    },
-                },
-            },
-            'path_delimiter': '/',
-        }
-        self._create_json_output(json_dict)
-        # Also create a checked-in metadata file for this test. This filename
-        # matches the test *file* name, not the test name (which includes test
-        # scope).
-        self.fs.write_text_file(
-            self.fs.join(self.processor.web_tests_dir, 'external', 'wpt',
-                         'dir/multiglob.https.any.js.ini'),
-            textwrap.dedent("""\
-                [multiglob.https.any.worker.html]
-                  expected: OK
-
-                [multiglob.https.any.window.html]
-                  expected: FAIL
-                """))
-
-        with self.fs.patch_builtins():
-            self.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
-        artifacts_subdir = self.fs.join(self.processor.artifacts_dir)
-        actual_path = self.fs.join(
-            artifacts_subdir, 'dir/multiglob.https.any.worker-actual.txt')
-        self.assertEqual(
-            textwrap.dedent("""\
-                [multiglob.https.any.worker.html]
-                  expected: OK
-                """), self.fs.read_text_file(actual_path))
-        # The checked-in metadata file gets renamed from .ini to -expected.txt
-        # and cut to the `worker` scope.
-        expected_path = self.fs.join(
-            artifacts_subdir, 'dir/multiglob.https.any.worker-expected.txt')
-        self.assertEqual(
-            textwrap.dedent("""\
-                [multiglob.https.any.worker.html]
-                  expected: OK
-                """), self.fs.read_text_file(expected_path))
-
-        # Ensure the artifacts in the json were replaced with the locations of
-        # the newly-created files.
-        updated_json = self._load_json_output()
-        test_node_parent = updated_json['tests']
-        test_node = test_node_parent['dir/multiglob.https.any.worker.html']
-        path_from_out_dir_base = self.fs.join('layout-test-results')
-        self.assertNotIn('wpt_actual_metadata', test_node['artifacts'])
-        self.assertEqual([
-            self.fs.join(path_from_out_dir_base,
-                         'dir/multiglob.https.any.worker-actual.txt')
-        ], test_node['artifacts']['actual_text'])
-        self.assertEqual([
-            self.fs.join(path_from_out_dir_base,
-                         'dir/multiglob.https.any.worker-expected.txt')
-        ], test_node['artifacts']['expected_text'])
+        failing_results_match = re.fullmatch(
+            'ADD_RESULTS\((?P<json>.*)\);',
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'failing_results.json')))
+        self.assertIsNotNone(failing_results_match)
+        failing_results = json.loads(failing_results_match['json'])
+        self.assertNotIn('test.html', failing_results['tests'])
+        self.assertNotIn('variant.html?foo=bar/abc', failing_results['tests'])
+        self.assertIn('variant.html?foo=baz', failing_results['tests'])
+        self.assertRegex(
+            self.fs.read_text_file(
+                self.fs.join('/mock-checkout', 'out', 'Default',
+                             'layout-test-results', 'full_results_jsonp.js')),
+            'ADD_FULL_RESULTS\(.*\);$')
 
     def test_process_wpt_report(self):
         report_src = self.fs.join('/mock-checkout', 'out', 'Default',
@@ -951,12 +769,14 @@
         self.fs.write_text_file(report_src,
                                 (json.dumps(self.wpt_report) + '\n') * 2)
         self.processor.process_wpt_report(report_src)
-        artifacts = self.processor.sink.invocation_level_artifacts
         report_dest = self.fs.join('/mock-checkout', 'out', 'Default',
                                    'layout-test-results', 'wpt_report.json')
-        self.assertEqual(artifacts['wpt_report.json'], {
-            'filePath': report_dest,
-        })
+        self.processor.sink.report_invocation_level_artifacts.assert_called_once_with(
+            {
+                'wpt_report.json': {
+                    'filePath': report_dest,
+                },
+            })
         report = json.loads(self.fs.read_text_file(report_dest))
         self.assertEqual(report['run_info'], self.wpt_report['run_info'])
         self.assertEqual(report['results'], self.wpt_report['results'] * 2)
@@ -967,12 +787,14 @@
         self.wpt_report['run_info']['used_upstream'] = False
         self.fs.write_text_file(report_src, json.dumps(self.wpt_report))
         self.processor.process_wpt_report(report_src)
-        artifacts = self.processor.sink.invocation_level_artifacts
         report_dest = self.fs.join('/mock-checkout', 'out', 'Default',
                                    'layout-test-results', 'wpt_report.json')
-        self.assertEqual(artifacts['wpt_report.json'], {
-            'filePath': report_dest,
-        })
+        self.processor.sink.report_invocation_level_artifacts.assert_called_once_with(
+            {
+                'wpt_report.json': {
+                    'filePath': report_dest,
+                },
+            })
         report = json.loads(self.fs.read_text_file(report_dest))
         self.assertEqual(
             report['run_info'], {
diff --git a/third_party/blink/tools/run_wpt_tests.py b/third_party/blink/tools/run_wpt_tests.py
index cb51f03e..f9898674 100755
--- a/third_party/blink/tools/run_wpt_tests.py
+++ b/third_party/blink/tools/run_wpt_tests.py
@@ -22,10 +22,12 @@
 from blinkpy.common import path_finder
 from blinkpy.common.host import Host
 from blinkpy.common.path_finder import PathFinder
+from blinkpy.w3c.wpt_results_processor import WPTResultsProcessor
 from blinkpy.web_tests.port.android import (
     ANDROID_WEBVIEW,
     CHROME_ANDROID,
 )
+from blinkpy.web_tests.port.base import ARTIFACTS_SUB_DIR
 
 path_finder.add_testing_dir_to_sys_path()
 path_finder.add_build_android_to_sys_path()
@@ -266,6 +268,7 @@
         output_dir = self.path_from_output_dir(options.target)
         if not self.fs.isdir(output_dir):
             raise ValueError("'--target' must be a directory under //out")
+        self.port.set_option_default('target', options.target)
         if options.log_chromium == '':
             options.log_chromium = self.fs.join(output_dir, 'results.json')
         if options.log_wptreport == '':
@@ -281,7 +284,6 @@
             if filename:
                 filename = self.fs.abspath(filename)
                 setattr(options, dest, [mozlog.commandline.log_file(filename)])
-
         options.log = wptlogging.setup(dict(vars(options)),
                                        {'grouped': sys.stdout})
         logging.root.handlers.clear()
@@ -408,8 +410,8 @@
             stack.callback(self.port.clean_up_test_run)
             self.fs.chdir(self.path_finder.web_tests_dir())
             run = _load_entry_point(tools_root)
+            stack.enter_context(self.process_and_upload_results(options))
             exit_code = run(**vars(options))
-            self.process_and_upload_results(options)
             return exit_code
 
     def _make_product(self, options: argparse.Namespace) -> 'Product':
@@ -449,49 +451,32 @@
         with self.fs.open_text_file_for_writing(run_info_path) as file_handle:
             json.dump(run_info, file_handle)
 
+    @contextlib.contextmanager
     def process_and_upload_results(
             self,
             options,
-            layout_test_results_subdir: str = 'layout-test-results',
+            layout_test_results_subdir: str = ARTIFACTS_SUB_DIR,
     ):
-        if not options.log_chromium:
-            return
-        json_results_filename = options.log_chromium[0].name
-        artifacts_dir = os.path.join(os.path.dirname(json_results_filename),
-                                     layout_test_results_subdir)
-        command = [
-            self.port.python3_command(),
-            os.path.join(path_finder.get_blink_tools_dir(),
-                         'wpt_process_results.py'),
-            '--target',
-            options.target,
-            '--web-tests-dir',
-            self.path_finder.web_tests_dir(),
-            '--artifacts-dir',
-            artifacts_dir,
-            '--wpt-results',
-            json_results_filename,
-        ]
-        if options.verbose:
-            command.append('--verbose')
+        if options.log_chromium:
+            artifacts_dir = self.fs.join(
+                self.fs.dirname(options.log_chromium[0].name),
+                layout_test_results_subdir)
+        else:
+            artifacts_dir = self.path_from_output_dir(
+                options.target, layout_test_results_subdir)
+        processor = WPTResultsProcessor(self.host.filesystem,
+                                        self.port,
+                                        artifacts_dir=artifacts_dir)
+        with processor.stream_results() as events:
+            options.log.add_handler(events.put)
+            yield
         if options.log_wptreport:
-            command.extend(['--wpt-report', options.log_wptreport[0].name])
-        exit_code = common.run_command(command)
-        if (exit_code != exit_codes.INTERRUPTED_EXIT_STATUS
-                and options.show_results
-                and self.has_regressions(artifacts_dir)):
-            self.show_results_in_browser(artifacts_dir)
-
-    def show_results_in_browser(self, artifacts_dir: str):
-        results_file = self.fs.join(artifacts_dir, 'results.html')
-        self.port.show_results_html_file(results_file)
-
-    def has_regressions(self, artifacts_dir: str):
-        full_results_file = self.fs.join(artifacts_dir, 'full_results.json')
-        with self.fs.open_text_file_for_reading(
-                full_results_file) as full_results:
-            results = json.load(full_results)
-        return results["num_regressions"] > 0
+            processor.process_wpt_report(options.log_wptreport[0].name)
+        if options.log_chromium:
+            processor.process_results_json(options.log_chromium[0].name)
+        if options.show_results and processor.has_regressions:
+            self.port.show_results_html_file(
+                self.fs.join(artifacts_dir, 'results.html'))
 
     def add_configuration_arguments(self, parser: argparse.ArgumentParser):
         group = parser.add_argument_group('Configuration')
diff --git a/third_party/blink/tools/wpt_process_results.py b/third_party/blink/tools/wpt_process_results.py
deleted file mode 100755
index 362be55d..0000000
--- a/third_party/blink/tools/wpt_process_results.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env vpython3
-# Copyright 2022 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Process WPT results for upload to ResultDB."""
-
-from blinkpy.common import exit_codes
-from blinkpy.common.host import Host
-from blinkpy.common.path_finder import add_depot_tools_dir_to_os_path
-from blinkpy.w3c.wpt_results_processor import WPTResultsProcessor
-
-
-def main():
-    add_depot_tools_dir_to_os_path()
-    host = Host()
-    options = WPTResultsProcessor.parse_args()
-    processor = WPTResultsProcessor.from_options(host, options)
-    try:
-        host.exit(processor.main(options))
-    except KeyboardInterrupt:
-        host.print_('Interrupted, exiting')
-        host.exit(exit_codes.INTERRUPTED_EXIT_STATUS)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c3631d8..5bff14a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1825,6 +1825,9 @@
 crbug.com/567837 [ Linux ] virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure Timeout ]
 crbug.com/567837 [ Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure Timeout ]
 
+# Popover test timeout
+crbug.com/1416284 external/wpt/html/semantics/popovers/popover-attribute-basic.html [ Pass Timeout ]
+
 # Only virtual/threaded version of these tests pass (or running them with --enable-threaded-compositing).
 crbug.com/936891 fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html [ Failure ]
 
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 4b87e444..d7d6b1d8 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -758,6 +758,18 @@
     "args": ["--disable-blink-features=CSSTrigonometricFunctions"],
     "expires": "Jul 1, 2023"
   },
+   {
+    "prefix": "css-sign-related-functions-disabled",
+    "platforms": ["Linux", "Mac", "Win"],
+    "bases": [
+      "external/wpt/css/css-values/signs-abs-computed.html",
+      "external/wpt/css/css-values/signs-abs-serialize.html",
+      "external/wpt/css/css-values/signs-abs-invalid.html"
+    ],
+    "args": ["--disable-blink-features=CSSSignRelatedFunctions"],
+    "expires": "Jul 1, 2023"
+  },
+
   {
     "prefix": "import-maps-disabled",
     "platforms": ["Linux", "Mac", "Win"],
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html
new file mode 100644
index 0000000..3360681
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#text-wrap">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+#container {
+  width: 20ch;
+}
+.balance {
+  text-wrap: balance;
+}
+</style>
+<div id="container"></div>
+<script>
+const container = document.getElementById('container');
+for (const text of [
+    'Balancing should',
+    'Balancing should not change',
+    'Balancing should not change the number of lines.',
+  ]) {
+  const normal = document.createElement('div');
+  const balance = document.createElement('div');
+  normal.textContent = text;
+  balance.textContent = text;
+  balance.classList.add('balance');
+  container.appendChild(normal);
+  container.appendChild(balance);
+  test(() => {
+    assert_equals(normal.offsetHeight, balance.offsetHeight);
+  });
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed-expected.txt
index d2f1550..4e330539 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -1,146 +1,192 @@
 This is a testharness.js-based test.
-Found 142 tests; 0 PASS, 142 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL abs(1) should be used-value-equivalent to 1 assert_not_equals: abs(1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1) should be used-value-equivalent to 1 assert_not_equals: sign(1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL abs(-1) should be used-value-equivalent to 1 assert_not_equals: abs(-1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1) should be used-value-equivalent to -1 assert_not_equals: sign(-1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL abs(sign(1)) should be used-value-equivalent to 1 assert_not_equals: abs(sign(1)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL abs(sign(sign(1))) should be used-value-equivalent to 1 assert_not_equals: abs(sign(sign(1))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 assert_not_equals: sign(sign(sign(1) + sign(1))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 assert_not_equals: calc(abs(0.1 + 0.2) + 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 assert_not_equals: calc(sign(0.1 + 0.2) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 assert_not_equals: calc(abs(0.1 + 0.2) * 2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 assert_not_equals: calc(abs(sign(0.1) + 0.2) / 2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 assert_not_equals: calc(abs(0.1 + 0.2) * -2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 assert_not_equals: calc(sign(0.1 - 0.2) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 assert_not_equals: calc(sign(1) + sign(1) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL calc(sign(-0)) should be used-value-equivalent to -0 assert_not_equals: calc(sign(-0)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL calc(sign(0)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1px) should be used-value-equivalent to 1 assert_not_equals: sign(1px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1cm) should be used-value-equivalent to 1 assert_not_equals: sign(1cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1mm) should be used-value-equivalent to 1 assert_not_equals: sign(1mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1Q) should be used-value-equivalent to 1 assert_not_equals: sign(1Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1in) should be used-value-equivalent to 1 assert_not_equals: sign(1in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1pc) should be used-value-equivalent to 1 assert_not_equals: sign(1pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1pt) should be used-value-equivalent to 1 assert_not_equals: sign(1pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1em) should be used-value-equivalent to 1 assert_not_equals: sign(1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1ex) should be used-value-equivalent to 1 assert_not_equals: sign(1ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1ch) should be used-value-equivalent to 1 assert_not_equals: sign(1ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1rem) should be used-value-equivalent to 1 assert_not_equals: sign(1rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1vh) should be used-value-equivalent to 1 assert_not_equals: sign(1vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1vw) should be used-value-equivalent to 1 assert_not_equals: sign(1vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1vmin) should be used-value-equivalent to 1 assert_not_equals: sign(1vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1vmax) should be used-value-equivalent to 1 assert_not_equals: sign(1vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1px) should be used-value-equivalent to -1 assert_not_equals: sign(-1px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1cm) should be used-value-equivalent to -1 assert_not_equals: sign(-1cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1mm) should be used-value-equivalent to -1 assert_not_equals: sign(-1mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1Q) should be used-value-equivalent to -1 assert_not_equals: sign(-1Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1in) should be used-value-equivalent to -1 assert_not_equals: sign(-1in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1pc) should be used-value-equivalent to -1 assert_not_equals: sign(-1pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1pt) should be used-value-equivalent to -1 assert_not_equals: sign(-1pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1em) should be used-value-equivalent to -1 assert_not_equals: sign(-1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1ex) should be used-value-equivalent to -1 assert_not_equals: sign(-1ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1ch) should be used-value-equivalent to -1 assert_not_equals: sign(-1ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1rem) should be used-value-equivalent to -1 assert_not_equals: sign(-1rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1vh) should be used-value-equivalent to -1 assert_not_equals: sign(-1vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1vw) should be used-value-equivalent to -1 assert_not_equals: sign(-1vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1vmin) should be used-value-equivalent to -1 assert_not_equals: sign(-1vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1vmax) should be used-value-equivalent to -1 assert_not_equals: sign(-1vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1s) should be used-value-equivalent to 1 assert_not_equals: sign(1s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1ms) should be used-value-equivalent to 1 assert_not_equals: sign(1ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1s) should be used-value-equivalent to -1 assert_not_equals: sign(-1s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1ms) should be used-value-equivalent to -1 assert_not_equals: sign(-1ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1deg) should be used-value-equivalent to 1 assert_not_equals: sign(1deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1grad) should be used-value-equivalent to 1 assert_not_equals: sign(1grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1rad) should be used-value-equivalent to 1 assert_not_equals: sign(1rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(1turn) should be used-value-equivalent to 1 assert_not_equals: sign(1turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1deg) should be used-value-equivalent to -1 assert_not_equals: sign(-1deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1grad) should be used-value-equivalent to -1 assert_not_equals: sign(-1grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1rad) should be used-value-equivalent to -1 assert_not_equals: sign(-1rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-1turn) should be used-value-equivalent to -1 assert_not_equals: sign(-1turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0px) should be used-value-equivalent to 0 assert_not_equals: sign(0px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0cm) should be used-value-equivalent to 0 assert_not_equals: sign(0cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0mm) should be used-value-equivalent to 0 assert_not_equals: sign(0mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0Q) should be used-value-equivalent to 0 assert_not_equals: sign(0Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0in) should be used-value-equivalent to 0 assert_not_equals: sign(0in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0pc) should be used-value-equivalent to 0 assert_not_equals: sign(0pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0pt) should be used-value-equivalent to 0 assert_not_equals: sign(0pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0em) should be used-value-equivalent to 0 assert_not_equals: sign(0em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0ex) should be used-value-equivalent to 0 assert_not_equals: sign(0ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0ch) should be used-value-equivalent to 0 assert_not_equals: sign(0ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0rem) should be used-value-equivalent to 0 assert_not_equals: sign(0rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0vh) should be used-value-equivalent to 0 assert_not_equals: sign(0vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0vw) should be used-value-equivalent to 0 assert_not_equals: sign(0vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0vmin) should be used-value-equivalent to 0 assert_not_equals: sign(0vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0vmax) should be used-value-equivalent to 0 assert_not_equals: sign(0vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0px) should be used-value-equivalent to -0 assert_not_equals: sign(-0px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0cm) should be used-value-equivalent to -0 assert_not_equals: sign(-0cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0mm) should be used-value-equivalent to -0 assert_not_equals: sign(-0mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0Q) should be used-value-equivalent to -0 assert_not_equals: sign(-0Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0in) should be used-value-equivalent to -0 assert_not_equals: sign(-0in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0pc) should be used-value-equivalent to -0 assert_not_equals: sign(-0pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0pt) should be used-value-equivalent to -0 assert_not_equals: sign(-0pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0em) should be used-value-equivalent to -0 assert_not_equals: sign(-0em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0ex) should be used-value-equivalent to -0 assert_not_equals: sign(-0ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0ch) should be used-value-equivalent to -0 assert_not_equals: sign(-0ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0rem) should be used-value-equivalent to -0 assert_not_equals: sign(-0rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0vh) should be used-value-equivalent to -0 assert_not_equals: sign(-0vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0vw) should be used-value-equivalent to -0 assert_not_equals: sign(-0vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0vmin) should be used-value-equivalent to -0 assert_not_equals: sign(-0vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0vmax) should be used-value-equivalent to -0 assert_not_equals: sign(-0vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0s) should be used-value-equivalent to 0 assert_not_equals: sign(0s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0ms) should be used-value-equivalent to 0 assert_not_equals: sign(0ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0s) should be used-value-equivalent to 0 assert_not_equals: sign(-0s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0ms) should be used-value-equivalent to 0 assert_not_equals: sign(-0ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0deg) should be used-value-equivalent to 0 assert_not_equals: sign(0deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0grad) should be used-value-equivalent to 0 assert_not_equals: sign(0grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0rad) should be used-value-equivalent to 0 assert_not_equals: sign(0rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(0turn) should be used-value-equivalent to 0 assert_not_equals: sign(0turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0deg) should be used-value-equivalent to -0 assert_not_equals: sign(-0deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0grad) should be used-value-equivalent to -0 assert_not_equals: sign(-0grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0rad) should be used-value-equivalent to -0 assert_not_equals: sign(-0rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL sign(-0turn) should be used-value-equivalent to -0 assert_not_equals: sign(-0turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
-FAIL abs(1px) should be used-value-equivalent to 1px assert_not_equals: abs(1px) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1cm) should be used-value-equivalent to 1cm assert_not_equals: abs(1cm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1mm) should be used-value-equivalent to 1mm assert_not_equals: abs(1mm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1Q) should be used-value-equivalent to 1Q assert_not_equals: abs(1Q) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1in) should be used-value-equivalent to 1in assert_not_equals: abs(1in) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1pc) should be used-value-equivalent to 1pc assert_not_equals: abs(1pc) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1pt) should be used-value-equivalent to 1pt assert_not_equals: abs(1pt) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1em) should be used-value-equivalent to 1em assert_not_equals: abs(1em) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1ex) should be used-value-equivalent to 1ex assert_not_equals: abs(1ex) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1ch) should be used-value-equivalent to 1ch assert_not_equals: abs(1ch) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1rem) should be used-value-equivalent to 1rem assert_not_equals: abs(1rem) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1vh) should be used-value-equivalent to 1vh assert_not_equals: abs(1vh) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1vw) should be used-value-equivalent to 1vw assert_not_equals: abs(1vw) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_not_equals: abs(1vmin) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_not_equals: abs(1vmax) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1px) should be used-value-equivalent to 1px assert_not_equals: abs(-1px) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_not_equals: abs(-1cm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_not_equals: abs(-1mm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_not_equals: abs(-1Q) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1in) should be used-value-equivalent to 1in assert_not_equals: abs(-1in) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_not_equals: abs(-1pc) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_not_equals: abs(-1pt) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1em) should be used-value-equivalent to 1em assert_not_equals: abs(-1em) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_not_equals: abs(-1ex) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_not_equals: abs(-1ch) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_not_equals: abs(-1rem) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_not_equals: abs(-1vh) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_not_equals: abs(-1vw) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_not_equals: abs(-1vmin) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_not_equals: abs(-1vmax) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
-FAIL abs(1s) should be used-value-equivalent to 1s assert_not_equals: abs(1s) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
-FAIL abs(1ms) should be used-value-equivalent to 1ms assert_not_equals: abs(1ms) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
-FAIL abs(-1s) should be used-value-equivalent to 1s assert_not_equals: abs(-1s) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
-FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_not_equals: abs(-1ms) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
-FAIL abs(1deg) should be used-value-equivalent to 1deg assert_not_equals: abs(1deg) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(1grad) should be used-value-equivalent to 1grad assert_not_equals: abs(1grad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(1rad) should be used-value-equivalent to 1rad assert_not_equals: abs(1rad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(1turn) should be used-value-equivalent to 1turn assert_not_equals: abs(1turn) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(-1deg) should be used-value-equivalent to 1deg assert_not_equals: abs(-1deg) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(-1grad) should be used-value-equivalent to 1grad assert_not_equals: abs(-1grad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(-1rad) should be used-value-equivalent to 1rad assert_not_equals: abs(-1rad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
-FAIL abs(-1turn) should be used-value-equivalent to 1turn assert_not_equals: abs(-1turn) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+Found 188 tests; 186 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS abs(1) should be used-value-equivalent to 1
+PASS sign(1) should be used-value-equivalent to 1
+PASS abs(-1) should be used-value-equivalent to 1
+PASS sign(-1) should be used-value-equivalent to -1
+PASS abs(sign(1)) should be used-value-equivalent to 1
+PASS abs(sign(sign(1))) should be used-value-equivalent to 1
+PASS sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1
+PASS calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35
+PASS calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95
+PASS calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6
+PASS calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6
+PASS calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6
+PASS calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05
+PASS calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95
+PASS calc(calc(sign(-0))) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(calc(sign(-0)))), 1) should be used-value-equivalent to -1
+PASS calc(calc(sign(0))) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(calc(sign(0)))), 1) should be used-value-equivalent to 1
+PASS sign(1px) should be used-value-equivalent to 1
+PASS sign(1cm) should be used-value-equivalent to 1
+PASS sign(1mm) should be used-value-equivalent to 1
+PASS sign(1Q) should be used-value-equivalent to 1
+PASS sign(1in) should be used-value-equivalent to 1
+PASS sign(1pc) should be used-value-equivalent to 1
+PASS sign(1pt) should be used-value-equivalent to 1
+PASS sign(1em) should be used-value-equivalent to 1
+PASS sign(1ex) should be used-value-equivalent to 1
+PASS sign(1ch) should be used-value-equivalent to 1
+PASS sign(1rem) should be used-value-equivalent to 1
+PASS sign(1vh) should be used-value-equivalent to 1
+PASS sign(1vw) should be used-value-equivalent to 1
+PASS sign(1vmin) should be used-value-equivalent to 1
+PASS sign(1vmax) should be used-value-equivalent to 1
+PASS sign(-1px) should be used-value-equivalent to -1
+PASS sign(-1cm) should be used-value-equivalent to -1
+PASS sign(-1mm) should be used-value-equivalent to -1
+PASS sign(-1Q) should be used-value-equivalent to -1
+PASS sign(-1in) should be used-value-equivalent to -1
+PASS sign(-1pc) should be used-value-equivalent to -1
+PASS sign(-1pt) should be used-value-equivalent to -1
+PASS sign(-1em) should be used-value-equivalent to -1
+PASS sign(-1ex) should be used-value-equivalent to -1
+PASS sign(-1ch) should be used-value-equivalent to -1
+PASS sign(-1rem) should be used-value-equivalent to -1
+PASS sign(-1vh) should be used-value-equivalent to -1
+PASS sign(-1vw) should be used-value-equivalent to -1
+PASS sign(-1vmin) should be used-value-equivalent to -1
+PASS sign(-1vmax) should be used-value-equivalent to -1
+PASS sign(1s) should be used-value-equivalent to 1
+PASS sign(1ms) should be used-value-equivalent to 1
+PASS sign(-1s) should be used-value-equivalent to -1
+PASS sign(-1ms) should be used-value-equivalent to -1
+PASS sign(1deg) should be used-value-equivalent to 1
+PASS sign(1grad) should be used-value-equivalent to 1
+PASS sign(1rad) should be used-value-equivalent to 1
+PASS sign(1turn) should be used-value-equivalent to 1
+PASS sign(-1deg) should be used-value-equivalent to -1
+PASS sign(-1grad) should be used-value-equivalent to -1
+PASS sign(-1rad) should be used-value-equivalent to -1
+PASS sign(-1turn) should be used-value-equivalent to -1
+PASS calc(sign(0px)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0px))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0cm)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0cm))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0mm)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0mm))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0Q)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0Q))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0in)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0in))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0pc)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0pc))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0pt)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0pt))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0em)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0em))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0ex)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0ex))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0ch)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0ch))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0rem)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0rem))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0vh)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0vh))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0vw)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0vw))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0vmin)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0vmin))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0vmax)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0vmax))), 1) should be used-value-equivalent to 1
+PASS calc(sign(-0px)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0px))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0cm)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0cm))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0mm)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0mm))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0Q)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0Q))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0in)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0in))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0pc)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0pc))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0pt)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0pt))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0em)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0em))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0ex)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0ex))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0ch)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0ch))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0rem)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0rem))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0vh)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0vh))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0vw)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0vw))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0vmin)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0vmin))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0vmax)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0vmax))), 1) should be used-value-equivalent to -1
+PASS calc(sign(0s)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0s))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0ms)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0ms))), 1) should be used-value-equivalent to 1
+PASS calc(sign(-0s)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0s))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0ms)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0ms))), 1) should be used-value-equivalent to -1
+PASS calc(sign(0deg)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0deg))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0grad)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0grad))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0rad)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0rad))), 1) should be used-value-equivalent to 1
+PASS calc(sign(0turn)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(0turn))), 1) should be used-value-equivalent to 1
+PASS calc(sign(-0deg)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0deg))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0grad)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0grad))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0rad)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0rad))), 1) should be used-value-equivalent to -1
+PASS calc(sign(-0turn)) should be used-value-equivalent to 0
+PASS clamp(-1, calc( 1 / sign(sign(-0turn))), 1) should be used-value-equivalent to -1
+PASS abs(1px) should be used-value-equivalent to 1px
+PASS abs(1cm) should be used-value-equivalent to 1cm
+PASS abs(1mm) should be used-value-equivalent to 1mm
+PASS abs(1Q) should be used-value-equivalent to 1Q
+PASS abs(1in) should be used-value-equivalent to 1in
+PASS abs(1pc) should be used-value-equivalent to 1pc
+PASS abs(1pt) should be used-value-equivalent to 1pt
+PASS abs(1em) should be used-value-equivalent to 1em
+PASS abs(1ex) should be used-value-equivalent to 1ex
+PASS abs(1ch) should be used-value-equivalent to 1ch
+PASS abs(1rem) should be used-value-equivalent to 1rem
+PASS abs(1vh) should be used-value-equivalent to 1vh
+PASS abs(1vw) should be used-value-equivalent to 1vw
+PASS abs(1vmin) should be used-value-equivalent to 1vmin
+PASS abs(1vmax) should be used-value-equivalent to 1vmax
+PASS abs(-1px) should be used-value-equivalent to 1px
+PASS abs(-1cm) should be used-value-equivalent to 1cm
+PASS abs(-1mm) should be used-value-equivalent to 1mm
+PASS abs(-1Q) should be used-value-equivalent to 1Q
+PASS abs(-1in) should be used-value-equivalent to 1in
+PASS abs(-1pc) should be used-value-equivalent to 1pc
+PASS abs(-1pt) should be used-value-equivalent to 1pt
+PASS abs(-1em) should be used-value-equivalent to 1em
+PASS abs(-1ex) should be used-value-equivalent to 1ex
+PASS abs(-1ch) should be used-value-equivalent to 1ch
+PASS abs(-1rem) should be used-value-equivalent to 1rem
+PASS abs(-1vh) should be used-value-equivalent to 1vh
+PASS abs(-1vw) should be used-value-equivalent to 1vw
+PASS abs(-1vmin) should be used-value-equivalent to 1vmin
+PASS abs(-1vmax) should be used-value-equivalent to 1vmax
+PASS abs(1s) should be used-value-equivalent to 1s
+PASS abs(1ms) should be used-value-equivalent to 1ms
+PASS abs(-1s) should be used-value-equivalent to 1s
+PASS abs(-1ms) should be used-value-equivalent to 1ms
+PASS abs(1deg) should be used-value-equivalent to 1deg
+PASS abs(1grad) should be used-value-equivalent to 1grad
+PASS abs(1rad) should be used-value-equivalent to 1rad
+PASS abs(1turn) should be used-value-equivalent to 1turn
+PASS abs(-1deg) should be used-value-equivalent to 1deg
+PASS abs(-1grad) should be used-value-equivalent to 1grad
+PASS abs(-1rad) should be used-value-equivalent to 1rad
+PASS abs(-1turn) should be used-value-equivalent to 1turn
+FAIL sign(10px - 1em) should be used-value-equivalent to 0; fontSize=10px assert_not_equals: sign(10px - 1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(10px - 2em) should be used-value-equivalent to -1; fontSize=10px assert_not_equals: sign(10px - 2em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html
index 74dff7c..774ca34cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html
@@ -6,8 +6,20 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="../support/numeric-testcommon.js"></script>
-<div id="target"></div>
+<div id="container" style="font-size: 20px">
+  <div id="target"></div>
+</div>
 <script>
+function test_zero(expression, { is_negative }) {
+  test_math_used(`calc(${expression})`, '0', {type:'integer'});
+  // to test zero sign, make it to negative infinity and clamp it between -1 and 1
+  test_math_used(`clamp(-1, calc( 1 / sign(${expression})), 1)`, (is_negative)? '-1' : '1', {type:'integer'});
+}
+
+function test_length_equals(value, expected, msgExtra) {
+  test_math_used(value, expected, {msgExtra, type: 'integer'});
+}
+
 // Identity tests
 test_math_used('abs(1)', '1', {type:'integer'});
 test_math_used('sign(1)', '1', {type:'integer'});
@@ -29,8 +41,8 @@
 test_math_used('calc(sign(1) + sign(1) - 0.05)', '1.95', {type:'number', approx:0.1});
 
 // Test sign for zero
-test_math_used('calc(sign(-0))', '-0', {type:'integer'});
-test_math_used('calc(sign(0))', '0', {type:'integer'});
+test_zero('calc(sign(-0))', {is_negative: true});
+test_zero('calc(sign(0))', {is_negative: false});
 
 //Type checking sign
 test_math_used('sign(1px)', '1', {type:'integer'});
@@ -75,48 +87,48 @@
 test_math_used('sign(-1grad)', '-1', {type:'integer'});
 test_math_used('sign(-1rad)', '-1', {type:'integer'});
 test_math_used('sign(-1turn)', '-1', {type:'integer'});
-test_math_used('sign(0px)', '0', {type:'integer'});
-test_math_used('sign(0cm)', '0', {type:'integer'});
-test_math_used('sign(0mm)', '0', {type:'integer'});
-test_math_used('sign(0Q)', '0', {type:'integer'});
-test_math_used('sign(0in)', '0', {type:'integer'});
-test_math_used('sign(0pc)', '0', {type:'integer'});
-test_math_used('sign(0pt)', '0', {type:'integer'});
-test_math_used('sign(0em)', '0', {type:'integer'});
-test_math_used('sign(0ex)', '0', {type:'integer'});
-test_math_used('sign(0ch)', '0', {type:'integer'});
-test_math_used('sign(0rem)', '0', {type:'integer'});
-test_math_used('sign(0vh)', '0', {type:'integer'});
-test_math_used('sign(0vw)', '0', {type:'integer'});
-test_math_used('sign(0vmin)', '0', {type:'integer'});
-test_math_used('sign(0vmax)', '0', {type:'integer'});
-test_math_used('sign(-0px)', '-0', {type:'integer'});
-test_math_used('sign(-0cm)', '-0', {type:'integer'});
-test_math_used('sign(-0mm)', '-0', {type:'integer'});
-test_math_used('sign(-0Q)', '-0', {type:'integer'});
-test_math_used('sign(-0in)', '-0', {type:'integer'});
-test_math_used('sign(-0pc)', '-0', {type:'integer'});
-test_math_used('sign(-0pt)', '-0', {type:'integer'});
-test_math_used('sign(-0em)', '-0', {type:'integer'});
-test_math_used('sign(-0ex)', '-0', {type:'integer'});
-test_math_used('sign(-0ch)', '-0', {type:'integer'});
-test_math_used('sign(-0rem)', '-0', {type:'integer'});
-test_math_used('sign(-0vh)', '-0', {type:'integer'});
-test_math_used('sign(-0vw)', '-0', {type:'integer'});
-test_math_used('sign(-0vmin)', '-0', {type:'integer'});
-test_math_used('sign(-0vmax)', '-0', {type:'integer'});
-test_math_used('sign(0s)', '0', {type:'integer'});
-test_math_used('sign(0ms)', '0', {type:'integer'});
-test_math_used('sign(-0s)', '0', {type:'integer'});
-test_math_used('sign(-0ms)', '0', {type:'integer'});
-test_math_used('sign(0deg)', '0', {type:'integer'});
-test_math_used('sign(0grad)', '0', {type:'integer'});
-test_math_used('sign(0rad)', '0', {type:'integer'});
-test_math_used('sign(0turn)', '0', {type:'integer'});
-test_math_used('sign(-0deg)', '-0', {type:'integer'});
-test_math_used('sign(-0grad)', '-0', {type:'integer'});
-test_math_used('sign(-0rad)', '-0', {type:'integer'});
-test_math_used('sign(-0turn)', '-0', {type:'integer'});
+test_zero('sign(0px)', {is_negative: false});
+test_zero('sign(0cm)', {is_negative: false});
+test_zero('sign(0mm)', {is_negative: false});
+test_zero('sign(0Q)', {is_negative: false});
+test_zero('sign(0in)', {is_negative: false});
+test_zero('sign(0pc)', {is_negative: false});
+test_zero('sign(0pt)', {is_negative: false});
+test_zero('sign(0em)', {is_negative: false});
+test_zero('sign(0ex)', {is_negative: false});
+test_zero('sign(0ch)', {is_negative: false});
+test_zero('sign(0rem)', {is_negative: false});
+test_zero('sign(0vh)', {is_negative: false});
+test_zero('sign(0vw)', {is_negative: false});
+test_zero('sign(0vmin)', {is_negative: false});
+test_zero('sign(0vmax)', {is_negative: false});
+test_zero('sign(-0px)', {is_negative: true});
+test_zero('sign(-0cm)', {is_negative: true});
+test_zero('sign(-0mm)', {is_negative: true});
+test_zero('sign(-0Q)', {is_negative: true});
+test_zero('sign(-0in)', {is_negative: true});
+test_zero('sign(-0pc)', {is_negative: true});
+test_zero('sign(-0pt)', {is_negative: true});
+test_zero('sign(-0em)', {is_negative: true});
+test_zero('sign(-0ex)', {is_negative: true});
+test_zero('sign(-0ch)', {is_negative: true});
+test_zero('sign(-0rem)', {is_negative: true});
+test_zero('sign(-0vh)', {is_negative: true});
+test_zero('sign(-0vw)', {is_negative: true});
+test_zero('sign(-0vmin)', {is_negative: true});
+test_zero('sign(-0vmax)', {is_negative: true});
+test_zero('sign(0s)', {is_negative: false});
+test_zero('sign(0ms)', {is_negative: false});
+test_zero('sign(-0s)', {is_negative: true});
+test_zero('sign(-0ms)', {is_negative: true});
+test_zero('sign(0deg)', {is_negative: false});
+test_zero('sign(0grad)', {is_negative: false});
+test_zero('sign(0rad)', {is_negative: false});
+test_zero('sign(0turn)', {is_negative: false});
+test_zero('sign(-0deg)', {is_negative: true});
+test_zero('sign(-0grad)', {is_negative: true});
+test_zero('sign(-0rad)', {is_negative: true});
+test_zero('sign(-0turn)', {is_negative: true});
 
 //Type checking abs
 test_math_used('abs(1px)', '1px');
@@ -161,4 +173,12 @@
 test_math_used('abs(-1grad)', '1grad', {type:'angle', approx:0.001});
 test_math_used('abs(-1rad)', '1rad', {type:'angle', approx:0.001});
 test_math_used('abs(-1turn)', '1turn', {type:'angle', approx:0.001});
+
+// with relative length
+document.getElementById('container').style.fontSize = '10px';
+test_length_equals('sign(10px - 1em)', '0', 'fontSize=10px');
+test_length_equals('sign(10px - 2em)', '-1', 'fontSize=10px');
+document.getElementById('container').style.fontSize = '20px';
+
+
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html.ini b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html.ini
deleted file mode 100644
index 1ac87ea..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html.ini
+++ /dev/null
@@ -1,426 +0,0 @@
-[signs-abs-computed.html]
-  [abs(1) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [abs(-1) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(-1) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [abs(sign(1)) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [abs(sign(sign(1))) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35]
-    expected: FAIL
-
-  [calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95]
-    expected: FAIL
-
-  [calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6]
-    expected: FAIL
-
-  [calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6]
-    expected: FAIL
-
-  [calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6]
-    expected: FAIL
-
-  [calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05]
-    expected: FAIL
-
-  [calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95]
-    expected: FAIL
-
-  [calc(sign(-0)) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [calc(sign(0)) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(1px) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1cm) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1mm) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1Q) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1in) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1pc) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1pt) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1em) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1ex) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1ch) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1rem) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1vh) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1vw) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1vmin) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1vmax) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(-1px) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1cm) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1mm) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1Q) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1in) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1pc) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1pt) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1em) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1ex) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1ch) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1rem) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1vh) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1vw) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1vmin) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1vmax) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(1s) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1ms) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(-1s) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1ms) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(1deg) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1grad) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1rad) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(1turn) should be used-value-equivalent to 1]
-    expected: FAIL
-
-  [sign(-1deg) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1grad) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1rad) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(-1turn) should be used-value-equivalent to -1]
-    expected: FAIL
-
-  [sign(0px) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0cm) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0mm) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0Q) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0in) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0pc) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0pt) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0em) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0ex) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0ch) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0rem) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0vh) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0vw) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0vmin) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0vmax) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(-0px) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0cm) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0mm) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0Q) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0in) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0pc) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0pt) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0em) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0ex) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0ch) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0rem) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0vh) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0vw) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0vmin) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0vmax) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(0s) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0ms) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(-0s) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(-0ms) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0deg) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0grad) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0rad) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(0turn) should be used-value-equivalent to 0]
-    expected: FAIL
-
-  [sign(-0deg) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0grad) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0rad) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [sign(-0turn) should be used-value-equivalent to -0]
-    expected: FAIL
-
-  [abs(1px) should be used-value-equivalent to 1px]
-    expected: FAIL
-
-  [abs(1cm) should be used-value-equivalent to 1cm]
-    expected: FAIL
-
-  [abs(1mm) should be used-value-equivalent to 1mm]
-    expected: FAIL
-
-  [abs(1Q) should be used-value-equivalent to 1Q]
-    expected: FAIL
-
-  [abs(1in) should be used-value-equivalent to 1in]
-    expected: FAIL
-
-  [abs(1pc) should be used-value-equivalent to 1pc]
-    expected: FAIL
-
-  [abs(1pt) should be used-value-equivalent to 1pt]
-    expected: FAIL
-
-  [abs(1em) should be used-value-equivalent to 1em]
-    expected: FAIL
-
-  [abs(1ex) should be used-value-equivalent to 1ex]
-    expected: FAIL
-
-  [abs(1ch) should be used-value-equivalent to 1ch]
-    expected: FAIL
-
-  [abs(1rem) should be used-value-equivalent to 1rem]
-    expected: FAIL
-
-  [abs(1vh) should be used-value-equivalent to 1vh]
-    expected: FAIL
-
-  [abs(1vw) should be used-value-equivalent to 1vw]
-    expected: FAIL
-
-  [abs(1vmin) should be used-value-equivalent to 1vmin]
-    expected: FAIL
-
-  [abs(1vmax) should be used-value-equivalent to 1vmax]
-    expected: FAIL
-
-  [abs(-1px) should be used-value-equivalent to 1px]
-    expected: FAIL
-
-  [abs(-1cm) should be used-value-equivalent to 1cm]
-    expected: FAIL
-
-  [abs(-1mm) should be used-value-equivalent to 1mm]
-    expected: FAIL
-
-  [abs(-1Q) should be used-value-equivalent to 1Q]
-    expected: FAIL
-
-  [abs(-1in) should be used-value-equivalent to 1in]
-    expected: FAIL
-
-  [abs(-1pc) should be used-value-equivalent to 1pc]
-    expected: FAIL
-
-  [abs(-1pt) should be used-value-equivalent to 1pt]
-    expected: FAIL
-
-  [abs(-1em) should be used-value-equivalent to 1em]
-    expected: FAIL
-
-  [abs(-1ex) should be used-value-equivalent to 1ex]
-    expected: FAIL
-
-  [abs(-1ch) should be used-value-equivalent to 1ch]
-    expected: FAIL
-
-  [abs(-1rem) should be used-value-equivalent to 1rem]
-    expected: FAIL
-
-  [abs(-1vh) should be used-value-equivalent to 1vh]
-    expected: FAIL
-
-  [abs(-1vw) should be used-value-equivalent to 1vw]
-    expected: FAIL
-
-  [abs(-1vmin) should be used-value-equivalent to 1vmin]
-    expected: FAIL
-
-  [abs(-1vmax) should be used-value-equivalent to 1vmax]
-    expected: FAIL
-
-  [abs(1s) should be used-value-equivalent to 1s]
-    expected: FAIL
-
-  [abs(1ms) should be used-value-equivalent to 1ms]
-    expected: FAIL
-
-  [abs(-1s) should be used-value-equivalent to 1s]
-    expected: FAIL
-
-  [abs(-1ms) should be used-value-equivalent to 1ms]
-    expected: FAIL
-
-  [abs(1deg) should be used-value-equivalent to 1deg]
-    expected: FAIL
-
-  [abs(1grad) should be used-value-equivalent to 1grad]
-    expected: FAIL
-
-  [abs(1rad) should be used-value-equivalent to 1rad]
-    expected: FAIL
-
-  [abs(1turn) should be used-value-equivalent to 1turn]
-    expected: FAIL
-
-  [abs(-1deg) should be used-value-equivalent to 1deg]
-    expected: FAIL
-
-  [abs(-1grad) should be used-value-equivalent to 1grad]
-    expected: FAIL
-
-  [abs(-1rad) should be used-value-equivalent to 1rad]
-    expected: FAIL
-
-  [abs(-1turn) should be used-value-equivalent to 1turn]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt
deleted file mode 100644
index 39973d9c..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-This is a testharness.js-based test.
-Found 56 tests; 4 PASS, 52 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL 'abs(1)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'abs(1)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(abs(1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(abs(1))' should be valid in transform. got disallowed value ""
-PASS 'abs(1)' as a computed value should serialize as '1'.
-FAIL 'scale(abs(1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(abs(1))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
-FAIL 'sign(.1)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'sign(.1)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(sign(.1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(.1))' should be valid in transform. got disallowed value ""
-PASS 'sign(.1)' as a computed value should serialize as '1'.
-FAIL 'scale(sign(.1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(sign(.1))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
-FAIL 'abs(1 + 2 + 3)' as a specified value should serialize as 'calc(6)'. assert_not_equals: 'abs(1 + 2 + 3)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(abs(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(6))'. assert_not_equals: 'scale(abs(1 + 2 + 3))' should be valid in transform. got disallowed value ""
-FAIL 'abs(1 + 2 + 3)' as a computed value should serialize as '6'. assert_equals: '6' should round-trip exactly in computed values. expected "6" but got "1"
-FAIL 'scale(abs(1 + 2 + 3))' as a computed value should serialize as 'matrix(6, 0, 0, 6, 0, 0)'. assert_equals: 'scale(abs(1 + 2 + 3))' and 'matrix(6, 0, 0, 6, 0, 0)' should serialize the same in computed values. expected "matrix(6, 0, 0, 6, 0, 0)" but got "none"
-FAIL 'sign(1 + 2 + 3)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'sign(1 + 2 + 3)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(sign(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(1 + 2 + 3))' should be valid in transform. got disallowed value ""
-PASS 'sign(1 + 2 + 3)' as a computed value should serialize as '1'.
-FAIL 'scale(sign(1 + 2 + 3))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(sign(1 + 2 + 3))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
-FAIL 'calc(abs(1) + abs(2))' as a specified value should serialize as 'calc(3)'. assert_not_equals: 'calc(abs(1) + abs(2))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(abs(1) + abs(2)))' as a specified value should serialize as 'scale(calc(3))'. assert_not_equals: 'scale(calc(abs(1) + abs(2)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(abs(1) + abs(2))' as a computed value should serialize as '3'. assert_equals: '3' should round-trip exactly in computed values. expected "3" but got "1"
-FAIL 'scale(calc(abs(1) + abs(2)))' as a computed value should serialize as 'matrix(3, 0, 0, 3, 0, 0)'. assert_equals: 'scale(calc(abs(1) + abs(2)))' and 'matrix(3, 0, 0, 3, 0, 0)' should serialize the same in computed values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none"
-FAIL 'calc(sign(.1) + sign(.2))' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(sign(.1) + sign(.2))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(sign(.1) + sign(.2)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + sign(.2)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(sign(.1) + sign(.2))' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1"
-FAIL 'scale(calc(sign(.1) + sign(.2)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(sign(.1) + sign(.2)))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none"
-FAIL 'calc(1 + abs(1))' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(1 + abs(1))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(1 + abs(1)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(1 + abs(1)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(1 + abs(1))' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1"
-FAIL 'scale(calc(1 + abs(1)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(1 + abs(1)))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none"
-FAIL 'calc(sign(.1) + 1)' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(sign(.1) + 1)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(sign(.1) + 1))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + 1))' should be valid in transform. got disallowed value ""
-FAIL 'calc(sign(.1) + 1)' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1"
-FAIL 'scale(calc(sign(.1) + 1))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(sign(.1) + 1))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none"
-FAIL 'calc(abs(inFinity))' as a specified value should serialize as 'calc(inFinity)'. assert_not_equals: 'calc(abs(inFinity))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(abs(inFinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(inFinity)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(abs(inFinity))' as a computed value should serialize as 'infinity'. assert_equals: 'infinity' should round-trip exactly in computed values. expected "infinity" but got "1"
-FAIL 'scale(calc(abs(inFinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'. assert_equals: 'matrix(infinity, 0, 0, infinity, 0, 0)' should round-trip exactly in computed values. expected "matrix(infinity, 0, 0, infinity, 0, 0)" but got "none"
-FAIL 'calc(abs(infinity))' as a specified value should serialize as 'calc(infinity)'. assert_not_equals: 'calc(abs(infinity))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(abs(infinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(infinity)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(abs(infinity))' as a computed value should serialize as 'infinity'. assert_equals: 'infinity' should round-trip exactly in computed values. expected "infinity" but got "1"
-FAIL 'scale(calc(abs(infinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'. assert_equals: 'matrix(infinity, 0, 0, infinity, 0, 0)' should round-trip exactly in computed values. expected "matrix(infinity, 0, 0, infinity, 0, 0)" but got "none"
-FAIL 'calc(sign(infinity))' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'calc(sign(infinity))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(sign(infinity)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(sign(infinity)))' should be valid in transform. got disallowed value ""
-PASS 'calc(sign(infinity))' as a computed value should serialize as '1'.
-FAIL 'scale(calc(sign(infinity)))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(calc(sign(infinity)))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
-FAIL 'abs(infinity)' as a specified value should serialize as 'calc(infinity)'. assert_not_equals: 'abs(infinity)' should be valid in opacity. got disallowed value ""
-FAIL 'scale(abs(infinity))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(abs(infinity))' should be valid in transform. got disallowed value ""
-FAIL 'abs(infinity)' as a computed value should serialize as 'infinity'. assert_equals: 'infinity' should round-trip exactly in computed values. expected "infinity" but got "1"
-FAIL 'scale(abs(infinity))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'. assert_equals: 'matrix(infinity, 0, 0, infinity, 0, 0)' should round-trip exactly in computed values. expected "matrix(infinity, 0, 0, infinity, 0, 0)" but got "none"
-FAIL 'calc(abs(-infinity))' as a specified value should serialize as 'calc(infinity)'. assert_not_equals: 'calc(abs(-infinity))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(abs(-infinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(-infinity)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(abs(-infinity))' as a computed value should serialize as 'infinity'. assert_equals: 'infinity' should round-trip exactly in computed values. expected "infinity" but got "1"
-FAIL 'scale(calc(abs(-infinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'. assert_equals: 'matrix(infinity, 0, 0, infinity, 0, 0)' should round-trip exactly in computed values. expected "matrix(infinity, 0, 0, infinity, 0, 0)" but got "none"
-FAIL 'calc(sign(-1 * infinity))' as a specified value should serialize as 'calc(-1)'. assert_not_equals: 'calc(sign(-1 * infinity))' should be valid in opacity. got disallowed value ""
-FAIL 'scale(calc(sign(-1 * infinity)))' as a specified value should serialize as 'scale(calc(-1))'. assert_not_equals: 'scale(calc(sign(-1 * infinity)))' should be valid in transform. got disallowed value ""
-FAIL 'calc(sign(-1 * infinity))' as a computed value should serialize as '-1'. assert_equals: '-1' should round-trip exactly in computed values. expected "-1" but got "0"
-FAIL 'scale(calc(sign(-1 * infinity)))' as a computed value should serialize as 'matrix(-1, 0, 0, -1, 0, 0)'. assert_equals: 'scale(calc(sign(-1 * infinity)))' and 'matrix(-1, 0, 0, -1, 0, 0)' should serialize the same in computed values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html
index 28d04b9..ea3d0cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html
@@ -9,10 +9,7 @@
 <div id=target></div>
 <script>
 function test_serialization(t,s,c) {
-    test_specified_serialization('opacity', t, s);
     test_specified_serialization('transform', `scale(${t})`, `scale(calc(${c}))`);
-    test_computed_serialization('opacity', t, c);
-    test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`);
 }
 
 test_serialization(
@@ -77,4 +74,14 @@
     'calc(sign(-1 * infinity))',
     'calc(-1)',
     '-1');
+
+test_serialization(
+  'calc(sign(-1 * NaN))',
+  'calc(NaN)',
+  'NaN');
+
+test_serialization(
+  'calc(sign(1 * NaN))',
+  'calc(NaN)',
+  'NaN');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html.ini b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html.ini
deleted file mode 100644
index f46ffb3..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html.ini
+++ /dev/null
@@ -1,156 +0,0 @@
-[signs-abs-serialize.html]
-  ['abs(1)' as a specified value should serialize as 'calc(1)'.]
-    expected: FAIL
-
-  ['scale(abs(1))' as a specified value should serialize as 'scale(calc(1))'.]
-    expected: FAIL
-
-  ['scale(abs(1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.]
-    expected: FAIL
-
-  ['sign(.1)' as a specified value should serialize as 'calc(1)'.]
-    expected: FAIL
-
-  ['scale(sign(.1))' as a specified value should serialize as 'scale(calc(1))'.]
-    expected: FAIL
-
-  ['scale(sign(.1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.]
-    expected: FAIL
-
-  ['abs(1 + 2 + 3)' as a specified value should serialize as 'calc(6)'.]
-    expected: FAIL
-
-  ['scale(abs(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(6))'.]
-    expected: FAIL
-
-  ['abs(1 + 2 + 3)' as a computed value should serialize as '6'.]
-    expected: FAIL
-
-  ['scale(abs(1 + 2 + 3))' as a computed value should serialize as 'matrix(6, 0, 0, 6, 0, 0)'.]
-    expected: FAIL
-
-  ['sign(1 + 2 + 3)' as a specified value should serialize as 'calc(1)'.]
-    expected: FAIL
-
-  ['scale(sign(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(1))'.]
-    expected: FAIL
-
-  ['scale(sign(1 + 2 + 3))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(abs(1) + abs(2))' as a specified value should serialize as 'calc(3)'.]
-    expected: FAIL
-
-  ['scale(calc(abs(1) + abs(2)))' as a specified value should serialize as 'scale(calc(3))'.]
-    expected: FAIL
-
-  ['calc(abs(1) + abs(2))' as a computed value should serialize as '3'.]
-    expected: FAIL
-
-  ['scale(calc(abs(1) + abs(2)))' as a computed value should serialize as 'matrix(3, 0, 0, 3, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(sign(.1) + sign(.2))' as a specified value should serialize as 'calc(2)'.]
-    expected: FAIL
-
-  ['scale(calc(sign(.1) + sign(.2)))' as a specified value should serialize as 'scale(calc(2))'.]
-    expected: FAIL
-
-  ['calc(sign(.1) + sign(.2))' as a computed value should serialize as '2'.]
-    expected: FAIL
-
-  ['scale(calc(sign(.1) + sign(.2)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(1 + abs(1))' as a specified value should serialize as 'calc(2)'.]
-    expected: FAIL
-
-  ['scale(calc(1 + abs(1)))' as a specified value should serialize as 'scale(calc(2))'.]
-    expected: FAIL
-
-  ['calc(1 + abs(1))' as a computed value should serialize as '2'.]
-    expected: FAIL
-
-  ['scale(calc(1 + abs(1)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(sign(.1) + 1)' as a specified value should serialize as 'calc(2)'.]
-    expected: FAIL
-
-  ['scale(calc(sign(.1) + 1))' as a specified value should serialize as 'scale(calc(2))'.]
-    expected: FAIL
-
-  ['calc(sign(.1) + 1)' as a computed value should serialize as '2'.]
-    expected: FAIL
-
-  ['scale(calc(sign(.1) + 1))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(abs(inFinity))' as a specified value should serialize as 'calc(inFinity)'.]
-    expected: FAIL
-
-  ['scale(calc(abs(inFinity)))' as a specified value should serialize as 'scale(calc(infinity))'.]
-    expected: FAIL
-
-  ['calc(abs(inFinity))' as a computed value should serialize as 'infinity'.]
-    expected: FAIL
-
-  ['scale(calc(abs(inFinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(abs(infinity))' as a specified value should serialize as 'calc(infinity)'.]
-    expected: FAIL
-
-  ['scale(calc(abs(infinity)))' as a specified value should serialize as 'scale(calc(infinity))'.]
-    expected: FAIL
-
-  ['calc(abs(infinity))' as a computed value should serialize as 'infinity'.]
-    expected: FAIL
-
-  ['scale(calc(abs(infinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(sign(infinity))' as a specified value should serialize as 'calc(1)'.]
-    expected: FAIL
-
-  ['scale(calc(sign(infinity)))' as a specified value should serialize as 'scale(calc(1))'.]
-    expected: FAIL
-
-  ['scale(calc(sign(infinity)))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.]
-    expected: FAIL
-
-  ['abs(infinity)' as a specified value should serialize as 'calc(infinity)'.]
-    expected: FAIL
-
-  ['scale(abs(infinity))' as a specified value should serialize as 'scale(calc(infinity))'.]
-    expected: FAIL
-
-  ['abs(infinity)' as a computed value should serialize as 'infinity'.]
-    expected: FAIL
-
-  ['scale(abs(infinity))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(abs(-infinity))' as a specified value should serialize as 'calc(infinity)'.]
-    expected: FAIL
-
-  ['scale(calc(abs(-infinity)))' as a specified value should serialize as 'scale(calc(infinity))'.]
-    expected: FAIL
-
-  ['calc(abs(-infinity))' as a computed value should serialize as 'infinity'.]
-    expected: FAIL
-
-  ['scale(calc(abs(-infinity)))' as a computed value should serialize as 'matrix(infinity, 0, 0, infinity, 0, 0)'.]
-    expected: FAIL
-
-  ['calc(sign(-1 * infinity))' as a specified value should serialize as 'calc(-1)'.]
-    expected: FAIL
-
-  ['scale(calc(sign(-1 * infinity)))' as a specified value should serialize as 'scale(calc(-1))'.]
-    expected: FAIL
-
-  ['calc(sign(-1 * infinity))' as a computed value should serialize as '-1'.]
-    expected: FAIL
-
-  ['scale(calc(sign(-1 * infinity)))' as a computed value should serialize as 'matrix(-1, 0, 0, -1, 0, 0)'.]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html b/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html
deleted file mode 100644
index a69b642..0000000
--- a/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<meta charset="utf-8" />
-<meta name="timeout" content="long">
-<link rel="author" title="Noam Rosenthal" href="noam@chromium.org">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
-<script src="resources/entry-invariants.js"></script>
-</head>
-<body>
-<script>
-const {REMOTE_ORIGIN} = get_host_info();
-
-promise_test(async t => {
-  const success_url = new URL("/resource-timing/resources/object-frame-options-200.asis", REMOTE_ORIGIN).href;
-  const fail_url = new URL("/resource-timing/resources/object-frame-options-403.asis", REMOTE_ORIGIN).href;
-  const load_object = async url => {
-    const object = document.createElement("object");
-    object.data = url;
-    document.body.appendChild(object);
-    t.add_cleanup(() => object.remove());
-    await new Promise(resolve => {
-      object.onload = object.onerror = resolve;
-    });
-  };
-
-  await Promise.all([success_url, fail_url].map(load_object));
-  assert_equals(performance.getEntriesByName(success_url).length, 1);
-  assert_equals(performance.getEntriesByName(fail_url).length, 1);
-}, "Test that object elements with X-Frame-Options: Deny produce resource timing entries");
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html b/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html
index 5d719fb9..02d1c36 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html
@@ -3,7 +3,6 @@
 <title>Test the sequence of events when reporting iframe timing.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="resources/entry-invariants.js"></script>
 <script src="resources/frame-timing.js"></script>
 <script src="/common/utils.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js
index 65710e2..019bd42 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js
@@ -25,8 +25,8 @@
 
 
 function test_frame_timing_change_src(type,
-                                      origin1 = location.origin,
-                                      origin2 = location.origin,
+                                      origin1 = document.origin,
+                                      origin2 = document.origin,
                                       tao = false, label = '') {
   const uid = token();
   promise_test(async t => {
@@ -59,11 +59,5 @@
 
     const entries = performance.getEntries().filter(e => e.name.includes(uid));
     assert_equals(entries.length, 2);
-    for (const entry of entries) {
-      if (tao || entry.name.startsWith(location.origin))
-        invariants.assert_tao_pass_no_redirect_http(entry);
-      else
-        invariants.assert_tao_failure_resource(entry);
-    }
   }, label || `A ${type} should report separate RT entries if its src changed from the outside`);
 }
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis
deleted file mode 100644
index 12244532..0000000
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis
+++ /dev/null
@@ -1,6 +0,0 @@
-HTTP/1.0 200 OK
-Content-Type: text/html
-X-Frame-Options: DENY
-Content-Security-Policy: frame-ancestors 'none'
-
-Hello
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis
deleted file mode 100644
index fd64f0bc..0000000
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis
+++ /dev/null
@@ -1,6 +0,0 @@
-HTTP/1.0 403 OK
-Content-Type: text/html
-X-Frame-Options: DENY
-Content-Security-Policy: frame-ancestors 'none'
-
-Hello
diff --git a/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form-expected.txt b/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form-expected.txt
index 85d8ca1..b35446e 100644
--- a/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form-expected.txt
+++ b/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form-expected.txt
@@ -8,6 +8,10 @@
 PASS document.getElementById("input2").value is "value2"
 PASS document.getElementById("textarea2").value is "good"
 PASS document.getElementById("select2").value is "BSD"
+Controls in the third form should have their default values:
+PASS document.getElementById("input3").value is ""
+PASS document.getElementById("textarea3").value is ""
+PASS document.getElementById("select3").value is "Mac"
 PASS successfullyParsed is true
 
 TEST COMPLETE
@@ -20,3 +24,7 @@
 Mac
 Windows
 BSD
+  
+Mac
+Windows
+BSD
diff --git a/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form.html b/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form.html
index 9ef9c07..832b29a1 100644
--- a/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form.html
+++ b/third_party/blink/web_tests/fast/forms/state-restore-to-non-autocomplete-form.html
@@ -9,16 +9,21 @@
 
 <input id=emptyOnFirstVisit>
 <div id=parent>
-<form action="../../resources/back.html" id=form1 autocomplete=off>
-<input name=user id=input1>
-<textarea name=comment id=textarea1></textarea>
-<select name=os id=select1><option>Mac<option>Windows<option>BSD</select>
-</form>
-<form action="../../resources/back.html" id=form2>
-<input name=user id=input2>
-<textarea name=comment id=textarea2></textarea>
-<select name=os id=select2><option>Mac<option>Windows<option>BSD</select>
-</form>
+  <form action="../../resources/back.html" id=form1 autocomplete=off>
+    <input name=user id=input1>
+    <textarea name=comment id=textarea1></textarea>
+    <select name=os id=select1><option>Mac<option>Windows<option>BSD</select>
+  </form>
+  <form action="../../resources/back.html" id=form2>
+    <input name=user id=input2>
+    <textarea name=comment id=textarea2></textarea>
+    <select name=os id=select2><option>Mac<option>Windows<option>BSD</select>
+  </form>
+  <form action="../../resources/back.html" id=form3>
+    <input name=user id=input3 autocomplete=off>
+    <textarea name=comment id=textarea3 autocomplete=off></textarea>
+    <select name=os id=select3 autocomplete=off><option>Mac<option>Windows<option>BSD</select>
+  </form>
 </div>
 
 <script>
@@ -38,6 +43,9 @@
         document.getElementById('input2').value = 'value2';
         document.getElementById('textarea2').value = 'good';
         document.getElementById('select2').value = 'BSD';
+        document.getElementById('input3').value = 'value3';
+        document.getElementById('textarea3').value = 'great';
+        document.getElementById('select3').value = 'BSD';
         // Submit form in a timeout to make sure that we create a new back/forward list item.
         setTimeout(function() {document.getElementById('form2').submit();}, 0);
     } else {
@@ -50,6 +58,10 @@
         shouldBe('document.getElementById("input2").value', '"value2"');
         shouldBe('document.getElementById("textarea2").value', '"good"');
         shouldBe('document.getElementById("select2").value', '"BSD"');
+        debug('Controls in the third form should have their default values:');
+        shouldBe('document.getElementById("input3").value', '""');
+        shouldBe('document.getElementById("textarea3").value', '""');
+        shouldBe('document.getElementById("select3").value', '"Mac"');
         finishJSTest();
     }
  }
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any-expected.txt
deleted file mode 100644
index 02844e31..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any-expected.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-This is a testharness.js-based test.
-FAIL clamp float32 1D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any.worker-expected.txt
deleted file mode 100644
index a079576..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/clamp.https.any.worker-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-This is a testharness.js-based test.
-Found 64 tests; 0 PASS, 64 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL clamp float32 1D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL clamp float32 1D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor default options.maxValue and specified negative options.minValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.maxValue and specified options.minValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor default options.maxValue and specified positive options.minValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor default options.minValue and specified negative options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor default options.minValue and specified options.maxValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor default options.minValue and specified positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 5D tensor specified both negative options.minValue and options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 4D tensor specified negative options.minValue and options.maxValue=0.0 / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 3D tensor specified negative options.minValue and positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 2D tensor specified options.minValue=0.0 and positive options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL clamp float32 1D tensor specified both positive options.minValue and options.maxValue / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any-expected.txt
deleted file mode 100644
index 7f15524..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any-expected.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-This is a testharness.js-based test.
-Found 52 tests; 0 PASS, 52 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.groups / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors all options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.groups / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors all options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any.worker-expected.txt
deleted file mode 100644
index 736a050..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/conv2d.https.any.worker-expected.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-This is a testharness.js-based test.
-Found 104 tests; 0 PASS, 104 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.dilations / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.groups / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors all options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.dilations / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.groups / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter tensors all options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.groups / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors all options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter(non-constant) tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.padding and options.autoPad='explicit' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-upper' ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.autoPad='same-lower' ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.groups / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nchw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='oihw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='hwio' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ohwi' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.filterLayout='ihwo' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='oihw' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='hwio' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ohwi' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.inputLayout='nhwc' and options.filterLayout='ihwo' / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors 1D options.bias / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=relu / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.activation=sigmoid / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL conv2d float32 4D input and filter tensors all options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any-expected.txt
deleted file mode 100644
index f196661..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any-expected.txt
+++ /dev/null
@@ -1,136 +0,0 @@
-This is a testharness.js-based test.
-Found 132 tests; 0 PASS, 132 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL add float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any.worker-expected.txt
deleted file mode 100644
index 0f26d03..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/elementwise_binary.https.any.worker-expected.txt
+++ /dev/null
@@ -1,268 +0,0 @@
-This is a testharness.js-based test.
-Found 264 tests; 0 PASS, 264 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL add float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL add float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sub float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL mul float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL div float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL max float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 1D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 2D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 3D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 4D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 5D tensors / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 1D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 2D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 3D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 4D to 4D / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 1D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 2D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 3D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 4D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 5D tensors / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 1D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 2D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 3D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL min float32 broadcast 4D to 4D / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / cpu / sync builder[operationName] is not a function
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / gpu / sync builder[operationName] is not a function
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / gpu / sync builder[operationName] is not a function
-FAIL add float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL add float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sub float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL mul float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL div float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL max float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 1D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 2D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 3D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 4D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 5D tensors / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 1D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 2D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 3D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 4D to 4D / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 1D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 2D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 3D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 4D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 5D tensors / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 1D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 2D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 3D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL min float32 broadcast 4D to 4D / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / cpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D base tensor and 1D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D base tensor and 2D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 3D base tensor and 3D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and 4D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 5D base tensor and 5D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 1D positive base tensor and 1D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 2D positive base tensor and 2D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D positive base tensor and 4D exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 1D positive base tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 2D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D base tensor and broadcastable 3D integer exponent tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL pow float32 4D exponent tensor and broadcastable 4D positive base tensor / gpu / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any-expected.txt
deleted file mode 100644
index 4b661f11..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any-expected.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-This is a testharness.js-based test.
-FAIL gemm two float32 2D tensors (b is non-constant) default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors scalar options.c / cpu / async promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present."
-FAIL gemm two float32 2D tensors options.alpha / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.beta / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c and options.beta / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being true / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being true / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors all options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors (b is non-constant) default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors scalar options.c / gpu / async promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present."
-FAIL gemm two float32 2D tensors options.alpha / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.beta / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c and options.beta / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being true / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being true / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors all options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any.worker-expected.txt
deleted file mode 100644
index 3526fd6..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/gemm.https.any.worker-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-This is a testharness.js-based test.
-Found 64 tests; 0 PASS, 64 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL gemm two float32 2D tensors (b is non-constant) default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.c / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors scalar options.c / cpu / sync Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present.
-FAIL gemm two float32 2D tensors options.alpha / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.beta / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.c and options.beta / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.aTranspose being true / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.bTranspose being true / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors all options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors (b is non-constant) default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.c / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors scalar options.c / gpu / sync Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present.
-FAIL gemm two float32 2D tensors options.alpha / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.beta / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.c and options.beta / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.aTranspose being true / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.bTranspose being true / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors all options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL gemm two float32 2D tensors (b is non-constant) default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors scalar options.c / cpu / async promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present."
-FAIL gemm two float32 2D tensors options.alpha / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.beta / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c and options.beta / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being true / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being true / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors all options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors (b is non-constant) default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 5] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [3, 1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1, 1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors broadcast options.c [1] => [3, 5] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors scalar options.c / gpu / async promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': 2 arguments required, but only 1 present."
-FAIL gemm two float32 2D tensors options.alpha / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.beta / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.c and options.beta / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being true / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.aTranspose being explicit false / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being true / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors options.bTranspose being explicit false / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL gemm two float32 2D tensors all options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any-expected.txt
deleted file mode 100644
index d76de0a1..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any-expected.txt
+++ /dev/null
@@ -1,407 +0,0 @@
-This is a testharness.js-based test.
-Found 403 tests; 230 PASS, 173 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-PASS idl_test validation
-PASS Partial interface MLContext: original interface defined
-PASS Partial interface MLContext: member names are unique
-PASS Partial interface MLContext[2]: original interface defined
-PASS Partial interface MLContext[2]: member names are unique
-PASS Partial interface MLContext[3]: original interface defined
-PASS Partial interface MLContext[3]: member names are unique
-PASS Partial interface MLCommandEncoder: original interface defined
-PASS Partial interface MLCommandEncoder: member names are unique
-PASS Partial interface MLCommandEncoder[2]: original interface defined
-PASS Partial interface MLCommandEncoder[2]: member names are unique
-PASS Partial interface MLCommandEncoder[3]: original interface defined
-PASS Partial interface MLCommandEncoder[3]: member names are unique
-PASS Partial interface MLGraphBuilder: original interface defined
-PASS Partial interface MLGraphBuilder: member names are unique
-PASS Partial interface MLGraphBuilder[2]: original interface defined
-PASS Partial interface MLGraphBuilder[2]: member names are unique
-PASS Partial interface MLGraphBuilder[3]: original interface defined
-PASS Partial interface MLGraphBuilder[3]: member names are unique
-PASS Partial interface MLGraphBuilder[4]: original interface defined
-PASS Partial interface MLGraphBuilder[4]: member names are unique
-PASS Partial interface MLGraphBuilder[5]: original interface defined
-PASS Partial interface MLGraphBuilder[5]: member names are unique
-PASS Partial interface MLGraphBuilder[6]: original interface defined
-PASS Partial interface MLGraphBuilder[6]: member names are unique
-PASS Partial interface MLGraphBuilder[7]: original interface defined
-PASS Partial interface MLGraphBuilder[7]: member names are unique
-PASS Partial interface MLGraphBuilder[8]: original interface defined
-PASS Partial interface MLGraphBuilder[8]: member names are unique
-PASS Partial interface MLGraphBuilder[9]: original interface defined
-PASS Partial interface MLGraphBuilder[9]: member names are unique
-PASS Partial interface MLGraphBuilder[10]: original interface defined
-PASS Partial interface MLGraphBuilder[10]: member names are unique
-PASS Partial interface MLGraphBuilder[11]: original interface defined
-PASS Partial interface MLGraphBuilder[11]: member names are unique
-PASS Partial interface MLGraphBuilder[12]: original interface defined
-PASS Partial interface MLGraphBuilder[12]: member names are unique
-PASS Partial interface MLGraphBuilder[13]: original interface defined
-PASS Partial interface MLGraphBuilder[13]: member names are unique
-PASS Partial interface MLGraphBuilder[14]: original interface defined
-PASS Partial interface MLGraphBuilder[14]: member names are unique
-PASS Partial interface MLGraphBuilder[15]: original interface defined
-PASS Partial interface MLGraphBuilder[15]: member names are unique
-PASS Partial interface MLGraphBuilder[16]: original interface defined
-PASS Partial interface MLGraphBuilder[16]: member names are unique
-PASS Partial interface MLGraphBuilder[17]: original interface defined
-PASS Partial interface MLGraphBuilder[17]: member names are unique
-PASS Partial interface MLGraphBuilder[18]: original interface defined
-PASS Partial interface MLGraphBuilder[18]: member names are unique
-PASS Partial interface MLGraphBuilder[19]: original interface defined
-PASS Partial interface MLGraphBuilder[19]: member names are unique
-PASS Partial interface MLGraphBuilder[20]: original interface defined
-PASS Partial interface MLGraphBuilder[20]: member names are unique
-PASS Partial interface MLGraphBuilder[21]: original interface defined
-PASS Partial interface MLGraphBuilder[21]: member names are unique
-PASS Partial interface MLGraphBuilder[22]: original interface defined
-PASS Partial interface MLGraphBuilder[22]: member names are unique
-PASS Partial interface MLGraphBuilder[23]: original interface defined
-PASS Partial interface MLGraphBuilder[23]: member names are unique
-PASS Partial interface MLGraphBuilder[24]: original interface defined
-PASS Partial interface MLGraphBuilder[24]: member names are unique
-PASS Partial interface MLGraphBuilder[25]: original interface defined
-PASS Partial interface MLGraphBuilder[25]: member names are unique
-PASS Partial interface MLGraphBuilder[26]: original interface defined
-PASS Partial interface MLGraphBuilder[26]: member names are unique
-PASS Partial interface MLGraphBuilder[27]: original interface defined
-PASS Partial interface MLGraphBuilder[27]: member names are unique
-PASS Partial interface MLGraphBuilder[28]: original interface defined
-PASS Partial interface MLGraphBuilder[28]: member names are unique
-PASS Partial interface MLGraphBuilder[29]: original interface defined
-PASS Partial interface MLGraphBuilder[29]: member names are unique
-PASS Partial interface MLGraphBuilder[30]: original interface defined
-PASS Partial interface MLGraphBuilder[30]: member names are unique
-PASS Partial interface MLGraphBuilder[31]: original interface defined
-PASS Partial interface MLGraphBuilder[31]: member names are unique
-PASS Partial interface MLGraphBuilder[32]: original interface defined
-PASS Partial interface MLGraphBuilder[32]: member names are unique
-PASS Partial interface MLGraphBuilder[33]: original interface defined
-PASS Partial interface MLGraphBuilder[33]: member names are unique
-PASS Partial interface MLGraphBuilder[34]: original interface defined
-PASS Partial interface MLGraphBuilder[34]: member names are unique
-PASS Partial interface Navigator: member names are unique
-PASS Partial interface mixin NavigatorID: member names are unique
-PASS Navigator includes NavigatorML: member names are unique
-PASS WorkerNavigator includes NavigatorML: member names are unique
-PASS Navigator includes NavigatorID: member names are unique
-PASS Navigator includes NavigatorLanguage: member names are unique
-PASS Navigator includes NavigatorOnLine: member names are unique
-PASS Navigator includes NavigatorContentUtils: member names are unique
-PASS Navigator includes NavigatorCookies: member names are unique
-PASS Navigator includes NavigatorPlugins: member names are unique
-PASS Navigator includes NavigatorConcurrentHardware: member names are unique
-PASS WorkerNavigator includes NavigatorID: member names are unique
-PASS WorkerNavigator includes NavigatorLanguage: member names are unique
-PASS WorkerNavigator includes NavigatorOnLine: member names are unique
-PASS WorkerNavigator includes NavigatorConcurrentHardware: member names are unique
-PASS Navigator includes NavigatorGPU: member names are unique
-PASS WorkerNavigator includes NavigatorGPU: member names are unique
-PASS GPUBuffer includes GPUObjectBase: member names are unique
-PASS GPUTexture includes GPUObjectBase: member names are unique
-FAIL NavigatorML must be primary interface of navigator assert_own_property: self does not have own property "NavigatorML" expected property "NavigatorML" missing
-FAIL Stringification of navigator assert_class_string: class string of navigator expected "[object NavigatorML]" but got "[object Navigator]"
-PASS NavigatorML interface: navigator must inherit property "ml" with the proper type
-PASS ML interface: existence and properties of interface object
-PASS ML interface object length
-PASS ML interface object name
-PASS ML interface: existence and properties of interface prototype object
-PASS ML interface: existence and properties of interface prototype object's "constructor" property
-PASS ML interface: existence and properties of interface prototype object's @@unscopables property
-PASS ML interface: operation createContext(optional MLContextOptions)
-PASS ML interface: operation createContext(GPUDevice)
-PASS ML interface: member createContextSync
-PASS ML must be primary interface of navigator.ml
-PASS Stringification of navigator.ml
-PASS ML interface: navigator.ml must inherit property "createContext(optional MLContextOptions)" with the proper type
-PASS ML interface: calling createContext(optional MLContextOptions) on navigator.ml with too few arguments must throw TypeError
-PASS ML interface: navigator.ml must inherit property "createContext(GPUDevice)" with the proper type
-PASS ML interface: calling createContext(GPUDevice) on navigator.ml with too few arguments must throw TypeError
-PASS ML interface: navigator.ml must not have property "createContextSync"
-PASS MLGraph interface: existence and properties of interface object
-PASS MLGraph interface object length
-PASS MLGraph interface object name
-PASS MLGraph interface: existence and properties of interface prototype object
-PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
-FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-PASS MLOperand interface: existence and properties of interface object
-PASS MLOperand interface object length
-PASS MLOperand interface object name
-PASS MLOperand interface: existence and properties of interface prototype object
-PASS MLOperand interface: existence and properties of interface prototype object's "constructor" property
-PASS MLOperand interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLOperand must be primary interface of input
-PASS Stringification of input
-PASS MLOperand must be primary interface of filter
-PASS Stringification of filter
-PASS MLOperand must be primary interface of output
-PASS Stringification of output
-FAIL MLActivation interface: existence and properties of interface object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface object length assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface object name assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation must be primary interface of relu assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL Stringification of relu assert_class_string: class string of relu expected "[object MLActivation]" but got "[object MLOperator]"
-PASS MLContext interface: existence and properties of interface object
-PASS MLContext interface object length
-PASS MLContext interface object name
-PASS MLContext interface: existence and properties of interface prototype object
-PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
-PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLContext interface: member computeSync
-PASS MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)
-FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
-PASS MLContext must be primary interface of context
-PASS Stringification of context
-PASS MLContext interface: context must not have property "computeSync"
-PASS MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type
-PASS MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError
-FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
-FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-PASS MLGraphBuilder interface: existence and properties of interface object
-PASS MLGraphBuilder interface object length
-PASS MLGraphBuilder interface object name
-PASS MLGraphBuilder interface: existence and properties of interface prototype object
-PASS MLGraphBuilder interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraphBuilder interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLGraphBuilder interface: operation input(DOMString, MLOperandDescriptor)
-FAIL MLGraphBuilder interface: operation constant(MLOperandDescriptor, MLBufferView) assert_equals: property has wrong .length expected 1 but got 2
-FAIL MLGraphBuilder interface: operation constant(double, optional MLOperandType) assert_equals: property has wrong .length expected 1 but got 2
-PASS MLGraphBuilder interface: operation build(MLNamedOperands)
-PASS MLGraphBuilder interface: member buildSync
-FAIL MLGraphBuilder interface: operation batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions) assert_own_property: interface prototype object missing non-static operation expected property "batchNormalization" missing
-PASS MLGraphBuilder interface: operation clamp(MLOperand, optional MLClampOptions)
-PASS MLGraphBuilder interface: operation clamp(optional MLClampOptions)
-FAIL MLGraphBuilder interface: operation concat(sequence<MLOperand>, long) assert_own_property: interface prototype object missing non-static operation expected property "concat" missing
-PASS MLGraphBuilder interface: operation conv2d(MLOperand, MLOperand, optional MLConv2dOptions)
-FAIL MLGraphBuilder interface: operation convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "convTranspose2d" missing
-PASS MLGraphBuilder interface: operation add(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation sub(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation mul(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation div(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation max(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation min(MLOperand, MLOperand)
-FAIL MLGraphBuilder interface: operation pow(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "pow" missing
-FAIL MLGraphBuilder interface: operation abs(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "abs" missing
-FAIL MLGraphBuilder interface: operation ceil(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "ceil" missing
-FAIL MLGraphBuilder interface: operation cos(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "cos" missing
-FAIL MLGraphBuilder interface: operation exp(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "exp" missing
-FAIL MLGraphBuilder interface: operation floor(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "floor" missing
-FAIL MLGraphBuilder interface: operation log(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "log" missing
-FAIL MLGraphBuilder interface: operation neg(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "neg" missing
-FAIL MLGraphBuilder interface: operation sin(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "sin" missing
-FAIL MLGraphBuilder interface: operation tan(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "tan" missing
-FAIL MLGraphBuilder interface: operation elu(MLOperand, optional MLEluOptions) assert_own_property: interface prototype object missing non-static operation expected property "elu" missing
-FAIL MLGraphBuilder interface: operation elu(optional MLEluOptions) assert_own_property: interface prototype object missing non-static operation expected property "elu" missing
-PASS MLGraphBuilder interface: operation gemm(MLOperand, MLOperand, optional MLGemmOptions)
-FAIL MLGraphBuilder interface: operation gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions) assert_own_property: interface prototype object missing non-static operation expected property "gru" missing
-FAIL MLGraphBuilder interface: operation gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "gruCell" missing
-FAIL MLGraphBuilder interface: operation hardSigmoid(MLOperand, optional MLHardSigmoidOptions) assert_own_property: interface prototype object missing non-static operation expected property "hardSigmoid" missing
-FAIL MLGraphBuilder interface: operation hardSigmoid(optional MLHardSigmoidOptions) assert_own_property: interface prototype object missing non-static operation expected property "hardSigmoid" missing
-PASS MLGraphBuilder interface: operation hardSwish(MLOperand)
-PASS MLGraphBuilder interface: operation hardSwish()
-FAIL MLGraphBuilder interface: operation instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions) assert_own_property: interface prototype object missing non-static operation expected property "instanceNormalization" missing
-FAIL MLGraphBuilder interface: operation leakyRelu(MLOperand, optional MLLeakyReluOptions) assert_own_property: interface prototype object missing non-static operation expected property "leakyRelu" missing
-FAIL MLGraphBuilder interface: operation leakyRelu(optional MLLeakyReluOptions) assert_own_property: interface prototype object missing non-static operation expected property "leakyRelu" missing
-FAIL MLGraphBuilder interface: operation linear(MLOperand, optional MLLinearOptions) assert_own_property: interface prototype object missing non-static operation expected property "linear" missing
-FAIL MLGraphBuilder interface: operation linear(optional MLLinearOptions) assert_own_property: interface prototype object missing non-static operation expected property "linear" missing
-FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
-FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
-FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
-PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
-FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
-PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
-FAIL MLGraphBuilder interface: operation reduceL1(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceL1" missing
-FAIL MLGraphBuilder interface: operation reduceL2(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceL2" missing
-FAIL MLGraphBuilder interface: operation reduceLogSum(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceLogSum" missing
-FAIL MLGraphBuilder interface: operation reduceLogSumExp(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceLogSumExp" missing
-FAIL MLGraphBuilder interface: operation reduceMax(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMax" missing
-FAIL MLGraphBuilder interface: operation reduceMean(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMean" missing
-FAIL MLGraphBuilder interface: operation reduceMin(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMin" missing
-FAIL MLGraphBuilder interface: operation reduceProduct(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceProduct" missing
-FAIL MLGraphBuilder interface: operation reduceSum(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceSum" missing
-FAIL MLGraphBuilder interface: operation reduceSumSquare(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceSumSquare" missing
-PASS MLGraphBuilder interface: operation relu(MLOperand)
-PASS MLGraphBuilder interface: operation relu()
-PASS MLGraphBuilder interface: operation resample2d(MLOperand, optional MLResample2dOptions)
-PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
-PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
-PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
-FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
-FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
-FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
-FAIL MLGraphBuilder interface: operation softplus(optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
-FAIL MLGraphBuilder interface: operation softsign(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "softsign" missing
-FAIL MLGraphBuilder interface: operation softsign() assert_own_property: interface prototype object missing non-static operation expected property "softsign" missing
-FAIL MLGraphBuilder interface: operation split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions) assert_own_property: interface prototype object missing non-static operation expected property "split" missing
-FAIL MLGraphBuilder interface: operation squeeze(MLOperand, optional MLSqueezeOptions) assert_own_property: interface prototype object missing non-static operation expected property "squeeze" missing
-FAIL MLGraphBuilder interface: operation tanh(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "tanh" missing
-FAIL MLGraphBuilder interface: operation tanh() assert_own_property: interface prototype object missing non-static operation expected property "tanh" missing
-FAIL MLGraphBuilder interface: operation transpose(MLOperand, optional MLTransposeOptions) assert_own_property: interface prototype object missing non-static operation expected property "transpose" missing
-PASS MLGraphBuilder must be primary interface of builder
-PASS Stringification of builder
-PASS MLGraphBuilder interface: builder must inherit property "input(DOMString, MLOperandDescriptor)" with the proper type
-PASS MLGraphBuilder interface: calling input(DOMString, MLOperandDescriptor) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "constant(MLOperandDescriptor, MLBufferView)" with the proper type
-PASS MLGraphBuilder interface: calling constant(MLOperandDescriptor, MLBufferView) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "constant(double, optional MLOperandType)" with the proper type
-PASS MLGraphBuilder interface: calling constant(double, optional MLOperandType) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "build(MLNamedOperands)" with the proper type
-PASS MLGraphBuilder interface: calling build(MLNamedOperands) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must not have property "buildSync"
-FAIL MLGraphBuilder interface: builder must inherit property "batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions)" with the proper type assert_inherits: property "batchNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: calling batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions) on builder with too few arguments must throw TypeError assert_inherits: property "batchNormalization" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "clamp(MLOperand, optional MLClampOptions)" with the proper type
-PASS MLGraphBuilder interface: calling clamp(MLOperand, optional MLClampOptions) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "clamp(optional MLClampOptions)" with the proper type
-PASS MLGraphBuilder interface: calling clamp(optional MLClampOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "concat(sequence<MLOperand>, long)" with the proper type assert_inherits: property "concat" not found in prototype chain
-FAIL MLGraphBuilder interface: calling concat(sequence<MLOperand>, long) on builder with too few arguments must throw TypeError assert_inherits: property "concat" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "conv2d(MLOperand, MLOperand, optional MLConv2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling conv2d(MLOperand, MLOperand, optional MLConv2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions)" with the proper type assert_inherits: property "convTranspose2d" not found in prototype chain
-FAIL MLGraphBuilder interface: calling convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions) on builder with too few arguments must throw TypeError assert_inherits: property "convTranspose2d" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "add(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling add(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sub(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling sub(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "mul(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling mul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "div(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling div(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "max(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling max(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "min(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling min(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "pow(MLOperand, MLOperand)" with the proper type assert_inherits: property "pow" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pow(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "pow" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "abs(MLOperand)" with the proper type assert_inherits: property "abs" not found in prototype chain
-FAIL MLGraphBuilder interface: calling abs(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "abs" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "ceil(MLOperand)" with the proper type assert_inherits: property "ceil" not found in prototype chain
-FAIL MLGraphBuilder interface: calling ceil(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "ceil" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "cos(MLOperand)" with the proper type assert_inherits: property "cos" not found in prototype chain
-FAIL MLGraphBuilder interface: calling cos(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "cos" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "exp(MLOperand)" with the proper type assert_inherits: property "exp" not found in prototype chain
-FAIL MLGraphBuilder interface: calling exp(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "exp" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "floor(MLOperand)" with the proper type assert_inherits: property "floor" not found in prototype chain
-FAIL MLGraphBuilder interface: calling floor(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "floor" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "log(MLOperand)" with the proper type assert_inherits: property "log" not found in prototype chain
-FAIL MLGraphBuilder interface: calling log(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "log" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "neg(MLOperand)" with the proper type assert_inherits: property "neg" not found in prototype chain
-FAIL MLGraphBuilder interface: calling neg(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "neg" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "sin(MLOperand)" with the proper type assert_inherits: property "sin" not found in prototype chain
-FAIL MLGraphBuilder interface: calling sin(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "sin" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tan(MLOperand)" with the proper type assert_inherits: property "tan" not found in prototype chain
-FAIL MLGraphBuilder interface: calling tan(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "tan" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "elu(MLOperand, optional MLEluOptions)" with the proper type assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling elu(MLOperand, optional MLEluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "elu(optional MLEluOptions)" with the proper type assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling elu(optional MLEluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "elu" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "gemm(MLOperand, MLOperand, optional MLGemmOptions)" with the proper type
-PASS MLGraphBuilder interface: calling gemm(MLOperand, MLOperand, optional MLGemmOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions)" with the proper type assert_inherits: property "gru" not found in prototype chain
-FAIL MLGraphBuilder interface: calling gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions) on builder with too few arguments must throw TypeError assert_inherits: property "gru" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions)" with the proper type assert_inherits: property "gruCell" not found in prototype chain
-FAIL MLGraphBuilder interface: calling gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "gruCell" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "hardSigmoid(MLOperand, optional MLHardSigmoidOptions)" with the proper type assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: calling hardSigmoid(MLOperand, optional MLHardSigmoidOptions) on builder with too few arguments must throw TypeError assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "hardSigmoid(optional MLHardSigmoidOptions)" with the proper type assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: calling hardSigmoid(optional MLHardSigmoidOptions) on builder with too few arguments must throw TypeError assert_inherits: property "hardSigmoid" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "hardSwish(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling hardSwish(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "hardSwish()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions)" with the proper type assert_inherits: property "instanceNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: calling instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions) on builder with too few arguments must throw TypeError assert_inherits: property "instanceNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "leakyRelu(MLOperand, optional MLLeakyReluOptions)" with the proper type assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling leakyRelu(MLOperand, optional MLLeakyReluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "leakyRelu(optional MLLeakyReluOptions)" with the proper type assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling leakyRelu(optional MLLeakyReluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "linear(MLOperand, optional MLLinearOptions)" with the proper type assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: calling linear(MLOperand, optional MLLinearOptions) on builder with too few arguments must throw TypeError assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "linear(optional MLLinearOptions)" with the proper type assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: calling linear(optional MLLinearOptions) on builder with too few arguments must throw TypeError assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions)" with the proper type assert_inherits: property "lstm" not found in prototype chain
-FAIL MLGraphBuilder interface: calling lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstm" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions)" with the proper type assert_inherits: property "lstmCell" not found in prototype chain
-FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
-FAIL MLGraphBuilder interface: calling l2Pool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError assert_inherits: property "l2Pool2d" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "maxPool2d(MLOperand, optional MLPool2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling maxPool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "reduceL1(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceL1" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceL1(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceL1" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceL2(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceL2" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceL2(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceL2" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceLogSum(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceLogSum" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceLogSum(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceLogSum" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceLogSumExp(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceLogSumExp" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceLogSumExp(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceLogSumExp" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMax(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMax" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMax(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMax" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMean(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMean" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMean(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMean" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMin(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMin" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMin(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMin" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceProduct(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceProduct" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceProduct(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceProduct" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceSum(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceSum" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceSum(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceSum" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceSumSquare(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceSumSquare" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceSumSquare(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceSumSquare" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "relu(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling relu(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "relu()" with the proper type
-PASS MLGraphBuilder interface: builder must inherit property "resample2d(MLOperand, optional MLResample2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling resample2d(MLOperand, optional MLResample2dOptions) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "reshape(MLOperand, sequence<unsigned long?>)" with the proper type
-PASS MLGraphBuilder interface: calling reshape(MLOperand, sequence<unsigned long?>) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "softplus(MLOperand, optional MLSoftplusOptions)" with the proper type assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softplus(MLOperand, optional MLSoftplusOptions) on builder with too few arguments must throw TypeError assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softplus(optional MLSoftplusOptions)" with the proper type assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softplus(optional MLSoftplusOptions) on builder with too few arguments must throw TypeError assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softsign(MLOperand)" with the proper type assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softsign(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softsign()" with the proper type assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions)" with the proper type assert_inherits: property "split" not found in prototype chain
-FAIL MLGraphBuilder interface: calling split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions) on builder with too few arguments must throw TypeError assert_inherits: property "split" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "squeeze(MLOperand, optional MLSqueezeOptions)" with the proper type assert_inherits: property "squeeze" not found in prototype chain
-FAIL MLGraphBuilder interface: calling squeeze(MLOperand, optional MLSqueezeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "squeeze" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tanh(MLOperand)" with the proper type assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: calling tanh(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tanh()" with the proper type assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "transpose(MLOperand, optional MLTransposeOptions)" with the proper type assert_inherits: property "transpose" not found in prototype chain
-FAIL MLGraphBuilder interface: calling transpose(MLOperand, optional MLTransposeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "transpose" not found in prototype chain
-PASS Navigator interface: attribute ml
-PASS Navigator interface: navigator must inherit property "ml" with the proper type
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any.worker-expected.txt
deleted file mode 100644
index a4c52718..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ /dev/null
@@ -1,413 +0,0 @@
-This is a testharness.js-based test.
-Found 409 tests; 235 PASS, 174 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented"
-PASS idl_test validation
-PASS Partial interface MLContext: original interface defined
-PASS Partial interface MLContext: member names are unique
-PASS Partial interface MLContext[2]: original interface defined
-PASS Partial interface MLContext[2]: member names are unique
-PASS Partial interface MLContext[3]: original interface defined
-PASS Partial interface MLContext[3]: member names are unique
-PASS Partial interface MLCommandEncoder: original interface defined
-PASS Partial interface MLCommandEncoder: member names are unique
-PASS Partial interface MLCommandEncoder[2]: original interface defined
-PASS Partial interface MLCommandEncoder[2]: member names are unique
-PASS Partial interface MLCommandEncoder[3]: original interface defined
-PASS Partial interface MLCommandEncoder[3]: member names are unique
-PASS Partial interface MLGraphBuilder: original interface defined
-PASS Partial interface MLGraphBuilder: member names are unique
-PASS Partial interface MLGraphBuilder[2]: original interface defined
-PASS Partial interface MLGraphBuilder[2]: member names are unique
-PASS Partial interface MLGraphBuilder[3]: original interface defined
-PASS Partial interface MLGraphBuilder[3]: member names are unique
-PASS Partial interface MLGraphBuilder[4]: original interface defined
-PASS Partial interface MLGraphBuilder[4]: member names are unique
-PASS Partial interface MLGraphBuilder[5]: original interface defined
-PASS Partial interface MLGraphBuilder[5]: member names are unique
-PASS Partial interface MLGraphBuilder[6]: original interface defined
-PASS Partial interface MLGraphBuilder[6]: member names are unique
-PASS Partial interface MLGraphBuilder[7]: original interface defined
-PASS Partial interface MLGraphBuilder[7]: member names are unique
-PASS Partial interface MLGraphBuilder[8]: original interface defined
-PASS Partial interface MLGraphBuilder[8]: member names are unique
-PASS Partial interface MLGraphBuilder[9]: original interface defined
-PASS Partial interface MLGraphBuilder[9]: member names are unique
-PASS Partial interface MLGraphBuilder[10]: original interface defined
-PASS Partial interface MLGraphBuilder[10]: member names are unique
-PASS Partial interface MLGraphBuilder[11]: original interface defined
-PASS Partial interface MLGraphBuilder[11]: member names are unique
-PASS Partial interface MLGraphBuilder[12]: original interface defined
-PASS Partial interface MLGraphBuilder[12]: member names are unique
-PASS Partial interface MLGraphBuilder[13]: original interface defined
-PASS Partial interface MLGraphBuilder[13]: member names are unique
-PASS Partial interface MLGraphBuilder[14]: original interface defined
-PASS Partial interface MLGraphBuilder[14]: member names are unique
-PASS Partial interface MLGraphBuilder[15]: original interface defined
-PASS Partial interface MLGraphBuilder[15]: member names are unique
-PASS Partial interface MLGraphBuilder[16]: original interface defined
-PASS Partial interface MLGraphBuilder[16]: member names are unique
-PASS Partial interface MLGraphBuilder[17]: original interface defined
-PASS Partial interface MLGraphBuilder[17]: member names are unique
-PASS Partial interface MLGraphBuilder[18]: original interface defined
-PASS Partial interface MLGraphBuilder[18]: member names are unique
-PASS Partial interface MLGraphBuilder[19]: original interface defined
-PASS Partial interface MLGraphBuilder[19]: member names are unique
-PASS Partial interface MLGraphBuilder[20]: original interface defined
-PASS Partial interface MLGraphBuilder[20]: member names are unique
-PASS Partial interface MLGraphBuilder[21]: original interface defined
-PASS Partial interface MLGraphBuilder[21]: member names are unique
-PASS Partial interface MLGraphBuilder[22]: original interface defined
-PASS Partial interface MLGraphBuilder[22]: member names are unique
-PASS Partial interface MLGraphBuilder[23]: original interface defined
-PASS Partial interface MLGraphBuilder[23]: member names are unique
-PASS Partial interface MLGraphBuilder[24]: original interface defined
-PASS Partial interface MLGraphBuilder[24]: member names are unique
-PASS Partial interface MLGraphBuilder[25]: original interface defined
-PASS Partial interface MLGraphBuilder[25]: member names are unique
-PASS Partial interface MLGraphBuilder[26]: original interface defined
-PASS Partial interface MLGraphBuilder[26]: member names are unique
-PASS Partial interface MLGraphBuilder[27]: original interface defined
-PASS Partial interface MLGraphBuilder[27]: member names are unique
-PASS Partial interface MLGraphBuilder[28]: original interface defined
-PASS Partial interface MLGraphBuilder[28]: member names are unique
-PASS Partial interface MLGraphBuilder[29]: original interface defined
-PASS Partial interface MLGraphBuilder[29]: member names are unique
-PASS Partial interface MLGraphBuilder[30]: original interface defined
-PASS Partial interface MLGraphBuilder[30]: member names are unique
-PASS Partial interface MLGraphBuilder[31]: original interface defined
-PASS Partial interface MLGraphBuilder[31]: member names are unique
-PASS Partial interface MLGraphBuilder[32]: original interface defined
-PASS Partial interface MLGraphBuilder[32]: member names are unique
-PASS Partial interface MLGraphBuilder[33]: original interface defined
-PASS Partial interface MLGraphBuilder[33]: member names are unique
-PASS Partial interface MLGraphBuilder[34]: original interface defined
-PASS Partial interface MLGraphBuilder[34]: member names are unique
-PASS Partial interface Navigator: member names are unique
-PASS Partial interface mixin NavigatorID: member names are unique
-PASS Navigator includes NavigatorML: member names are unique
-PASS WorkerNavigator includes NavigatorML: member names are unique
-PASS Navigator includes NavigatorID: member names are unique
-PASS Navigator includes NavigatorLanguage: member names are unique
-PASS Navigator includes NavigatorOnLine: member names are unique
-PASS Navigator includes NavigatorContentUtils: member names are unique
-PASS Navigator includes NavigatorCookies: member names are unique
-PASS Navigator includes NavigatorPlugins: member names are unique
-PASS Navigator includes NavigatorConcurrentHardware: member names are unique
-PASS WorkerNavigator includes NavigatorID: member names are unique
-PASS WorkerNavigator includes NavigatorLanguage: member names are unique
-PASS WorkerNavigator includes NavigatorOnLine: member names are unique
-PASS WorkerNavigator includes NavigatorConcurrentHardware: member names are unique
-PASS Navigator includes NavigatorGPU: member names are unique
-PASS WorkerNavigator includes NavigatorGPU: member names are unique
-PASS GPUBuffer includes GPUObjectBase: member names are unique
-PASS GPUTexture includes GPUObjectBase: member names are unique
-FAIL NavigatorML must be primary interface of navigator assert_own_property: self does not have own property "NavigatorML" expected property "NavigatorML" missing
-FAIL Stringification of navigator assert_class_string: class string of navigator expected "[object NavigatorML]" but got "[object WorkerNavigator]"
-FAIL NavigatorML interface: navigator must not have property "ml" assert_false: expected false got true
-PASS ML interface: existence and properties of interface object
-PASS ML interface object length
-PASS ML interface object name
-PASS ML interface: existence and properties of interface prototype object
-PASS ML interface: existence and properties of interface prototype object's "constructor" property
-PASS ML interface: existence and properties of interface prototype object's @@unscopables property
-PASS ML interface: operation createContext(optional MLContextOptions)
-PASS ML interface: operation createContext(GPUDevice)
-PASS ML interface: operation createContextSync(optional MLContextOptions)
-PASS ML interface: operation createContextSync(GPUDevice)
-PASS ML must be primary interface of navigator.ml
-PASS Stringification of navigator.ml
-PASS ML interface: navigator.ml must inherit property "createContext(optional MLContextOptions)" with the proper type
-PASS ML interface: calling createContext(optional MLContextOptions) on navigator.ml with too few arguments must throw TypeError
-PASS ML interface: navigator.ml must inherit property "createContext(GPUDevice)" with the proper type
-PASS ML interface: calling createContext(GPUDevice) on navigator.ml with too few arguments must throw TypeError
-PASS ML interface: navigator.ml must inherit property "createContextSync(optional MLContextOptions)" with the proper type
-PASS ML interface: calling createContextSync(optional MLContextOptions) on navigator.ml with too few arguments must throw TypeError
-PASS ML interface: navigator.ml must inherit property "createContextSync(GPUDevice)" with the proper type
-PASS ML interface: calling createContextSync(GPUDevice) on navigator.ml with too few arguments must throw TypeError
-PASS MLGraph interface: existence and properties of interface object
-PASS MLGraph interface object length
-PASS MLGraph interface object name
-PASS MLGraph interface: existence and properties of interface prototype object
-PASS MLGraph interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraph interface: existence and properties of interface prototype object's @@unscopables property
-FAIL MLGraph must be primary interface of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-FAIL Stringification of graph assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined"
-PASS MLOperand interface: existence and properties of interface object
-PASS MLOperand interface object length
-PASS MLOperand interface object name
-PASS MLOperand interface: existence and properties of interface prototype object
-PASS MLOperand interface: existence and properties of interface prototype object's "constructor" property
-PASS MLOperand interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLOperand must be primary interface of input
-PASS Stringification of input
-PASS MLOperand must be primary interface of filter
-PASS Stringification of filter
-PASS MLOperand must be primary interface of output
-PASS Stringification of output
-FAIL MLActivation interface: existence and properties of interface object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface object length assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface object name assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL MLActivation must be primary interface of relu assert_own_property: self does not have own property "MLActivation" expected property "MLActivation" missing
-FAIL Stringification of relu assert_class_string: class string of relu expected "[object MLActivation]" but got "[object MLOperator]"
-PASS MLContext interface: existence and properties of interface object
-PASS MLContext interface object length
-PASS MLContext interface object name
-PASS MLContext interface: existence and properties of interface prototype object
-PASS MLContext interface: existence and properties of interface prototype object's "constructor" property
-PASS MLContext interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLContext interface: operation computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)
-PASS MLContext interface: operation compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)
-FAIL MLContext interface: operation createCommandEncoder() assert_own_property: interface prototype object missing non-static operation expected property "createCommandEncoder" missing
-PASS MLContext must be primary interface of context
-PASS Stringification of context
-PASS MLContext interface: context must inherit property "computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type
-PASS MLContext interface: calling computeSync(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError
-PASS MLContext interface: context must inherit property "compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews)" with the proper type
-PASS MLContext interface: calling compute(MLGraph, MLNamedArrayBufferViews, MLNamedArrayBufferViews) on context with too few arguments must throw TypeError
-FAIL MLContext interface: context must inherit property "createCommandEncoder()" with the proper type assert_inherits: property "createCommandEncoder" not found in prototype chain
-FAIL MLCommandEncoder interface: existence and properties of interface object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object length assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface object name assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation initializeGraph(MLGraph) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation dispatch(MLGraph, MLNamedGPUResources, MLNamedGPUResources) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-FAIL MLCommandEncoder interface: operation finish(optional GPUCommandBufferDescriptor) assert_own_property: self does not have own property "MLCommandEncoder" expected property "MLCommandEncoder" missing
-PASS MLGraphBuilder interface: existence and properties of interface object
-PASS MLGraphBuilder interface object length
-PASS MLGraphBuilder interface object name
-PASS MLGraphBuilder interface: existence and properties of interface prototype object
-PASS MLGraphBuilder interface: existence and properties of interface prototype object's "constructor" property
-PASS MLGraphBuilder interface: existence and properties of interface prototype object's @@unscopables property
-PASS MLGraphBuilder interface: operation input(DOMString, MLOperandDescriptor)
-FAIL MLGraphBuilder interface: operation constant(MLOperandDescriptor, MLBufferView) assert_equals: property has wrong .length expected 1 but got 2
-FAIL MLGraphBuilder interface: operation constant(double, optional MLOperandType) assert_equals: property has wrong .length expected 1 but got 2
-PASS MLGraphBuilder interface: operation build(MLNamedOperands)
-PASS MLGraphBuilder interface: operation buildSync(MLNamedOperands)
-FAIL MLGraphBuilder interface: operation batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions) assert_own_property: interface prototype object missing non-static operation expected property "batchNormalization" missing
-PASS MLGraphBuilder interface: operation clamp(MLOperand, optional MLClampOptions)
-PASS MLGraphBuilder interface: operation clamp(optional MLClampOptions)
-FAIL MLGraphBuilder interface: operation concat(sequence<MLOperand>, long) assert_own_property: interface prototype object missing non-static operation expected property "concat" missing
-PASS MLGraphBuilder interface: operation conv2d(MLOperand, MLOperand, optional MLConv2dOptions)
-FAIL MLGraphBuilder interface: operation convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "convTranspose2d" missing
-PASS MLGraphBuilder interface: operation add(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation sub(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation mul(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation div(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation max(MLOperand, MLOperand)
-PASS MLGraphBuilder interface: operation min(MLOperand, MLOperand)
-FAIL MLGraphBuilder interface: operation pow(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "pow" missing
-FAIL MLGraphBuilder interface: operation abs(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "abs" missing
-FAIL MLGraphBuilder interface: operation ceil(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "ceil" missing
-FAIL MLGraphBuilder interface: operation cos(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "cos" missing
-FAIL MLGraphBuilder interface: operation exp(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "exp" missing
-FAIL MLGraphBuilder interface: operation floor(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "floor" missing
-FAIL MLGraphBuilder interface: operation log(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "log" missing
-FAIL MLGraphBuilder interface: operation neg(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "neg" missing
-FAIL MLGraphBuilder interface: operation sin(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "sin" missing
-FAIL MLGraphBuilder interface: operation tan(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "tan" missing
-FAIL MLGraphBuilder interface: operation elu(MLOperand, optional MLEluOptions) assert_own_property: interface prototype object missing non-static operation expected property "elu" missing
-FAIL MLGraphBuilder interface: operation elu(optional MLEluOptions) assert_own_property: interface prototype object missing non-static operation expected property "elu" missing
-PASS MLGraphBuilder interface: operation gemm(MLOperand, MLOperand, optional MLGemmOptions)
-FAIL MLGraphBuilder interface: operation gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions) assert_own_property: interface prototype object missing non-static operation expected property "gru" missing
-FAIL MLGraphBuilder interface: operation gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "gruCell" missing
-FAIL MLGraphBuilder interface: operation hardSigmoid(MLOperand, optional MLHardSigmoidOptions) assert_own_property: interface prototype object missing non-static operation expected property "hardSigmoid" missing
-FAIL MLGraphBuilder interface: operation hardSigmoid(optional MLHardSigmoidOptions) assert_own_property: interface prototype object missing non-static operation expected property "hardSigmoid" missing
-PASS MLGraphBuilder interface: operation hardSwish(MLOperand)
-PASS MLGraphBuilder interface: operation hardSwish()
-FAIL MLGraphBuilder interface: operation instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions) assert_own_property: interface prototype object missing non-static operation expected property "instanceNormalization" missing
-FAIL MLGraphBuilder interface: operation leakyRelu(MLOperand, optional MLLeakyReluOptions) assert_own_property: interface prototype object missing non-static operation expected property "leakyRelu" missing
-FAIL MLGraphBuilder interface: operation leakyRelu(optional MLLeakyReluOptions) assert_own_property: interface prototype object missing non-static operation expected property "leakyRelu" missing
-FAIL MLGraphBuilder interface: operation linear(MLOperand, optional MLLinearOptions) assert_own_property: interface prototype object missing non-static operation expected property "linear" missing
-FAIL MLGraphBuilder interface: operation linear(optional MLLinearOptions) assert_own_property: interface prototype object missing non-static operation expected property "linear" missing
-FAIL MLGraphBuilder interface: operation lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstm" missing
-FAIL MLGraphBuilder interface: operation lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) assert_own_property: interface prototype object missing non-static operation expected property "lstmCell" missing
-FAIL MLGraphBuilder interface: operation matmul(MLOperand, MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "matmul" missing
-FAIL MLGraphBuilder interface: operation pad(MLOperand, MLOperand, optional MLPadOptions) assert_own_property: interface prototype object missing non-static operation expected property "pad" missing
-PASS MLGraphBuilder interface: operation averagePool2d(MLOperand, optional MLPool2dOptions)
-FAIL MLGraphBuilder interface: operation l2Pool2d(MLOperand, optional MLPool2dOptions) assert_own_property: interface prototype object missing non-static operation expected property "l2Pool2d" missing
-PASS MLGraphBuilder interface: operation maxPool2d(MLOperand, optional MLPool2dOptions)
-FAIL MLGraphBuilder interface: operation reduceL1(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceL1" missing
-FAIL MLGraphBuilder interface: operation reduceL2(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceL2" missing
-FAIL MLGraphBuilder interface: operation reduceLogSum(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceLogSum" missing
-FAIL MLGraphBuilder interface: operation reduceLogSumExp(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceLogSumExp" missing
-FAIL MLGraphBuilder interface: operation reduceMax(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMax" missing
-FAIL MLGraphBuilder interface: operation reduceMean(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMean" missing
-FAIL MLGraphBuilder interface: operation reduceMin(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceMin" missing
-FAIL MLGraphBuilder interface: operation reduceProduct(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceProduct" missing
-FAIL MLGraphBuilder interface: operation reduceSum(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceSum" missing
-FAIL MLGraphBuilder interface: operation reduceSumSquare(MLOperand, optional MLReduceOptions) assert_own_property: interface prototype object missing non-static operation expected property "reduceSumSquare" missing
-PASS MLGraphBuilder interface: operation relu(MLOperand)
-PASS MLGraphBuilder interface: operation relu()
-PASS MLGraphBuilder interface: operation resample2d(MLOperand, optional MLResample2dOptions)
-PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
-PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
-PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
-FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
-FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
-FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
-FAIL MLGraphBuilder interface: operation softplus(optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
-FAIL MLGraphBuilder interface: operation softsign(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "softsign" missing
-FAIL MLGraphBuilder interface: operation softsign() assert_own_property: interface prototype object missing non-static operation expected property "softsign" missing
-FAIL MLGraphBuilder interface: operation split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions) assert_own_property: interface prototype object missing non-static operation expected property "split" missing
-FAIL MLGraphBuilder interface: operation squeeze(MLOperand, optional MLSqueezeOptions) assert_own_property: interface prototype object missing non-static operation expected property "squeeze" missing
-FAIL MLGraphBuilder interface: operation tanh(MLOperand) assert_own_property: interface prototype object missing non-static operation expected property "tanh" missing
-FAIL MLGraphBuilder interface: operation tanh() assert_own_property: interface prototype object missing non-static operation expected property "tanh" missing
-FAIL MLGraphBuilder interface: operation transpose(MLOperand, optional MLTransposeOptions) assert_own_property: interface prototype object missing non-static operation expected property "transpose" missing
-PASS MLGraphBuilder must be primary interface of builder
-PASS Stringification of builder
-PASS MLGraphBuilder interface: builder must inherit property "input(DOMString, MLOperandDescriptor)" with the proper type
-PASS MLGraphBuilder interface: calling input(DOMString, MLOperandDescriptor) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "constant(MLOperandDescriptor, MLBufferView)" with the proper type
-PASS MLGraphBuilder interface: calling constant(MLOperandDescriptor, MLBufferView) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "constant(double, optional MLOperandType)" with the proper type
-PASS MLGraphBuilder interface: calling constant(double, optional MLOperandType) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "build(MLNamedOperands)" with the proper type
-PASS MLGraphBuilder interface: calling build(MLNamedOperands) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "buildSync(MLNamedOperands)" with the proper type
-PASS MLGraphBuilder interface: calling buildSync(MLNamedOperands) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions)" with the proper type assert_inherits: property "batchNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: calling batchNormalization(MLOperand, MLOperand, MLOperand, optional MLBatchNormalizationOptions) on builder with too few arguments must throw TypeError assert_inherits: property "batchNormalization" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "clamp(MLOperand, optional MLClampOptions)" with the proper type
-PASS MLGraphBuilder interface: calling clamp(MLOperand, optional MLClampOptions) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "clamp(optional MLClampOptions)" with the proper type
-PASS MLGraphBuilder interface: calling clamp(optional MLClampOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "concat(sequence<MLOperand>, long)" with the proper type assert_inherits: property "concat" not found in prototype chain
-FAIL MLGraphBuilder interface: calling concat(sequence<MLOperand>, long) on builder with too few arguments must throw TypeError assert_inherits: property "concat" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "conv2d(MLOperand, MLOperand, optional MLConv2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling conv2d(MLOperand, MLOperand, optional MLConv2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions)" with the proper type assert_inherits: property "convTranspose2d" not found in prototype chain
-FAIL MLGraphBuilder interface: calling convTranspose2d(MLOperand, MLOperand, optional MLConvTranspose2dOptions) on builder with too few arguments must throw TypeError assert_inherits: property "convTranspose2d" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "add(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling add(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sub(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling sub(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "mul(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling mul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "div(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling div(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "max(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling max(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "min(MLOperand, MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling min(MLOperand, MLOperand) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "pow(MLOperand, MLOperand)" with the proper type assert_inherits: property "pow" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pow(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "pow" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "abs(MLOperand)" with the proper type assert_inherits: property "abs" not found in prototype chain
-FAIL MLGraphBuilder interface: calling abs(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "abs" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "ceil(MLOperand)" with the proper type assert_inherits: property "ceil" not found in prototype chain
-FAIL MLGraphBuilder interface: calling ceil(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "ceil" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "cos(MLOperand)" with the proper type assert_inherits: property "cos" not found in prototype chain
-FAIL MLGraphBuilder interface: calling cos(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "cos" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "exp(MLOperand)" with the proper type assert_inherits: property "exp" not found in prototype chain
-FAIL MLGraphBuilder interface: calling exp(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "exp" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "floor(MLOperand)" with the proper type assert_inherits: property "floor" not found in prototype chain
-FAIL MLGraphBuilder interface: calling floor(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "floor" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "log(MLOperand)" with the proper type assert_inherits: property "log" not found in prototype chain
-FAIL MLGraphBuilder interface: calling log(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "log" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "neg(MLOperand)" with the proper type assert_inherits: property "neg" not found in prototype chain
-FAIL MLGraphBuilder interface: calling neg(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "neg" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "sin(MLOperand)" with the proper type assert_inherits: property "sin" not found in prototype chain
-FAIL MLGraphBuilder interface: calling sin(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "sin" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tan(MLOperand)" with the proper type assert_inherits: property "tan" not found in prototype chain
-FAIL MLGraphBuilder interface: calling tan(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "tan" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "elu(MLOperand, optional MLEluOptions)" with the proper type assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling elu(MLOperand, optional MLEluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "elu(optional MLEluOptions)" with the proper type assert_inherits: property "elu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling elu(optional MLEluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "elu" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "gemm(MLOperand, MLOperand, optional MLGemmOptions)" with the proper type
-PASS MLGraphBuilder interface: calling gemm(MLOperand, MLOperand, optional MLGemmOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions)" with the proper type assert_inherits: property "gru" not found in prototype chain
-FAIL MLGraphBuilder interface: calling gru(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLGruOptions) on builder with too few arguments must throw TypeError assert_inherits: property "gru" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions)" with the proper type assert_inherits: property "gruCell" not found in prototype chain
-FAIL MLGraphBuilder interface: calling gruCell(MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLGruCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "gruCell" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "hardSigmoid(MLOperand, optional MLHardSigmoidOptions)" with the proper type assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: calling hardSigmoid(MLOperand, optional MLHardSigmoidOptions) on builder with too few arguments must throw TypeError assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "hardSigmoid(optional MLHardSigmoidOptions)" with the proper type assert_inherits: property "hardSigmoid" not found in prototype chain
-FAIL MLGraphBuilder interface: calling hardSigmoid(optional MLHardSigmoidOptions) on builder with too few arguments must throw TypeError assert_inherits: property "hardSigmoid" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "hardSwish(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling hardSwish(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "hardSwish()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions)" with the proper type assert_inherits: property "instanceNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: calling instanceNormalization(MLOperand, optional MLInstanceNormalizationOptions) on builder with too few arguments must throw TypeError assert_inherits: property "instanceNormalization" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "leakyRelu(MLOperand, optional MLLeakyReluOptions)" with the proper type assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling leakyRelu(MLOperand, optional MLLeakyReluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "leakyRelu(optional MLLeakyReluOptions)" with the proper type assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: calling leakyRelu(optional MLLeakyReluOptions) on builder with too few arguments must throw TypeError assert_inherits: property "leakyRelu" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "linear(MLOperand, optional MLLinearOptions)" with the proper type assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: calling linear(MLOperand, optional MLLinearOptions) on builder with too few arguments must throw TypeError assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "linear(optional MLLinearOptions)" with the proper type assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: calling linear(optional MLLinearOptions) on builder with too few arguments must throw TypeError assert_inherits: property "linear" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions)" with the proper type assert_inherits: property "lstm" not found in prototype chain
-FAIL MLGraphBuilder interface: calling lstm(MLOperand, MLOperand, MLOperand, unsigned long, unsigned long, optional MLLstmOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstm" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions)" with the proper type assert_inherits: property "lstmCell" not found in prototype chain
-FAIL MLGraphBuilder interface: calling lstmCell(MLOperand, MLOperand, MLOperand, MLOperand, MLOperand, unsigned long, optional MLLstmCellOptions) on builder with too few arguments must throw TypeError assert_inherits: property "lstmCell" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "matmul(MLOperand, MLOperand)" with the proper type assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: calling matmul(MLOperand, MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "matmul" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "pad(MLOperand, MLOperand, optional MLPadOptions)" with the proper type assert_inherits: property "pad" not found in prototype chain
-FAIL MLGraphBuilder interface: calling pad(MLOperand, MLOperand, optional MLPadOptions) on builder with too few arguments must throw TypeError assert_inherits: property "pad" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "averagePool2d(MLOperand, optional MLPool2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling averagePool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "l2Pool2d(MLOperand, optional MLPool2dOptions)" with the proper type assert_inherits: property "l2Pool2d" not found in prototype chain
-FAIL MLGraphBuilder interface: calling l2Pool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError assert_inherits: property "l2Pool2d" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "maxPool2d(MLOperand, optional MLPool2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling maxPool2d(MLOperand, optional MLPool2dOptions) on builder with too few arguments must throw TypeError
-FAIL MLGraphBuilder interface: builder must inherit property "reduceL1(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceL1" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceL1(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceL1" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceL2(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceL2" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceL2(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceL2" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceLogSum(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceLogSum" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceLogSum(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceLogSum" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceLogSumExp(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceLogSumExp" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceLogSumExp(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceLogSumExp" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMax(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMax" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMax(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMax" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMean(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMean" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMean(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMean" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceMin(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceMin" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceMin(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceMin" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceProduct(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceProduct" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceProduct(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceProduct" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceSum(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceSum" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceSum(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceSum" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "reduceSumSquare(MLOperand, optional MLReduceOptions)" with the proper type assert_inherits: property "reduceSumSquare" not found in prototype chain
-FAIL MLGraphBuilder interface: calling reduceSumSquare(MLOperand, optional MLReduceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "reduceSumSquare" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "relu(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling relu(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "relu()" with the proper type
-PASS MLGraphBuilder interface: builder must inherit property "resample2d(MLOperand, optional MLResample2dOptions)" with the proper type
-PASS MLGraphBuilder interface: calling resample2d(MLOperand, optional MLResample2dOptions) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "reshape(MLOperand, sequence<unsigned long?>)" with the proper type
-PASS MLGraphBuilder interface: calling reshape(MLOperand, sequence<unsigned long?>) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<long>, sequence<long>, optional MLSliceOptions) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
-PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
-PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
-PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "softplus(MLOperand, optional MLSoftplusOptions)" with the proper type assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softplus(MLOperand, optional MLSoftplusOptions) on builder with too few arguments must throw TypeError assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softplus(optional MLSoftplusOptions)" with the proper type assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softplus(optional MLSoftplusOptions) on builder with too few arguments must throw TypeError assert_inherits: property "softplus" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softsign(MLOperand)" with the proper type assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: calling softsign(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "softsign()" with the proper type assert_inherits: property "softsign" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions)" with the proper type assert_inherits: property "split" not found in prototype chain
-FAIL MLGraphBuilder interface: calling split(MLOperand, (unsigned long or sequence<unsigned long>), optional MLSplitOptions) on builder with too few arguments must throw TypeError assert_inherits: property "split" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "squeeze(MLOperand, optional MLSqueezeOptions)" with the proper type assert_inherits: property "squeeze" not found in prototype chain
-FAIL MLGraphBuilder interface: calling squeeze(MLOperand, optional MLSqueezeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "squeeze" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tanh(MLOperand)" with the proper type assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: calling tanh(MLOperand) on builder with too few arguments must throw TypeError assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "tanh()" with the proper type assert_inherits: property "tanh" not found in prototype chain
-FAIL MLGraphBuilder interface: builder must inherit property "transpose(MLOperand, optional MLTransposeOptions)" with the proper type assert_inherits: property "transpose" not found in prototype chain
-FAIL MLGraphBuilder interface: calling transpose(MLOperand, optional MLTransposeOptions) on builder with too few arguments must throw TypeError assert_inherits: property "transpose" not found in prototype chain
-PASS WorkerNavigator interface: attribute ml
-PASS WorkerNavigator interface: navigator must inherit property "ml" with the proper type
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any-expected.txt
deleted file mode 100644
index 7dafaad..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any-expected.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-This is a testharness.js-based test.
-Found 68 tests; 0 PASS, 68 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL averagePool2d float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.windowDimensions / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nchw / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.windowDimensions / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nchw / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.windowDimensions / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nchw / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.windowDimensions / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nchw / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any.worker-expected.txt
deleted file mode 100644
index 2a20a0f..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/pooling.https.any.worker-expected.txt
+++ /dev/null
@@ -1,140 +0,0 @@
-This is a testharness.js-based test.
-Found 136 tests; 0 PASS, 136 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL averagePool2d float32 4D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.windowDimensions / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.dilations / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.layout=nchw / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.windowDimensions / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.dilations / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.layout=nchw / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor default options / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.windowDimensions / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.dilations / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.layout=nchw / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor default options / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.windowDimensions / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.dilations / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.layout=nchw / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL averagePool2d float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.windowDimensions / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nchw / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.windowDimensions / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=explicit / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nchw / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.layout=nhwc / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL averagePool2d float32 4D tensor options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor default options / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.windowDimensions / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nchw / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor default options / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.windowDimensions / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=explicit / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-upper ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.autoPad=same-lower ignores options.padding / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nchw / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.layout=nhwc / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL maxPool2d float32 4D tensor options.dilations with options.strides / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any-expected.txt
deleted file mode 100644
index 703aed7..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-FAIL relu float32 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 3D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 4D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 5D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 3D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 4D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 5D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any.worker-expected.txt
deleted file mode 100644
index 15429c4..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/relu.https.any.worker-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-FAIL relu float32 1D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 2D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 3D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 4D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 5D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 1D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 2D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 3D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 4D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 5D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL relu float32 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 3D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 4D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 5D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 3D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 4D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL relu float32 5D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any-expected.txt
deleted file mode 100644
index e3eff715..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (extend dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (extend dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any.worker-expected.txt
deleted file mode 100644
index 42c42ef..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/reshape.https.any.worker-expected.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-This is a testharness.js-based test.
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (extend dimensions) / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to 1D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (extend dimensions) / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to 1D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (extend dimensions) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reorder all dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (reduce dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (extend dimensions) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to a new shape (one dimension being the special value of null) / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL reshape float32 tensor to 1D tensor newShape=[null] / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any-expected.txt
deleted file mode 100644
index 7947e84..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-FAIL sigmoid float32 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 3D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 4D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 5D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 3D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 4D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 5D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any.worker-expected.txt
deleted file mode 100644
index 2c3387e6..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/sigmoid.https.any.worker-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-FAIL sigmoid float32 1D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 2D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 3D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 4D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 5D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 1D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 2D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 3D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 4D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 5D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL sigmoid float32 1D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 3D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 4D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 5D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 1D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 3D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 4D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL sigmoid float32 5D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any-expected.txt
deleted file mode 100644
index 137d19ab..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL softmax float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL softmax float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any.worker-expected.txt
deleted file mode 100644
index 9a33b4b..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/webnn/softmax.https.any.worker-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-FAIL softmax float32 2D tensor / cpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL softmax float32 2D tensor / gpu / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
-FAIL softmax float32 2D tensor / cpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-FAIL softmax float32 2D tensor / gpu / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/README.md b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/README.md
new file mode 100644
index 0000000..4592dc5
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/README.md
@@ -0,0 +1,3 @@
+This suite runs the tests with
+--disable-blink-features=CSSSignRelatedFunctions.
+That should be failed because abs(), sign() should not be parsed and evaluated.
diff --git a/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt
new file mode 100644
index 0000000..691ff68
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -0,0 +1,192 @@
+This is a testharness.js-based test.
+Found 188 tests; 0 PASS, 188 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL abs(1) should be used-value-equivalent to 1 assert_not_equals: abs(1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1) should be used-value-equivalent to 1 assert_not_equals: sign(1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL abs(-1) should be used-value-equivalent to 1 assert_not_equals: abs(-1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1) should be used-value-equivalent to -1 assert_not_equals: sign(-1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL abs(sign(1)) should be used-value-equivalent to 1 assert_not_equals: abs(sign(1)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL abs(sign(sign(1))) should be used-value-equivalent to 1 assert_not_equals: abs(sign(sign(1))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 assert_not_equals: sign(sign(sign(1) + sign(1))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 assert_not_equals: calc(abs(0.1 + 0.2) + 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 assert_not_equals: calc(sign(0.1 + 0.2) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 assert_not_equals: calc(abs(0.1 + 0.2) * 2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 assert_not_equals: calc(abs(sign(0.1) + 0.2) / 2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 assert_not_equals: calc(abs(0.1 + 0.2) * -2) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 assert_not_equals: calc(sign(0.1 - 0.2) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 assert_not_equals: calc(sign(1) + sign(1) - 0.05) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL calc(calc(sign(-0))) should be used-value-equivalent to 0 assert_not_equals: calc(calc(sign(-0))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(calc(sign(-0)))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(calc(sign(-0)))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(calc(sign(0))) should be used-value-equivalent to 0 assert_not_equals: calc(calc(sign(0))) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(calc(sign(0)))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(calc(sign(0)))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1px) should be used-value-equivalent to 1 assert_not_equals: sign(1px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1cm) should be used-value-equivalent to 1 assert_not_equals: sign(1cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1mm) should be used-value-equivalent to 1 assert_not_equals: sign(1mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1Q) should be used-value-equivalent to 1 assert_not_equals: sign(1Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1in) should be used-value-equivalent to 1 assert_not_equals: sign(1in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1pc) should be used-value-equivalent to 1 assert_not_equals: sign(1pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1pt) should be used-value-equivalent to 1 assert_not_equals: sign(1pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1em) should be used-value-equivalent to 1 assert_not_equals: sign(1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1ex) should be used-value-equivalent to 1 assert_not_equals: sign(1ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1ch) should be used-value-equivalent to 1 assert_not_equals: sign(1ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1rem) should be used-value-equivalent to 1 assert_not_equals: sign(1rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1vh) should be used-value-equivalent to 1 assert_not_equals: sign(1vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1vw) should be used-value-equivalent to 1 assert_not_equals: sign(1vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1vmin) should be used-value-equivalent to 1 assert_not_equals: sign(1vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1vmax) should be used-value-equivalent to 1 assert_not_equals: sign(1vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1px) should be used-value-equivalent to -1 assert_not_equals: sign(-1px) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1cm) should be used-value-equivalent to -1 assert_not_equals: sign(-1cm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1mm) should be used-value-equivalent to -1 assert_not_equals: sign(-1mm) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1Q) should be used-value-equivalent to -1 assert_not_equals: sign(-1Q) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1in) should be used-value-equivalent to -1 assert_not_equals: sign(-1in) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1pc) should be used-value-equivalent to -1 assert_not_equals: sign(-1pc) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1pt) should be used-value-equivalent to -1 assert_not_equals: sign(-1pt) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1em) should be used-value-equivalent to -1 assert_not_equals: sign(-1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1ex) should be used-value-equivalent to -1 assert_not_equals: sign(-1ex) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1ch) should be used-value-equivalent to -1 assert_not_equals: sign(-1ch) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1rem) should be used-value-equivalent to -1 assert_not_equals: sign(-1rem) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1vh) should be used-value-equivalent to -1 assert_not_equals: sign(-1vh) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1vw) should be used-value-equivalent to -1 assert_not_equals: sign(-1vw) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1vmin) should be used-value-equivalent to -1 assert_not_equals: sign(-1vmin) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1vmax) should be used-value-equivalent to -1 assert_not_equals: sign(-1vmax) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1s) should be used-value-equivalent to 1 assert_not_equals: sign(1s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1ms) should be used-value-equivalent to 1 assert_not_equals: sign(1ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1s) should be used-value-equivalent to -1 assert_not_equals: sign(-1s) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1ms) should be used-value-equivalent to -1 assert_not_equals: sign(-1ms) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1deg) should be used-value-equivalent to 1 assert_not_equals: sign(1deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1grad) should be used-value-equivalent to 1 assert_not_equals: sign(1grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1rad) should be used-value-equivalent to 1 assert_not_equals: sign(1rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(1turn) should be used-value-equivalent to 1 assert_not_equals: sign(1turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1deg) should be used-value-equivalent to -1 assert_not_equals: sign(-1deg) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1grad) should be used-value-equivalent to -1 assert_not_equals: sign(-1grad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1rad) should be used-value-equivalent to -1 assert_not_equals: sign(-1rad) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(-1turn) should be used-value-equivalent to -1 assert_not_equals: sign(-1turn) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0px)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0px)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0px))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0px))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0cm)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0cm)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0cm))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0cm))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0mm)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0mm)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0mm))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0mm))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0Q)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0Q)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0Q))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0Q))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0in)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0in)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0in))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0in))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0pc)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0pc)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0pc))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0pc))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0pt)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0pt)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0pt))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0pt))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0em)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0em)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0em))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0em))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0ex)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0ex)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0ex))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0ex))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0ch)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0ch)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0ch))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0ch))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0rem)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0rem)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0rem))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0rem))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0vh)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0vh)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0vh))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0vh))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0vw)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0vw)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0vw))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0vw))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0vmin)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0vmin)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0vmin))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0vmin))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0vmax)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0vmax)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0vmax))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0vmax))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0px)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0px)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0px))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0px))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0cm)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0cm)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0cm))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0cm))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0mm)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0mm)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0mm))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0mm))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0Q)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0Q)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0Q))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0Q))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0in)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0in)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0in))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0in))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0pc)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0pc)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0pc))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0pc))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0pt)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0pt)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0pt))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0pt))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0em)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0em)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0em))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0em))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0ex)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0ex)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0ex))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0ex))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0ch)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0ch)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0ch))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0ch))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0rem)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0rem)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0rem))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0rem))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0vh)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0vh)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0vh))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0vh))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0vw)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0vw)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0vw))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0vw))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0vmin)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0vmin)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0vmin))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0vmin))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0vmax)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0vmax)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0vmax))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0vmax))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0s)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0s)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0s))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0s))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0ms)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0ms)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0ms))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0ms))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0s)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0s)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0s))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0s))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0ms)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0ms)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0ms))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0ms))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0deg)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0deg)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0deg))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0deg))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0grad)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0grad)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0grad))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0grad))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0rad)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0rad)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0rad))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0rad))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(0turn)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(0turn)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(0turn))), 1) should be used-value-equivalent to 1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(0turn))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0deg)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0deg)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0deg))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0deg))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0grad)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0grad)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0grad))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0grad))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0rad)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0rad)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0rad))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0rad))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL calc(sign(-0turn)) should be used-value-equivalent to 0 assert_not_equals: calc(sign(-0turn)) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL clamp(-1, calc( 1 / sign(sign(-0turn))), 1) should be used-value-equivalent to -1 assert_not_equals: clamp(-1, calc( 1 / sign(sign(-0turn))), 1) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL abs(1px) should be used-value-equivalent to 1px assert_not_equals: abs(1px) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1cm) should be used-value-equivalent to 1cm assert_not_equals: abs(1cm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1mm) should be used-value-equivalent to 1mm assert_not_equals: abs(1mm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1Q) should be used-value-equivalent to 1Q assert_not_equals: abs(1Q) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1in) should be used-value-equivalent to 1in assert_not_equals: abs(1in) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1pc) should be used-value-equivalent to 1pc assert_not_equals: abs(1pc) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1pt) should be used-value-equivalent to 1pt assert_not_equals: abs(1pt) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1em) should be used-value-equivalent to 1em assert_not_equals: abs(1em) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1ex) should be used-value-equivalent to 1ex assert_not_equals: abs(1ex) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1ch) should be used-value-equivalent to 1ch assert_not_equals: abs(1ch) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1rem) should be used-value-equivalent to 1rem assert_not_equals: abs(1rem) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1vh) should be used-value-equivalent to 1vh assert_not_equals: abs(1vh) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1vw) should be used-value-equivalent to 1vw assert_not_equals: abs(1vw) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_not_equals: abs(1vmin) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_not_equals: abs(1vmax) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1px) should be used-value-equivalent to 1px assert_not_equals: abs(-1px) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_not_equals: abs(-1cm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_not_equals: abs(-1mm) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_not_equals: abs(-1Q) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1in) should be used-value-equivalent to 1in assert_not_equals: abs(-1in) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_not_equals: abs(-1pc) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_not_equals: abs(-1pt) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1em) should be used-value-equivalent to 1em assert_not_equals: abs(-1em) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_not_equals: abs(-1ex) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_not_equals: abs(-1ch) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_not_equals: abs(-1rem) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_not_equals: abs(-1vh) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_not_equals: abs(-1vw) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_not_equals: abs(-1vmin) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_not_equals: abs(-1vmax) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px"
+FAIL abs(1s) should be used-value-equivalent to 1s assert_not_equals: abs(1s) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
+FAIL abs(1ms) should be used-value-equivalent to 1ms assert_not_equals: abs(1ms) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
+FAIL abs(-1s) should be used-value-equivalent to 1s assert_not_equals: abs(-1s) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
+FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_not_equals: abs(-1ms) isn't valid in 'transition-delay'; got the default value instead. got disallowed value "0s"
+FAIL abs(1deg) should be used-value-equivalent to 1deg assert_not_equals: abs(1deg) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(1grad) should be used-value-equivalent to 1grad assert_not_equals: abs(1grad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(1rad) should be used-value-equivalent to 1rad assert_not_equals: abs(1rad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(1turn) should be used-value-equivalent to 1turn assert_not_equals: abs(1turn) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(-1deg) should be used-value-equivalent to 1deg assert_not_equals: abs(-1deg) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(-1grad) should be used-value-equivalent to 1grad assert_not_equals: abs(-1grad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(-1rad) should be used-value-equivalent to 1rad assert_not_equals: abs(-1rad) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL abs(-1turn) should be used-value-equivalent to 1turn assert_not_equals: abs(-1turn) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
+FAIL sign(10px - 1em) should be used-value-equivalent to 0; fontSize=10px assert_not_equals: sign(10px - 1em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+FAIL sign(10px - 2em) should be used-value-equivalent to -1; fontSize=10px assert_not_equals: sign(10px - 2em) isn't valid in 'z-index'; got the default value instead. got disallowed value "auto"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-serialize-expected.txt b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-serialize-expected.txt
new file mode 100644
index 0000000..a3b41bc2
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/css-sign-related-functions-disabled/external/wpt/css/css-values/signs-abs-serialize-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL 'scale(abs(1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(abs(1))' should be valid in transform. got disallowed value ""
+FAIL 'scale(sign(.1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(.1))' should be valid in transform. got disallowed value ""
+FAIL 'scale(abs(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(6))'. assert_not_equals: 'scale(abs(1 + 2 + 3))' should be valid in transform. got disallowed value ""
+FAIL 'scale(sign(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(1 + 2 + 3))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(abs(1) + abs(2)))' as a specified value should serialize as 'scale(calc(3))'. assert_not_equals: 'scale(calc(abs(1) + abs(2)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(.1) + sign(.2)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + sign(.2)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(1 + abs(1)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(1 + abs(1)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(.1) + 1))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + 1))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(abs(inFinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(inFinity)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(abs(infinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(infinity)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(infinity)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(sign(infinity)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(abs(infinity))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(abs(infinity))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(abs(-infinity)))' as a specified value should serialize as 'scale(calc(infinity))'. assert_not_equals: 'scale(calc(abs(-infinity)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(-1 * infinity)))' as a specified value should serialize as 'scale(calc(-1))'. assert_not_equals: 'scale(calc(sign(-1 * infinity)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(-1 * NaN)))' as a specified value should serialize as 'scale(calc(NaN))'. assert_not_equals: 'scale(calc(sign(-1 * NaN)))' should be valid in transform. got disallowed value ""
+FAIL 'scale(calc(sign(1 * NaN)))' as a specified value should serialize as 'scale(calc(NaN))'. assert_not_equals: 'scale(calc(sign(1 * NaN)))' should be valid in transform. got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/closure_compiler/externs/management.js b/third_party/closure_compiler/externs/management.js
deleted file mode 100644
index 29f4a76..0000000
--- a/third_party/closure_compiler/externs/management.js
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file was generated by:
-//   tools/json_schema_compiler/compiler.py.
-// NOTE: The format of types has changed. 'FooType' is now
-//   'chrome.management.FooType'.
-// Please run the closure compiler before committing changes.
-// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
-
-/**
- * @fileoverview Externs generated from namespace: management
- * @externs
- */
-
-/** @const */
-chrome.management = {};
-
-/**
- * Information about an icon belonging to an extension, app, or theme.
- * @typedef {{
- *   size: number,
- *   url: string
- * }}
- * @see https://developer.chrome.com/extensions/management#type-IconInfo
- */
-chrome.management.IconInfo;
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/management#type-LaunchType
- */
-chrome.management.LaunchType = {
-  OPEN_AS_REGULAR_TAB: 'OPEN_AS_REGULAR_TAB',
-  OPEN_AS_PINNED_TAB: 'OPEN_AS_PINNED_TAB',
-  OPEN_AS_WINDOW: 'OPEN_AS_WINDOW',
-  OPEN_FULL_SCREEN: 'OPEN_FULL_SCREEN',
-};
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/management#type-ExtensionDisabledReason
- */
-chrome.management.ExtensionDisabledReason = {
-  UNKNOWN: 'unknown',
-  PERMISSIONS_INCREASE: 'permissions_increase',
-};
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/management#type-ExtensionType
- */
-chrome.management.ExtensionType = {
-  EXTENSION: 'extension',
-  HOSTED_APP: 'hosted_app',
-  PACKAGED_APP: 'packaged_app',
-  LEGACY_PACKAGED_APP: 'legacy_packaged_app',
-  THEME: 'theme',
-  LOGIN_SCREEN_EXTENSION: 'login_screen_extension',
-};
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/management#type-ExtensionInstallType
- */
-chrome.management.ExtensionInstallType = {
-  ADMIN: 'admin',
-  DEVELOPMENT: 'development',
-  NORMAL: 'normal',
-  SIDELOAD: 'sideload',
-  OTHER: 'other',
-};
-
-/**
- * Information about an installed extension, app, or theme.
- * @typedef {{
- *   id: string,
- *   name: string,
- *   shortName: string,
- *   description: string,
- *   version: string,
- *   versionName: (string|undefined),
- *   mayDisable: boolean,
- *   mayEnable: (boolean|undefined),
- *   enabled: boolean,
- *   disabledReason: (!chrome.management.ExtensionDisabledReason|undefined),
- *   isApp: boolean,
- *   type: !chrome.management.ExtensionType,
- *   appLaunchUrl: (string|undefined),
- *   homepageUrl: (string|undefined),
- *   updateUrl: (string|undefined),
- *   offlineEnabled: boolean,
- *   optionsUrl: string,
- *   icons: (!Array<!chrome.management.IconInfo>|undefined),
- *   permissions: !Array<string>,
- *   hostPermissions: !Array<string>,
- *   installType: !chrome.management.ExtensionInstallType,
- *   launchType: (!chrome.management.LaunchType|undefined),
- *   availableLaunchTypes: (!Array<!chrome.management.LaunchType>|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/management#type-ExtensionInfo
- */
-chrome.management.ExtensionInfo;
-
-/**
- * Options for how to handle the extension's uninstallation.
- * @typedef {{
- *   showConfirmDialog: (boolean|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/management#type-UninstallOptions
- */
-chrome.management.UninstallOptions;
-
-/**
- * Returns a list of information about installed extensions and apps.
- * @param {function(!Array<!chrome.management.ExtensionInfo>): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-getAll
- */
-chrome.management.getAll = function(callback) {};
-
-/**
- * Returns information about the installed extension, app, or theme that has the
- * given ID.
- * @param {string} id The ID from an item of $(ref:management.ExtensionInfo).
- * @param {function(!chrome.management.ExtensionInfo): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-get
- */
-chrome.management.get = function(id, callback) {};
-
-/**
- * Returns information about the calling extension, app, or theme. Note: This
- * function can be used without requesting the 'management' permission in the
- * manifest.
- * @param {function(!chrome.management.ExtensionInfo): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-getSelf
- */
-chrome.management.getSelf = function(callback) {};
-
-/**
- * Returns a list of <a href='permission_warnings'>permission warnings</a> for
- * the given extension id.
- * @param {string} id The ID of an already installed extension.
- * @param {function(!Array<string>): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-getPermissionWarningsById
- */
-chrome.management.getPermissionWarningsById = function(id, callback) {};
-
-/**
- * Returns a list of <a href='permission_warnings'>permission warnings</a> for
- * the given extension manifest string. Note: This function can be used without
- * requesting the 'management' permission in the manifest.
- * @param {string} manifestStr Extension manifest JSON string.
- * @param {function(!Array<string>): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-getPermissionWarningsByManifest
- */
-chrome.management.getPermissionWarningsByManifest = function(manifestStr, callback) {};
-
-/**
- * Enables or disables an app or extension. In most cases this function must be
- * called in the context of a user gesture (e.g. an onclick handler for a
- * button), and may present the user with a native confirmation UI as a way of
- * preventing abuse.
- * @param {string} id This should be the id from an item of
- *     $(ref:management.ExtensionInfo).
- * @param {boolean} enabled Whether this item should be enabled or disabled.
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-setEnabled
- */
-chrome.management.setEnabled = function(id, enabled, callback) {};
-
-/**
- * Uninstalls a currently installed app or extension. Note: This function does
- * not work in managed environments when the user is not allowed to uninstall
- * the specified extension/app. If the uninstall fails (e.g. the user cancels
- * the dialog) the promise will be rejected or the callback will be called with
- * $(ref:runtime.lastError) set.
- * @param {string} id This should be the id from an item of
- *     $(ref:management.ExtensionInfo).
- * @param {!chrome.management.UninstallOptions=} options
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-uninstall
- */
-chrome.management.uninstall = function(id, options, callback) {};
-
-/**
- * Uninstalls the calling extension. Note: This function can be used without
- * requesting the 'management' permission in the manifest. This function does
- * not work in managed environments when the user is not allowed to uninstall
- * the specified extension/app.
- * @param {!chrome.management.UninstallOptions=} options
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-uninstallSelf
- */
-chrome.management.uninstallSelf = function(options, callback) {};
-
-/**
- * Launches an application.
- * @param {string} id The extension id of the application.
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-launchApp
- */
-chrome.management.launchApp = function(id, callback) {};
-
-/**
- * Display options to create shortcuts for an app. On Mac, only packaged app
- * shortcuts can be created.
- * @param {string} id This should be the id from an app item of
- *     $(ref:management.ExtensionInfo).
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-createAppShortcut
- */
-chrome.management.createAppShortcut = function(id, callback) {};
-
-/**
- * Set the launch type of an app.
- * @param {string} id This should be the id from an app item of
- *     $(ref:management.ExtensionInfo).
- * @param {!chrome.management.LaunchType} launchType The target launch type.
- *     Always check and make sure this launch type is in
- *     $(ref:ExtensionInfo.availableLaunchTypes), because the available launch
- *     types vary on different platforms and configurations.
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-setLaunchType
- */
-chrome.management.setLaunchType = function(id, launchType, callback) {};
-
-/**
- * Generate an app for a URL. Returns the generated bookmark app.
- * @param {string} url The URL of a web page. The scheme of the URL can only be
- *     "http" or "https".
- * @param {string} title The title of the generated app.
- * @param {function(!chrome.management.ExtensionInfo): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-generateAppForLink
- */
-chrome.management.generateAppForLink = function(url, title, callback) {};
-
-/**
- * Checks if the replacement android app can be installed. Errors generated by
- * this API are reported by setting $(ref:runtime.lastError) and executing the
- * function's regular callback.
- * @param {function(boolean): void} callback
- * @see https://developer.chrome.com/extensions/management#method-canInstallReplacementAndroidApp
- */
-chrome.management.canInstallReplacementAndroidApp = function(callback) {};
-
-/**
- * Prompts the user to install the replacement Android app from the manifest.
- * Errors generated by this API are reported by setting $(ref:runtime.lastError)
- * and executing the function's regular callback.
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-installReplacementAndroidApp
- */
-chrome.management.installReplacementAndroidApp = function(callback) {};
-
-/**
- * Launches the replacement_web_app specified in the manifest. Prompts the user
- * to install if not already installed.
- * @param {function(): void=} callback
- * @see https://developer.chrome.com/extensions/management#method-installReplacementWebApp
- */
-chrome.management.installReplacementWebApp = function(callback) {};
-
-/**
- * Fired when an app or extension has been installed.
- * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/management#event-onInstalled
- */
-chrome.management.onInstalled;
-
-/**
- * Fired when an app or extension has been uninstalled.
- * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/management#event-onUninstalled
- */
-chrome.management.onUninstalled;
-
-/**
- * Fired when an app or extension has been enabled.
- * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/management#event-onEnabled
- */
-chrome.management.onEnabled;
-
-/**
- * Fired when an app or extension has been disabled.
- * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/management#event-onDisabled
- */
-chrome.management.onDisabled;
diff --git a/third_party/closure_compiler/externs/mime_handler_private.js b/third_party/closure_compiler/externs/mime_handler_private.js
deleted file mode 100644
index 3bf33fc8..0000000
--- a/third_party/closure_compiler/externs/mime_handler_private.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file was generated by:
-//   tools/json_schema_compiler/compiler.py.
-// NOTE: The format of types has changed. 'FooType' is now
-//   'chrome.mimeHandlerPrivate.FooType'.
-// Please run the closure compiler before committing changes.
-// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
-
-/**
- * @fileoverview Externs generated from namespace: mimeHandlerPrivate
- * @externs
- */
-
-/** @const */
-chrome.mimeHandlerPrivate = {};
-
-/**
- * @typedef {{
- *   mimeType: string,
- *   originalUrl: string,
- *   streamUrl: string,
- *   tabId: number,
- *   responseHeaders: Object,
- *   embedded: boolean
- * }}
- */
-chrome.mimeHandlerPrivate.StreamInfo;
-
-/**
- * @typedef {{
- *   backgroundColor: number,
- *   allowJavascript: boolean
- * }}
- */
-chrome.mimeHandlerPrivate.PdfPluginAttributes;
-
-/**
- * Returns the StreamInfo for the stream for this context if there is one.
- * @param {function(!chrome.mimeHandlerPrivate.StreamInfo): void} callback
- */
-chrome.mimeHandlerPrivate.getStreamInfo = function(callback) {};
-
-/**
- * Sets PDF plugin attributes in the stream for this context if there is one.
- * @param {!chrome.mimeHandlerPrivate.PdfPluginAttributes} pdfPluginAttributes
- */
-chrome.mimeHandlerPrivate.setPdfPluginAttributes = function(pdfPluginAttributes) {};
-
-/**
- * Instructs the PluginDocument, if running in one, to show a dialog in response
- * to beforeunload events.
- * @param {boolean} showDialog
- * @param {function(): void=} callback
- */
-chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog = function(showDialog, callback) {};
-
-/**
- * Fired when the browser wants the listener to perform a save.
- * @type {!ChromeEvent}
- */
-chrome.mimeHandlerPrivate.onSave;
diff --git a/third_party/closure_compiler/externs/system_display.js b/third_party/closure_compiler/externs/system_display.js
deleted file mode 100644
index 43d57429..0000000
--- a/third_party/closure_compiler/externs/system_display.js
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file was generated by:
-//   tools/json_schema_compiler/compiler.py.
-// NOTE: The format of types has changed. 'FooType' is now
-//   'chrome.system.display.FooType'.
-// Please run the closure compiler before committing changes.
-// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
-
-// TODO(crbug.com/1086377): Disable automatic extern generation until fixed.
-// This was modified to add 'chrome.system = {};'
-// If the above tool that generates this file removes it, please readd it or
-// the closure compiler will fail.
-
-/**
- * @fileoverview Externs generated from namespace: system.display
- * @externs
- */
-
-/** @const */
-chrome.system = {};
-
-/** @const */
-chrome.system.display = {};
-
-/**
- * @typedef {{
- *   left: number,
- *   top: number,
- *   width: number,
- *   height: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-Bounds
- */
-chrome.system.display.Bounds;
-
-/**
- * @typedef {{
- *   left: number,
- *   top: number,
- *   right: number,
- *   bottom: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-Insets
- */
-chrome.system.display.Insets;
-
-/**
- * @typedef {{
- *   x: number,
- *   y: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-Point
- */
-chrome.system.display.Point;
-
-/**
- * @typedef {{
- *   displayPoint: !chrome.system.display.Point,
- *   touchPoint: !chrome.system.display.Point
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-TouchCalibrationPair
- */
-chrome.system.display.TouchCalibrationPair;
-
-/**
- * @typedef {{
- *   pair1: !chrome.system.display.TouchCalibrationPair,
- *   pair2: !chrome.system.display.TouchCalibrationPair,
- *   pair3: !chrome.system.display.TouchCalibrationPair,
- *   pair4: !chrome.system.display.TouchCalibrationPair
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-TouchCalibrationPairQuad
- */
-chrome.system.display.TouchCalibrationPairQuad;
-
-/**
- * @typedef {{
- *   width: number,
- *   height: number,
- *   widthInNativePixels: number,
- *   heightInNativePixels: number,
- *   uiScale: (number|undefined),
- *   deviceScaleFactor: number,
- *   refreshRate: number,
- *   isNative: boolean,
- *   isSelected: boolean,
- *   isInterlaced: (boolean|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-DisplayMode
- */
-chrome.system.display.DisplayMode;
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/system.display#type-LayoutPosition
- */
-chrome.system.display.LayoutPosition = {
-  TOP: 'top',
-  RIGHT: 'right',
-  BOTTOM: 'bottom',
-  LEFT: 'left',
-};
-
-/**
- * @typedef {{
- *   id: string,
- *   parentId: string,
- *   position: !chrome.system.display.LayoutPosition,
- *   offset: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-DisplayLayout
- */
-chrome.system.display.DisplayLayout;
-
-/**
- * @typedef {{
- *   manufacturerId: string,
- *   productId: string,
- *   yearOfManufacture: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-Edid
- */
-chrome.system.display.Edid;
-
-/**
- * @typedef {{
- *   id: string,
- *   name: string,
- *   edid: (!chrome.system.display.Edid|undefined),
- *   mirroringSourceId: string,
- *   mirroringDestinationIds: !Array<string>,
- *   isPrimary: boolean,
- *   isInternal: boolean,
- *   isEnabled: boolean,
- *   isUnified: boolean,
- *   isAutoRotationAllowed: (boolean|undefined),
- *   dpiX: number,
- *   dpiY: number,
- *   rotation: number,
- *   bounds: !chrome.system.display.Bounds,
- *   overscan: !chrome.system.display.Insets,
- *   workArea: !chrome.system.display.Bounds,
- *   modes: !Array<!chrome.system.display.DisplayMode>,
- *   hasTouchSupport: boolean,
- *   hasAccelerometerSupport: boolean,
- *   availableDisplayZoomFactors: !Array<number>,
- *   displayZoomFactor: number
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-DisplayUnitInfo
- */
-chrome.system.display.DisplayUnitInfo;
-
-/**
- * @typedef {{
- *   isUnified: (boolean|undefined),
- *   mirroringSourceId: (string|undefined),
- *   isPrimary: (boolean|undefined),
- *   overscan: (!chrome.system.display.Insets|undefined),
- *   rotation: (number|undefined),
- *   boundsOriginX: (number|undefined),
- *   boundsOriginY: (number|undefined),
- *   displayMode: (!chrome.system.display.DisplayMode|undefined),
- *   displayZoomFactor: (number|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-DisplayProperties
- */
-chrome.system.display.DisplayProperties;
-
-/**
- * @typedef {{
- *   singleUnified: (boolean|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-GetInfoFlags
- */
-chrome.system.display.GetInfoFlags;
-
-/**
- * @enum {string}
- * @see https://developer.chrome.com/extensions/system.display#type-MirrorMode
- */
-chrome.system.display.MirrorMode = {
-  OFF: 'off',
-  NORMAL: 'normal',
-  MIXED: 'mixed',
-};
-
-/**
- * @typedef {{
- *   mode: !chrome.system.display.MirrorMode,
- *   mirroringSourceId: (string|undefined),
- *   mirroringDestinationIds: (!Array<string>|undefined)
- * }}
- * @see https://developer.chrome.com/extensions/system.display#type-MirrorModeInfo
- */
-chrome.system.display.MirrorModeInfo;
-
-/**
- * Requests the information for all attached display devices.
- * @param {?chrome.system.display.GetInfoFlags|undefined} flags Options
- *     affecting how the information is returned.
- * @param {function(!Array<!chrome.system.display.DisplayUnitInfo>): void}
- *     callback The callback to invoke with the results.
- * @see https://developer.chrome.com/extensions/system.display#method-getInfo
- */
-chrome.system.display.getInfo = function(flags, callback) {};
-
-/**
- * Requests the layout info for all displays. NOTE: This is only available to
- * Chrome OS Kiosk apps and Web UI.
- * @param {function(!Array<!chrome.system.display.DisplayLayout>): void}
- *     callback The callback to invoke with the results.
- * @see https://developer.chrome.com/extensions/system.display#method-getDisplayLayout
- */
-chrome.system.display.getDisplayLayout = function(callback) {};
-
-/**
- * Updates the properties for the display specified by |id|, according to the
- * information provided in |info|. On failure, $(ref:runtime.lastError) will be
- * set. NOTE: This is only available to Chrome OS Kiosk apps and Web UI.
- * @param {string} id The display's unique identifier.
- * @param {!chrome.system.display.DisplayProperties} info The information about
- *     display properties that should be changed.     A property will be changed
- *     only if a new value for it is specified in     |info|.
- * @param {function(): void=} callback Empty function called when the function
- *     finishes. To find out     whether the function succeeded,
- *     $(ref:runtime.lastError) should be     queried.
- * @see https://developer.chrome.com/extensions/system.display#method-setDisplayProperties
- */
-chrome.system.display.setDisplayProperties = function(id, info, callback) {};
-
-/**
- * Set the layout for all displays. Any display not included will use the
- * default layout. If a layout would overlap or be otherwise invalid it will be
- * adjusted to a valid layout. After layout is resolved, an onDisplayChanged
- * event will be triggered. NOTE: This is only available to Chrome OS Kiosk apps
- * and Web UI.
- * @param {!Array<!chrome.system.display.DisplayLayout>} layouts The layout
- *     information, required for all displays except     the primary display.
- * @param {function(): void=} callback Empty function called when the function
- *     finishes. To find out     whether the function succeeded,
- *     $(ref:runtime.lastError) should be     queried.
- * @see https://developer.chrome.com/extensions/system.display#method-setDisplayLayout
- */
-chrome.system.display.setDisplayLayout = function(layouts, callback) {};
-
-/**
- * Enables/disables the unified desktop feature. If enabled while mirroring is
- * active, the desktop mode will not change until mirroring is turned off.
- * Otherwise, the desktop mode will switch to unified immediately. NOTE: This is
- * only available to Chrome OS Kiosk apps and Web UI.
- * @param {boolean} enabled True if unified desktop should be enabled.
- * @see https://developer.chrome.com/extensions/system.display#method-enableUnifiedDesktop
- */
-chrome.system.display.enableUnifiedDesktop = function(enabled) {};
-
-/**
- * Starts overscan calibration for a display. This will show an overlay on the
- * screen indicating the current overscan insets. If overscan calibration for
- * display |id| is in progress this will reset calibration.
- * @param {string} id The display's unique identifier.
- * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationStart
- */
-chrome.system.display.overscanCalibrationStart = function(id) {};
-
-/**
- * Adjusts the current overscan insets for a display. Typically this should
- * either move the display along an axis (e.g. left+right have the same value)
- * or scale it along an axis (e.g. top+bottom have opposite values). Each Adjust
- * call is cumulative with previous calls since Start.
- * @param {string} id The display's unique identifier.
- * @param {!chrome.system.display.Insets} delta The amount to change the
- *     overscan insets.
- * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationAdjust
- */
-chrome.system.display.overscanCalibrationAdjust = function(id, delta) {};
-
-/**
- * Resets the overscan insets for a display to the last saved value (i.e before
- * Start was called).
- * @param {string} id The display's unique identifier.
- * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationReset
- */
-chrome.system.display.overscanCalibrationReset = function(id) {};
-
-/**
- * Complete overscan adjustments for a display  by saving the current values and
- * hiding the overlay.
- * @param {string} id The display's unique identifier.
- * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationComplete
- */
-chrome.system.display.overscanCalibrationComplete = function(id) {};
-
-/**
- * Displays the native touch calibration UX for the display with |id| as display
- * id. This will show an overlay on the screen with required instructions on how
- * to proceed. The callback will be invoked in case of successful calibration
- * only. If the calibration fails, this will throw an error.
- * @param {string} id The display's unique identifier.
- * @param {function(boolean): void=} callback Optional callback to inform the
- *     caller that the touch      calibration has ended. The argument of the
- *     callback informs if the      calibration was a success or not.
- * @see https://developer.chrome.com/extensions/system.display#method-showNativeTouchCalibration
- */
-chrome.system.display.showNativeTouchCalibration = function(id, callback) {};
-
-/**
- * Starts custom touch calibration for a display. This should be called when
- * using a custom UX for collecting calibration data. If another touch
- * calibration is already in progress this will throw an error.
- * @param {string} id The display's unique identifier.
- * @see https://developer.chrome.com/extensions/system.display#method-startCustomTouchCalibration
- */
-chrome.system.display.startCustomTouchCalibration = function(id) {};
-
-/**
- * Sets the touch calibration pairs for a display. These |pairs| would be used
- * to calibrate the touch screen for display with |id| called in
- * startCustomTouchCalibration(). Always call |startCustomTouchCalibration|
- * before calling this method. If another touch calibration is already in
- * progress this will throw an error.
- * @param {!chrome.system.display.TouchCalibrationPairQuad} pairs The pairs of
- *     point used to calibrate the display.
- * @param {!chrome.system.display.Bounds} bounds Bounds of the display when the
- *     touch calibration was performed.     |bounds.left| and |bounds.top|
- *     values are ignored.
- * @see https://developer.chrome.com/extensions/system.display#method-completeCustomTouchCalibration
- */
-chrome.system.display.completeCustomTouchCalibration = function(pairs, bounds) {};
-
-/**
- * Resets the touch calibration for the display and brings it back to its
- * default state by clearing any touch calibration data associated with the
- * display.
- * @param {string} id The display's unique identifier.
- * @see https://developer.chrome.com/extensions/system.display#method-clearTouchCalibration
- */
-chrome.system.display.clearTouchCalibration = function(id) {};
-
-/**
- * Sets the display mode to the specified mirror mode. Each call resets the
- * state from previous calls. Calling setDisplayProperties() will fail for the
- * mirroring destination displays. NOTE: This is only available to Chrome OS
- * Kiosk apps and Web UI.
- * @param {!chrome.system.display.MirrorModeInfo} info The information of the
- *     mirror mode that should be applied to the     display mode.
- * @param {function(): void=} callback Empty function called when the function
- *     finishes. To find out     whether the function succeeded,
- *     $(ref:runtime.lastError) should be     queried.
- * @see https://developer.chrome.com/extensions/system.display#method-setMirrorMode
- */
-chrome.system.display.setMirrorMode = function(info, callback) {};
-
-/**
- * Fired when anything changes to the display configuration.
- * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/system.display#event-onDisplayChanged
- */
-chrome.system.display.onDisplayChanged;
diff --git a/third_party/closure_compiler/externs/users_private.js b/third_party/closure_compiler/externs/users_private.js
deleted file mode 100644
index 0158337..0000000
--- a/third_party/closure_compiler/externs/users_private.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file was generated by:
-//   tools/json_schema_compiler/compiler.py.
-// NOTE: The format of types has changed. 'FooType' is now
-//   'chrome.usersPrivate.FooType'.
-// Please run the closure compiler before committing changes.
-// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
-
-/**
- * @fileoverview Externs generated from namespace: usersPrivate
- * @externs
- */
-
-/** @const */
-chrome.usersPrivate = {};
-
-/**
- * @typedef {{
- *   email: string,
- *   displayEmail: string,
- *   name: string,
- *   isOwner: boolean,
- *   isChild: boolean
- * }}
- */
-chrome.usersPrivate.User;
-
-/**
- * @typedef {{
- *   isLoggedIn: boolean,
- *   isScreenLocked: boolean
- * }}
- */
-chrome.usersPrivate.LoginStatusDict;
-
-/**
- * Gets a list of known users.
- * @param {function(!Array<!chrome.usersPrivate.User>): void} callback
- */
-chrome.usersPrivate.getUsers = function(callback) {};
-
-/**
- * Checks to see if the user is already present in the user list.
- * @param {string} email
- * @param {function(boolean): void} callback
- */
-chrome.usersPrivate.isUserInList = function(email, callback) {};
-
-/**
- * Adds a new user with the given email to the user list. The callback is called
- * with true if the user was added succesfully, or with false if not (e.g.
- * because the user was already present, or the current user isn't the owner).
- * @param {string} email
- * @param {function(boolean): void} callback
- */
-chrome.usersPrivate.addUser = function(email, callback) {};
-
-/**
- * Removes the user with the given email from the user list. The callback is
- * called with true if the user was removed succesfully, or with false if not
- * (e.g. because the user was not already present, or the current user isn't the
- * owner).
- * @param {string} email
- * @param {function(boolean): void} callback
- */
-chrome.usersPrivate.removeUser = function(email, callback) {};
-
-/**
- * Whether the user list is managed by enterprise.
- * @param {function(boolean): void} callback
- */
-chrome.usersPrivate.isUserListManaged = function(callback) {};
-
-/**
- * Returns the current user.
- * @param {function(!chrome.usersPrivate.User): void} callback
- */
-chrome.usersPrivate.getCurrentUser = function(callback) {};
-
-/**
- * Get login status.
- * @param {function(!chrome.usersPrivate.LoginStatusDict): void} callback
- */
-chrome.usersPrivate.getLoginStatus = function(callback) {};
diff --git a/third_party/cpuinfo/BUILD.gn b/third_party/cpuinfo/BUILD.gn
index 181abae..381e0c0 100644
--- a/third_party/cpuinfo/BUILD.gn
+++ b/third_party/cpuinfo/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("//third_party/blink/renderer/modules/ml/webnn/features.gni")
+
 config("cpuinfo_include") {
   include_dirs = [
     "src/include",
@@ -10,6 +12,11 @@
   ]
 }
 
+# Build cpuinfo as a shared library to avoid initialization issue in renderer
+# process sandbox (crbug.com/1341106) for WebNN XNNPACK Linux component build.
+build_cpuinfo_shared_library =
+    build_webnn_with_xnnpack && is_linux && is_component_build
+
 config("cpuinfo_config") {
   cflags = [
     # For chipset.c and utils.h.
@@ -22,6 +29,11 @@
     "-Wno-unused-function",
   ]
 
+  if (build_cpuinfo_shared_library) {
+    # Export all symbols when building shared library.
+    cflags += [ "-fvisibility=default" ]
+  }
+
   defines = [
     "_GNU_SOURCE=1",  # Required for CPU_SETSIZE to be available.
     "CPUINFO_INTERNAL=",
@@ -29,7 +41,13 @@
   ]
 }
 
-source_set("cpuinfo") {
+if (build_cpuinfo_shared_library) {
+  _cpuinfo_target_type = "shared_library"
+} else {
+  _cpuinfo_target_type = "source_set"
+}
+
+target(_cpuinfo_target_type, "cpuinfo") {
   public = [ "src/include/cpuinfo.h" ]
 
   sources = [
diff --git a/third_party/jsoncpp/BUILD.gn b/third_party/jsoncpp/BUILD.gn
index ba01b561..0d445cc 100644
--- a/third_party/jsoncpp/BUILD.gn
+++ b/third_party/jsoncpp/BUILD.gn
@@ -4,19 +4,8 @@
 
 import("//testing/libfuzzer/fuzzer_test.gni")
 
-declare_args() {
-  # Allow individual projects to remove the warning suppression
-  # by overriding this in their .gn file or through custom args.gn
-  # TODO(crbug.com/983223): Set this to false on all platforms, then remove it.
-  jsoncpp_no_deprecated_declarations = is_win && is_clang
-}
-
 config("jsoncpp_config") {
   include_dirs = [ "source/include" ]
-
-  if (jsoncpp_no_deprecated_declarations) {
-    cflags_cc = [ "-Wno-deprecated-declarations" ]
-  }
 }
 
 source_set("jsoncpp") {
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
index 68ea2d1b..7a52f64 100644
--- a/third_party/libaom/README.chromium
+++ b/third_party/libaom/README.chromium
@@ -2,9 +2,9 @@
 Short Name: libaom
 URL: https://aomedia.googlesource.com/aom/
 Version: 0
-Date: Friday February 03 2023
-Revision: 70b12695e1967d9589dd15b345a039e575e8f429
-CPEPrefix: cpe:/a:aomedia:aomedia:3.5.0
+Date: Friday February 24 2023
+Revision: ba3388ace34eab65010dc12e2c0c4c009cb39f4b
+CPEPrefix: cpe:/a:aomedia:aomedia:3.6.0
 License: BSD
 License File: source/libaom/LICENSE
 Security Critical: yes
diff --git a/third_party/libaom/libaom_srcs.gni b/third_party/libaom/libaom_srcs.gni
index 4efc431..688338b 100644
--- a/third_party/libaom/libaom_srcs.gni
+++ b/third_party/libaom/libaom_srcs.gni
@@ -323,6 +323,7 @@
   "//third_party/libaom/source/libaom/av1/encoder/motion_search_facade.h",
   "//third_party/libaom/source/libaom/av1/encoder/mv_prec.c",
   "//third_party/libaom/source/libaom/av1/encoder/mv_prec.h",
+  "//third_party/libaom/source/libaom/av1/encoder/nonrd_opt.c",
   "//third_party/libaom/source/libaom/av1/encoder/nonrd_opt.h",
   "//third_party/libaom/source/libaom/av1/encoder/nonrd_pickmode.c",
   "//third_party/libaom/source/libaom/av1/encoder/palette.c",
@@ -347,6 +348,8 @@
   "//third_party/libaom/source/libaom/av1/encoder/rdopt_utils.h",
   "//third_party/libaom/source/libaom/av1/encoder/reconinter_enc.c",
   "//third_party/libaom/source/libaom/av1/encoder/reconinter_enc.h",
+  "//third_party/libaom/source/libaom/av1/encoder/saliency_map.c",
+  "//third_party/libaom/source/libaom/av1/encoder/saliency_map.h",
   "//third_party/libaom/source/libaom/av1/encoder/segmentation.c",
   "//third_party/libaom/source/libaom/av1/encoder/segmentation.h",
   "//third_party/libaom/source/libaom/av1/encoder/sorting_network.h",
@@ -622,20 +625,6 @@
 
 aom_ports_asm_x86 = [ "//third_party/libaom/source/libaom/aom_ports/float.asm" ]
 
-aom_rc_interface_sources = [
-  "//third_party/libaom/source/libaom/common/y4minput.c",
-  "//third_party/libaom/source/libaom/common/y4minput.h",
-  "//third_party/libaom/source/libaom/test/codec_factory.h",
-  "//third_party/libaom/source/libaom/test/decode_test_driver.cc",
-  "//third_party/libaom/source/libaom/test/decode_test_driver.h",
-  "//third_party/libaom/source/libaom/test/encode_test_driver.cc",
-  "//third_party/libaom/source/libaom/test/encode_test_driver.h",
-  "//third_party/libaom/source/libaom/test/ratectrl_rtc_test.cc",
-  "//third_party/libaom/source/libaom/test/test_aom_rc_interface.cc",
-  "//third_party/libaom/source/libaom/test/y4m_video_source.h",
-  "//third_party/libaom/source/libaom/test/yuv_video_source.h",
-]
-
 aom_rtcd_sources = [
   "//third_party/libaom/source/libaom/aom_dsp/aom_dsp_rtcd.c",
   "//third_party/libaom/source/libaom/aom_scale/aom_scale_rtcd.c",
@@ -689,16 +678,6 @@
   "//third_party/libaom/source/libaom/common/webmenc.h",
 ]
 
-av1_rc_qmode_sources = [
-  "//third_party/libaom/source/libaom/common/tools_common.c",
-  "//third_party/libaom/source/libaom/common/tools_common.h",
-  "//third_party/libaom/source/libaom/common/y4minput.c",
-  "//third_party/libaom/source/libaom/common/y4minput.h",
-  "//third_party/libaom/source/libaom/test/ducky_encode_test.cc",
-  "//third_party/libaom/source/libaom/test/mock_ratectrl_qmode.h",
-  "//third_party/libaom/source/libaom/test/ratectrl_qmode_test.cc",
-]
-
 # Files below this line are generated by the libaom build system.
 
 aom_rtcd_sources_gen = [
@@ -714,6 +693,3 @@
 
 aom_version_sources_gen =
     [ "//third_party/libaom/source/libaom/config/aom_version.h" ]
-
-av1_rc_qmode_sources_gen =
-    [ "//third_party/libaom/source/libaom/gen_src/usage_exit.c" ]
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h
index d449b49..c24736f 100644
--- a/third_party/libaom/source/config/config/aom_version.h
+++ b/third_party/libaom/source/config/config/aom_version.h
@@ -10,10 +10,10 @@
  */
 
 #define VERSION_MAJOR 3
-#define VERSION_MINOR 5
+#define VERSION_MINOR 6
 #define VERSION_PATCH 0
-#define VERSION_EXTRA "752-g70b12695e"
+#define VERSION_EXTRA "276-gba3388ace"
 #define VERSION_PACKED \
   ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH))
-#define VERSION_STRING_NOSP "3.5.0-752-g70b12695e"
-#define VERSION_STRING " 3.5.0-752-g70b12695e"
+#define VERSION_STRING_NOSP "3.6.0-276-gba3388ace"
+#define VERSION_STRING " 3.6.0-276-gba3388ace"
diff --git a/third_party/wpt_tools/PRESUBMIT.py b/third_party/wpt_tools/PRESUBMIT.py
index 0eb104d6..87ca0efa 100644
--- a/third_party/wpt_tools/PRESUBMIT.py
+++ b/third_party/wpt_tools/PRESUBMIT.py
@@ -10,10 +10,6 @@
 
 USE_PYTHON3 = True
 
-import pathlib
-import textwrap
-
-
 def _TestWPTLint(input_api, output_api):
   # We test 'wpt lint' by deferring to the web_tests/external presubmit test,
   # which runs 'wpt lint' against web_tests/external/wpt.
@@ -59,47 +55,10 @@
   return []
 
 
-def _TestWPTRolled(input_api, output_api):
-  """Warn developers making manual changes to `wpt_tools/`."""
-  subject, *_ = input_api.change.DescriptionText().splitlines()
-  if input_api.re.search(r'\broll wpt tooling\b', subject,
-                         input_api.re.IGNORECASE):
-    return []
-
-  include_file = input_api.os_path.join(input_api.PresubmitLocalPath(),
-                                        'WPTIncludeList')
-  rolled_files = {pathlib.PurePosixPath(line)
-                  for line in input_api.ReadFile(include_file).splitlines()}
-  wpt_dir = pathlib.Path(input_api.PresubmitLocalPath()) / 'wpt'
-
-  def exclude_unrolled_files(affected_file):
-    try:
-      path_from_wpt = pathlib.Path(
-        affected_file.AbsoluteLocalPath()).relative_to(wpt_dir)
-      return pathlib.PurePosixPath(path_from_wpt.as_posix()) in rolled_files
-    except ValueError:
-      # Exclude file relative to `wpt_tools` but not to `wpt_tools/wpt`.
-      return False
-
-  if input_api.AffectedFiles(file_filter=exclude_unrolled_files):
-    message = textwrap.dedent(
-      """\
-      Thanks for your patch to `//third_party/wpt_tools/wpt`. This directory is
-      semiregularly overwritten by rolls from the upstream repo:
-        https://github.com/web-platform-tests/wpt
-
-      Please submit your change upstream as a pull request instead, then run
-      `//third_party/wpt_tools/roll_wpt.py` to pick up the change.
-      """)
-    return [output_api.PresubmitPromptWarning(message)]
-  return []
-
-
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results += _TestWPTLint(input_api, output_api)
   results += _TestWPTManifest(input_api, output_api)
-  results += _TestWPTRolled(input_api, output_api)
   return results
 
 
@@ -107,5 +66,4 @@
   results = []
   results += _TestWPTLint(input_api, output_api)
   results += _TestWPTManifest(input_api, output_api)
-  results += _TestWPTRolled(input_api, output_api)
   return results
diff --git a/tools/binary_size/libsupersize/apkanalyzer.py b/tools/binary_size/libsupersize/apkanalyzer.py
index b86b94c..7071952d 100644
--- a/tools/binary_size/libsupersize/apkanalyzer.py
+++ b/tools/binary_size/libsupersize/apkanalyzer.py
@@ -540,10 +540,11 @@
     dex_total_size: Sum of the sizes of all .dex files in the apk.
     class_deobfuscation_map: Map from obfuscated names to class names.
     size_info_prefix: Path such as: out/Release/size-info/BaseName.
-    metrics_by_file: Dict from DEX file name to a dict of {metric_name: value}.
 
   Returns:
-    A tuple of (section_ranges, raw_symbols).
+    A tuple of (section_ranges, raw_symbols, metrics_by_file), where
+    metrics_by_file is a dict from DEX file name to a dict of
+    {metric_name: value}.
   """
   logging.debug('Waiting for apkanalyzer to finish')
   apk_analyzer_result = apk_analyzer_async_result.get()
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index fc5a6bb..95c00dc 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -355,16 +355,17 @@
 
   elf_info = None
   if native_spec:
-    section_ranges, native_symbols, elf_info = native.CreateSymbols(
-        apk_spec=apk_spec,
-        native_spec=native_spec,
-        output_directory=output_directory,
-        pak_id_map=pak_id_map)
+    section_ranges, native_symbols, elf_info, native_metrics_by_file = (
+        native.CreateSymbols(apk_spec=apk_spec,
+                             native_spec=native_spec,
+                             output_directory=output_directory,
+                             pak_id_map=pak_id_map))
     add_syms(section_ranges,
              native_symbols,
              source_path_prefix=native_spec.source_path_prefix,
              component=native_spec.component,
              paths_already_normalized=True)
+    metrics_by_file.update(native_metrics_by_file)
   elif apk_spec and apk_spec.analyze_dex:
     logging.info('Analyzing DEX')
     apk_infolist = apk_file_manager.InfoList(apk_spec.apk_path)
diff --git a/tools/binary_size/libsupersize/native.py b/tools/binary_size/libsupersize/native.py
index 294f04d..9ff2f25 100644
--- a/tools/binary_size/libsupersize/native.py
+++ b/tools/binary_size/libsupersize/native.py
@@ -719,7 +719,8 @@
     pak_id_map: Instance of PakIdMap.
 
   Returns:
-    A tuple of (section_ranges, raw_symbols, elf_info).
+    A tuple of (section_ranges, raw_symbols, elf_info, metrics_by_file), where
+    metrics_by_file is a dict from file name to a dict of {metric_name: value}.
   """
   apk_elf_info_result = None
   if apk_spec and native_spec.apk_so_path:
@@ -732,6 +733,7 @@
   dwarf_source_mapper = None
   section_ranges = {}
   ninja_elf_object_paths = None
+  metrics_by_file = {}
   if output_directory and native_spec.map_path:
     # Finds all objects passed to the linker and creates a map of .o -> .cc.
     ninja_source_mapper, ninja_elf_object_paths = _ParseNinjaFiles(
@@ -804,6 +806,11 @@
 
   if elf_info:
     section_ranges = elf_info.section_ranges.copy()
+    if native_spec.elf_path:
+      metrics_by_file[posixpath.basename(native_spec.elf_path)] = {
+          'SIZE/' + k: size
+          for (k, (offset, size)) in section_ranges.items()
+      }
 
   source_path = ''
   if native_spec.apk_so_path:
@@ -848,4 +855,4 @@
     logging.debug('Connecting nm aliases')
     _ConnectNmAliases(raw_symbols)
 
-  return section_ranges, raw_symbols, elf_info
+  return section_ranges, raw_symbols, elf_info, metrics_by_file
diff --git a/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden b/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
index d8113bf6..ff7a1781 100644
--- a/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
+++ b/tools/binary_size/libsupersize/testdata/ArchiveContainers.golden
@@ -446,7 +446,9 @@
 <Container1:>.other@0(size_without_padding=0,padding=818,full_name=Overhead: APK file,object_path=,source_path=,flags={},num_aliases=1,component=)
 MetricsByFile:
 Container1:/test.so (armeabi-v7a)
+elf={'SIZE/.ARM.attributes': 60, 'SIZE/.ARM.exidx': 1536456, 'SIZE/.ARM.extab': 183632, 'SIZE/.bss': 1300456, 'SIZE/.data': 101768, 'SIZE/.data.rel.ro': 1065224, 'SIZE/.data.rel.ro.local': 790024, 'SIZE/.dynamic': 304, 'SIZE/.dynstr': 4025, 'SIZE/.dynsym': 6496, 'SIZE/.fini_array': 8, 'SIZE/.gnu.version': 812, 'SIZE/.gnu.version_d': 28, 'SIZE/.gnu.version_r': 96, 'SIZE/.got': 42956, 'SIZE/.hash': 2684, 'SIZE/.init_array': 8, 'SIZE/.interp': 19, 'SIZE/.note.gnu.build-id': 36, 'SIZE/.note.gnu.gold-version': 28, 'SIZE/.plt': 4244, 'SIZE/.rel.dyn': 2655384, 'SIZE/.rel.plt': 2816, 'SIZE/.rodata': 5927652, 'SIZE/.shstrtab': 436, 'SIZE/.strtab': 34841854, 'SIZE/.symtab': 17166112, 'SIZE/.text': 35982248}
 Container2:
+elf={'SIZE/.ARM.attributes': 60, 'SIZE/.ARM.exidx': 1536456, 'SIZE/.ARM.extab': 183632, 'SIZE/.bss': 1300456, 'SIZE/.data': 101768, 'SIZE/.data.rel.ro': 1065224, 'SIZE/.data.rel.ro.local': 790024, 'SIZE/.dynamic': 304, 'SIZE/.dynstr': 4025, 'SIZE/.dynsym': 6496, 'SIZE/.fini_array': 8, 'SIZE/.gnu.version': 812, 'SIZE/.gnu.version_d': 28, 'SIZE/.gnu.version_r': 96, 'SIZE/.got': 42956, 'SIZE/.hash': 2684, 'SIZE/.init_array': 8, 'SIZE/.interp': 19, 'SIZE/.note.gnu.build-id': 36, 'SIZE/.note.gnu.gold-version': 28, 'SIZE/.plt': 4244, 'SIZE/.rel.dyn': 2655384, 'SIZE/.rel.plt': 2816, 'SIZE/.rodata': 5927652, 'SIZE/.shstrtab': 436, 'SIZE/.strtab': 34841854, 'SIZE/.symtab': 17166112, 'SIZE/.text': 35982248}
 Container1:/smalltest.so (x86)
 Container1:
 classes.dex={'COUNT/ANNOTATION': 1, 'COUNT/ANNOTATIONS_DIRECTORY': 1, 'COUNT/ANNOTATION_SET': 2, 'COUNT/CLASS_DATA': 2, 'COUNT/CLASS_DEF': 2, 'COUNT/CODE': 8, 'COUNT/DEBUG_INFO': 8, 'COUNT/ENCODED_ARRAY': 1, 'COUNT/FIELD_ID': 2, 'COUNT/HEADER': 1, 'COUNT/MAP': 1, 'COUNT/METHOD_ID': 14, 'COUNT/PROTO_ID': 10, 'COUNT/STRING_DATA': 40, 'COUNT/STRING_ID': 40, 'COUNT/TYPE': 6, 'COUNT/TYPE_ID': 13, 'SIZE/ANNOTATION': 8, 'SIZE/ANNOTATIONS_DIRECTORY': 24, 'SIZE/ANNOTATION_SET': 12, 'SIZE/CLASS_DATA': 48, 'SIZE/CLASS_DEF': 64, 'SIZE/CODE': 432, 'SIZE/DEBUG_INFO': 72, 'SIZE/ENCODED_ARRAY': 4, 'SIZE/FIELD_ID': 16, 'SIZE/HEADER': 112, 'SIZE/MAP': 208, 'SIZE/METHOD_ID': 112, 'SIZE/PROTO_ID': 120, 'SIZE/STRING_DATA': 522, 'SIZE/STRING_ID': 160, 'SIZE/TYPE': 50, 'SIZE/TYPE_ID': 52}
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version
index add67a2..d47725f7 100644
--- a/tools/cast3p/runtime.version
+++ b/tools/cast3p/runtime.version
@@ -1 +1 @@
-345874
+346625
diff --git a/tools/clang/scripts/upload_revision.py b/tools/clang/scripts/upload_revision.py
index ab766ff..2ca01c6 100755
--- a/tools/clang/scripts/upload_revision.py
+++ b/tools/clang/scripts/upload_revision.py
@@ -74,11 +74,20 @@
 Cq-Include-Trybots: chrome/try:linux-chromeos-chrome
 Cq-Include-Trybots: chrome/try:win-chrome,win64-chrome,linux-chrome,mac-chrome
 Cq-Include-Trybots: chrome/try:linux-pgo,mac-pgo,win32-pgo,win64-pgo
-Cq-Include-Trybots: luci.chromium.try:android-rust-arm-dbg
-Cq-Include-Trybots: luci.chromium.try:android-rust-arm-rel
+'''
+
+RUST_BOTS = \
+'''
+Cq-Include-Trybots: luci.chromium.try:android-rust-arm32-rel
 Cq-Include-Trybots: luci.chromium.try:linux-rust-x64-dbg
 Cq-Include-Trybots: luci.chromium.try:linux-rust-x64-rel
 '''
+# TODO: Add more Rust bots as they are ready:
+# Cq-Include-Trybots: luci.chromium.try:android-rust-arm64-dbg
+# Cq-Include-Trybots: luci.chromium.try:android-rust-arm64-rel
+# Cq-Include-Trybots: luci.chromium.try:win-rust-x64-dbg
+# Cq-Include-Trybots: luci.chromium.try:win-rust-x64-rel
+# Cq-Include-Trybots: luci.chromium.try:mac-rust-x64-rel
 
 is_win = sys.platform.startswith('win32')
 
@@ -347,6 +356,8 @@
   body = f'{clang_change_log}{rust_change_log}Ran: {cmd}'
 
   commit_message = f'{title}\n\n{body}\n{COMMIT_FOOTER}'
+  if args.roll_rust:
+    commit_message += f'{RUST_BOTS}'
 
   Git('add',
       CLANG_UPDATE_PY_PATH,
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index b9826db3..20ea9a8 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -730,10 +730,14 @@
     },
 
     'chromium.rust': {
-      'android-rust-arm-dbg': 'debug_bot_rust_android_arm_reclient',
-      'android-rust-arm-rel': 'release_rust_android_arm_reclient',
-      'linux-rust-x64-dbg': 'debug_bot_rust_linux_x64_reclient',
-      'linux-rust-x64-rel': 'release_rust_linux_x64_reclient',
+      'android-rust-arm32-rel': 'release_rust_android_arm32_reclient',
+      'android-rust-arm64-dbg': 'debug_bot_rust_android_arm64_reclient',
+      'android-rust-arm64-rel': 'release_rust_android_arm64_reclient',
+      'linux-rust-x64-dbg': 'debug_bot_rust_desktop_x64_reclient',
+      'linux-rust-x64-rel': 'release_rust_desktop_x64_reclient',
+      'mac-rust-x64-rel': 'release_rust_desktop_x64_reclient',
+      'win-rust-x64-dbg': 'debug_bot_rust_desktop_x64_reclient',
+      'win-rust-x64-rel': 'release_rust_desktop_x64_reclient',
     },
 
     'chromium.swangle': {
@@ -937,9 +941,7 @@
       'chromeos-trogdor64-chrome-skylab': 'chromeos_trogdor64_include_unwind_tables_official_dchecks_skylab',
       'lacros-amd64-generic-chrome': 'chromeos_amd64-generic_lacros_official_no_symbols',
       'lacros-amd64-generic-chrome-skylab': 'chromeos_amd64-generic_lacros_official_skylab',
-      'lacros-arm-generic-chrome': 'chromeos_arm-generic_lacros_official',
       'lacros-arm-generic-chrome-skylab': 'chromeos_arm-generic_lacros_official_skylab',
-      'lacros-arm64-generic-chrome': 'chromeos_arm64-generic_lacros_official',
       'lacros-arm64-generic-chrome-skylab': 'chromeos_arm64-generic_lacros_official_skylab',
       'linux-chrome': 'official_goma',
       'linux-chrome-beta': 'official_goma',
@@ -1324,11 +1326,15 @@
     },
 
     'tryserver.chromium.rust': {
-      'android-rust-arm-dbg': 'debug_bot_rust_android_arm_reclient',
-      'android-rust-arm-rel': 'release_rust_android_arm_reclient',
-      'linux-rust-x64-dbg': 'debug_bot_rust_linux_x64_reclient',
-      'linux-rust-x64-rel': 'release_rust_linux_x64_reclient',
+      'android-rust-arm32-rel': 'release_rust_android_arm32_reclient',
+      'android-rust-arm64-dbg': 'debug_bot_rust_android_arm64_reclient',
+      'android-rust-arm64-rel': 'release_rust_android_arm64_reclient',
+      'linux-rust-x64-dbg': 'debug_bot_rust_desktop_x64_reclient',
+      'linux-rust-x64-rel': 'release_rust_desktop_x64_reclient',
       'linux-rust-x64-rel-android-toolchain': 'release_rust_linux_x64_android_toolchain_reclient',
+      'mac-rust-x64-rel': 'release_rust_desktop_x64_reclient',
+      'win-rust-x64-dbg': 'debug_bot_rust_desktop_x64_reclient',
+      'win-rust-x64-rel': 'release_rust_desktop_x64_reclient',
     },
 
     'tryserver.chromium.swangle': {
@@ -2053,9 +2059,6 @@
       'chromeos_device_reclient', 'arm-generic', 'dcheck_always_on', 'ozone_headless'
     ],
 
-    'chromeos_arm-generic_lacros_official': [
-      'chromeos_arm-generic-crostoolchain', 'lacros', 'official', 'minimal_symbols', 'cfi', 'thin_lto',
-    ],
     'chromeos_arm-generic_lacros_official_reclient': [
       'chromeos_arm-generic-crostoolchain_reclient', 'lacros', 'official', 'minimal_symbols', 'cfi', 'thin_lto',
     ],
@@ -2094,9 +2097,6 @@
       'chromeos_device_reclient', 'arm64-generic', 'dcheck_always_on', 'ozone_headless'
     ],
 
-    'chromeos_arm64-generic_lacros_official': [
-      'chromeos_arm64-generic-crostoolchain', 'lacros', 'official', 'minimal_symbols', 'cfi', 'thin_lto',
-    ],
     'chromeos_arm64-generic_lacros_official_reclient': [
       'chromeos_arm64-generic-crostoolchain_reclient', 'lacros', 'official', 'minimal_symbols', 'cfi', 'thin_lto',
     ],
@@ -2473,11 +2473,11 @@
       'debug_bot_reclient',
     ],
 
-    'debug_bot_rust_android_arm_reclient': [
-      'debug_bot_reclient', 'enable_rust', 'android', 'arm',
+    'debug_bot_rust_android_arm64_reclient': [
+      'debug_bot_reclient', 'enable_rust', 'android', 'arm64',
     ],
 
-    'debug_bot_rust_linux_x64_reclient': [
+    'debug_bot_rust_desktop_x64_reclient': [
       'debug_bot_reclient', 'enable_rust', 'x64',
     ],
 
@@ -3458,18 +3458,21 @@
       'release', 'official_optimize_reclient', 'fuchsia', 'arm64', 'cast_receiver_size_optimized',
     ],
 
-    'release_rust_android_arm_reclient': [
+    'release_rust_android_arm32_reclient': [
       'release_trybot_minimal_symbols_reclient', 'enable_rust', 'android', 'arm',
     ],
+    'release_rust_android_arm64_reclient': [
+      'release_trybot_minimal_symbols_reclient', 'enable_rust', 'android', 'arm64',
+    ],
+
+    'release_rust_desktop_x64_reclient': [
+      'release_trybot_minimal_symbols_reclient', 'enable_rust', 'x64',
+    ],
 
     'release_rust_linux_x64_android_toolchain_reclient': [
       'release_trybot_minimal_symbols_reclient', 'enable_rust', 'use_android_rust_toolchain', 'x64',
     ],
 
-    'release_rust_linux_x64_reclient': [
-      'release_trybot_minimal_symbols_reclient', 'enable_rust', 'x64',
-    ],
-
     'release_trybot': [
       'release_trybot',
     ],
diff --git a/tools/mb/mb_config_expectations/chromium.rust.json b/tools/mb/mb_config_expectations/chromium.rust.json
index 98d7eb7..230f011 100644
--- a/tools/mb/mb_config_expectations/chromium.rust.json
+++ b/tools/mb/mb_config_expectations/chromium.rust.json
@@ -1,19 +1,5 @@
 {
-  "android-rust-arm-dbg": {
-    "gn_args": {
-      "debuggable_apks": false,
-      "enable_rust": true,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": true,
-      "is_debug": true,
-      "proprietary_codecs": true,
-      "symbol_level": 1,
-      "target_cpu": "arm",
-      "target_os": "android",
-      "use_remoteexec": true
-    }
-  },
-  "android-rust-arm-rel": {
+  "android-rust-arm32-rel": {
     "gn_args": {
       "dcheck_always_on": true,
       "debuggable_apks": false,
@@ -28,6 +14,35 @@
       "use_remoteexec": true
     }
   },
+  "android-rust-arm64-dbg": {
+    "gn_args": {
+      "debuggable_apks": false,
+      "enable_rust": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": true,
+      "is_debug": true,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "arm64",
+      "target_os": "android",
+      "use_remoteexec": true
+    }
+  },
+  "android-rust-arm64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "debuggable_apks": false,
+      "enable_rust": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "arm64",
+      "target_os": "android",
+      "use_remoteexec": true
+    }
+  },
   "linux-rust-x64-dbg": {
     "gn_args": {
       "enable_rust": true,
@@ -48,5 +63,37 @@
       "target_cpu": "x64",
       "use_remoteexec": true
     }
+  },
+  "mac-rust-x64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "enable_rust": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
+  },
+  "win-rust-x64-dbg": {
+    "gn_args": {
+      "enable_rust": true,
+      "is_component_build": true,
+      "is_debug": true,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
+  },
+  "win-rust-x64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "enable_rust": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
   }
 }
\ No newline at end of file
diff --git a/tools/mb/mb_config_expectations/tryserver.chrome.json b/tools/mb/mb_config_expectations/tryserver.chrome.json
index 7b117e5..c4a3f25 100644
--- a/tools/mb/mb_config_expectations/tryserver.chrome.json
+++ b/tools/mb/mb_config_expectations/tryserver.chrome.json
@@ -289,22 +289,6 @@
       "use_thin_lto": true
     }
   },
-  "lacros-arm-generic-chrome": {
-    "args_file": "//build/args/chromeos/arm-generic-crostoolchain.gni",
-    "gn_args": {
-      "chromeos_is_browser_only": true,
-      "dcheck_always_on": false,
-      "is_cfi": true,
-      "is_chrome_branded": true,
-      "is_chromeos_device": true,
-      "is_official_build": true,
-      "ozone_platform_headless": true,
-      "symbol_level": 1,
-      "target_os": "chromeos",
-      "use_goma": true,
-      "use_thin_lto": true
-    }
-  },
   "lacros-arm-generic-chrome-skylab": {
     "args_file": "//build/args/chromeos/arm-generic-crostoolchain.gni",
     "gn_args": {
@@ -322,22 +306,6 @@
       "use_thin_lto": true
     }
   },
-  "lacros-arm64-generic-chrome": {
-    "args_file": "//build/args/chromeos/arm64-generic-crostoolchain.gni",
-    "gn_args": {
-      "chromeos_is_browser_only": true,
-      "dcheck_always_on": false,
-      "is_cfi": true,
-      "is_chrome_branded": true,
-      "is_chromeos_device": true,
-      "is_official_build": true,
-      "ozone_platform_headless": true,
-      "symbol_level": 1,
-      "target_os": "chromeos",
-      "use_goma": true,
-      "use_thin_lto": true
-    }
-  },
   "lacros-arm64-generic-chrome-skylab": {
     "args_file": "//build/args/chromeos/arm64-generic-crostoolchain.gni",
     "gn_args": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.rust.json b/tools/mb/mb_config_expectations/tryserver.chromium.rust.json
index f527bda..94b18f3 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.rust.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.rust.json
@@ -1,19 +1,5 @@
 {
-  "android-rust-arm-dbg": {
-    "gn_args": {
-      "debuggable_apks": false,
-      "enable_rust": true,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": true,
-      "is_debug": true,
-      "proprietary_codecs": true,
-      "symbol_level": 1,
-      "target_cpu": "arm",
-      "target_os": "android",
-      "use_remoteexec": true
-    }
-  },
-  "android-rust-arm-rel": {
+  "android-rust-arm32-rel": {
     "gn_args": {
       "dcheck_always_on": true,
       "debuggable_apks": false,
@@ -28,6 +14,35 @@
       "use_remoteexec": true
     }
   },
+  "android-rust-arm64-dbg": {
+    "gn_args": {
+      "debuggable_apks": false,
+      "enable_rust": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": true,
+      "is_debug": true,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "arm64",
+      "target_os": "android",
+      "use_remoteexec": true
+    }
+  },
+  "android-rust-arm64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "debuggable_apks": false,
+      "enable_rust": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "arm64",
+      "target_os": "android",
+      "use_remoteexec": true
+    }
+  },
   "linux-rust-x64-dbg": {
     "gn_args": {
       "enable_rust": true,
@@ -60,5 +75,37 @@
       "use_chromium_rust_toolchain": false,
       "use_remoteexec": true
     }
+  },
+  "mac-rust-x64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "enable_rust": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
+  },
+  "win-rust-x64-dbg": {
+    "gn_args": {
+      "enable_rust": true,
+      "is_component_build": true,
+      "is_debug": true,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
+  },
+  "win-rust-x64-rel": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "enable_rust": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x64",
+      "use_remoteexec": true
+    }
   }
 }
\ No newline at end of file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 7b75595..c5b3a866 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -42310,7 +42310,7 @@
   <int value="4442" label="PrivateNetworkAccessFetchedSubFrame"/>
   <int value="4443" label="PrivateNetworkAccessFetchedTopFrame"/>
   <int value="4444" label="DisableThirdPartyStoragePartitioning"/>
-  <int value="4445" label="ServiceWorkerFetchHandlerUpdateAfterInitialization"/>
+  <int value="4445" label="ServiceWorkerFetchHandlerAddedAfterInitialization"/>
   <int value="4446" label="ObsoleteCreateImageBitmapImageOrientationNone"/>
   <int value="4447" label="WindowManagementPermissionDescriptorUsed"/>
   <int value="4448" label="WindowPlacementPermissionDescriptorUsed"/>
@@ -42336,9 +42336,9 @@
   <int value="4465" label="PopoverTypeManual"/>
   <int value="4466" label="PopoverTypeInvalid"/>
   <int value="4467" label="CSSAnchorPositioning"/>
-  <int value="4468" label="ServiceWorkerAddHandlerAfterInitialization"/>
+  <int value="4468" label="ServiceWorkerEventHandlerAddedAfterInitialization"/>
   <int value="4469"
-      label="ServiceWorkerSetAttributeHandlerAfterInitialization"/>
+      label="ServiceWorkerEventHandlerModifiedAfterInitialization"/>
   <int value="4470" label="AuthorizationCrossOrigin"/>
   <int value="4471" label="CSSColorMixFunction"/>
   <int value="4472" label="CSSColorColorSpecifiedSpace"/>
@@ -56510,6 +56510,7 @@
   <int value="31" label="URL handler"/>
   <int value="32" label="Lock screen"/>
   <int value="33" label="App Home Page (chrome://apps)"/>
+  <int value="34" label="Reparenting"/>
 </enum>
 
 <enum name="LaunchType">
@@ -58436,6 +58437,7 @@
   <int value="-1876955850" label="EnablePciguardUi:enabled"/>
   <int value="-1876881908"
       label="disable-infobar-for-protected-media-identifier"/>
+  <int value="-1875836063" label="UserNotes:disabled"/>
   <int value="-1875383510" label="UseGoogleLocalNtp:disabled"/>
   <int value="-1875168316" label="UseMonitorColorSpace:disabled"/>
   <int value="-1874908826" label="enable-instant-search-clicks"/>
@@ -58489,7 +58491,6 @@
   <int value="-1847775690"
       label="DiacriticsOnPhysicalKeyboardLongpress:disabled"/>
   <int value="-1846680525" label="WebUIA11yEnhancements:enabled"/>
-  <int value="-1846613349" label="OmniboxActiveSearchEngines:disabled"/>
   <int value="-1846471618"
       label="enable-experimental-accessibility-switch-access-text"/>
   <int value="-1844754731" label="Mash:disabled"/>
@@ -59263,6 +59264,7 @@
   <int value="-1415244717" label="CrostiniVirtualKeyboardSupport:disabled"/>
   <int value="-1414699084" label="CameraAppLowStorageWarning:enabled"/>
   <int value="-1414531531" label="NtpModulesRedesignedLayout:disabled"/>
+  <int value="-1414207639" label="RequestDesktopSiteDefaultsLogging:enabled"/>
   <int value="-1412230070" label="query-tiles-instant-background-task"/>
   <int value="-1411980923" label="LinkCapturingUiUpdate:enabled"/>
   <int value="-1411733990" label="OmniboxDedupeGoogleDriveURLs:disabled"/>
@@ -60768,6 +60770,7 @@
       label="WebAuthenticationPasskeysUIExperiment:enabled"/>
   <int value="-582870536" label="BluetoothNextHandsfreeProfile:enabled"/>
   <int value="-582570706" label="PPAPISharedImagesSwapChain:disabled"/>
+  <int value="-582300629" label="UserNotes:enabled"/>
   <int value="-581236612" label="ConnectivityDiagnosticsWebUi:disabled"/>
   <int value="-580897686" label="SharedHighlightingAmp:enabled"/>
   <int value="-579656054" label="CCTResizableSideSheetForThirdParties:enabled"/>
@@ -60789,7 +60792,6 @@
   <int value="-571655232" label="SideSearch:enabled"/>
   <int value="-571236436" label="AppManagement:disabled"/>
   <int value="-570889908" label="CCTModuleDexLoading:enabled"/>
-  <int value="-570572517" label="OmniboxActiveSearchEngines:enabled"/>
   <int value="-570005880"
       label="AutofillFixServerQueriesIfPasswordManagerIsEnabled:disabled"/>
   <int value="-569256428" label="MacAddressRandomization:enabled"/>
@@ -63379,6 +63381,7 @@
   <int value="913138924" label="RecurrentInterstitialFeature:disabled"/>
   <int value="913855453" label="VirtualKeyboardFloatingResizable:disabled"/>
   <int value="914708297" label="CCTResizableAllowResizeByUserGesture:enabled"/>
+  <int value="915046146" label="RequestDesktopSiteDefaultsLogging:disabled"/>
   <int value="915402820" label="RequestDesktopSiteExceptions:disabled"/>
   <int value="916316159" label="disable-new-app-list-mixer"/>
   <int value="916841877" label="OmniboxMostVisitedTilesFadingOnTablet:enabled"/>
@@ -64334,6 +64337,7 @@
   <int value="1454527518" label="ArcNativeBridgeExperiment:enabled"/>
   <int value="1455881930" label="V8VmFuture:enabled"/>
   <int value="1455970119" label="MacCoreLocationBackend:disabled"/>
+  <int value="1457383851" label="NtpHistoryClustersModule:disabled"/>
   <int value="1457465866" label="TouchToFillPasswordSubmission:disabled"/>
   <int value="1458041527" label="ShowScrollableMVTOnNTPAndroid:enabled"/>
   <int value="1458085218" label="MultiDisplayOverviewAndSplitView:disabled"/>
@@ -65535,6 +65539,7 @@
   <int value="2126030721" label="VCBackgroundBlur:disabled"/>
   <int value="2126203058" label="force-show-update-menu-badge"/>
   <int value="2127648677" label="OmniboxExperimentalSuggestScoring:disabled"/>
+  <int value="2127700228" label="NtpHistoryClustersModule:enabled"/>
   <int value="2129184006" label="NTPOfflinePageDownloadSuggestions:enabled"/>
   <int value="2129524809" label="PasswordCheck:disabled"/>
   <int value="2129639191" label="ArcWindowPredictor:disabled"/>
@@ -76998,6 +77003,8 @@
   <int value="1206" label="Add Input Method"/>
   <int value="1207" label="Spell Check"/>
   <int value="1208" label="Show Predictive Writing"/>
+  <int value="1209" label="Show PK Auto-correction"/>
+  <int value="1210" label="Show VK Auto-correction"/>
   <int value="1300" label="Google Drive Connection"/>
   <int value="1400" label="Add Printer"/>
   <int value="1401" label="Saved Printers"/>
@@ -77236,6 +77243,7 @@
   <int value="1508" label="Cursor And Touchpad Page"/>
   <int value="1509" label="Audio And Captions Page"/>
   <int value="1510" label="Select-to-speak Subpage"/>
+  <int value="1511" label="ChromeVox Subpage"/>
   <int value="1700" label="About Chrome OS Details"/>
   <int value="1701" label="Detailed Build Info"/>
   <int value="1800" label="Kerberos Accounts V2"/>
@@ -81906,6 +81914,7 @@
   <int value="29" label="DOWNLOAD_FAILED_403"/>
   <int value="30" label="DOWNLOAD_FAILED_404"/>
   <int value="31" label="DOWNLOAD_SIZE_MISMATCH"/>
+  <int value="32" label="EXISTING_IMAGE_INVALID"/>
 </enum>
 
 <enum name="PluginVmSetupResult">
@@ -109152,6 +109161,7 @@
   <int value="-512116630" label="/search"/>
   <int value="-442978022" label="/networks"/>
   <int value="-378866134" label="/networkDetail"/>
+  <int value="-358922358" label="/textToSpeech/chromeVox"/>
   <int value="-319293467" label="/multidevice"/>
   <int value="-295702530" label="/smbShares"/>
   <int value="-237154443" label="/manageAccessibility/tts/googleTtsEngine"/>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 94cd663c..3709b00 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -357,6 +357,9 @@
 
 <histogram name="Extensions.BookmarkAppLaunchContainer"
     enum="AppLaunchContainer" expires_after="2023-08-14">
+  <obsolete>
+    Replaced by WebApp.LaunchContainer in M113.
+  </obsolete>
   <owner>phillis@chromium.org</owner>
   <owner>benwells@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
@@ -369,6 +372,9 @@
 
 <histogram name="Extensions.BookmarkAppLaunchSource" enum="AppLaunchSource"
     expires_after="2023-07-09">
+  <obsolete>
+    Replaced by WebApp.LaunchSource in M113.
+  </obsolete>
   <owner>phillis@chromium.org</owner>
   <owner>benwells@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index 352906f..028c00e 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1264,6 +1264,46 @@
 </histogram>
 
 <histogram
+    name="History.Clusters.Backend.UpdateClusterTriggerability.DidUpdateClusterTriggerability{Segment}"
+    enum="Boolean" expires_after="2023-10-01">
+  <owner>sophiechang@chromium.org</owner>
+  <owner>chrome-journeys@google.com</owner>
+  <component>UI&gt;Browser&gt;Journeys</component>
+  <summary>
+    On navigation, context clusters are created, grown, and persisted.
+
+    On startup and every 1 hour afterwards, these context clusters have their
+    triggability calculated. Context clusters older than 2 hours are not updated
+    are not re-updated after the initial triggability is calculated. However, if
+    there are unclustered visits (due to visits from before the user had context
+    clustering enabled or synced visits without a cluster ID), they will also be
+    context clustered with their triggerability calculated as well.
+
+    When a user visits the Journeys WebUI, persisted clusters (both those with
+    and without triggerability calculated) are fetched. Clusters are then
+    augmented with appropriate metadata needed for displaying on the Journeys
+    WebUI (e.g. ranking, deduping, labeling).
+
+    When the keyword cache used to match omnibox inputs and show journey chips
+    or suggestions in the omnibox needs updating, context clusters (both those
+    with and without triggerability calculated) are fetched.
+
+    This histogram records whether there was at least one cluster's
+    triggerability was updated {Segment}.
+
+    Recorded for every batch of clusters to be updated; can be recorded more
+    than once every hour (Finch-configurable).
+  </summary>
+  <token key="Segment">
+    <variant name="" summary="during a run of the task"/>
+    <variant name=".AfterFilteredClustersEmpty"
+        summary="after a call to fetch persisted clusters returned only
+                 clusters that have all had their triggerability calculated
+                 already"/>
+  </token>
+</histogram>
+
+<histogram
     name="History.Clusters.Backend.UpdateClusterTriggerability.HadUnclusteredVisitsToCluster"
     enum="Boolean" expires_after="2023-10-01">
   <owner>sophiechang@chromium.org</owner>
@@ -1292,8 +1332,8 @@
     in the first run of this task. When this trends to all false, this
     additional step can get deleted.
 
-    Recorded for every batch of visits clustered; can be recorded more than once
-    every hour.
+    Recorded for every batch of clusters to be updated; can be recorded more
+    than once every hour.
   </summary>
 </histogram>
 
@@ -1325,8 +1365,8 @@
     This histogram records the latency breakdown for updating cluster
     triggerability.
 
-    Recorded for every batch of visits clustered; can be recorded more than once
-    every hour.
+    Recorded for every batch of clusters to be updated; can be recorded more
+    than once every hour.
 
     This slice records the time between the main thread requesting and
     {Segment}.
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index af292b54..1160f09 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -59,7 +59,7 @@
 </variants>
 
 <histogram name="Network.Ash.Cellular.Apn.CreateCustomApn.ApnTypes"
-    enum="ApnTypes" expires_after="2023-10-18">
+    enum="ApnTypes" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -69,7 +69,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.CreateCustomApn.AuthenticationType"
-    enum="ApnAuthenticationType" expires_after="2023-10-18">
+    enum="ApnAuthenticationType" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -79,7 +79,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.CreateCustomApn.IpType"
-    enum="ApnIpType" expires_after="2023-10-18">
+    enum="ApnIpType" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -89,14 +89,14 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.CreateCustomApn.Result"
-    enum="BooleanSuccess" expires_after="2023-10-18">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>Records the result of an attempt to create a custom APN.</summary>
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.CustomApns.Count" units="count"
-    expires_after="2023-10-18">
+    expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -106,7 +106,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.CustomApns.{CustomApnState}.Count"
-    units="count" expires_after="2023-10-18">
+    units="count" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -120,7 +120,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.DisableCustomApn.ApnTypes"
-    enum="ApnTypes" expires_after="2023-10-18">
+    enum="ApnTypes" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -130,14 +130,14 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.DisableCustomApn.Result"
-    enum="BooleanSuccess" expires_after="2023-10-18">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>Records the result of an attempt to disable a custom APN.</summary>
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.EnableCustomApn.ApnTypes"
-    enum="ApnTypes" expires_after="2023-10-18">
+    enum="ApnTypes" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -147,14 +147,14 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.EnableCustomApn.Result"
-    enum="BooleanSuccess" expires_after="2023-10-18">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>Records the result of an attempt to enable a custom APN.</summary>
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.ModifyCustomApn.ApnTypes"
-    enum="ApnTypes" expires_after="2023-10-18">
+    enum="ApnTypes" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -164,14 +164,14 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.ModifyCustomApn.Result"
-    enum="BooleanSuccess" expires_after="2023-10-18">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>Records the result of an attempt to modify a custom APN.</summary>
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.RemoveCustomApn.ApnTypes"
-    enum="ApnTypes" expires_after="2023-10-18">
+    enum="ApnTypes" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -181,14 +181,14 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.Apn.RemoveCustomApn.Result"
-    enum="BooleanSuccess" expires_after="2023-10-18">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>Records the result of an attempt to remove a custom APN.</summary>
 </histogram>
 
 <histogram name="Network.Ash.Cellular.ConfigurationFailure.Type"
-    enum="CellularConfigurationFailureType" expires_after="2023-11-01">
+    enum="CellularConfigurationFailureType" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -198,7 +198,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.ConnectionResult.{CustomApnsStatus}.All"
-    enum="ShillConnectResult" expires_after="2023-10-18">
+    enum="ShillConnectResult" expires_after="2023-12-31">
   <owner>gordonseto@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -216,7 +216,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.SimLock.Policy.Notification.Event"
-    enum="SimLockNotificationEvent" expires_after="2023-03-12">
+    enum="SimLockNotificationEvent" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>nikhilcn@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -228,7 +228,7 @@
 </histogram>
 
 <histogram name="Network.Ash.Cellular.SimLock.Policy.Notification.LockType"
-    enum="SimPinLockType" expires_after="2023-03-12">
+    enum="SimPinLockType" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>nikhilcn@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -287,7 +287,7 @@
 </histogram>
 
 <histogram name="Network.Ash.WiFi.Hidden.RemovalAttempt.Result"
-    enum="BooleanSuccess" expires_after="2023-11-09">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>chadduffin@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -302,7 +302,7 @@
 </histogram>
 
 <histogram name="Network.Ash.WiFi.Hidden.{LoginStatus}" enum="Boolean"
-    expires_after="2023-11-09">
+    expires_after="2023-12-31">
   <owner>chadduffin@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -316,7 +316,7 @@
 </histogram>
 
 <histogram name="Network.Ash.{NetworkType}.ConnectionResult.All"
-    enum="ShillConnectResult" expires_after="2023-11-01">
+    enum="ShillConnectResult" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -330,7 +330,7 @@
 </histogram>
 
 <histogram name="Network.Ash.{NetworkType}.ConnectionResult.UserInitiated"
-    enum="UserInitiatedNetworkConnectResult" expires_after="2023-11-01">
+    enum="UserInitiatedNetworkConnectResult" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -341,7 +341,7 @@
 </histogram>
 
 <histogram name="Network.Ash.{NetworkType}.DisconnectionsWithoutUserAction"
-    enum="NetworkConnectionState" expires_after="2023-11-01">
+    enum="NetworkConnectionState" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -352,7 +352,7 @@
 </histogram>
 
 <histogram name="Network.Ash.{TechnologyType}.EnabledState.{Operation}.Result"
-    enum="BooleanSuccess" expires_after="2023-11-01">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -373,7 +373,7 @@
 
 <histogram
     name="Network.Ash.{TechnologyType}.EnabledState.{Operation}.ResultCode"
-    enum="ShillConnectResult" expires_after="2023-08-01">
+    enum="ShillConnectResult" expires_after="2023-12-31">
   <owner>nikhilcn@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -489,7 +489,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.Apn.UseAttachApnOnSave" enum="Boolean"
-    expires_after="2023-05-18">
+    expires_after="2023-12-31">
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -500,7 +500,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.DisableProfile.Result"
-    enum="HermesResponseStatus" expires_after="2023-10-13">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -513,7 +513,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.EnableProfile.Result"
-    enum="HermesResponseStatus" expires_after="2023-09-01">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -526,7 +526,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Installation.NonUserErrorSuccessRate"
-    enum="HermesResponseStatus" expires_after="2023-07-30">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>nikhilcn@chromium.org</owner>
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -543,7 +543,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallationResult"
-    enum="NetworkCellularESimInstallResult" expires_after="2023-04-09">
+    enum="NetworkCellularESimInstallResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -593,7 +593,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallViaQrCode.Result"
-    enum="HermesResponseStatus" expires_after="2023-04-09">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -609,7 +609,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.BlockNonManagedCellularBehavior"
-    enum="NetworkBlockNonManagedCellularBehavior" expires_after="2023-08-08">
+    enum="NetworkBlockNonManagedCellularBehavior" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -648,7 +648,7 @@
 
 <histogram
     name="Network.Cellular.ESim.Policy.ESimInstall.OperationResult{OperationType}"
-    enum="NetworkCellularESimInstallResult" expires_after="2023-09-01">
+    enum="NetworkCellularESimInstallResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -668,7 +668,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.EuiccStatusUploadResult"
-    enum="BooleanSuccess" expires_after="2023-08-08">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -682,7 +682,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.ResetEuicc.Duration" units="ms"
-    expires_after="2023-09-01">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -692,7 +692,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.ResetEuicc.Result"
-    enum="NetworkCellularResetEuiccResult" expires_after="2023-09-01">
+    enum="NetworkCellularResetEuiccResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -705,7 +705,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.ServiceAtLogin.Count"
-    units="units" expires_after="2023-08-08">
+    units="units" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -716,7 +716,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.StatusAtLogin"
-    enum="NetworkESimPolicyStatusAtLogin" expires_after="2023-08-08">
+    enum="NetworkESimPolicyStatusAtLogin" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -741,7 +741,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Policy.Usage.Duration" units="seconds"
-    expires_after="2023-09-01">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -753,7 +753,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.ProfileDiscovery.Latency" units="ms"
-    expires_after="2023-11-01">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -800,7 +800,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.RequestPendingProfiles.Latency"
-    units="ms" expires_after="2023-09-01">
+    units="ms" expires_after="2023-12-31">
   <owner>nikhilcn@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -812,7 +812,7 @@
 
 <histogram name="Network.Cellular.ESim.RequestPendingProfiles.OperationResult"
     enum="NetworkCellularESimRequestPendingProfilesResult"
-    expires_after="2024-01-15">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -827,7 +827,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.RequestPendingProfiles.Result"
-    enum="HermesResponseStatus" expires_after="2023-09-01">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -838,7 +838,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.ServiceAtLogin.Count" units="units"
-    expires_after="2023-01-15">
+    expires_after="2023-12-31">
   <obsolete>
     Removed as of 07/2022. This is has been replaced with a new metric that adds
     information on whether sim locking is allowed or not.
@@ -847,12 +847,13 @@
   <owner>cros-connectivity@google.com</owner>
   <summary>
     Tracks how many eSIM profiles are installed on the devices after a primary
-    user login.
+    user login. Warning: this histogram was expired from 2023-01-15 to
+    2023-01-28; data may be missing
   </summary>
 </histogram>
 
 <histogram name="Network.Cellular.ESim.SetupFlowResult"
-    enum="ESimSetupFlowResult" expires_after="2023-04-09">
+    enum="ESimSetupFlowResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -862,7 +863,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.StatusAtLogin"
-    enum="NetworkCellularESimProfileStatus" expires_after="2023-06-18">
+    enum="NetworkCellularESimProfileStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -874,7 +875,7 @@
 
 <histogram name="Network.Cellular.ESim.UninstallProfile.OperationResult"
     enum="NetworkCellularESimUninstallOperationResult"
-    expires_after="2023-10-13">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -888,7 +889,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.UninstallProfile.Result"
-    enum="HermesResponseStatus" expires_after="2023-10-13">
+    enum="HermesResponseStatus" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -899,7 +900,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.Usage.Count" enum="NetworkCellularUsage"
-    expires_after="2023-06-04">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -929,7 +930,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.InhibitResult"
-    enum="NetworkCellularInhibitResult" expires_after="2023-09-01">
+    enum="NetworkCellularInhibitResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -941,7 +942,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.Pin.{SimPinOperation}"
-    enum="SimPinOperationResult" expires_after="2023-06-01">
+    enum="SimPinOperationResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -968,7 +969,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PrepareCellularConnection.OperationResult"
-    enum="NetworkCellularPrepareForConnectionResult" expires_after="2023-07-30">
+    enum="NetworkCellularPrepareForConnectionResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -982,7 +983,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.OtaActivationResult"
-    enum="NetworkCellularPSimActivationResult" expires_after="2023-07-09">
+    enum="NetworkCellularPSimActivationResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -993,7 +994,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.ServiceAtLogin.Count" units="units"
-    expires_after="2023-01-15">
+    expires_after="2023-12-31">
   <obsolete>
     Removed as of 07/2022. This is has been replaced with a new metric that adds
     information on whether sim locking is allowed or not.
@@ -1007,7 +1008,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.SetupFlowResult"
-    enum="PSimSetupFlowResult" expires_after="2023-11-01">
+    enum="PSimSetupFlowResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -1018,7 +1019,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.StatusAtLogin"
-    enum="NetworkCellularPSimActivationState" expires_after="2023-06-25">
+    enum="NetworkCellularPSimActivationState" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -1029,7 +1030,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.Usage.Count" enum="NetworkCellularUsage"
-    expires_after="2023-06-18">
+    expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -1039,7 +1040,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.SimPINLockPolicy.{SimPinOperation}"
-    enum="SimPinOperationResult" expires_after="2023-06-01">
+    enum="SimPinOperationResult" expires_after="2023-12-31">
   <obsolete>
     Replaced this with
     &quot;Network.Cellular.{SimPinOperation}.SimPINLockPolicy&quot; which emits
@@ -1061,7 +1062,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{AllowSIMLock}.ESim.ServiceAtLogin.Count"
-    units="units" expires_after="2024-01-15">
+    units="units" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -1075,7 +1076,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{AllowSIMLock}.PSim.ServiceAtLogin.Count"
-    units="units" expires_after="2024-01-15">
+    units="units" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -1089,7 +1090,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{SimPinOperation}.SimPINLockPolicy"
-    enum="BooleanEnabled" expires_after="2023-06-01">
+    enum="BooleanEnabled" expires_after="2023-12-31">
   <owner>nikhilcn@chromium.org</owner>
   <owner>hsuregan@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -1125,7 +1126,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{SimType}.ConnectionResult.All"
-    enum="ShillCellularConnectResult" expires_after="2022-10-01">
+    enum="ShillCellularConnectResult" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
@@ -1134,6 +1135,9 @@
     {SimType} network becomes connected from a non-connected state. When a
     {SimType} network goes from a connecting state to a disconnected state, a
     shill failure reason is emitted.
+
+    Warning: this histogram was expired from 2022-10-01 to 2023-02-28; data may
+    be missing
   </summary>
   <token key="SimType">
     <variant name="ESim"/>
@@ -1158,7 +1162,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{SimType}.DisconnectByPolicy.Result"
-    enum="BooleanSuccess" expires_after="2023-09-01">
+    enum="BooleanSuccess" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -1173,7 +1177,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.{SimType}.Disconnections"
-    enum="NetworkCellularConnectionState" expires_after="2023-09-01">
+    enum="NetworkCellularConnectionState" expires_after="2023-12-31">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -1515,7 +1519,7 @@
 </histogram>
 
 <histogram name="Network.Patchpanel.ArcService"
-    enum="NetworkPatchpanelArcEvent" expires_after="2023-07-16">
+    enum="NetworkPatchpanelArcEvent" expires_after="2023-12-31">
   <owner>hugobenichi@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -1530,7 +1534,7 @@
 </histogram>
 
 <histogram name="Network.Patchpanel.Dbus" enum="NetworkPatchpanelDbusEvent"
-    expires_after="2023-05-07">
+    expires_after="2023-12-31">
   <owner>hugobenichi@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -1554,16 +1558,6 @@
   </summary>
 </histogram>
 
-<histogram name="Network.Radio.PossibleWakeupTrigger.RadioUtilsOverhead"
-    units="ms" expires_after="2023-04-09">
-  <owner>bashi@chromium.org</owner>
-  <owner>blink-network-stack@google.com</owner>
-  <summary>
-    Records overheads of calling Android's RadioUtils APIs. Only recorded on
-    Android.
-  </summary>
-</histogram>
-
 <histogram name="Network.Radio.SimpleURLLoaderIsThrottled" enum="Boolean"
     expires_after="2023-06-25">
   <owner>bashi@chromium.org</owner>
@@ -1636,7 +1630,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.ConnectResult"
-    enum="PlatformCellularConnectResult" expires_after="2023-07-16">
+    enum="PlatformCellularConnectResult" expires_after="2023-12-31">
   <owner>danielwinkler@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
@@ -2273,7 +2267,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.Ikev2.AuthenticationType"
-    enum="VPNIPsecAuthenticationType" expires_after="2023-08-20">
+    enum="VPNIPsecAuthenticationType" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2284,7 +2278,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.Ikev2.EndReason" enum="NetworkServiceError"
-    expires_after="2023-08-20">
+    expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2297,7 +2291,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.L2tpIpsec.SwanctlEndReason"
-    enum="NetworkServiceError" expires_after="2023-06-25">
+    enum="NetworkServiceError" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2311,7 +2305,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.L2tpIpsecTunnelGroupUsage"
-    enum="VPNL2TPIPsecTunnelGroupUsage" expires_after="2023-05-07">
+    enum="VPNL2TPIPsecTunnelGroupUsage" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2323,7 +2317,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.OpenVPNCipher" enum="VPNOpenVPNCipher"
-    expires_after="2023-06-25">
+    expires_after="2023-12-31">
   <owner>taoyl@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2418,7 +2412,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.EspEncryptionAlgorithm"
-    enum="VPNIPsecEncryptionAlgorithm" expires_after="2023-05-07">
+    enum="VPNIPsecEncryptionAlgorithm" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2431,7 +2425,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.EspIntegrityAlgorithm"
-    enum="VPNIPsecIntegrirtyAlgorithm" expires_after="2023-05-07">
+    enum="VPNIPsecIntegrirtyAlgorithm" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2444,7 +2438,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.IkeDHGroup" enum="VPNIPsecDHGroup"
-    expires_after="2023-05-07">
+    expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2457,7 +2451,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.IkeEncryptionAlgorithm"
-    enum="VPNIPsecEncryptionAlgorithm" expires_after="2023-05-07">
+    enum="VPNIPsecEncryptionAlgorithm" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2470,7 +2464,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.IkeIntegrityAlgorithm"
-    enum="VPNIPsecIntegrirtyAlgorithm" expires_after="2023-05-07">
+    enum="VPNIPsecIntegrirtyAlgorithm" expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -2483,7 +2477,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Vpn.{VPNType}.IPType" enum="VPNIPType"
-    expires_after="2023-12-01">
+    expires_after="2023-12-31">
   <owner>jiejiang@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
@@ -3550,7 +3544,7 @@
 
 <histogram name="NetworkService.MemoryCache.BlockedByRequestHeaderReason"
     enum="NetworkServiceMemoryCacheBlockedByRequestHeaderReason"
-    expires_after="2023-04-09">
+    expires_after="2023-08-28">
   <owner>bashi@chromium.org</owner>
   <owner>blink-network-stack@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index f079a74..bd01272d 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -13271,6 +13271,9 @@
 
 <histogram name="Tablet.AppDrag.EndWindowState"
     enum="AppWindowDragEndWindowState" expires_after="2022-10-01">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13281,6 +13284,9 @@
 
 <histogram name="Tablet.AppWindowDrag.CountOfPerUserSession" units="times"
     expires_after="2023-07-02">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13292,6 +13298,9 @@
 
 <histogram name="Tablet.AppWindowDrag.InSplitView.CountOfPerUserSession"
     units="times" expires_after="2023-07-02">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13313,6 +13322,9 @@
 
 <histogram name="Tablet.TabDrag.CountOfPerUserSession" units="times"
     expires_after="2023-05-01">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13324,6 +13336,9 @@
 
 <histogram name="Tablet.TabDrag.DragType" enum="TabDragType"
     expires_after="2022-12-25">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13334,6 +13349,9 @@
 
 <histogram name="Tablet.TabDrag.InSplitView.CountOfPerUserSession"
     units="times" expires_after="2023-07-02">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13345,6 +13363,9 @@
 
 <histogram name="Tablet.WindowDrag.DragEndEventType"
     enum="WindowDragEndEventType" expires_after="2023-06-11">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
@@ -13355,6 +13376,9 @@
 
 <histogram name="Tablet.WindowDrag.OpenedWindowsNumber" units="numbers"
     expires_after="2022-10-01">
+  <obsolete>
+    The corresponding feature was removed.
+  </obsolete>
   <owner>minch@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 740fb0c..62b2eed3 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -1425,7 +1425,7 @@
 </histogram>
 
 <histogram name="Power.DimEvent{PowerSource}" enum="PowerDimEvent"
-    expires_after="2023-03-01">
+    expires_after="2024-03-01">
   <owner>mqg@chromium.org</owner>
   <owner>charleszhao@chromium.org</owner>
   <summary>
@@ -2039,7 +2039,7 @@
 </histogram>
 
 <histogram name="Power.LockEvent{PowerSource}" enum="PowerLockEvent"
-    expires_after="2023-03-01">
+    expires_after="2024-03-01">
   <owner>mqg@chromium.org</owner>
   <owner>charleszhao@chromium.org</owner>
   <summary>
@@ -2408,7 +2408,7 @@
 </histogram>
 
 <histogram name="Power.{HpsEvent}.DurationSeconds" units="seconds"
-    expires_after="2023-03-01">
+    expires_after="2024-03-01">
   <owner>mqg@chromium.org</owner>
   <owner>charleszhao@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index a63c6ab..36d0cb5 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -453,7 +453,7 @@
 </histogram>
 
 <histogram name="Settings.PrivacySandbox.PromptStartupState"
-    enum="SettingsPrivacySandboxStartupStates" expires_after="2023-08-20">
+    enum="SettingsPrivacySandboxPromptStartupState" expires_after="2023-08-20">
   <owner>sauski@google.com</owner>
   <owner>olesiamarukhno@chromium.org</owner>
   <owner>msramek@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index ccf16574..664fde6 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -827,6 +827,17 @@
   </summary>
 </histogram>
 
+<histogram name="WebApp.LaunchContainer" enum="AppLaunchContainer"
+    expires_after="2023-08-14">
+  <owner>phillis@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records the container used for a web app launch, when the app is launched
+    (eg. via UI surfaces or intents). Not recorded when the web app is navigated
+    to via URL.
+  </summary>
+</histogram>
+
 <histogram name="WebApp.Launcher.LaunchResult"
     enum="WebAppLauncherLaunchResult" expires_after="2023-07-02">
   <owner>davidbienvenu@chromium.org</owner>
@@ -837,6 +848,16 @@
   </summary>
 </histogram>
 
+<histogram name="WebApp.LaunchSource" enum="LaunchSource"
+    expires_after="2023-07-09">
+  <owner>phillis@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    The number of times web apps are launched, grouped by apps::LaunchSource.
+    The equivalent histogram on Android is called Launch.HomeScreenSource.
+  </summary>
+</histogram>
+
 <histogram name="WebApp.Mover.Result" enum="WebAppMoverResult"
     expires_after="2022-04-24">
   <owner>dmurph@chromium.org</owner>
diff --git a/tools/typescript/validate_tsconfig.py b/tools/typescript/validate_tsconfig.py
index 163fa354..ccfcc455 100644
--- a/tools/typescript/validate_tsconfig.py
+++ b/tools/typescript/validate_tsconfig.py
@@ -38,14 +38,15 @@
 
 # Allowed compilerOptions
 _allowed_compiler_options = [
-    'typeRoots',
-    'types',
+    'allowUmdGlobalAccess',
+    'lib',
+    'noPropertyAccessFromIndexSignature',
     'noUncheckedIndexedAccess',
     'noUnusedLocals',
-    'strictPropertyInitialization',
-    'noPropertyAccessFromIndexSignature',
-    'allowUmdGlobalAccess',
     'skipLibCheck',
+    'strictPropertyInitialization',
+    'typeRoots',
+    'types',
 ]
 
 
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index 98cdec1..623d430 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -95,7 +95,6 @@
 
   void MatchLayersToOldTreeDefault(CARendererLayerTree* old_tree);
   void MatchLayersToOldTree(CARendererLayerTree* old_tree);
-  void VerifyCommittedCALayers();
 
   class RootLayer {
    public:
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index cbc0f1f9..0dfdc35 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -39,12 +39,6 @@
   }
 };
 
-// TODO(https://crbug.com/1313999): Remove debug prints after the code is
-// stable.
-constexpr bool g_print_ca_layers = false;
-// Output level for VLOG.
-constexpr int kOutputLevel = 4;
-
 BASE_FEATURE(kCALayerTreeOptimization,
              "CALayerTreeOptimization",
              base::FEATURE_ENABLED_BY_DEFAULT);
@@ -366,12 +360,6 @@
   RecordIOSurfaceHistograms(changed_io_surfaces_during_commit_,
                             unchanged_io_surfaces_during_commit_,
                             total_updated_io_surface_size_during_commit_);
-
-// TODO(https://crbug.com/1313999): Remove verfication after the code is stable.
-#ifndef NDEBUG
-  if (ca_layer_tree_optimization_)
-    VerifyCommittedCALayers();
-#endif
 }
 
 void CARendererLayerTree::MatchLayersToOldTreeDefault(
@@ -399,7 +387,6 @@
   if (old_tree->scale_factor_ != scale_factor_)
     return;
 
-  VLOG(kOutputLevel) << "--Mapping....";
   DCHECK(ca_layer_map_.empty()) << "ca_layer_map_ is not empty.";
 
   root_layer_.old_layer_ =
@@ -419,8 +406,6 @@
   // Try to match unused old layers to saving reallocation of CALayer even
   // though the IOSurface will be different.
   root_layer_.CALayerFallBack();
-
-  VLOG(kOutputLevel) << "--";
 }
 
 void CARendererLayerTree::ContentLayer::UpdateMapAndMatchOldLayers(
@@ -445,14 +430,6 @@
 
   auto matched_content_layer = it->second;
 
-  if (matched_content_layer->ca_layer_used_) {
-    VLOG(kOutputLevel) << "     Skip. The matched content layer has been used. "
-                       << matched_content_layer->ca_layer_;
-  } else if (matched_content_layer->layer_order_ < last_old_layer_order) {
-    VLOG(kOutputLevel) << "     Skip. Wrong order. "
-                       << matched_content_layer->ca_layer_;
-  }
-
   // Should we try multimap for the same IOSurface used twice in the old tree?
   if (matched_content_layer->ca_layer_used_)
     return;
@@ -471,8 +448,6 @@
       parent_layer_->parent_layer_->old_layer_ =
           matched_clip_layer->weak_factory_for_new_layer_.GetWeakPtr();
       matched_clip_layer->ca_layer_used_ = true;
-      VLOG(kOutputLevel) << "ClipAndSort: "
-                         << matched_clip_layer->clipping_ca_layer_;
     } else {
       [matched_transform_layer->ca_layer_ removeFromSuperlayer];
     }
@@ -485,8 +460,6 @@
       parent_layer_->old_layer_ =
           matched_transform_layer->weak_factory_for_new_layer_.GetWeakPtr();
       matched_transform_layer->ca_layer_used_ = true;
-      VLOG(kOutputLevel) << " Transform: "
-                         << matched_transform_layer->ca_layer_;
     } else {
       [matched_content_layer->ca_layer_ removeFromSuperlayer];
     }
@@ -518,8 +491,6 @@
     str = ", transform layer's superlayer has changed";
   if ([matched_content_layer->ca_layer_ superlayer] == nil)
     str = ",  clip layer's superlayer has changed ";
-  VLOG(kOutputLevel) << "   Content: " << matched_content_layer->ca_layer_
-                     << " io_surface_ref: " << io_surface_ref << str;
 }
 
 void CARendererLayerTree::RootLayer::CALayerFallBack() {
@@ -1088,20 +1059,6 @@
     }
   }
 
-  if (g_print_ca_layers) {
-    std::string str;
-    if (old_layer_) {
-      str = " Reuse, ";
-    } else {
-      str = " New, ";
-    }
-    if (!update_is_clipped && !update_clip_rect)
-      str = str + "HIT";
-
-    VLOG(kOutputLevel) << "ClipAndSortingLayer: clip: " << clipping_ca_layer_
-                       << " round:" << rounded_corner_ca_layer_ << str;
-  }
-
   CALayer* last_committed_transform_ca_layer = nullptr;
   for (auto& child_layer : transform_layers_) {
     child_layer.CommitToCA(last_committed_transform_ca_layer);
@@ -1147,19 +1104,6 @@
     [ca_layer_ setTransform:ca_transform];
   }
 
-  if (g_print_ca_layers) {
-    std::string str;
-    if (old_layer_) {
-      str = " Reuse, ";
-    } else {
-      str = " New, ";
-    }
-    if (!update_transform)
-      str = str + "HIT";
-
-    VLOG(kOutputLevel) << " TransformLayer: " << ca_layer_ << str;
-  }
-
   CALayer* last_committed_content_ca_layer_ = nullptr;
   for (auto& child_layer : content_layers_) {
     child_layer.CommitToCA(last_committed_content_ca_layer_);
@@ -1398,85 +1342,6 @@
     }
   }
 #endif
-
-  // Print CALayer optimizaton info
-  if (g_print_ca_layers) {
-    IOSurfaceRef io_surface_ref = io_surface_.get();
-
-    std::string str;
-    if (io_surface_ref) {
-      if (old_layer_ && old_layer_->type_ == type_) {
-        if (update_contents) {
-          IOSurfaceRef old_io_surface = nullptr;
-          if (old_layer_->io_surface_) {
-            old_io_surface = old_layer_->io_surface_.get();
-          } else if (old_layer_->solid_color_contents_) {
-            old_io_surface =
-                old_layer_->solid_color_contents_->GetIOSurfaceRef();
-          }
-
-          str = ", Missed, Reuse " +
-                base::StringPrintf("0x%lx", (unsigned long)old_io_surface);
-        } else {
-          str = ", HIT";
-        }
-      } else {
-        str = ", insert_new";
-      }
-    }
-
-    VLOG(kOutputLevel) << "   ContentLayer: " << ca_layer_
-                       << " io_surface_ref: " << io_surface_ref << str;
-  }
-}
-
-void CARendererLayerTree::VerifyCommittedCALayers() {
-  bool print_whole_tree = false;
-
-  NSArray<__kindof CALayer*>* _Nullable clip_sublayers =
-      [root_layer_.ca_layer_ sublayers];
-  if (print_whole_tree) {
-    VLOG(kOutputLevel) << "Veryfy Committed CALayers.";
-    VLOG(kOutputLevel) << "Clip and Sorting Sublayers: " << clip_sublayers;
-  }
-
-  int clip_index = 0;
-  for (auto& clip_and_sorting_layer : root_layer_.clip_and_sorting_layers_) {
-    DCHECK_EQ(clip_and_sorting_layer.clipping_ca_layer_.get(),
-              clip_sublayers[clip_index]);
-
-    NSArray<__kindof CALayer*>* _Nullable transform_sublayers =
-        [clip_and_sorting_layer.rounded_corner_ca_layer_ sublayers];
-    if (print_whole_tree) {
-      VLOG(kOutputLevel) << "Transform Sublayers of Clip[" << clip_index
-                         << "]: " << transform_sublayers;
-    }
-
-    int transform_index = 0;
-    for (auto& transform_layer : clip_and_sorting_layer.transform_layers_) {
-      DCHECK_EQ(transform_layer.ca_layer_.get(),
-                transform_sublayers[transform_index]);
-
-      NSArray<__kindof CALayer*>* _Nullable content_sublayers =
-          [transform_layer.ca_layer_ sublayers];
-      if (print_whole_tree) {
-        VLOG(kOutputLevel) << "Content Sublayers of Transform["
-                           << transform_index << "]: " << content_sublayers;
-      }
-
-      int content_index = 0;
-      for (auto& content_layer : transform_layer.content_layers_) {
-        DCHECK_EQ(content_layer.ca_layer_.get(),
-                  content_sublayers[content_index])
-            << "Incorrect content layer "
-            << " ( " << clip_index << ", " << transform_index << ", "
-            << content_index << ")";
-        content_index++;
-      }
-      transform_index++;
-    }
-    clip_index++;
-  }
 }
 
 }  // namespace ui
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 00750e95..f6ba893 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -283,9 +283,13 @@
 bool IsDeprecateAltBasedSixPackEnabled() {
   return base::FeatureList::IsEnabled(kDeprecateAltBasedSixPack);
 }
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
-// Whether to enable new touch text editing features for ChromeOS.
-// TODO(b/262297017): Remove after touch text editing redesign ships.
+#if defined(USE_AURA)
+// Whether to enable new touch text editing features such as extra touch
+// selection gestures and quick menu options. Planning to release for ChromeOS
+// first, then possibly also enable some parts for other aura platforms later.
+// TODO(b/262297017): Clean up after touch text editing redesign ships.
 BASE_FEATURE(kTouchTextEditingRedesign,
              "TouchTextEditingRedesign",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -293,7 +297,7 @@
 bool IsTouchTextEditingRedesignEnabled() {
   return base::FeatureList::IsEnabled(kTouchTextEditingRedesign);
 }
-#endif  // BUILDFLAG(IS_CHROMEOS)
+#endif  // defined(USE_AURA)
 
 // Enables forced colors mode for web content.
 BASE_FEATURE(kForcedColors, "ForcedColors", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index 8fc60b8..9eb8e8fa 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -77,11 +77,14 @@
 BASE_DECLARE_FEATURE(kDeprecateAltBasedSixPack);
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 bool IsDeprecateAltBasedSixPackEnabled();
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
+#if defined(USE_AURA)
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 BASE_DECLARE_FEATURE(kTouchTextEditingRedesign);
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 bool IsTouchTextEditingRedesignEnabled();
-#endif  // BUILDFLAG(IS_CHROMEOS)
+#endif  // defined(USE_AURA)
 
 // Used to enable forced colors mode for web content.
 COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kForcedColors);
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
index a0214ec..190c40c 100644
--- a/ui/color/color_id.h
+++ b/ui/color/color_id.h
@@ -222,11 +222,9 @@
   E_CPONLY(kColorButtonBorder) \
   E_CPONLY(kColorButtonBorderDisabled) \
   E_CPONLY(kColorButtonForeground) \
-  E_CPONLY(kColorButtonForegroundChecked) \
   E_CPONLY(kColorButtonForegroundDisabled) \
   E_CPONLY(kColorButtonForegroundProminent) \
   E_CPONLY(kColorButtonForegroundTonal) \
-  E_CPONLY(kColorButtonForegroundUnchecked) \
   E_CPONLY(kColorMultitaskFeedbackButtonLabelBackground) \
   E_CPONLY(kColorMultitaskFeedbackButtonLabelForeground) \
   E_CPONLY(kColorMultitaskMenuNudgePulse) \
@@ -310,6 +308,9 @@
   E_CPONLY(kColorOverlayScrollbarStrokeHoveredLight) \
   E_CPONLY(kColorProgressBar) \
   E_CPONLY(kColorProgressBarPaused) \
+  E_CPONLY(kColorRadioButtonForegroundUnchecked) \
+  E_CPONLY(kColorRadioButtonForegroundDisabled) \
+  E_CPONLY(kColorRadioButtonForegroundChecked) \
   E_CPONLY(kColorScrollbarArrowBackgroundHovered) \
   E_CPONLY(kColorScrollbarArrowBackgroundPressed) \
   E_CPONLY(kColorScrollbarArrowForeground) \
diff --git a/ui/color/material_ui_color_mixer.cc b/ui/color/material_ui_color_mixer.cc
index c2defe01..4f14bf5f 100644
--- a/ui/color/material_ui_color_mixer.cc
+++ b/ui/color/material_ui_color_mixer.cc
@@ -36,10 +36,8 @@
   mixer[kColorButtonBorder] = {kColorSysOutline};
   mixer[kColorButtonBorderDisabled] = {kColorSysStateDisabled};
   mixer[kColorButtonForeground] = {kColorSysOnSurfacePrimary};
-  mixer[kColorButtonForegroundChecked] = {kColorButtonForeground};
   mixer[kColorButtonForegroundDisabled] = {kColorSysStateDisabled};
   mixer[kColorButtonForegroundProminent] = {kColorSysOnPrimary};
-  mixer[kColorButtonForegroundUnchecked] = {kColorSysOnSurfaceVariant};
   mixer[kColorCheckboxBackgroundDisabled] = {kColorSysStateDisabledContainer};
   mixer[kColorCheckboxForegroundChecked] = {kColorSysOnSurfacePrimary};
   mixer[kColorCheckboxForegroundDisabled] = {kColorSysStateDisabled};
@@ -52,6 +50,10 @@
   mixer[kColorFrameActive] = {kColorSysHeader};
   mixer[kColorFrameActiveUnthemed] = {kColorSysHeader};
   mixer[kColorFrameInactive] = {kColorSysHeaderInactive};
+  mixer[kColorRadioButtonForegroundChecked] = {kColorSysOnSurfacePrimary};
+  mixer[kColorRadioButtonForegroundDisabled] = {
+      kColorSysStateDisabledContainer};
+  mixer[kColorRadioButtonForegroundUnchecked] = {kColorSysOutline};
   mixer[kColorSliderThumb] = {kColorSysPrimary};
   mixer[kColorSliderThumbMinimal] = {kColorSysSecondary};
   mixer[kColorSliderTrack] = {kColorSysOnPrimary};
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc
index 13e834c..53ade87 100644
--- a/ui/color/ui_color_mixer.cc
+++ b/ui/color/ui_color_mixer.cc
@@ -55,12 +55,10 @@
   mixer[kColorButtonForeground] =
       PickGoogleColor(kColorAccent, kColorButtonBackground,
                       color_utils::kMinimumReadableContrastRatio);
-  mixer[kColorButtonForegroundChecked] = {kColorButtonForeground};
   mixer[kColorButtonForegroundDisabled] = {kColorDisabledForeground};
   mixer[kColorButtonForegroundProminent] =
       GetColorWithMaxContrast(kColorButtonBackgroundProminent);
   mixer[kColorButtonForegroundTonal] = {kColorSysOnPrimaryContainer};
-  mixer[kColorButtonForegroundUnchecked] = {kColorSecondaryForeground};
   mixer[kColorCheckboxForegroundUnchecked] = {kColorSecondaryForeground};
   mixer[kColorCheckboxForegroundChecked] = {kColorButtonForeground};
   mixer[kColorMultitaskFeedbackButtonLabelBackground] = {
@@ -179,6 +177,8 @@
   mixer[kColorProgressBar] =
       PickGoogleColor(kColorAccent, kColorDialogBackground,
                       color_utils::kMinimumVisibleContrastRatio);
+  mixer[kColorRadioButtonForegroundChecked] = {kColorButtonForeground};
+  mixer[kColorRadioButtonForegroundUnchecked] = {kColorSecondaryForeground};
   mixer[kColorScrollbarArrowBackgroundHovered] = {
       dark_mode ? SkColorSetRGB(0x4F, 0x4F, 0x4F)
                 : SkColorSetRGB(0xD2, 0xD2, 0xD2)};
diff --git a/ui/color/win/native_color_mixers_win.cc b/ui/color/win/native_color_mixers_win.cc
index 9003a51..8f396970 100644
--- a/ui/color/win/native_color_mixers_win.cc
+++ b/ui/color/win/native_color_mixers_win.cc
@@ -145,7 +145,7 @@
   if (key.contrast_mode == ColorProviderManager::ContrastMode::kNormal)
     return;
 
-  mixer[kColorButtonForegroundChecked] = {
+  mixer[kColorRadioButtonForegroundChecked] = {
       key.color_mode == ColorProviderManager::ColorMode::kDark
           ? gfx::kGoogleBlue100
           : gfx::kGoogleBlue900};
diff --git a/ui/file_manager/file_manager/BUILD.gn b/ui/file_manager/file_manager/BUILD.gn
index fc567ced..218b1b2 100644
--- a/ui/file_manager/file_manager/BUILD.gn
+++ b/ui/file_manager/file_manager/BUILD.gn
@@ -71,6 +71,7 @@
     "foreground/images/files/ui/holding_space_welcome_image.svg",
     "foreground/images/files/ui/info.svg",
     "foreground/images/files/ui/list_check.svg",
+    "foreground/images/files/ui/check.svg",
     "foreground/images/files/ui/menu_ng.svg",
     "foreground/images/files/ui/ms365.svg",
     "foreground/images/files/ui/nudge_star_icon.svg",
diff --git a/ui/file_manager/file_manager/common/js/api.js b/ui/file_manager/file_manager/common/js/api.js
index 77f7eaf8..ac66ab5 100644
--- a/ui/file_manager/file_manager/common/js/api.js
+++ b/ui/file_manager/file_manager/common/js/api.js
@@ -52,7 +52,8 @@
  */
 export async function resolveIsolatedEntries(isolatedEntries) {
   return promisify(
-      chrome.fileManagerPrivate.resolveIsolatedEntries, isolatedEntries);
+      chrome.fileManagerPrivate.resolveIsolatedEntries,
+      isolatedEntries.map(e => util.unwrapEntry(e)));
 }
 
 /**
@@ -69,7 +70,8 @@
  */
 export async function validatePathNameLength(parentEntry, name) {
   return promisify(
-      chrome.fileManagerPrivate.validatePathNameLength, parentEntry, name);
+      chrome.fileManagerPrivate.validatePathNameLength,
+      util.unwrapEntry(parentEntry), name);
 }
 
 /**
@@ -292,7 +294,8 @@
  */
 export async function getFileTasks(entries, dlpSourceUrls) {
   return promisify(
-      chrome.fileManagerPrivate.getFileTasks, entries, dlpSourceUrls);
+      chrome.fileManagerPrivate.getFileTasks,
+      entries.map(e => util.unwrapEntry(e)), dlpSourceUrls);
 }
 
 /**
@@ -302,7 +305,8 @@
  */
 export async function executeTask(taskDescriptor, entries) {
   return promisify(
-      chrome.fileManagerPrivate.executeTask, taskDescriptor, entries);
+      chrome.fileManagerPrivate.executeTask, taskDescriptor,
+      entries.map(e => util.unwrapEntry(e)));
 }
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/check.svg b/ui/file_manager/file_manager/foreground/images/files/ui/check.svg
new file mode 100644
index 0000000..da38628
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/check.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="m9.55 18-5.7-5.7 1.425-1.425L9.55 15.15l9.175-9.175L20.15 7.4Z"/></svg>
\ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model.js b/ui/file_manager/file_manager/foreground/js/actions_model.js
index 31957269..20dc124 100644
--- a/ui/file_manager/file_manager/foreground/js/actions_model.js
+++ b/ui/file_manager/file_manager/foreground/js/actions_model.js
@@ -614,7 +614,7 @@
    */
   execute() {
     chrome.fileManagerPrivate.executeCustomAction(
-        this.entries_, this.id_, () => {
+        this.entries_.map(e => util.unwrapEntry(e)), this.id_, () => {
           if (chrome.runtime.lastError) {
             console.error(
                 'Failed to execute a custom action because of: ' +
@@ -808,7 +808,8 @@
             // For FSP, fetch custom actions via an API.
             case VolumeManagerCommon.VolumeType.PROVIDED:
               chrome.fileManagerPrivate.getCustomActions(
-                  this.entries_, customActions => {
+                  this.entries_.map(e => util.unwrapEntry(e)),
+                  customActions => {
                     if (chrome.runtime.lastError) {
                       console.error(
                           'Failed to fetch custom actions because of: ' +
diff --git a/ui/file_manager/file_manager/foreground/js/constants.js b/ui/file_manager/file_manager/foreground/js/constants.js
index 0c111c0..feb06edd 100644
--- a/ui/file_manager/file_manager/foreground/js/constants.js
+++ b/ui/file_manager/file_manager/foreground/js/constants.js
@@ -132,6 +132,7 @@
   AUDIO: 'audio',
   BRUSCHETTA: 'bruschetta',
   CAMERA_FOLDER: 'camera-folder',
+  CHECK: 'check',
   CLOUD_DONE: 'cloud_done',
   CLOUD_ERROR: 'cloud_error',
   CLOUD_OFFLINE: 'cloud_offline',
@@ -141,6 +142,7 @@
   COMPUTERS_GRAND_ROOT: 'computers_grand_root',
   CROSTINI: 'crostini',
   DOWNLOADS: 'downloads',
+  DRIVE_LOGO: 'drive_logo',
   DRIVE_OFFLINE: 'drive_offline',
   DRIVE_RECENT: 'drive_recent',
   DRIVE_SHARED_WITH_ME: 'drive_shared_with_me',
diff --git a/ui/file_manager/file_manager/foreground/js/deferred_elements.js b/ui/file_manager/file_manager/foreground/js/deferred_elements.js
index e13a1e4..7d77d86 100644
--- a/ui/file_manager/file_manager/foreground/js/deferred_elements.js
+++ b/ui/file_manager/file_manager/foreground/js/deferred_elements.js
@@ -20,3 +20,4 @@
 import '../../widgets/xf_cloud_panel.js';
 import '../../widgets/xf_icon.js';
 import '../../widgets/xf_conflict_dialog.js';
+import '../../widgets/xf_bulk_pinning_dialog.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 2c838a7..804729a 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1900,7 +1900,8 @@
             fileManager.metadataModel.getCache(entries, ['sourceUrl'])
                 .map(m => m.sourceUrl || '');
         chrome.fileManagerPrivate.invokeSharesheet(
-            entries, launchSource, dlpSourceUrls, () => {
+            entries.map(e => util.unwrapEntry(e)), launchSource, dlpSourceUrls,
+            () => {
               if (chrome.runtime.lastError) {
                 console.warn(chrome.runtime.lastError.message);
                 return;
@@ -2587,15 +2588,14 @@
     if (!entry || !entry.isDirectory) {
       return;
     }
-    const dir = /** @type {!DirectoryEntry} */ (entry);
-    const info = fileManager.volumeManager.getLocationInfo(dir);
+    const info = fileManager.volumeManager.getLocationInfo(entry);
     if (!info) {
       return;
     }
     const share = () => {
       // Always persist shares via right-click > Share with Linux.
       chrome.fileManagerPrivate.sharePathsWithCrostini(
-          this.vmName_, [dir], true /* persist */, () => {
+          this.vmName_, [util.unwrapEntry(entry)], true /* persist */, () => {
             if (chrome.runtime.lastError) {
               console.warn(
                   'Error sharing with guest: ' +
@@ -2615,7 +2615,7 @@
     };
     // Show a confirmation dialog if we are sharing the root of a volume.
     // Non-Drive volume roots are always '/'.
-    if (dir.fullPath == '/') {
+    if (entry.fullPath == '/') {
       fileManager.ui.confirmDialog.showHtml(
           strf(`SHARE_ROOT_FOLDER_WITH_${this.typeForStrings_}_TITLE`),
           strf(
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
index 77bdb6e..9dba4fc 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
@@ -218,7 +218,7 @@
       }
     }
 
-    const fileEntry = /** @type {!FileEntry} */ (entry);
+    const fileEntry = /** @type {!FileEntry} */ (util.unwrapEntry(entry));
     this.getContentMetadata_(fileEntry, names).then(callback);
   }
 
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 3e23172..91afc67 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
@@ -271,6 +271,7 @@
    */
   setDirectorySize_(entry, isSameEntry) {
     assert(entry.isDirectory);
+    entry = /** @type {!DirectoryEntry} */ (util.unwrapEntry(entry));
 
     if (this.metadataBox_.size === '') {
       this.metadataBox_.size = ' ';  // Provide a dummy size value.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.html b/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.html
index 7463f987..46e9322 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.html
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.html
@@ -4,8 +4,8 @@
   }
 </style>
 <educational-banner>
-  <span slot="title">TODO: This is currently just a placeholder</span>
-  <span slot="subtitle">TODO: This is currently just a placeholder</span>
+  <span slot="title">Make everything in your Google Drive available when you’re offline</span>
+  <span slot="subtitle">This will automatically download all files in your My Drive, allowing you to access and edit your files without an internet connection. <a href="." class="learn-more">Learn more</a></span>
   <cr-button slot="extra-button">
     Enable
   </cr-button>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.js b/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.js
index dc6c4ad..847b1ad 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/drive_bulk_pinning_banner.js
@@ -22,6 +22,16 @@
  * A banner that prompts users to bulk pin their files.
  */
 export class DriveBulkPinningBanner extends EducationalBanner {
+  constructor() {
+    super();
+
+    this.shadowRoot.querySelector('.learn-more')
+        .addEventListener('click', (e) => {
+          e.preventDefault();
+          document.querySelector('xf-bulk-pinning-dialog').show();
+        });
+  }
+
   /**
    * Returns the HTML template for the Drive Bulk Pinning educational banner.
    * @returns {!Node}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
index 2ddd223..9949035 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
@@ -34,6 +34,7 @@
     super.showWithTitle(
         str('IMPORT_CROSTINI_IMAGE_DIALOG_TITLE'),
         str('IMPORT_CROSTINI_IMAGE_DIALOG_DESCRIPTION'),
-        chrome.fileManagerPrivate.importCrostiniImage.bind(null, entry));
+        chrome.fileManagerPrivate.importCrostiniImage.bind(
+            null, /** @type {!Entry} */ (util.unwrapEntry(entry))));
   }
 }
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index f29d36cab..fedc3d2 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -519,6 +519,7 @@
     <div id="drop-label"></div>
     <files-toast id="toast"></files-toast>
     <files-format-dialog id="format-dialog"></files-format-dialog>
+    <xf-bulk-pinning-dialog></xf-bulk-pinning-dialog>
     <xf-nudge></xf-nudge>
   </body>
 </html>
diff --git a/ui/file_manager/file_manager/widgets/xf_bulk_pinning_dialog.ts b/ui/file_manager/file_manager/widgets/xf_bulk_pinning_dialog.ts
new file mode 100644
index 0000000..494fa9fa
--- /dev/null
+++ b/ui/file_manager/file_manager/widgets/xf_bulk_pinning_dialog.ts
@@ -0,0 +1,128 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import {str} from '../common/js/util.js';
+
+import {css, customElement, html, query, XfBase} from './xf_base.js';
+
+/**
+ * Dialog that shows the benefits of enabling bulk pinning along with storage
+ * information if the feature can't be enabled.
+ */
+@customElement('xf-bulk-pinning-dialog')
+export class XfBulkPinningDialog extends XfBase {
+  @query('cr-dialog') private $dialog_?: CrDialogElement;
+
+  private copy_ = {
+    cancel: str('CANCEL_LABEL'),
+    continue: 'Continue',  // TODO: replace with final copy when available.
+  };
+
+  show() {
+    this.$dialog_!.showModal();
+  }
+
+  static override get styles() {
+    return getCSS();
+  }
+
+  override render() {
+    return html`
+      <cr-dialog>
+        <div slot="title">
+          <xf-icon type="drive_logo" size="large"></xf-icon>
+          <div class="title">
+            Make everything in your Google Drive available when you're offline
+          </div>
+        </div>
+        <div slot="body">
+          <div class="description">
+            This will automatically download all files in your My Drive,
+            allowing you to access and edit your files without an internet
+            connection.
+          </div>
+          <ul>
+            <li>
+              <xf-icon type="check"></xf-icon> Store all My Drive files in the cloud
+              and on your computer
+            </li>
+            <li>
+              <xf-icon type="check"></xf-icon> Access files from a folder on your
+              computer
+            </li>
+            <li>
+              <xf-icon type="check"></xf-icon> All files are automatically available
+              offline
+            </li>
+          </ul>
+          <div class="note">
+            This will use about 12.2 GB leaving 96.8 GB available
+          </div>
+        </div>
+        <div slot="button-container">
+          <cr-button class="cancel-button"> ${this.copy_.cancel} </cr-button>
+          <cr-button class="continue-button"> ${this.copy_.continue} </cr-button>
+        </div>
+      </cr-dialog>
+    `;
+  }
+}
+
+function getCSS() {
+  return css`
+    cr-dialog [slot="body"] {
+      color: var(--cros-text-color-secondary);
+      display: flex;
+      flex-direction: column;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 20px;
+    }
+
+    cr-dialog [slot="title"] {
+      display: flex;
+      font-size: 18px;
+      font-weight: 500;
+      line-height: 24px;
+    }
+
+    cr-dialog [slot="title"] xf-icon {
+      margin-right: 16px;
+    }
+
+    .description {
+      margin-bottom: 24px;
+    }
+
+    ul {
+      border-bottom: 0;
+      border-radius: 12px 12px 0 0;
+      border: 1px solid var(--cros-separator-color);
+      margin: 0;
+      padding: 20px 18px;
+    }
+
+    .note {
+      background-color: var(--cros-sys-app_base_shaded);
+      border-radius: 0 0 12px 12px;
+      border-top: 0;
+      border: 1px solid var(--cros-separator-color);
+      padding: 16px;
+    }
+
+    li {
+      display: flex;
+    }
+
+    li + li {
+      margin-top: 16px;
+    }
+
+    li > xf-icon {
+      --xf-icon-color: var(--cros-icon-color-green);
+      margin-right: 10px;
+    }
+  `;
+}
diff --git a/ui/file_manager/file_manager/widgets/xf_icon.ts b/ui/file_manager/file_manager/widgets/xf_icon.ts
index ab2342f..312c90c 100644
--- a/ui/file_manager/file_manager/widgets/xf_icon.ts
+++ b/ui/file_manager/file_manager/widgets/xf_icon.ts
@@ -78,6 +78,7 @@
     }
 
     const shouldKeepColor = [
+      constants.ICON_TYPES.DRIVE_LOGO,
       constants.ICON_TYPES.EXCEL,
       constants.ICON_TYPES.POWERPOINT,
       constants.ICON_TYPES.WORD,
@@ -211,6 +212,10 @@
       -webkit-mask-image: url(../foreground/images/volumes/shared.svg);
     }
 
+    :host([type="drive_logo"]) span {
+      background-image: url(../foreground/images/files/ui/drive_logo.svg);
+    }
+
     :host([type="excel"]) span {
       background-image: url(../foreground/images/filetype/filetype_excel.svg);
     }
@@ -356,6 +361,10 @@
     :host([type="word"]) span {
       background-image: url(../foreground/images/filetype/filetype_word.svg);
     }
+
+    :host([type="check"]) span {
+      -webkit-mask-image: url(../foreground/images/files/ui/check.svg);
+    }
   `;
 }
 
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni
index 5f4c50f6..703a9c5 100644
--- a/ui/file_manager/file_names.gni
+++ b/ui/file_manager/file_names.gni
@@ -274,6 +274,7 @@
   # Widgets.
   "file_manager/widgets/xf_base.ts",
   "file_manager/widgets/xf_breadcrumb.ts",
+  "file_manager/widgets/xf_bulk_pinning_dialog.ts",
   "file_manager/widgets/xf_conflict_dialog.ts",
   "file_manager/widgets/xf_dlp_restriction_details_dialog.ts",
   "file_manager/widgets/xf_icon.ts",
diff --git a/ui/gfx/image/image_skia_operations.cc b/ui/gfx/image/image_skia_operations.cc
index 04fa4fa2..38e361b9 100644
--- a/ui/gfx/image/image_skia_operations.cc
+++ b/ui/gfx/image/image_skia_operations.cc
@@ -569,6 +569,46 @@
   const gfx::ImageSkia image_;
 };
 
+// Image source to create an image with a rounded rect background.
+class ImageWithRoundRectBackgroundSource : public gfx::CanvasImageSource {
+ public:
+  ImageWithRoundRectBackgroundSource(float size,
+                                     int radius,
+                                     SkColor color,
+                                     const gfx::ImageSkia& image)
+      : gfx::CanvasImageSource(gfx::Size(size, size)),
+        size_(size),
+        radius_(radius),
+        color_(color),
+        image_(image) {}
+
+  ImageWithRoundRectBackgroundSource(
+      const ImageWithRoundRectBackgroundSource&) = delete;
+  ImageWithRoundRectBackgroundSource& operator=(
+      const ImageWithRoundRectBackgroundSource&) = delete;
+
+  ~ImageWithRoundRectBackgroundSource() override = default;
+
+  // gfx::CanvasImageSource:
+  void Draw(gfx::Canvas* canvas) override {
+    cc::PaintFlags flags;
+    flags.setAntiAlias(true);
+    flags.setStyle(cc::PaintFlags::kFill_Style);
+    flags.setColor(color_);
+    canvas->DrawRoundRect(RectF{size_, size_}, radius_, flags);
+    // Center the image.
+    const int x = (size_ - image_.width()) / 2;
+    const int y = (size_ - image_.height()) / 2;
+    canvas->DrawImageInt(image_, x, y);
+  }
+
+ private:
+  const float size_;
+  const int radius_;
+  const SkColor color_;
+  const gfx::ImageSkia image_;
+};
+
 // Image source to create an image with a roundrect clip path.
 class ImageWithRoundRectClipSource : public gfx::CanvasImageSource {
  public:
@@ -771,6 +811,17 @@
       radius, color, image);
 }
 
+ImageSkia ImageSkiaOperations::CreateImageWithRoundRectBackground(
+    float size,
+    int radius,
+    SkColor color,
+    const ImageSkia& image) {
+  DCHECK_GE(size, image.width());
+  DCHECK_GE(size, image.height());
+  return gfx::CanvasImageSource::MakeImageSkia<
+      ImageWithRoundRectBackgroundSource>(size, radius, color, image);
+}
+
 ImageSkia ImageSkiaOperations::CreateImageWithRoundRectClip(
     int radius,
     const ImageSkia& image) {
diff --git a/ui/gfx/image/image_skia_operations.h b/ui/gfx/image/image_skia_operations.h
index a74d762..359a828 100644
--- a/ui/gfx/image/image_skia_operations.h
+++ b/ui/gfx/image/image_skia_operations.h
@@ -46,8 +46,10 @@
   // because it tiles the original image, so your coordinates can extend
   // outside the bounds of the original image.
   static ImageSkia CreateTiledImage(const ImageSkia& image,
-                                    int src_x, int src_y,
-                                    int dst_w, int dst_h);
+                                    int src_x,
+                                    int src_y,
+                                    int dst_w,
+                                    int dst_h);
 
   // Shift an image's HSL values. The shift values are in the range of 0-1,
   // with the option to specify -1 for 'no change'. The shift values are
@@ -119,6 +121,13 @@
                                                    SkColor color,
                                                    const ImageSkia& image);
 
+  // Creates an image with a rounded rect background of the specified `size`,
+  // `color`, and `radius`.
+  static ImageSkia CreateImageWithRoundRectBackground(float size,
+                                                      int radius,
+                                                      SkColor color,
+                                                      const ImageSkia& image);
+
   // Creates an image with a roundrect clip path with `radius`.
   static ImageSkia CreateImageWithRoundRectClip(int radius,
                                                 const ImageSkia& image);
diff --git a/ui/gtk/gtk_color_mixers.cc b/ui/gtk/gtk_color_mixers.cc
index e507140..ce486e3 100644
--- a/ui/gtk/gtk_color_mixers.cc
+++ b/ui/gtk/gtk_color_mixers.cc
@@ -86,11 +86,9 @@
   mixer[ui::kColorButtonBorder] = {button_border};
   mixer[ui::kColorButtonBorderDisabled] = {button_bg_disabled};
   mixer[ui::kColorButtonForeground] = {GetFgColor("button.text-button label")};
-  mixer[ui::kColorButtonForegroundChecked] = {ui::kColorAccent};
   mixer[ui::kColorButtonForegroundDisabled] = {
       GetFgColor("button.text-button:disabled label")};
   mixer[ui::kColorButtonForegroundProminent] = {accent};
-  mixer[ui::kColorButtonForegroundUnchecked] = {ui::kColorButtonForeground};
   mixer[ui::kColorDialogForeground] = {ui::kColorPrimaryForeground};
   mixer[ui::kColorDropdownBackground] = {GetBgColor(base::StrCat(
       {"combobox window.background.popup ", "menu(gtk-combobox-popup-menu) ",
@@ -140,6 +138,9 @@
   mixer[ui::kColorOverlayScrollbarStroke] = {GetBgColor("scrollbar trough")};
   mixer[ui::kColorOverlayScrollbarStrokeHovered] = {
       GetBgColor("scrollbar trough:hover")};
+  mixer[ui::kColorRadioButtonForegroundChecked] = {ui::kColorAccent};
+  mixer[ui::kColorRadioButtonForegroundUnchecked] = {
+      ui::kColorButtonForeground};
   mixer[ui::kColorSliderThumb] = {GetBgColor("scale highlight")};
   mixer[ui::kColorSliderThumbMinimal] = {
       GetBgColor("scale:disabled highlight")};
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index d49c73d..78fdc2f 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -1514,8 +1514,8 @@
     const gfx::VectorIcon& radio_icon =
         toggled ? kMenuRadioSelectedIcon : kMenuRadioEmptyIcon;
     const SkColor radio_icon_color = GetColorProvider()->GetColor(
-        toggled ? ui::kColorButtonForegroundChecked
-                : ui::kColorButtonForegroundUnchecked);
+        toggled ? ui::kColorRadioButtonForegroundChecked
+                : ui::kColorRadioButtonForegroundUnchecked);
     radio_check_image_view_->SetImage(ui::ImageModel::FromVectorIcon(
         radio_icon, radio_icon_color, kMenuCheckSize));
   }
diff --git a/ui/views/examples/colors_example.cc b/ui/views/examples/colors_example.cc
index 9e714ab..dc66b15 100644
--- a/ui/views/examples/colors_example.cc
+++ b/ui/views/examples/colors_example.cc
@@ -76,7 +76,8 @@
   InsertColorRow(container, COLOR_LABEL_ARGS(kColorFocusableBorderUnfocused));
   InsertColorRow(container, COLOR_LABEL_ARGS(kColorButtonForeground));
   InsertColorRow(container, COLOR_LABEL_ARGS(kColorButtonForegroundDisabled));
-  InsertColorRow(container, COLOR_LABEL_ARGS(kColorButtonForegroundUnchecked));
+  InsertColorRow(container,
+                 COLOR_LABEL_ARGS(kColorRadioButtonForegroundUnchecked));
   InsertColorRow(container, COLOR_LABEL_ARGS(kColorButtonBackgroundProminent));
   InsertColorRow(container,
                  COLOR_LABEL_ARGS(kColorButtonBackgroundProminentFocused));
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index 1b890d3b..ee7a5a8 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -976,7 +976,14 @@
 
 gfx::Rect DesktopWindowTreeHostPlatform::ToPixelRect(
     const gfx::Rect& rect_in_dip) const {
-  return GetRootTransform().MapRect(rect_in_dip);
+  gfx::RectF rect_in_pixels_f =
+      GetRootTransform().MapRect(gfx::RectF(rect_in_dip));
+  // Due to the limitation of IEEE floating point representation and rounding
+  // error, the converted result may become slightly larger than expected value,
+  // such as 3000.0005. Allow 0.001 eplisin to round down in such case. This is
+  // also used in cc/viz. See crbug.com/1418606.
+  constexpr float kEpsilon = 0.001f;
+  return gfx::ToEnclosingRectIgnoringError(rect_in_pixels_f, kEpsilon);
 }
 
 Widget* DesktopWindowTreeHostPlatform::GetWidget() {
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
index 0058f2b3..82e1036 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
@@ -26,6 +26,12 @@
         width: var(--cr-icon-button-width);
       }
 
+      :host-context([chrome-refresh-2023]):host {
+        --cr-icon-button-fill-color: currentColor;
+        --cr-icon-button-size: 32px;
+        position: relative;
+      }
+
       :host(:hover) {
         background-color: var(--cr-icon-button-hover-background-color,
             var(--cr-hover-background-color));
@@ -44,11 +50,21 @@
         }
       }
 
-      :host(:active) {
+      :host-context(html:not([chrome-refresh-2023])) :host(:active) {
         background-color: var(--cr-icon-button-active-background-color,
             var(--cr-active-background-color));
       }
 
+      paper-ripple {
+        display: none;
+      }
+
+      :host-context([chrome-refresh-2023]) paper-ripple {
+        --paper-ripple-opacity: 1;
+        color: var(--cr-active-background-color);
+        display: block;
+      }
+
       :host([disabled]) {
         cursor: initial;
         opacity: var(--cr-disabled-opacity);
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.ts b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.ts
index 97fd124..cec34a9 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.ts
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.ts
@@ -47,7 +47,8 @@
 import '../cr_shared_vars.css.js';
 import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
 
-import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PaperRippleBehavior} from '//resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js';
+import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './cr_icon_button.html.js';
 
@@ -57,7 +58,13 @@
   };
 }
 
-export class CrIconButtonElement extends PolymerElement {
+const CrIconbuttonElementBase =
+    mixinBehaviors([PaperRippleBehavior], PolymerElement) as {
+      new (): PolymerElement & PaperRippleBehavior,
+    };
+
+
+export class CrIconButtonElement extends CrIconbuttonElementBase {
   static get is() {
     return 'cr-icon-button';
   }
@@ -118,6 +125,10 @@
     this.addEventListener('click', this.onClick_.bind(this));
     this.addEventListener('keydown', this.onKeyDown_.bind(this));
     this.addEventListener('keyup', this.onKeyUp_.bind(this));
+
+    if (document.documentElement.hasAttribute('chrome-refresh-2023')) {
+      this.addEventListener('pointerdown', this.onPointerDown_.bind(this));
+    }
   }
 
   override ready() {
@@ -214,6 +225,10 @@
       this.click();
     }
   }
+
+  private onPointerDown_() {
+    this.ensureRipple();
+  }
 }
 
 declare global {
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.html b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.html
index e792dbc..9fd1487 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.html
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.html
@@ -11,6 +11,7 @@
         on-keydown="onInputKeydown_">
       <div class="disc-border"></div>
       <div class="disc"></div>
+      <div id="overlay"></div>
     </div>
 
     <div id="labelWrapper">
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts
index 0c16dbd..402d247 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_mixin.ts
@@ -86,7 +86,9 @@
         override connectedCallback() {
           super.connectedCallback();
           this.addEventListener('blur', this.hideRipple_.bind(this));
-          this.addEventListener('focus', this.onFocus_.bind(this));
+          if (!document.documentElement.hasAttribute('chrome-refresh-2023')) {
+            this.addEventListener('focus', this.onFocus_.bind(this));
+          }
           this.addEventListener('up', this.hideRipple_.bind(this));
         }
 
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style.css b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style.css
index dcc727a..3bf953f5 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style.css
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style.css
@@ -39,6 +39,20 @@
         }
       }
 
+      :host-context([chrome-refresh-2023]):host {
+        --cr-radio-button-ink-size: 32px;
+        --cr-radio-button-checked-color:
+            var(--color-radio-button-foreground-checked,
+                var(--cr-fallback-color-primary));
+        --cr-radio-button-checked-ripple-color:
+            var(--cr-active-background-color);
+        --cr-radio-button-unchecked-color:
+            var(--color-radio-button-foreground-unchecked,
+                var(--cr-fallback-color-outline));
+        --cr-radio-button-unchecked-ripple-color:
+            var(--cr-active-background-color);
+      }
+
       @media (forced-colors: active) {
         :host {
           --cr-radio-button-checked-color: SelectedItem;
@@ -52,6 +66,15 @@
         pointer-events: none;
       }
 
+      :host-context([chrome-refresh-2023]):host([disabled]) {
+        opacity: 1;
+        --cr-radio-button-checked-color: var(--color-radio-foreground-disabled,
+            rgba(var(--cr-fallback-color-on-surface-rgb), .12));
+        --cr-radio-button-unchecked-color:
+            var(--color-radio-foreground-disabled,
+                rgba(var(--cr-fallback-color-on-surface-rgb), .12));
+      }
+
       :host(:not([disabled])) {
         cursor: pointer;
       }
@@ -61,6 +84,10 @@
         margin-inline-start: var(--cr-radio-button-label-spacing, 20px);
       }
 
+      :host-context([chrome-refresh-2023]):host([disabled]) #labelWrapper {
+        opacity: var(--cr-disabled-opacity);
+      }
+
       #label {
         color: inherit;
       }
@@ -118,6 +145,29 @@
         transform: scale(0.5);
       }
 
+      :host-context([chrome-refresh-2023]) #overlay {
+        border-radius: 50%;
+        box-sizing: border-box;
+        display: none;
+        height: var(--cr-radio-button-ink-size);
+        left: 50%;
+        pointer-events: none;
+        position: absolute;
+        top: 50%;
+        transform: translate(-50%, -50%);
+        width: var(--cr-radio-button-ink-size);
+      }
+
+      :host-context([chrome-refresh-2023]) #button:hover #overlay {
+        background-color: var(--cr-hover-background-color);
+        display: block;
+      }
+
+      :host-context([chrome-refresh-2023]) #button:focus-visible #overlay {
+        border: 2px solid var(--cr-focus-outline-color);
+        display: block;
+      }
+
       paper-ripple {
         --paper-ripple-opacity: 1;  /* Opacity in each color's alpha. */
         color: var(--cr-radio-button-unchecked-ripple-color);
diff --git a/ui/webui/resources/mojo/BUILD.gn b/ui/webui/resources/mojo/BUILD.gn
index c5e64590..0c25347 100644
--- a/ui/webui/resources/mojo/BUILD.gn
+++ b/ui/webui/resources/mojo/BUILD.gn
@@ -41,7 +41,6 @@
     "chromeos/ash/services/cellular_setup/public/mojom/cellular_setup.mojom-webui.js",
     "chromeos/ash/services/cellular_setup/public/mojom/esim_manager.mojom-webui.js",
     "chromeos/ash/services/device_sync/public/mojom/device_sync.mojom-webui.js",
-    "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js",
     "chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom-webui.js",
     "chromeos/ash/services/nearby/public/mojom/nearby_share_settings.mojom-webui.js",
     "chromeos/ash/services/nearby/public/mojom/nearby_share_target_types.mojom-webui.js",
@@ -56,6 +55,20 @@
     "ui/events/mojom/event.mojom-webui.js",
     "ui/latency/mojom/latency_info.mojom-webui.js",
   ]
+
+  mojo_ts_files = [ "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.ts" ]
+
+  preprocess_if_expr("copy_mojo_ts") {
+    visibility = [ ":build_ts" ]
+
+    in_folder = root_gen_dir
+    out_folder = "$target_gen_dir/preprocessed"
+    in_files = mojo_ts_files
+
+    deps = [
+      "//chromeos/ash/services/hotspot_config/public/mojom:mojom_ts__generator",
+    ]
+  }
 }
 
 # Move all the files out of mojom-webui to the expected location.
@@ -84,7 +97,6 @@
       "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_js__generator",
       "//chromeos/ash/services/cellular_setup/public/mojom:mojom_js__generator",
       "//chromeos/ash/services/device_sync/public/mojom:mojom_js__generator",
-      "//chromeos/ash/services/hotspot_config/public/mojom:mojom_js__generator",
       "//chromeos/ash/services/multidevice_setup/public/mojom:mojom_js__generator",
       "//chromeos/ash/services/nearby/public/mojom:nearby_share_settings_js__generator",
       "//chromeos/services/network_config/public/mojom:mojom_js__generator",
@@ -106,6 +118,9 @@
   allow_js = true
 
   in_files = mojo_js_files
+  if (is_chromeos_ash) {
+    in_files += mojo_ts_files
+  }
 
   definitions = [ "$tsc_folder/mojo/public/js/bindings.d.ts" ]
 
@@ -113,6 +128,9 @@
     ":copy_bindings_dts",
     ":copy_mojo",
   ]
+  if (is_chromeos_ash) {
+    extra_deps += [ ":copy_mojo_ts" ]
+  }
 
   path_mappings = [ "//resources/mojo/*|" +
                     rebase_path("$root_gen_dir/ui/webui/resources/tsc/mojo/*",