diff --git a/.gitignore b/.gitignore
index d68a1b2..baf86ec0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@
 .cipd
 .classpath
 .code-coverage
+.coverage
 .cproject
 .dir-locals.el
 .emulator_sdk
diff --git a/AUTHORS b/AUTHORS
index 786ee7c..6a31d5c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -58,6 +58,7 @@
 Alex Henrie <alexhenrie24@gmail.com>
 Alex Scheele <alexscheele@gmail.com>
 Alexander Douglas <agdoug@amazon.com>
+Alexander Forrence <alex.forrence@gmail.com>
 Alexander Guettler <alexander@guettler.io>
 Alexander Rezepkin <etu@vivaldi.net>
 Alexander Shalamov <alexander.shalamov@intel.com>
diff --git a/BUILD.gn b/BUILD.gn
index a3cf0a49..4efccb33 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1573,9 +1573,12 @@
 
   script_test("blink_python_tests") {
     script = "//testing/scripts/run_isolated_script_test.py"
-    args = [ "@WrappedPath(" +
-             rebase_path("//third_party/blink/tools/run_blinkpy_tests.py",
-                         root_build_dir) + ")" ]
+    args = [
+      "@WrappedPath(" +
+          rebase_path("//third_party/blink/tools/run_blinkpy_tests.py",
+                      root_build_dir) + ")",
+      "--coverage",
+    ]
 
     data = [
       # These tests use //build/android/devil_chromium.py even when !is_android,
diff --git a/DEPS b/DEPS
index df23b05b..43d7068 100644
--- a/DEPS
+++ b/DEPS
@@ -297,7 +297,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': 'b9ebeb2d851517507d7af20aba12a8f3d3255f5d',
+  'skia_revision': '4cda03a096acde5e67dc673a8d898e812dbdd285',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -320,11 +320,11 @@
   #
   # Note this revision should be updated with
   # third_party/boringssl/roll_boringssl.py, not roll-dep.
-  'boringssl_revision': '7528f03c8ad73216f462f86e1d64d3d780a5cd42',
+  'boringssl_revision': 'b95124305ab15c7523d3e21437309fa5dd717ee8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:9.20220720.1.1',
+  'fuchsia_version': 'version:9.20220720.2.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -340,7 +340,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lss
   # and whatever else without interference from each other.
-  'lss_revision': '3bb68597959611490cd8c1c127564aedef1da27a',
+  'lss_revision': '0d6435b731ef91d5182eaecff82ae96764222c48',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
@@ -368,7 +368,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': '45c6b725b53da182e84e21fc259ec01129d251b8',
+  'catapult_revision': 'abcd8ba23ed9836cf8d2e5f93b43ea47b05463d3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -376,7 +376,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '2d3b22fa0b77917e0313f7870d4b86847c9df995',
+  'devtools_frontend_revision': 'acb1198eae55e536573726bc3e4ef978d1353bdc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -412,7 +412,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': '256e026f6406bbf9cf03c518e66eedebff457921',
+  'dawn_revision': '3b8b9699d69f1eeb6fadddcbe56ffc68ae57715e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -782,7 +782,7 @@
   },
 
   'src/ios/third_party/edo/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '988a6d0c8e19654a1c412a0752d8d4340b028b2d',
+      'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '3d3dcee71993376f3abcf3457b046c1df6c13182',
       'condition': 'checkout_ios',
   },
 
@@ -1007,7 +1007,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/lint',
-               'version': 'OkpY7I7TtDs4jihQ9SmckN-GEVBpZ2y9xr4M7TimTqoC',
+               'version': 'INnGGTfg5gGJutJiBtWI6-QwusHDDnKvZzI53Q3UiecC',
           },
       ],
       'condition': 'checkout_android',
@@ -1184,7 +1184,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7298625c85355e802f21bca0168158b56bc6c34c',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6967a96b040a29ff7b640d75b742ea071820b21e',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1751,7 +1751,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '44e4c8770158c505b03ee7feafa4859d083b0912',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'bee49351f3258c1773561b87557c477df28560d1',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'd5e662bf6fa276fd33208e655db1663803099c5d',
 
   'src/third_party/webrtc':
     Var('webrtc_git') + '/src.git' + '@' + 'ed7526c3f188abdb90db9fbee7f46dd8a1408146',
@@ -1827,7 +1827,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@72a0cffd9cdf56961afc12f1058e429fa5710fda',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b43c6d4b6204be0c68cf76bbba4e251df36e1168',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/gfx/overlay_processor_webview.cc b/android_webview/browser/gfx/overlay_processor_webview.cc
index 76f89f2d..cd43da2 100644
--- a/android_webview/browser/gfx/overlay_processor_webview.cc
+++ b/android_webview/browser/gfx/overlay_processor_webview.cc
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/task/bind_post_task.h"
 #include "base/threading/thread_checker.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
 #include "components/viz/service/display/resolved_frame_data.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -142,8 +142,8 @@
    private:
     gfx::Rect crop_rect_;
     base::ScopedClosureRunner return_resource;
-    std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation_;
-    std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
+    std::unique_ptr<gpu::OverlayImageRepresentation> representation_;
+    std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
         read_access_;
     base::ScopedFD begin_read_fence_;
   };
@@ -893,9 +893,9 @@
     // TODO(vasilyt): We should get this from surface aggregator after
     // aggregator refactoring will be finished.
     const auto& frame = surface->GetActiveFrame();
-    auto* quad = viz::StreamVideoDrawQuad::MaterialCast(
+    auto* quad = viz::TextureDrawQuad::MaterialCast(
         frame.render_pass_list.back()->quad_list.front());
-    DCHECK(quad);
+    DCHECK(quad->is_stream_video);
 
     auto uv_rect = gfx::BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
 
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 8cd3198..43529e5 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -84,7 +84,6 @@
 
 bool AwContentRendererClient::HandleNavigation(
     content::RenderFrame* render_frame,
-    bool render_view_was_created_by_renderer,
     blink::WebFrame* frame,
     const blink::WebURLRequest& request,
     blink::WebNavigationType type,
@@ -114,16 +113,19 @@
        gurl.SchemeIs(url::kAboutScheme)))
     return false;
 
+  AwRenderViewExt* view =
+      AwRenderViewExt::FromWebView(render_frame->GetWebView());
+
   // use NavigationInterception throttle to handle the call as that can
   // be deferred until after the java side has been constructed.
   //
-  // TODO(nick): |render_view_was_created_by_renderer| was plumbed in to
+  // TODO(nick): `view->created_by_renderer()` was plumbed in to
   // preserve the existing code behavior, but it doesn't appear to be correct.
   // In particular, this value will be true for the initial navigation of a
   // RenderView created via window.open(), but it will also be true for all
   // subsequent navigations in that RenderView, no matter how they are
   // initiated.
-  if (render_view_was_created_by_renderer) {
+  if (view->created_by_renderer()) {
     return false;
   }
 
@@ -166,8 +168,9 @@
   new page_load_metrics::MetricsRenderFrameObserver(render_frame);
 }
 
-void AwContentRendererClient::WebViewCreated(blink::WebView* web_view) {
-  AwRenderViewExt::WebViewCreated(web_view);
+void AwContentRendererClient::WebViewCreated(blink::WebView* web_view,
+                                             bool was_created_by_renderer) {
+  AwRenderViewExt::WebViewCreated(web_view, was_created_by_renderer);
 }
 
 void AwContentRendererClient::PrepareErrorPage(
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index e6eda10..37e01ff 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -42,7 +42,8 @@
   void RenderThreadStarted() override;
   void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override;
   void RenderFrameCreated(content::RenderFrame* render_frame) override;
-  void WebViewCreated(blink::WebView* web_view) override;
+  void WebViewCreated(blink::WebView* web_view,
+                      bool was_created_by_renderer) override;
   void PrepareErrorPage(content::RenderFrame* render_frame,
                         const blink::WebURLError& error,
                         const std::string& http_method,
@@ -56,7 +57,6 @@
   std::unique_ptr<blink::WebSocketHandshakeThrottleProvider>
   CreateWebSocketHandshakeThrottleProvider() override;
   bool HandleNavigation(content::RenderFrame* render_frame,
-                        bool render_view_was_created_by_renderer,
                         blink::WebFrame* frame,
                         const blink::WebURLRequest& request,
                         blink::WebNavigationType type,
diff --git a/android_webview/renderer/aw_render_view_ext.cc b/android_webview/renderer/aw_render_view_ext.cc
index 83930968..d4b7b569 100644
--- a/android_webview/renderer/aw_render_view_ext.cc
+++ b/android_webview/renderer/aw_render_view_ext.cc
@@ -3,7 +3,12 @@
 // found in the LICENSE file.
 
 #include "android_webview/renderer/aw_render_view_ext.h"
+
+#include <map>
+
 #include "android_webview/common/mojom/frame.mojom.h"
+#include "base/containers/contains.h"
+#include "base/no_destructor.h"
 #include "content/public/renderer/render_frame.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/web/web_local_frame.h"
@@ -11,16 +16,55 @@
 
 namespace android_webview {
 
-AwRenderViewExt::AwRenderViewExt(blink::WebView* web_view)
-    : blink::WebViewObserver(web_view) {
-  DCHECK(web_view != nullptr);
+// Registry for blink::WebView => AwRenderViewExt lookups
+typedef std::map<blink::WebView*, AwRenderViewExt*> ViewExtMap;
+ViewExtMap* GetViewExtMap() {
+  static base::NoDestructor<ViewExtMap> map;
+  return map.get();
 }
 
-AwRenderViewExt::~AwRenderViewExt() {}
+AwRenderViewExt::AwRenderViewExt(blink::WebView* web_view,
+                                 bool created_by_renderer)
+    : blink::WebViewObserver(web_view),
+      created_by_renderer_(created_by_renderer) {
+  DCHECK(web_view != nullptr);
+  DCHECK(!base::Contains(*GetViewExtMap(), web_view));
+  GetViewExtMap()->emplace(web_view, this);
+}
+
+AwRenderViewExt::~AwRenderViewExt() {
+  // Remove myself from the blink::WebView => AwRenderViewExt register. Ideally,
+  // we'd just use GetWebView() and erase by key. However, by this time the
+  // GetWebView has already been cleared so we have to iterate over all
+  // WebViews in the map and wipe the one(s) that point to this
+  // AwRenderViewExt
+
+  auto* map = GetViewExtMap();
+  auto it = map->begin();
+  while (it != map->end()) {
+    if (it->second == this) {
+      it = map->erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
 
 // static
-void AwRenderViewExt::WebViewCreated(blink::WebView* web_view) {
-  new AwRenderViewExt(web_view);  // |web_view| takes ownership.
+void AwRenderViewExt::WebViewCreated(blink::WebView* web_view,
+                                     bool created_by_renderer) {
+  new AwRenderViewExt(web_view,
+                      created_by_renderer);  // |web_view| takes ownership.
+}
+
+// static
+AwRenderViewExt* AwRenderViewExt::FromWebView(blink::WebView* web_view) {
+  DCHECK(web_view != nullptr);
+  auto iter = GetViewExtMap()->find(web_view);
+  DCHECK(GetViewExtMap()->end() != iter)
+      << "AwRenderViewExt should always exist for a WebView";
+  AwRenderViewExt* render_view_ext = iter->second;
+  return render_view_ext;
 }
 
 void AwRenderViewExt::DidCommitCompositorFrame() {
diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h
index e8371ab..85e5f2a 100644
--- a/android_webview/renderer/aw_render_view_ext.h
+++ b/android_webview/renderer/aw_render_view_ext.h
@@ -23,10 +23,15 @@
   AwRenderViewExt(const AwRenderViewExt&) = delete;
   AwRenderViewExt& operator=(const AwRenderViewExt&) = delete;
 
-  static void WebViewCreated(blink::WebView* web_view);
+  static void WebViewCreated(blink::WebView* web_view,
+                             bool created_by_renderer);
+
+  static AwRenderViewExt* FromWebView(blink::WebView* web_view);
+
+  bool created_by_renderer() { return created_by_renderer_; }
 
  private:
-  AwRenderViewExt(blink::WebView* web_view);
+  AwRenderViewExt(blink::WebView* web_view, bool created_by_renderer);
   ~AwRenderViewExt() override;
 
   // blink::WebViewObserver overrides.
@@ -41,6 +46,8 @@
   // Whether the contents size may have changed and |UpdateContentsSize| needs
   // to be called.
   bool needs_contents_size_update_ = true;
+
+  bool created_by_renderer_;
 };
 
 }  // namespace android_webview
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 28b6940..6a1a79f4 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -977,6 +977,8 @@
     "style/system_shadow_on_nine_patch_layer.h",
     "style/system_toast_style.cc",
     "style/system_toast_style.h",
+    "style/temp_palette.cc",
+    "style/temp_palette.h",
     "system/accessibility/accessibility_feature_disable_dialog.cc",
     "system/accessibility/accessibility_feature_disable_dialog.h",
     "system/accessibility/accessibility_feature_pod_controller.cc",
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc
index 3f979ff1..69f2394 100644
--- a/ash/app_list/app_list_presenter_unittest.cc
+++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -562,19 +562,31 @@
     GetEventGenerator()->Dispatch(&long_press);
   }
 
-  void EnsureLauncherShown() {
+  void EnsureBubbleLauncherShown() {
+    Shell::Get()->app_list_controller()->bubble_presenter_for_test()->Show(
+        GetPrimaryDisplay().id());
+  }
+
+  void EnsureFullscreenLauncherShown() {
     auto* helper = GetAppListTestHelper();
-    if (should_show_bubble_launcher()) {
-      Shell::Get()->app_list_controller()->bubble_presenter_for_test()->Show(
-          GetPrimaryDisplay().id());
-    } else if (tablet_mode_param()) {
-      // App list is always visible in tablet mode so we do not need to show it.
-    } else {
-      // Show fullscreen so folders are available.
-      helper->ShowAndRunLoop(GetPrimaryDisplayId());
-      helper->GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
+    helper->ShowAndRunLoop(GetPrimaryDisplayId());
+    helper->GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
+  }
+
+  void EnsureLauncherShown() {
+    const bool in_tablet_mode = Shell::Get()->IsInTabletMode();
+
+    // App list always visible in tablet mode, so launcher needs to explicitly
+    // be shown only when in clamshell mode.
+    if (!in_tablet_mode) {
+      if (productivity_launcher_param())
+        EnsureBubbleLauncherShown();
+      else
+        EnsureFullscreenLauncherShown();
     }
-    if (should_show_bubble_launcher()) {
+
+    auto* helper = GetAppListTestHelper();
+    if (!in_tablet_mode && productivity_launcher_param()) {
       apps_grid_view_ = helper->GetScrollableAppsGridView();
     } else {
       apps_grid_view_ = helper->GetRootPagedAppsGridView();
@@ -1658,6 +1670,80 @@
   EXPECT_EQ(should_show_zero_state_search(), AppListSearchResultPageVisible());
 }
 
+// Verifies that changes in launcher search box do not cause duplicate search
+// requests if both clamshell and tablet app list views exist (and one of them
+// is hidden).
+TEST_P(AppListBubbleAndTabletTest, NoDuplicateSearchRequests) {
+  // Toggle tablet mode to ensure the app list view for tablet mode state
+  // opposite to the one used in test is created.
+  EnableTabletMode(!tablet_mode_param());
+  EnsureLauncherShown();
+  EnableTabletMode(tablet_mode_param());
+
+  TestAppListClient* const client = GetAppListTestHelper()->app_list_client();
+  // Closing the bubble launcher clears search.
+  if (tablet_mode_param() && productivity_launcher_param()) {
+    EXPECT_EQ(std::vector<std::u16string>({u""}),
+              client->GetAndResetPastSearchQueries());
+  }
+
+  EnsureLauncherShown();
+
+  // Type a character into the textfield and verify this issues a single search
+  // request.
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->PressKey(ui::VKEY_A, 0);
+  EXPECT_TRUE(AppListSearchResultPageVisible());
+
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
+  generator->PressKey(ui::VKEY_B, 0);
+  EXPECT_EQ(std::vector<std::u16string>({u"ab"}),
+            client->GetAndResetPastSearchQueries());
+  generator->PressKey(ui::VKEY_BACK, 0);
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
+  generator->PressKey(ui::VKEY_BACK, 0);
+  EXPECT_EQ(std::vector<std::u16string>({u""}),
+            client->GetAndResetPastSearchQueries());
+}
+
+TEST_P(AppListBubbleAndTabletTest, ClearSearchButtonClearsSearch) {
+  // Toggle tablet mode to ensure the app list view for tablet mode state
+  // opposite to the one used in test is created.
+  EnableTabletMode(!tablet_mode_param());
+  EnsureLauncherShown();
+  EnableTabletMode(tablet_mode_param());
+
+  TestAppListClient* const client = GetAppListTestHelper()->app_list_client();
+  // Closing the bubble launcher clears search.
+  if (tablet_mode_param() && productivity_launcher_param()) {
+    EXPECT_EQ(std::vector<std::u16string>({u""}),
+              client->GetAndResetPastSearchQueries());
+  }
+
+  EnsureLauncherShown();
+
+  // Type a character into the textfield and verify this issues a single search
+  // request.
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->PressKey(ui::VKEY_A, 0);
+  EXPECT_TRUE(AppListSearchResultPageVisible());
+
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
+  generator->PressKey(ui::VKEY_B, 0);
+  EXPECT_EQ(std::vector<std::u16string>({u"ab"}),
+            client->GetAndResetPastSearchQueries());
+
+  SearchBoxView* search_box_view = GetSearchBoxView();
+  EXPECT_TRUE(search_box_view->close_button()->GetVisible());
+  LeftClickOn(search_box_view->close_button());
+
+  EXPECT_EQ(std::vector<std::u16string>({u""}),
+            client->GetAndResetPastSearchQueries());
+}
+
 // Regression test for b/204482740.
 TEST_P(AppListBubbleAndTabletTest, AppListEventTargeterForAssistantScrolling) {
   EnableTabletMode(tablet_mode_param());
@@ -1990,7 +2076,7 @@
 
   EXPECT_TRUE(GetAppListTestHelper()
                   ->app_list_client()
-                  ->GetAndClearInvokedResultActions()
+                  ->GetAndResetInvokedResultActions()
                   .empty());
   ASSERT_TRUE(GetSearchResultPageDialog());
 
@@ -2003,7 +2089,7 @@
   EXPECT_FALSE(GetSearchResultPageDialog());
   EXPECT_TRUE(GetAppListTestHelper()
                   ->app_list_client()
-                  ->GetAndClearInvokedResultActions()
+                  ->GetAndResetInvokedResultActions()
                   .empty());
 
   // The result selection should be at the same position.
@@ -2032,7 +2118,7 @@
   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
       GetAppListTestHelper()
           ->app_list_client()
-          ->GetAndClearInvokedResultActions();
+          ->GetAndResetInvokedResultActions();
   EXPECT_EQ(expected_actions, invoked_actions);
 }
 
@@ -2080,7 +2166,7 @@
 
   EXPECT_TRUE(GetAppListTestHelper()
                   ->app_list_client()
-                  ->GetAndClearInvokedResultActions()
+                  ->GetAndResetInvokedResultActions()
                   .empty());
   ASSERT_TRUE(GetSearchResultPageDialog());
 
@@ -2094,7 +2180,7 @@
 
   EXPECT_TRUE(GetAppListTestHelper()
                   ->app_list_client()
-                  ->GetAndClearInvokedResultActions()
+                  ->GetAndResetInvokedResultActions()
                   .empty());
   EXPECT_FALSE(result_view->selected());
 
@@ -2123,7 +2209,7 @@
   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
       GetAppListTestHelper()
           ->app_list_client()
-          ->GetAndClearInvokedResultActions();
+          ->GetAndResetInvokedResultActions();
   EXPECT_EQ(expected_actions, invoked_actions);
 }
 
@@ -2665,8 +2751,14 @@
     EXPECT_TRUE(item_view->layer()) << "at " << i;
   }
 
-  // Layers should be destroyed once the bounds animation completes.
-  apps_grid_view_->CancelAnimationsForTest();
+  // Wait for each item's layer animation to complete.
+  LayerAnimationStoppedWaiter animation_waiter;
+  for (size_t i = 0; i < apps_grid_view_->view_model()->view_size(); i++) {
+    if (apps_grid_view_->view_model()->view_at(i)->layer())
+      animation_waiter.Wait(apps_grid_view_->view_model()->view_at(i)->layer());
+  }
+
+  // Layers should be destroyed once the item animations complete.
   for (int i = 0; i < kItemCount; ++i) {
     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
     EXPECT_FALSE(item_view->layer()) << "at " << i;
diff --git a/ash/app_list/app_list_test_api.cc b/ash/app_list/app_list_test_api.cc
index fb786b0..bfb0599 100644
--- a/ash/app_list/app_list_test_api.cc
+++ b/ash/app_list/app_list_test_api.cc
@@ -31,6 +31,7 @@
 #include "ash/app_list/views/contents_view.h"
 #include "ash/app_list/views/paged_apps_grid_view.h"
 #include "ash/app_list/views/scrollable_apps_grid_view.h"
+#include "ash/app_list/views/search_box_view.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/accelerators.h"
 #include "ash/shell.h"
@@ -46,6 +47,7 @@
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/controls/menu/submenu_view.h"
 #include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/view_model.h"
 
 namespace ash {
@@ -246,6 +248,12 @@
   return GetAppsContainerView()->GetRecentApps();
 }
 
+SearchBoxView* GetSearchBoxView() {
+  if (ShouldUseBubbleAppList())
+    return GetAppListBubbleView()->search_box_view_for_test();
+  return GetAppListView()->app_list_main_view()->search_box_view();
+}
+
 // AppListVisibilityChangedWaiter ----------------------------------------------
 
 // Waits until the app list visibility changes.
@@ -648,6 +656,14 @@
   return GetRecentAppsView()->GetItemViewAt(index);
 }
 
+void AppListTestApi::SimulateSearch(const std::u16string& query) {
+  views::Textfield* textfield = GetSearchBoxView()->search_box();
+  textfield->SetText(u"");
+  textfield->InsertText(
+      query,
+      ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
+}
+
 void AppListTestApi::ReorderByMouseClickAtContextMenuInAppsGrid(
     ash::AppsGridView* apps_grid_view,
     ash::AppListSortOrder order,
diff --git a/ash/app_list/test_app_list_client.cc b/ash/app_list/test_app_list_client.cc
index 147356a..7e0371d 100644
--- a/ash/app_list/test_app_list_client.cc
+++ b/ash/app_list/test_app_list_client.cc
@@ -40,7 +40,7 @@
 }
 
 void TestAppListClient::StartSearch(const std::u16string& trimmed_query) {
-  last_search_query_ = trimmed_query;
+  search_queries_.push_back(trimmed_query);
 }
 
 void TestAppListClient::OpenSearchResult(int profile_id,
@@ -88,12 +88,18 @@
 }
 
 std::vector<TestAppListClient::SearchResultActionId>
-TestAppListClient::GetAndClearInvokedResultActions() {
+TestAppListClient::GetAndResetInvokedResultActions() {
   std::vector<SearchResultActionId> result;
   result.swap(invoked_result_actions_);
   return result;
 }
 
+std::vector<std::u16string> TestAppListClient::GetAndResetPastSearchQueries() {
+  std::vector<std::u16string> result;
+  result.swap(search_queries_);
+  return result;
+}
+
 ash::AppListSortOrder TestAppListClient::GetPermanentSortingOrder() const {
   NOTIMPLEMENTED();
   return ash::AppListSortOrder::kCustom;
diff --git a/ash/app_list/test_app_list_client.h b/ash/app_list/test_app_list_client.h
index 06e992bf..916859b 100644
--- a/ash/app_list/test_app_list_client.h
+++ b/ash/app_list/test_app_list_client.h
@@ -75,7 +75,6 @@
   int zero_state_search_done_count() const {
     return zero_state_search_done_count_;
   }
-  std::u16string last_search_query() const { return last_search_query_; }
 
   // Returns the number of AppItems that have been activated. These items could
   // live in search, RecentAppsView, or ScrollableAppsGridView.
@@ -90,7 +89,13 @@
   }
 
   using SearchResultActionId = std::pair<std::string, int>;
-  std::vector<SearchResultActionId> GetAndClearInvokedResultActions();
+  std::vector<SearchResultActionId> GetAndResetInvokedResultActions();
+
+  // Returns the list of search queries that were requested.
+  // This clears the list of tracked queries - if the method gets called
+  // consecutively, the second call will not return queries returned returned by
+  // the first call.
+  std::vector<std::u16string> GetAndResetPastSearchQueries();
 
  private:
   // Called in response to StartZeroStateSearch() when
@@ -101,7 +106,7 @@
   int start_zero_state_search_count_ = 0;
   bool run_zero_state_callback_immediately_ = true;
   int zero_state_search_done_count_ = 0;
-  std::u16string last_search_query_;
+  std::vector<std::u16string> search_queries_;
   std::vector<SearchResultActionId> invoked_result_actions_;
   int activate_item_count_ = 0;
   std::string activate_item_last_id_;
diff --git a/ash/app_list/views/app_list_bubble_view.cc b/ash/app_list/views/app_list_bubble_view.cc
index 4290825..e5c01ec 100644
--- a/ash/app_list/views/app_list_bubble_view.cc
+++ b/ash/app_list/views/app_list_bubble_view.cc
@@ -625,11 +625,6 @@
     else
       ShowPage(AppListBubblePage::kApps);
   }
-
-  // Ask the controller to start the search.
-  std::u16string query =
-      AppListModelProvider::Get()->search_model()->search_box()->text();
-  view_delegate_->StartSearch(query);
   SchedulePaint();
 }
 
diff --git a/ash/app_list/views/app_list_bubble_view_unittest.cc b/ash/app_list/views/app_list_bubble_view_unittest.cc
index dbc27b26..31dd494 100644
--- a/ash/app_list/views/app_list_bubble_view_unittest.cc
+++ b/ash/app_list/views/app_list_bubble_view_unittest.cc
@@ -580,10 +580,13 @@
   EXPECT_TRUE(search_box_input->HasFocus());
   EXPECT_EQ(u"a", search_box_input->GetText());
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
-  EXPECT_EQ(u"a", client->last_search_query());
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
 
   // The app list view and widget are cached after this close.
   DismissAppList();
+  EXPECT_EQ(std::vector<std::u16string>({u""}),
+            client->GetAndResetPastSearchQueries());
 
   // Search box is empty on next show.
   ShowAppList();
@@ -594,7 +597,6 @@
   search_box_input = GetSearchBoxView()->search_box();
   EXPECT_TRUE(search_box_input->HasFocus());
   EXPECT_EQ(u"", search_box_input->GetText());
-  EXPECT_EQ(u"", client->last_search_query());
 }
 
 // Regression test for https://crbug.com/1313140
@@ -702,6 +704,10 @@
 TEST_F(AppListBubbleViewTest, SearchBoxCloseButton) {
   ShowAppList();
   PressAndReleaseKey(ui::VKEY_A);
+  TestAppListClient* const app_list_client =
+      GetAppListTestHelper()->app_list_client();
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            app_list_client->GetAndResetPastSearchQueries());
 
   // Close button is visible after typing text.
   SearchBoxView* search_box_view = GetSearchBoxView();
@@ -711,6 +717,8 @@
   // Clicking the close button clears the search, but the search box is still
   // focused/active.
   LeftClickOn(search_box_view->close_button());
+  EXPECT_EQ(std::vector<std::u16string>({u""}),
+            app_list_client->GetAndResetPastSearchQueries());
   EXPECT_FALSE(search_box_view->close_button()->GetVisible());
   EXPECT_TRUE(search_box_view->search_box()->GetText().empty());
   EXPECT_TRUE(search_box_view->search_box()->HasFocus());
@@ -747,15 +755,21 @@
 }
 
 TEST_F(AppListBubbleViewTest, TypingTextStartsSearch) {
-  TestAppListClient* client = GetAppListTestHelper()->app_list_client();
-
   ShowAppList();
 
   PressAndReleaseKey(ui::VKEY_A);
-  EXPECT_EQ(client->last_search_query(), u"a");
+
+  TestAppListClient* client = GetAppListTestHelper()->app_list_client();
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
 
   PressAndReleaseKey(ui::VKEY_B);
-  EXPECT_EQ(client->last_search_query(), u"ab");
+  EXPECT_EQ(std::vector<std::u16string>({u"ab"}),
+            client->GetAndResetPastSearchQueries());
+
+  PressAndReleaseKey(ui::VKEY_BACK);
+  EXPECT_EQ(std::vector<std::u16string>({u"a"}),
+            client->GetAndResetPastSearchQueries());
 }
 
 TEST_F(AppListBubbleViewTest, BackActionsClearSearch) {
diff --git a/ash/app_list/views/app_list_main_view.cc b/ash/app_list/views/app_list_main_view.cc
index 4d829db..529f4c8 100644
--- a/ash/app_list/views/app_list_main_view.cc
+++ b/ash/app_list/views/app_list_main_view.cc
@@ -131,8 +131,6 @@
   base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
   contents_view_->ShowSearchResults(search_box_view_->is_search_box_active() ||
                                     !query.empty());
-
-  delegate_->StartSearch(raw_query);
 }
 
 void AppListMainView::ActiveChanged(SearchBoxViewBase* sender) {
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 14aa6df..d70baf8 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -2244,18 +2244,7 @@
 
 bool AppsGridView::IsAnimationRunningForTest() {
   return bounds_animator_->IsAnimating() ||
-         bounds_animation_for_cardified_state_in_progress_ > 0;
-}
-
-void AppsGridView::CancelAnimationsForTest() {
-  bounds_animator_->Cancel();
-  drag_icon_proxy_.reset();
-
-  const size_t total_views = view_model_.view_size();
-  for (size_t i = 0; i < total_views; ++i) {
-    if (view_model_.view_at(i)->layer())
-      view_model_.view_at(i)->layer()->CompleteAllAnimations();
-  }
+         bounds_animation_for_cardified_state_in_progress_;
 }
 
 bool AppsGridView::FireFolderItemReparentTimerForTest() {
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index f8d668e..c5b6550 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -313,8 +313,6 @@
 
   // Returns true if any animation is running within the view.
   bool IsAnimationRunningForTest();
-  // Cancel any animations currently running within the view.
-  void CancelAnimationsForTest();
 
   AppsGridViewFolderDelegate* folder_delegate() const {
     return folder_delegate_;
@@ -577,7 +575,7 @@
   // TODO(crbug.com/1211608): Move cardified state members to PagedAppsGridView.
   bool cardified_state_ = false;
 
-  int bounds_animation_for_cardified_state_in_progress_ = 0;
+  bool bounds_animation_for_cardified_state_in_progress_ = false;
 
   // Tile spacing between the tile views.
   int horizontal_tile_padding_ = 0;
diff --git a/ash/app_list/views/continue_section_view_unittest.cc b/ash/app_list/views/continue_section_view_unittest.cc
index b7479c7..695d0619 100644
--- a/ash/app_list/views/continue_section_view_unittest.cc
+++ b/ash/app_list/views/continue_section_view_unittest.cc
@@ -783,7 +783,7 @@
   std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
       {"id1", SearchResultActionType::kRemove}};
   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
-      client->GetAndClearInvokedResultActions();
+      client->GetAndResetInvokedResultActions();
   EXPECT_EQ(expected_actions, invoked_actions);
 }
 
@@ -810,7 +810,7 @@
       {"id1", SearchResultActionType::kRemove},
       {"id2", SearchResultActionType::kRemove}};
   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
-      client->GetAndClearInvokedResultActions();
+      client->GetAndResetInvokedResultActions();
   EXPECT_EQ(expected_actions, invoked_actions);
 
   EXPECT_EQ(1, histogram_tester.GetBucketCount(
diff --git a/ash/app_list/views/paged_apps_grid_view.cc b/ash/app_list/views/paged_apps_grid_view.cc
index 04d5475..d52cf18 100644
--- a/ash/app_list/views/paged_apps_grid_view.cc
+++ b/ash/app_list/views/paged_apps_grid_view.cc
@@ -5,6 +5,7 @@
 #include "ash/app_list/views/paged_apps_grid_view.h"
 
 #include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "ash/app_list/app_list_metrics.h"
@@ -910,19 +911,6 @@
   presentation_time_recorder_.reset();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ui::ImplicitAnimationObserver:
-
-void PagedAppsGridView::OnImplicitAnimationsCompleted() {
-  if (layer()->opacity() == 0.0f)
-    SetVisible(false);
-  if (cardified_state_) {
-    MaskContainerToBackgroundBounds();
-    return;
-  }
-  RemoveAllBackgroundCards();
-}
-
 bool PagedAppsGridView::DoesIntersectRect(const views::View* target,
                                           const gfx::Rect& rect) const {
   gfx::Rect target_bounds(target->GetLocalBounds());
@@ -1101,11 +1089,17 @@
   page_flip_target_ = -1;
 }
 
+void PagedAppsGridView::MaybeAbortExistingCardifiedAnimations() {
+  if (cardified_animation_abort_handle_) {
+    cardified_animation_abort_handle_.reset();
+  }
+}
+
 void PagedAppsGridView::StartAppsGridCardifiedView() {
   if (IsInFolder())
     return;
   DCHECK(!cardified_state_);
-  StopObservingImplicitAnimations();
+  MaybeAbortExistingCardifiedAnimations();
   RemoveAllBackgroundCards();
   // Calculate background bounds for a normal grid so it animates from the
   // normal to the cardified bounds with the icons.
@@ -1126,7 +1120,7 @@
   if (IsInFolder())
     return;
   DCHECK(cardified_state_);
-  StopObservingImplicitAnimations();
+  MaybeAbortExistingCardifiedAnimations();
   cardified_state_ = false;
   // Update the padding between tiles, so we can animate back the apps grid
   // elements to their original positions.
@@ -1160,20 +1154,6 @@
   gfx::Point start_position = items_container()->origin();
   RecenterItemsContainer();
 
-  auto animation_settings = [this](ui::Layer* layer)
-      -> std::unique_ptr<ui::ScopedLayerAnimationSettings> {
-    auto settings = std::make_unique<ui::ScopedLayerAnimationSettings>(
-        layer->GetAnimator());
-    settings->SetPreemptionStrategy(
-        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-    settings->SetTweenType(kCardifiedStateTweenType);
-    if (!cardified_state_) {
-      settings->SetTransitionDuration(
-          base::Milliseconds(kDefaultAnimationDuration));
-    }
-    return settings;
-  };
-
   // Apps might be animating due to drag reorder. Cancel any active animations
   // so that the cardified state animation can be applied.
   bounds_animator()->Cancel();
@@ -1181,7 +1161,33 @@
   gfx::Vector2d translate_offset(
       0, start_position.y() - items_container()->origin().y());
 
-  AnimateAppListItemsForCardifiedState(translate_offset);
+  // Create background card animation metric reporters.
+  std::vector<std::unique_ptr<ui::AnimationThroughputReporter>> reporters;
+  for (auto& background_card : background_cards_) {
+    reporters.push_back(std::make_unique<ui::AnimationThroughputReporter>(
+        background_card->GetAnimator(),
+        metrics_util::ForSmoothness(base::BindRepeating(
+            &ReportCardifiedSmoothness, cardified_state_))));
+  }
+
+  views::AnimationBuilder animations;
+  cardified_animation_abort_handle_ = animations.GetAbortHandle();
+  animations
+      .OnEnded(base::BindOnce(&PagedAppsGridView::MaybeCallOnBoundsAnimatorDone,
+                              weak_ptr_factory_.GetWeakPtr()))
+      .OnAborted(
+          base::BindOnce(&PagedAppsGridView::MaybeCallOnBoundsAnimatorDone,
+                         weak_ptr_factory_.GetWeakPtr()))
+      .SetPreemptionStrategy(
+          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
+      .Once()
+      .SetDuration(base::Milliseconds(kDefaultAnimationDuration));
+
+  DCHECK(!bounds_animation_for_cardified_state_in_progress_);
+  bounds_animation_for_cardified_state_in_progress_ = true;
+
+  AnimateAppListItemsForCardifiedState(&animations.GetCurrentSequence(),
+                                       translate_offset);
 
   if (current_ghost_view_) {
     auto index = current_ghost_view_->index();
@@ -1196,8 +1202,9 @@
         gfx::RectF(items_container()->GetMirroredRect(current_bounds)));
     current_ghost_view_->layer()->SetTransform(transform);
 
-    auto animator = animation_settings(current_ghost_view_->layer());
-    current_ghost_view_->layer()->SetTransform(gfx::Transform());
+    animations.GetCurrentSequence().SetTransform(current_ghost_view_->layer(),
+                                                 gfx::Transform(),
+                                                 kCardifiedStateTweenType);
   }
 
   for (size_t i = 0; i < background_cards_.size(); i++) {
@@ -1206,26 +1213,24 @@
     gfx::Rect background_bounds = background_card->bounds();
     background_bounds.Offset(translate_offset);
     background_card->SetBounds(background_bounds);
-    auto animator = animation_settings(background_card.get());
-    animator->AddObserver(this);
-    ui::AnimationThroughputReporter reporter(
-        background_card->GetAnimator(),
-        metrics_util::ForSmoothness(
-            base::BindRepeating(&ReportCardifiedSmoothness, cardified_state_)));
     if (cardified_state_) {
       const bool is_active_page =
           background_cards_[pagination_model_.selected_page()] ==
           background_card;
       background_card->SetIsActivePage(is_active_page);
     } else {
-      background_card->SetOpacity(kBackgroundCardOpacityHide);
+      animations.GetCurrentSequence().SetOpacity(background_card.get(),
+                                                 kBackgroundCardOpacityHide);
     }
-    background_card->SetBounds(BackgroundCardBounds(i));
+    animations.GetCurrentSequence().SetBounds(background_card.get(),
+                                              BackgroundCardBounds(i),
+                                              kCardifiedStateTweenType);
   }
   highlighted_page_ = pagination_model_.selected_page();
 }
 
 void PagedAppsGridView::AnimateAppListItemsForCardifiedState(
+    views::AnimationSequenceBlock* animation_sequence,
     const gfx::Vector2d& translate_offset) {
   // Check that at least one item needs animating to avoid creating an animation
   // builder when no views need animating.
@@ -1238,26 +1243,8 @@
     }
   }
 
-  // When no items need animating, make sure that OnCardifiedStateEnded() gets
-  // called because MaybeCallOnBoundsAnimatorDone() is not called.
-  if (!items_need_animating) {
-    if (!cardified_state_)
-      OnCardifiedStateEnded();
+  if (!items_need_animating)
     return;
-  }
-
-  views::AnimationBuilder item_animations;
-  item_animations
-      .OnEnded(base::BindOnce(&PagedAppsGridView::MaybeCallOnBoundsAnimatorDone,
-                              weak_ptr_factory_.GetWeakPtr()))
-      .OnAborted(
-          base::BindOnce(&PagedAppsGridView::MaybeCallOnBoundsAnimatorDone,
-                         weak_ptr_factory_.GetWeakPtr()))
-      .SetPreemptionStrategy(
-          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
-      .Once()
-      .SetDuration(base::Milliseconds(kDefaultAnimationDuration));
-  bounds_animation_for_cardified_state_in_progress_++;
 
   for (size_t i = 0; i < view_model()->view_size(); ++i) {
     AppListItemView* entry_view = view_model()->view_at(i);
@@ -1297,23 +1284,30 @@
         gfx::RectF(items_container()->GetMirroredRect(current_bounds)));
     entry_view->layer()->SetTransform(transform);
 
-    item_animations.GetCurrentSequence().SetTransform(
-        entry_view->layer(), gfx::Transform(), kCardifiedStateTweenType);
+    animation_sequence->SetTransform(entry_view->layer(), gfx::Transform(),
+                                     kCardifiedStateTweenType);
   }
 }
 
 void PagedAppsGridView::MaybeCallOnBoundsAnimatorDone() {
-  --bounds_animation_for_cardified_state_in_progress_;
-  if (bounds_animation_for_cardified_state_in_progress_ == 0) {
-    DestroyLayerItemsIfNotNeeded();
+  DCHECK(bounds_animation_for_cardified_state_in_progress_);
+  bounds_animation_for_cardified_state_in_progress_ = false;
 
-    if (!cardified_state_)
-      OnCardifiedStateEnded();
+  DestroyLayerItemsIfNotNeeded();
+
+  if (layer()->opacity() == 0.0f)
+    SetVisible(false);
+
+  if (cardified_state_) {
+    MaskContainerToBackgroundBounds();
+  } else {
+    OnCardifiedStateEnded();
   }
 }
 
 void PagedAppsGridView::OnCardifiedStateEnded() {
   ignore_layout_ = false;
+  RemoveAllBackgroundCards();
 
   if (cardified_state_ended_test_callback_)
     cardified_state_ended_test_callback_.Run();
diff --git a/ash/app_list/views/paged_apps_grid_view.h b/ash/app_list/views/paged_apps_grid_view.h
index 78b90a97..e806a88 100644
--- a/ash/app_list/views/paged_apps_grid_view.h
+++ b/ash/app_list/views/paged_apps_grid_view.h
@@ -15,11 +15,11 @@
 #include "ash/public/cpp/pagination/pagination_model_observer.h"
 #include "base/time/time.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/presentation_time_recorder.h"
 #include "ui/compositor/throughput_tracker.h"
 #include "ui/events/types/event_type.h"
 #include "ui/gfx/geometry/point_f.h"
+#include "ui/views/animation/animation_abort_handle.h"
 #include "ui/views/view_targeter_delegate.h"
 
 namespace gfx {
@@ -42,7 +42,6 @@
 // for the transition into and out of the "cardified" state.
 class ASH_EXPORT PagedAppsGridView : public AppsGridView,
                                      public PaginationModelObserver,
-                                     public ui::ImplicitAnimationObserver,
                                      public views::ViewTargeterDelegate {
  public:
   class ContainerDelegate {
@@ -149,9 +148,6 @@
   void ScrollStarted() override;
   void ScrollEnded() override;
 
-  // ui::ImplicitAnimationObserver:
-  void OnImplicitAnimationsCompleted() override;
-
   // views::ViewTargeterDelegate:
   bool DoesIntersectRect(const views::View* target,
                          const gfx::Rect& rect) const override;
@@ -208,7 +204,7 @@
   // Animates items to their ideal bounds when the reorder nudge gets removed.
   void AnimateOnNudgeRemoved();
 
-  int GetBoundsAnimationForCardifiedStateInProgressCountForTest() {
+  bool GetBoundsAnimationForCardifiedStateInProgressForTest() {
     return bounds_animation_for_cardified_state_in_progress_;
   }
 
@@ -255,6 +251,9 @@
   // Stops the timer that triggers a page flip during a drag.
   void StopPageFlipTimer();
 
+  // Aborts cardified animations if any are running.
+  void MaybeAbortExistingCardifiedAnimations();
+
   // Helper functions to start the Apps Grid Cardified state.
   // The cardified state scales down apps and is shown when the user drags an
   // app in the AppList.
@@ -268,6 +267,7 @@
 
   // Animate app list items in the app grid to and from cardified state.
   void AnimateAppListItemsForCardifiedState(
+      views::AnimationSequenceBlock* animation_sequence,
       const gfx::Vector2d& translate_offset);
 
   // Call OnBoundsAnimatorDone when all layer animations finish.
@@ -391,6 +391,10 @@
   // The callback that runs once cardified state is ended.
   base::RepeatingClosure cardified_state_ended_test_callback_;
 
+  // Used to abort cardified state enter and exit animations.
+  std::unique_ptr<views::AnimationAbortHandle>
+      cardified_animation_abort_handle_;
+
   base::WeakPtrFactory<PagedAppsGridView> weak_ptr_factory_{this};
 };
 
diff --git a/ash/app_list/views/paged_apps_grid_view_unittest.cc b/ash/app_list/views/paged_apps_grid_view_unittest.cc
index c09b8998..ea5af67 100644
--- a/ash/app_list/views/paged_apps_grid_view_unittest.cc
+++ b/ash/app_list/views/paged_apps_grid_view_unittest.cc
@@ -775,9 +775,8 @@
   for (size_t i = 0; i < view_model->view_size(); i++)
     EXPECT_FALSE(view_model->view_at(i)->layer());
 
-  EXPECT_EQ(0,
-            GetPagedAppsGridView()
-                ->GetBoundsAnimationForCardifiedStateInProgressCountForTest());
+  EXPECT_FALSE(GetPagedAppsGridView()
+                   ->GetBoundsAnimationForCardifiedStateInProgressForTest());
 }
 
 // Test the case of beginning an item drag and then immediately ending the drag.
@@ -825,9 +824,8 @@
   // removed.
   for (size_t i = 0; i < view_model->view_size(); i++)
     EXPECT_FALSE(view_model->view_at(i)->layer());
-  EXPECT_EQ(0,
-            GetPagedAppsGridView()
-                ->GetBoundsAnimationForCardifiedStateInProgressCountForTest());
+  EXPECT_FALSE(GetPagedAppsGridView()
+                   ->GetBoundsAnimationForCardifiedStateInProgressForTest());
 
   // Now that cardified item animations are complete, make sure that
   // `OnCardifiedStateEnded()` is only called once.
@@ -888,9 +886,8 @@
   // removed.
   for (size_t i = 0; i < view_model->view_size(); i++)
     EXPECT_FALSE(view_model->view_at(i)->layer());
-  EXPECT_EQ(0,
-            GetPagedAppsGridView()
-                ->GetBoundsAnimationForCardifiedStateInProgressCountForTest());
+  EXPECT_FALSE(GetPagedAppsGridView()
+                   ->GetBoundsAnimationForCardifiedStateInProgressForTest());
   EXPECT_FALSE(IsRowChangeAnimatorAnimating());
   EXPECT_EQ(0, GetNumberOfRowChangeLayersForTest());
 
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc
index 1e05764e..ae87d3e0 100644
--- a/ash/app_list/views/search_box_view.cc
+++ b/ash/app_list/views/search_box_view.cc
@@ -285,6 +285,7 @@
         /*search_box_is_empty=*/true, /*triggered_by_contents_change=*/false);
   }
   NotifyQueryChanged();
+  view_delegate_->StartSearch(u"");
 }
 
 void SearchBoxView::HandleSearchBoxEvent(ui::LocatedEvent* located_event) {
@@ -365,6 +366,11 @@
 
   search_box_model->Update(new_query, initiated_by_user);
   search_box_model_observer_.Observe(search_box_model);
+
+  // Ask the controller to start the search if the change was initiated by the
+  // user.
+  if (initiated_by_user)
+    view_delegate_->StartSearch(new_query);
 }
 
 void SearchBoxView::UpdateSearchIcon() {
diff --git a/ash/clipboard/clipboard_history_menu_model_adapter.cc b/ash/clipboard/clipboard_history_menu_model_adapter.cc
index 46b99149..1c17cef8 100644
--- a/ash/clipboard/clipboard_history_menu_model_adapter.cc
+++ b/ash/clipboard/clipboard_history_menu_model_adapter.cc
@@ -137,7 +137,7 @@
   return iter->second;
 }
 
-int ClipboardHistoryMenuModelAdapter::GetMenuItemsCount() const {
+size_t ClipboardHistoryMenuModelAdapter::GetMenuItemsCount() const {
   // We should not use `root_view_` to retrieve the item count. Because the
   // menu item view is removed from `root_view_` asynchronously.
   return item_views_by_command_id_.size();
@@ -272,13 +272,13 @@
 }
 
 const views::MenuItemView*
-ClipboardHistoryMenuModelAdapter::GetMenuItemViewAtForTest(int index) const {
+ClipboardHistoryMenuModelAdapter::GetMenuItemViewAtForTest(size_t index) const {
   DCHECK(root_view_);
   return root_view_->GetSubmenu()->GetMenuItemAt(index);
 }
 
 views::MenuItemView* ClipboardHistoryMenuModelAdapter::GetMenuItemViewAtForTest(
-    int index) {
+    size_t index) {
   return const_cast<views::MenuItemView*>(
       const_cast<const ClipboardHistoryMenuModelAdapter*>(this)
           ->GetMenuItemViewAtForTest(index));
@@ -383,7 +383,7 @@
 views::MenuItemView* ClipboardHistoryMenuModelAdapter::AppendMenuItem(
     views::MenuItemView* menu,
     ui::MenuModel* model,
-    int index) {
+    size_t index) {
   const int command_id = model->GetCommandIdAt(index);
 
   views::MenuItemView* container = menu->AppendMenuItem(command_id);
diff --git a/ash/clipboard/clipboard_history_menu_model_adapter.h b/ash/clipboard/clipboard_history_menu_model_adapter.h
index cd068ce..1e3ab91e 100644
--- a/ash/clipboard/clipboard_history_menu_model_adapter.h
+++ b/ash/clipboard/clipboard_history_menu_model_adapter.h
@@ -69,7 +69,7 @@
   const ClipboardHistoryItem& GetItemFromCommandId(int command_id) const;
 
   // Returns the count of menu items.
-  int GetMenuItemsCount() const;
+  size_t GetMenuItemsCount() const;
 
   // Selects the menu item specified by `command_id`.
   void SelectMenuItemWithCommandId(int command_id);
@@ -89,8 +89,8 @@
   // Returns menu bounds in screen coordinates.
   gfx::Rect GetMenuBoundsInScreenForTest() const;
 
-  const views::MenuItemView* GetMenuItemViewAtForTest(int index) const;
-  views::MenuItemView* GetMenuItemViewAtForTest(int index);
+  const views::MenuItemView* GetMenuItemViewAtForTest(size_t index) const;
+  views::MenuItemView* GetMenuItemViewAtForTest(size_t index);
 
  private:
   class ScopedA11yIgnore;
@@ -115,7 +115,7 @@
   // views::MenuModelAdapter:
   views::MenuItemView* AppendMenuItem(views::MenuItemView* menu,
                                       ui::MenuModel* model,
-                                      int index) override;
+                                      size_t index) override;
   void OnMenuClosed(views::MenuItemView* menu) override;
 
   // The model which holds the contents of the menu.
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 5a277df3..2695514 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -146,7 +146,7 @@
 
 // Controls whether to enable support for ARC Input Overlay.
 const base::Feature kArcInputOverlay{"ArcInputOverlay",
-                                     base::FEATURE_DISABLED_BY_DEFAULT};
+                                     base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether to enable support for ARC ADB sideloading for managed
 // accounts and/or devices.
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 3cfe036..f85083e5 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -398,6 +398,7 @@
     "//ui/display",
     "//ui/events/devices",
     "//ui/message_center/public/cpp",
+    "//ui/strings:ui_strings_grit",
     "//ui/views",
     "//ui/wm",
     "//ui/wm/public",
diff --git a/ash/public/cpp/style/color_provider.h b/ash/public/cpp/style/color_provider.h
index 9114ba0..6093c1f 100644
--- a/ash/public/cpp/style/color_provider.h
+++ b/ash/public/cpp/style/color_provider.h
@@ -69,6 +69,8 @@
     kSeparatorColor,
 
     kTextColorPrimary,
+    // Inverted `kTextColorPrimary` on current color mode.
+    kInvertedTextColorPrimary,
     kTextColorSecondary,
     kTextColorAlert,
     kTextColorWarning,
@@ -89,6 +91,8 @@
 
     // The default color for button labels.
     kButtonLabelColor,
+    // Inverted `kButtonLabelColor` on current color mode.
+    kInvertedButtonLabelColor,
     kButtonLabelColorPrimary,
 
     // Color for blue button labels, e.g, 'Retry' button of the system toast.
diff --git a/ash/public/cpp/test/app_list_test_api.h b/ash/public/cpp/test/app_list_test_api.h
index 603d17d..1e96efb 100644
--- a/ash/public/cpp/test/app_list_test_api.h
+++ b/ash/public/cpp/test/app_list_test_api.h
@@ -167,6 +167,9 @@
   // Returns the recent app item item specified by `index`.
   views::View* GetRecentAppAt(int index);
 
+  // Updates launcher search box content, and triggers search.
+  void SimulateSearch(const std::u16string& query);
+
   // App list sort related methods ---------------------------------------------
 
   enum class MenuType {
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index 02daa85..973eb3f 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -116,7 +116,9 @@
 constexpr int kShelfPalmRejectionSwipeOffset = 80;
 
 const constexpr char* const kStylusAppIds[] = {
-    "fhapgmpiiiigioilnjmkiohjhlegnceb",  // Cursive/A4
+    "fhapgmpiiiigioilnjmkiohjhlegnceb",  // Cursive/A4 Dogfood
+    "apignacaigpffemhdbhmnajajaccbckh",  // Cursive/A4 Live
+    "ieailfmhaghpphfffooibmlghaeopach",  // Canvas
     "eilembjdkfgodjkcjnpgpaenohkicgjd",  // Google Keep Web
     "ifeodkfobgahmoofeclbhkdacaaopkek",  // Google Keep ARC
     "gjcfgmjegppjhimhlldbhhkfgkdjngcc",  // Squid
diff --git a/ash/shelf/shelf_tooltip_bubble.cc b/ash/shelf/shelf_tooltip_bubble.cc
index b1d28a21..94570dea 100644
--- a/ash/shelf/shelf_tooltip_bubble.cc
+++ b/ash/shelf/shelf_tooltip_bubble.cc
@@ -44,15 +44,14 @@
   const auto* color_provider = AshColorProvider::Get();
   const bool is_dark_light_mode_enabled = features::IsDarkLightModeEnabled();
   auto background_color_type = AshColorProvider::BaseLayerType::kTransparent80;
-  auto text_color_type = AshColorProvider::ContentLayerType::kTextColorPrimary;
   const SkColor tooltip_background =
       is_dark_light_mode_enabled
           ? color_provider->GetInvertedBaseLayerColor(background_color_type)
           : color_provider->GetBaseLayerColor(background_color_type);
-  const SkColor tooltip_text =
+  const SkColor tooltip_text = color_provider->GetContentLayerColor(
       is_dark_light_mode_enabled
-          ? color_provider->GetInvertedContentLayerColor(text_color_type)
-          : color_provider->GetContentLayerColor(text_color_type);
+          ? AshColorProvider::ContentLayerType::kInvertedTextColorPrimary
+          : AshColorProvider::ContentLayerType::kTextColorPrimary);
 
   set_color(tooltip_background);
   label->SetEnabledColor(tooltip_text);
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 5b29bceb..daafb44 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -144,6 +144,11 @@
 
   // Retrieves the release track on which the device resides.
   virtual version_info::Channel GetChannel() = 0;
+
+  // Tells browsers not to ask the user to confirm that they want to close a
+  // window when that window is closed.
+  virtual void ForceSkipWarningUserOnClose(
+      const std::vector<aura::Window*>& windows) = 0;
 };
 
 }  // namespace ash
diff --git a/ash/style/ash_color_id.h b/ash/style/ash_color_id.h
index ae51e55..11b7b93c 100644
--- a/ash/style/ash_color_id.h
+++ b/ash/style/ash_color_id.h
@@ -5,6 +5,7 @@
 #ifndef ASH_STYLE_ASH_COLOR_ID_H_
 #define ASH_STYLE_ASH_COLOR_ID_H_
 
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 
 namespace ash {
@@ -30,7 +31,7 @@
 #include "ui/color/color_id_macros.inc"
 
 enum AshColorIds : ui::ColorId {
-  kAshColorsStart = ui::kUiColorsEnd,
+  kAshColorsStart = cros_tokens::kCrosSysColorsEnd,
 
   ASH_COLOR_IDS
 
diff --git a/ash/style/ash_color_mixer.cc b/ash/style/ash_color_mixer.cc
index e30ab289..30a3f1fa 100644
--- a/ash/style/ash_color_mixer.cc
+++ b/ash/style/ash_color_mixer.cc
@@ -8,6 +8,7 @@
 #include "ash/public/cpp/style/scoped_light_mode_as_default.h"
 #include "ash/style/ash_color_id.h"
 #include "ash/style/ash_color_provider.h"
+#include "ash/style/temp_palette.h"
 #include "ash/system/tray/tray_constants.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -142,13 +143,113 @@
       cros_tokens::kCrosSysAppBase1};
 }
 
+// Adds the dynamic color palette tokens based on user_color. This is the base
+// palette so it is independent of ColorMode.
+void AddRefPalette(ui::ColorMixer& mixer,
+                   const ui::ColorProviderManager::Key& key) {
+  // TODO(skau): Before this launches, make sure this is always populated.
+  SkColor seed_color = key.user_color.value_or(gfx::kGoogleBlue400);
+
+  // TODO(skau): Replace with official implementation when available.
+  ToneMap tone_map = GetTempPalette(seed_color);
+
+  mixer[cros_tokens::kCrosRefPrimary0] = {tone_map.primary[Luma::k0]};
+  mixer[cros_tokens::kCrosRefPrimary10] = {tone_map.primary[Luma::k10]};
+  mixer[cros_tokens::kCrosRefPrimary20] = {tone_map.primary[Luma::k20]};
+  mixer[cros_tokens::kCrosRefPrimary30] = {tone_map.primary[Luma::k30]};
+  mixer[cros_tokens::kCrosRefPrimary40] = {tone_map.primary[Luma::k40]};
+  mixer[cros_tokens::kCrosRefPrimary50] = {tone_map.primary[Luma::k50]};
+  mixer[cros_tokens::kCrosRefPrimary60] = {tone_map.primary[Luma::k60]};
+  mixer[cros_tokens::kCrosRefPrimary70] = {tone_map.primary[Luma::k70]};
+  mixer[cros_tokens::kCrosRefPrimary80] = {tone_map.primary[Luma::k80]};
+  mixer[cros_tokens::kCrosRefPrimary90] = {tone_map.primary[Luma::k90]};
+  mixer[cros_tokens::kCrosRefPrimary95] = {tone_map.primary[Luma::k95]};
+  mixer[cros_tokens::kCrosRefPrimary99] = {tone_map.primary[Luma::k99]};
+  mixer[cros_tokens::kCrosRefPrimary100] = {tone_map.primary[Luma::k100]};
+
+  mixer[cros_tokens::kCrosRefSecondary0] = {tone_map.secondary[Luma::k0]};
+  mixer[cros_tokens::kCrosRefSecondary10] = {tone_map.secondary[Luma::k10]};
+  mixer[cros_tokens::kCrosRefSecondary20] = {tone_map.secondary[Luma::k20]};
+  mixer[cros_tokens::kCrosRefSecondary30] = {tone_map.secondary[Luma::k30]};
+  mixer[cros_tokens::kCrosRefSecondary40] = {tone_map.secondary[Luma::k40]};
+  mixer[cros_tokens::kCrosRefSecondary50] = {tone_map.secondary[Luma::k50]};
+  mixer[cros_tokens::kCrosRefSecondary60] = {tone_map.secondary[Luma::k60]};
+  mixer[cros_tokens::kCrosRefSecondary70] = {tone_map.secondary[Luma::k70]};
+  mixer[cros_tokens::kCrosRefSecondary80] = {tone_map.secondary[Luma::k80]};
+  mixer[cros_tokens::kCrosRefSecondary90] = {tone_map.secondary[Luma::k90]};
+  mixer[cros_tokens::kCrosRefSecondary95] = {tone_map.secondary[Luma::k95]};
+  mixer[cros_tokens::kCrosRefSecondary99] = {tone_map.secondary[Luma::k99]};
+  mixer[cros_tokens::kCrosRefSecondary100] = {tone_map.secondary[Luma::k100]};
+
+  mixer[cros_tokens::kCrosRefTertiary0] = {tone_map.tertiary[Luma::k0]};
+  mixer[cros_tokens::kCrosRefTertiary10] = {tone_map.tertiary[Luma::k10]};
+  mixer[cros_tokens::kCrosRefTertiary20] = {tone_map.tertiary[Luma::k20]};
+  mixer[cros_tokens::kCrosRefTertiary30] = {tone_map.tertiary[Luma::k30]};
+  mixer[cros_tokens::kCrosRefTertiary40] = {tone_map.tertiary[Luma::k40]};
+  mixer[cros_tokens::kCrosRefTertiary50] = {tone_map.tertiary[Luma::k50]};
+  mixer[cros_tokens::kCrosRefTertiary60] = {tone_map.tertiary[Luma::k60]};
+  mixer[cros_tokens::kCrosRefTertiary70] = {tone_map.tertiary[Luma::k70]};
+  mixer[cros_tokens::kCrosRefTertiary80] = {tone_map.tertiary[Luma::k80]};
+  mixer[cros_tokens::kCrosRefTertiary90] = {tone_map.tertiary[Luma::k90]};
+  mixer[cros_tokens::kCrosRefTertiary95] = {tone_map.tertiary[Luma::k95]};
+  mixer[cros_tokens::kCrosRefTertiary99] = {tone_map.tertiary[Luma::k99]};
+  mixer[cros_tokens::kCrosRefTertiary100] = {tone_map.tertiary[Luma::k100]};
+
+  mixer[cros_tokens::kCrosRefError0] = {tone_map.error[Luma::k0]};
+  mixer[cros_tokens::kCrosRefError10] = {tone_map.error[Luma::k10]};
+  mixer[cros_tokens::kCrosRefError20] = {tone_map.error[Luma::k20]};
+  mixer[cros_tokens::kCrosRefError30] = {tone_map.error[Luma::k30]};
+  mixer[cros_tokens::kCrosRefError40] = {tone_map.error[Luma::k40]};
+  mixer[cros_tokens::kCrosRefError50] = {tone_map.error[Luma::k50]};
+  mixer[cros_tokens::kCrosRefError60] = {tone_map.error[Luma::k60]};
+  mixer[cros_tokens::kCrosRefError70] = {tone_map.error[Luma::k70]};
+  mixer[cros_tokens::kCrosRefError80] = {tone_map.error[Luma::k80]};
+  mixer[cros_tokens::kCrosRefError90] = {tone_map.error[Luma::k90]};
+  mixer[cros_tokens::kCrosRefError95] = {tone_map.error[Luma::k95]};
+  mixer[cros_tokens::kCrosRefError99] = {tone_map.error[Luma::k99]};
+  mixer[cros_tokens::kCrosRefError100] = {tone_map.error[Luma::k100]};
+
+  mixer[cros_tokens::kCrosRefNeutral0] = {tone_map.neutral1[Luma::k0]};
+  mixer[cros_tokens::kCrosRefNeutral10] = {tone_map.neutral1[Luma::k10]};
+  mixer[cros_tokens::kCrosRefNeutral20] = {tone_map.neutral1[Luma::k20]};
+  mixer[cros_tokens::kCrosRefNeutral30] = {tone_map.neutral1[Luma::k30]};
+  mixer[cros_tokens::kCrosRefNeutral40] = {tone_map.neutral1[Luma::k40]};
+  mixer[cros_tokens::kCrosRefNeutral50] = {tone_map.neutral1[Luma::k50]};
+  mixer[cros_tokens::kCrosRefNeutral60] = {tone_map.neutral1[Luma::k60]};
+  mixer[cros_tokens::kCrosRefNeutral70] = {tone_map.neutral1[Luma::k70]};
+  mixer[cros_tokens::kCrosRefNeutral80] = {tone_map.neutral1[Luma::k80]};
+  mixer[cros_tokens::kCrosRefNeutral90] = {tone_map.neutral1[Luma::k90]};
+  mixer[cros_tokens::kCrosRefNeutral95] = {tone_map.neutral1[Luma::k95]};
+  mixer[cros_tokens::kCrosRefNeutral99] = {tone_map.neutral1[Luma::k99]};
+  mixer[cros_tokens::kCrosRefNeutral100] = {tone_map.neutral1[Luma::k100]};
+
+  mixer[cros_tokens::kCrosRefNeutralvariant0] = {tone_map.neutral2[Luma::k0]};
+  mixer[cros_tokens::kCrosRefNeutralvariant10] = {tone_map.neutral2[Luma::k10]};
+  mixer[cros_tokens::kCrosRefNeutralvariant20] = {tone_map.neutral2[Luma::k20]};
+  mixer[cros_tokens::kCrosRefNeutralvariant30] = {tone_map.neutral2[Luma::k30]};
+  mixer[cros_tokens::kCrosRefNeutralvariant40] = {tone_map.neutral2[Luma::k40]};
+  mixer[cros_tokens::kCrosRefNeutralvariant50] = {tone_map.neutral2[Luma::k50]};
+  mixer[cros_tokens::kCrosRefNeutralvariant60] = {tone_map.neutral2[Luma::k60]};
+  mixer[cros_tokens::kCrosRefNeutralvariant70] = {tone_map.neutral2[Luma::k70]};
+  mixer[cros_tokens::kCrosRefNeutralvariant80] = {tone_map.neutral2[Luma::k80]};
+  mixer[cros_tokens::kCrosRefNeutralvariant90] = {tone_map.neutral2[Luma::k90]};
+  mixer[cros_tokens::kCrosRefNeutralvariant95] = {tone_map.neutral2[Luma::k95]};
+  mixer[cros_tokens::kCrosRefNeutralvariant99] = {tone_map.neutral2[Luma::k99]};
+  mixer[cros_tokens::kCrosRefNeutralvariant100] = {
+      tone_map.neutral2[Luma::k100]};
+}
+
 }  // namespace
 
 void AddCrosStylesColorMixer(ui::ColorProvider* provider,
                              const ui::ColorProviderManager::Key& key) {
   ui::ColorMixer& mixer = provider->AddMixer();
   bool dark_mode = key.color_mode == ui::ColorProviderManager::ColorMode::kDark;
-  cros_tokens::AddCrosRefColorsToMixer(mixer, dark_mode);
+  if (ash::features::IsJellyEnabled()) {
+    AddRefPalette(mixer, key);
+  } else {
+    cros_tokens::AddCrosRefColorsToMixer(mixer, dark_mode);
+  }
   cros_tokens::AddCrosSysColorsToMixer(mixer, dark_mode);
 
   // TODO(b/234400002): Remove legacy colors once all usages are cleaned up.
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc
index ebe668faf..10b33b5 100644
--- a/ash/style/ash_color_provider.cc
+++ b/ash/style/ash_color_provider.cc
@@ -177,20 +177,10 @@
   return std::make_pair(base_color, opacity);
 }
 
-SkColor AshColorProvider::GetInvertedShieldLayerColor(
-    ShieldLayerType type) const {
-  return GetShieldLayerColorImpl(type, /*inverted=*/true);
-}
-
 SkColor AshColorProvider::GetInvertedBaseLayerColor(BaseLayerType type) const {
   return GetBaseLayerColorImpl(type, /*inverted=*/true);
 }
 
-SkColor AshColorProvider::GetInvertedContentLayerColor(
-    ContentLayerType type) const {
-  return GetContentLayerColorImpl(type, !IsDarkModeEnabled());
-}
-
 SkColor AshColorProvider::GetBackgroundColor() const {
   return GetBackgroundThemedColorImpl(GetBackgroundDefaultColor(),
                                       IsDarkModeEnabled());
@@ -321,6 +311,8 @@
     case ContentLayerType::kBatterySystemInfoBackgroundColor:
       return use_dark_color ? gfx::kGoogleGreen300 : gfx::kGoogleGreen600;
     case ContentLayerType::kBatterySystemInfoIconColor:
+    case ContentLayerType::kInvertedTextColorPrimary:
+    case ContentLayerType::kInvertedButtonLabelColor:
       return use_dark_color ? gfx::kGoogleGrey900 : gfx::kGoogleGrey200;
     default:
       return ResolveColor(type, use_dark_color);
diff --git a/ash/style/ash_color_provider.h b/ash/style/ash_color_provider.h
index c193ccb..0e63dd5 100644
--- a/ash/style/ash_color_provider.h
+++ b/ash/style/ash_color_provider.h
@@ -60,9 +60,7 @@
   // Gets the color of |type| of the corresponding layer based on the current
   // inverted color mode. For views that need LIGHT colors while DARK mode is
   // active, and vice versa.
-  SkColor GetInvertedShieldLayerColor(ShieldLayerType type) const;
   SkColor GetInvertedBaseLayerColor(BaseLayerType type) const;
-  SkColor GetInvertedContentLayerColor(ContentLayerType type) const;
 
   // Gets the background color that can be applied on any layer. The returned
   // color will be different based on color mode and color theme (see
diff --git a/ash/style/temp_palette.cc b/ash/style/temp_palette.cc
new file mode 100644
index 0000000..07d18f52
--- /dev/null
+++ b/ash/style/temp_palette.cc
@@ -0,0 +1,215 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/style/temp_palette.h"
+
+namespace ash {
+
+namespace {
+
+constexpr SkColor kPurple = 0xffca35c6U;
+constexpr SkColor kTeal = 0xff3cc3b8U;
+
+ToneMap PurpleTones() {
+  ToneMap tones;
+
+  tones.seed = kPurple;  // purple
+  tones.primary[Luma::k100] = 0xffffffffU;
+  tones.primary[Luma::k99] = 0xfffffbffU;
+  tones.primary[Luma::k95] = 0xffffebf7U;
+  tones.primary[Luma::k90] = 0xffffd7f5U;
+  tones.primary[Luma::k80] = 0xffffabf3U;
+  tones.primary[Luma::k70] = 0xffff76f5U;
+  tones.primary[Luma::k60] = 0xffe651e0U;
+  tones.primary[Luma::k50] = 0xffc732c3U;
+  tones.primary[Luma::k40] = 0xffa901a8U;
+  tones.primary[Luma::k30] = 0xff810080U;
+  tones.primary[Luma::k20] = 0xff5b005bU;
+  tones.primary[Luma::k10] = 0xff380038U;
+  tones.primary[Luma::k0] = 0xff000000U;
+
+  tones.secondary[Luma::k100] = 0xffffffffU;
+  tones.secondary[Luma::k99] = 0xfffffbffU;
+  tones.secondary[Luma::k95] = 0xffffebf7U;
+  tones.secondary[Luma::k90] = 0xfff7daefU;
+  tones.secondary[Luma::k80] = 0xffdabfd2U;
+  tones.secondary[Luma::k70] = 0xffbea4b7U;
+  tones.secondary[Luma::k60] = 0xffa2899cU;
+  tones.secondary[Luma::k50] = 0xff877082U;
+  tones.secondary[Luma::k40] = 0xff6e5869U;
+  tones.secondary[Luma::k30] = 0xff554151U;
+  tones.secondary[Luma::k20] = 0xff3d2b3aU;
+  tones.secondary[Luma::k10] = 0xff271624U;
+  tones.secondary[Luma::k0] = 0xff000000U;
+
+  tones.tertiary[Luma::k100] = 0xffffffffU;
+  tones.tertiary[Luma::k99] = 0xfffffbffU;
+  tones.tertiary[Luma::k95] = 0xffffede8U;
+  tones.tertiary[Luma::k90] = 0xffffdbd1U;
+  tones.tertiary[Luma::k80] = 0xfff5b8a7U;
+  tones.tertiary[Luma::k70] = 0xffd79e8dU;
+  tones.tertiary[Luma::k60] = 0xffba8474U;
+  tones.tertiary[Luma::k50] = 0xff9d6b5cU;
+  tones.tertiary[Luma::k40] = 0xff815345U;
+  tones.tertiary[Luma::k30] = 0xff663c2fU;
+  tones.tertiary[Luma::k20] = 0xff4c261bU;
+  tones.tertiary[Luma::k10] = 0xff321208U;
+  tones.tertiary[Luma::k0] = 0xff000000U;
+
+  tones.neutral1[Luma::k100] = 0xffffffffU;
+  tones.neutral1[Luma::k99] = 0xfffffbffU;
+  tones.neutral1[Luma::k95] = 0xfff8eef2U;
+  tones.neutral1[Luma::k90] = 0xffe9e0e4U;
+  tones.neutral1[Luma::k80] = 0xffcdc4c8U;
+  tones.neutral1[Luma::k70] = 0xffb1a9adU;
+  tones.neutral1[Luma::k60] = 0xff968f92U;
+  tones.neutral1[Luma::k50] = 0xff7c7579U;
+  tones.neutral1[Luma::k40] = 0xff635d60U;
+  tones.neutral1[Luma::k30] = 0xff4b4548U;
+  tones.neutral1[Luma::k20] = 0xff342f32U;
+  tones.neutral1[Luma::k10] = 0xff1e1a1dU;
+  tones.neutral1[Luma::k0] = 0xff000000U;
+
+  tones.neutral2[Luma::k100] = 0xffffffffU;
+  tones.neutral2[Luma::k99] = 0xfffffbffU;
+  tones.neutral2[Luma::k95] = 0xfffcecf5U;
+  tones.neutral2[Luma::k90] = 0xffeedee7U;
+  tones.neutral2[Luma::k80] = 0xffd1c2cbU;
+  tones.neutral2[Luma::k70] = 0xffb5a7b0U;
+  tones.neutral2[Luma::k60] = 0xff9a8d95U;
+  tones.neutral2[Luma::k50] = 0xff80747bU;
+  tones.neutral2[Luma::k40] = 0xff665b63U;
+  tones.neutral2[Luma::k30] = 0xff4e444bU;
+  tones.neutral2[Luma::k20] = 0xff372e34U;
+  tones.neutral2[Luma::k10] = 0xff21191fU;
+  tones.neutral2[Luma::k0] = 0xff000000U;
+
+  return tones;
+}
+
+ToneMap TealTones() {
+  ToneMap tones;
+
+  tones.seed = kTeal;  // teal
+  tones.primary[Luma::k100] = 0xffffffffU;
+  tones.primary[Luma::k99] = 0xfff2fffcU;
+  tones.primary[Luma::k95] = 0xffb2fff6U;
+  tones.primary[Luma::k90] = 0xff71f7ebU;
+  tones.primary[Luma::k80] = 0xff50dbcfU;
+  tones.primary[Luma::k70] = 0xff26bfb3U;
+  tones.primary[Luma::k60] = 0xff00a298U;
+  tones.primary[Luma::k50] = 0xff00867dU;
+  tones.primary[Luma::k40] = 0xff006a63U;
+  tones.primary[Luma::k30] = 0xff00504bU;
+  tones.primary[Luma::k20] = 0xff003733U;
+  tones.primary[Luma::k10] = 0xff00201dU;
+  tones.primary[Luma::k0] = 0xff000000U;
+
+  tones.secondary[Luma::k100] = 0xffffffffU;
+  tones.secondary[Luma::k99] = 0xfff2fffcU;
+  tones.secondary[Luma::k95] = 0xffdaf7f2U;
+  tones.secondary[Luma::k90] = 0xffcce8e4U;
+  tones.secondary[Luma::k80] = 0xffb1ccc8U;
+  tones.secondary[Luma::k70] = 0xff96b1adU;
+  tones.secondary[Luma::k60] = 0xff7b9692U;
+  tones.secondary[Luma::k50] = 0xff627c79U;
+  tones.secondary[Luma::k40] = 0xff4a6360U;
+  tones.secondary[Luma::k30] = 0xff324b48U;
+  tones.secondary[Luma::k20] = 0xff1c3532U;
+  tones.secondary[Luma::k10] = 0xff051f1dU;
+  tones.secondary[Luma::k0] = 0xff000000U;
+
+  tones.tertiary[Luma::k100] = 0xffffffffU;
+  tones.tertiary[Luma::k99] = 0xfffcfcffU;
+  tones.tertiary[Luma::k95] = 0xffe8f2ffU;
+  tones.tertiary[Luma::k90] = 0xffcee5ffU;
+  tones.tertiary[Luma::k80] = 0xffafc9e7U;
+  tones.tertiary[Luma::k70] = 0xff94aecaU;
+  tones.tertiary[Luma::k60] = 0xff7993afU;
+  tones.tertiary[Luma::k50] = 0xff607994U;
+  tones.tertiary[Luma::k40] = 0xff47617aU;
+  tones.tertiary[Luma::k30] = 0xff2f4961U;
+  tones.tertiary[Luma::k20] = 0xff17324aU;
+  tones.tertiary[Luma::k10] = 0xff001d33U;
+  tones.tertiary[Luma::k0] = 0xff000000U;
+
+  tones.neutral1[Luma::k100] = 0xffffffffU;
+  tones.neutral1[Luma::k99] = 0xfffafdfbU;
+  tones.neutral1[Luma::k95] = 0xffeff1f0U;
+  tones.neutral1[Luma::k90] = 0xffe0e3e1U;
+  tones.neutral1[Luma::k80] = 0xffc4c7c6U;
+  tones.neutral1[Luma::k70] = 0xffa9acaaU;
+  tones.neutral1[Luma::k60] = 0xff8e9190U;
+  tones.neutral1[Luma::k50] = 0xff747877U;
+  tones.neutral1[Luma::k40] = 0xff5b5f5eU;
+  tones.neutral1[Luma::k30] = 0xff444747U;
+  tones.neutral1[Luma::k20] = 0xff2d3130U;
+  tones.neutral1[Luma::k10] = 0xff191c1cU;
+  tones.neutral1[Luma::k0] = 0xff000000U;
+
+  tones.neutral2[Luma::k100] = 0xffffffffU;
+  tones.neutral2[Luma::k99] = 0xfff4fefcU;
+  tones.neutral2[Luma::k95] = 0xffe9f3f0U;
+  tones.neutral2[Luma::k90] = 0xffdae5e2U;
+  tones.neutral2[Luma::k80] = 0xffbec9c6U;
+  tones.neutral2[Luma::k70] = 0xffa3adabU;
+  tones.neutral2[Luma::k60] = 0xff899391U;
+  tones.neutral2[Luma::k50] = 0xff6f7977U;
+  tones.neutral2[Luma::k40] = 0xff56605fU;
+  tones.neutral2[Luma::k30] = 0xff3f4947U;
+  tones.neutral2[Luma::k20] = 0xff293231U;
+  tones.neutral2[Luma::k10] = 0xff141d1cU;
+  tones.neutral2[Luma::k0] = 0xff000000U;
+
+  return tones;
+}
+
+void AddErrorColors(ToneMap& tones) {
+  tones.error[Luma::k100] = 0xffffffffU;
+  tones.error[Luma::k99] = 0xfffffbffU;
+  tones.error[Luma::k95] = 0xffffedeaU;
+  tones.error[Luma::k90] = 0xffffdad6U;
+  tones.error[Luma::k80] = 0xffffb4abU;
+  tones.error[Luma::k70] = 0xffff897dU;
+  tones.error[Luma::k60] = 0xffff5449U;
+  tones.error[Luma::k50] = 0xffde3730U;
+  tones.error[Luma::k40] = 0xffba1a1aU;
+  tones.error[Luma::k30] = 0xff93000aU;
+  tones.error[Luma::k20] = 0xff690005U;
+  tones.error[Luma::k10] = 0xff410002U;
+  tones.error[Luma::k0] = 0xff000000U;
+}
+
+// Extracts the hue for |color| in degrees [0-360).
+SkScalar GetHue(SkColor color) {
+  SkScalar hsv[3];
+  SkColorToHSV(color, hsv);
+  // Index 0 is hue.
+  return hsv[0];
+}
+
+// Returns the difference in hue of two colors in degrees.
+SkScalar HueDistance(SkColor a, SkColor b) {
+  SkScalar hue_a = GetHue(a);
+  SkScalar hue_b = GetHue(b);
+
+  return std::min(360 - std::abs(hue_a - hue_b), std::abs(hue_a - hue_b));
+}
+
+}  // namespace
+
+ToneMap::ToneMap() = default;
+ToneMap::ToneMap(const ToneMap&) = default;
+ToneMap::~ToneMap() = default;
+
+const ToneMap GetTempPalette(SkColor seed_color) {
+  const SkScalar teal_distance = HueDistance(seed_color, kTeal);
+  const SkScalar purple_distance = HueDistance(seed_color, kPurple);
+  ToneMap tones =
+      (teal_distance < purple_distance) ? TealTones() : PurpleTones();
+  AddErrorColors(tones);
+  return tones;
+}
+
+}  // namespace ash
diff --git a/ash/style/temp_palette.h b/ash/style/temp_palette.h
new file mode 100644
index 0000000..09dfe0f
--- /dev/null
+++ b/ash/style/temp_palette.h
@@ -0,0 +1,53 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_STYLE_TEMP_PALETTE_H_
+#define ASH_STYLE_TEMP_PALETTE_H_
+
+#include "base/containers/flat_map.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace ash {
+
+enum class Luma {
+  k0 = 0,
+  k10 = 10,
+  k20 = 20,
+  k30 = 30,
+  k40 = 40,
+  k50 = 50,
+  k60 = 60,
+  k70 = 70,
+  k80 = 80,
+  k90 = 90,
+  k95 = 95,
+  k99 = 99,
+  k100 = 100
+};
+
+// The tones generated from `seed` in the luma range.
+struct ToneMap {
+  ToneMap();
+  ToneMap(const ToneMap&);
+  ~ToneMap();
+
+  SkColor seed;
+  base::flat_map<Luma, SkColor> primary;
+  base::flat_map<Luma, SkColor> secondary;
+  base::flat_map<Luma, SkColor> tertiary;
+
+  // Neutral tones
+  base::flat_map<Luma, SkColor> neutral1;
+  base::flat_map<Luma, SkColor> neutral2;
+
+  // Error tones
+  base::flat_map<Luma, SkColor> error;
+};
+
+// Returns the tones that closest match `seed_color`.
+const ToneMap GetTempPalette(SkColor seed_color);
+
+}  // namespace ash
+
+#endif  // ASH_STYLE_TEMP_PALETTE_H_
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc
index f894b5f..9c06e375 100644
--- a/ash/system/message_center/ash_notification_view.cc
+++ b/ash/system/message_center/ash_notification_view.cc
@@ -1434,8 +1434,8 @@
       (is_grouped_child_view_ && !notification->icon().IsEmpty()))
     return;
 
-  SkColor icon_color = AshColorProvider::Get()->GetInvertedContentLayerColor(
-      AshColorProvider::ContentLayerType::kButtonLabelColor);
+  SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
+      AshColorProvider::ContentLayerType::kInvertedButtonLabelColor);
   SkColor icon_background_color = CalculateIconAndButtonsColor(notification);
 
   // TODO(crbug.com/768748): figure out if this has a performance impact and
diff --git a/ash/system/message_center/stacked_notification_bar.cc b/ash/system/message_center/stacked_notification_bar.cc
index 171a0581..e2466eee8 100644
--- a/ash/system/message_center/stacked_notification_bar.cc
+++ b/ash/system/message_center/stacked_notification_bar.cc
@@ -49,6 +49,7 @@
             PillButton::Type::kIconlessAccentFloating,
             /*icon=*/nullptr,
             kNotificationPillButtonHorizontalSpacing,
+            kPillButtonHeight,
             /*use_light_colors=*/!features::IsNotificationsRefreshEnabled(),
             /*rounded_highlight_path=*/
             features::IsNotificationsRefreshEnabled()),
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc
index 1cefcf28..f21b2f8 100644
--- a/ash/system/message_center/unified_message_center_view_unittest.cc
+++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -904,4 +904,24 @@
   EXPECT_FALSE(message_center_view()->GetVisible());
 }
 
+TEST_P(UnifiedMessageCenterViewTest, ClearAllButtonHeight) {
+  std::string id0 = AddNotification(false /* pinned */);
+  std::string id1 = AddNotification(false /* pinned */);
+  CreateMessageCenterView();
+  EXPECT_TRUE(message_center_view()->GetVisible());
+  EXPECT_TRUE(GetNotificationBar()->GetVisible());
+  EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible());
+
+  // Get ClearAll Button height.
+  const int previous_button_height =
+      GetNotificationBarClearAllButton()->height();
+
+  // Remove a notification.
+  MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
+
+  // ClearAll Button height should remain the same.
+  EXPECT_EQ(previous_button_height,
+            GetNotificationBarClearAllButton()->height());
+}
+
 }  // namespace ash
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc
index 8c996a598..74bdb94 100644
--- a/ash/system/time/calendar_view.cc
+++ b/ash/system/time/calendar_view.cc
@@ -56,7 +56,7 @@
 constexpr int kLabelTextInBetweenPadding = 10;
 constexpr int kWeekRowHorizontalPadding =
     kContentHorizontalPadding - calendar_utils::kDateHorizontalPadding;
-constexpr int kExpandedCalendarPadding = 8;
+constexpr int kExpandedCalendarPadding = 11;
 constexpr int kChevronPadding = calendar_utils::kColumnSetPadding - 1;
 constexpr int kEventListViewVerticalPadding = 6;
 constexpr int kEventListViewHorizontalOffset = 1;
@@ -1022,12 +1022,11 @@
   // bounds.
   event_list_view_->SetBounds(
       scroll_view_->x() + kEventListViewHorizontalOffset,
-      scroll_view_->y() +
-          calendar_view_controller_->GetRowHeightWithEventListView(),
+      scroll_view_->y() + calendar_view_controller_->row_height(),
       scroll_view_->GetVisibleRect().width() -
           kEventListViewHorizontalOffset * 2,
       scroll_view_->GetVisibleRect().height() -
-          calendar_view_controller_->GetRowHeightWithEventListView() +
+          calendar_view_controller_->row_height() +
           kEventListViewVerticalPadding);
 
   set_should_months_animate(false);
@@ -1330,15 +1329,7 @@
   // first row and scrolling up.
   if (scroll_up && calendar_view_controller_->GetExpandedRowIndex() == 0) {
     ScrollUpOneMonth();
-    calendar_view_controller_->set_expanded_row_index(
-        current_month_->last_row_index());
-    const int row_height = calendar_view_controller_->GetExpandedRowIndex() *
-                           calendar_view_controller_->row_height();
-    scroll_view_->ScrollToPosition(
-        scroll_view_->vertical_scroll_bar(),
-        PositionOfCurrentMonth() + row_height + kExpandedCalendarPadding);
-    scroll_view_->SetVerticalScrollBarMode(
-        views::ScrollView::ScrollBarMode::kDisabled);
+    SetExpandedRowThenDisableScroll(current_month_->last_row_index());
     return;
   }
 
@@ -1347,24 +1338,12 @@
   if (!scroll_up && calendar_view_controller_->GetExpandedRowIndex() ==
                         current_month_->last_row_index()) {
     ScrollDownOneMonth();
-    calendar_view_controller_->set_expanded_row_index(0);
-    scroll_view_->ScrollToPosition(
-        scroll_view_->vertical_scroll_bar(),
-        PositionOfCurrentMonth() + kExpandedCalendarPadding);
-    scroll_view_->SetVerticalScrollBarMode(
-        views::ScrollView::ScrollBarMode::kDisabled);
+    SetExpandedRowThenDisableScroll(0);
     return;
   }
 
-  calendar_view_controller_->set_expanded_row_index(
+  SetExpandedRowThenDisableScroll(
       calendar_view_controller_->GetExpandedRowIndex() + (scroll_up ? -1 : 1));
-  const int row_height = calendar_view_controller_->GetExpandedRowIndex() *
-                         calendar_view_controller_->row_height();
-  scroll_view_->ScrollToPosition(
-      scroll_view_->vertical_scroll_bar(),
-      PositionOfCurrentMonth() + row_height + kExpandedCalendarPadding);
-  scroll_view_->SetVerticalScrollBarMode(
-      views::ScrollView::ScrollBarMode::kDisabled);
   return;
 }
 
@@ -1506,15 +1485,17 @@
         }
       }
       focus_manager->SetFocusedView(current_focusable_view);
+
       // After focusing on the new cell the view should have scrolled already
-      // if needed, disable the scroll bar mode if the even list is showing.
-      if (event_list_view_)
-        scroll_view_->SetVerticalScrollBarMode(
-            views::ScrollView::ScrollBarMode::kDisabled);
-      const int current_height =
-          scroll_view_->GetVisibleRect().y() - PositionOfCurrentMonth();
-      calendar_view_controller_->set_expanded_row_index(
-          current_height / calendar_view_controller_->row_height());
+      // if needed, but there's an offset compared with scrolled by
+      // `ScrollOneRowWithAnimation`. Manually scroll the view then disable the
+      // scroll bar mode if the even list is showing.
+      if (event_list_view_) {
+        const int current_height =
+            scroll_view_->GetVisibleRect().y() - PositionOfCurrentMonth();
+        SetExpandedRowThenDisableScroll(
+            current_height / calendar_view_controller_->row_height());
+      }
 
       AdjustDateCellVoxBounds();
 
@@ -1532,16 +1513,17 @@
       bool is_reverse = base::i18n::IsRTL() ? key_code == ui::VKEY_RIGHT
                                             : key_code == ui::VKEY_LEFT;
       focus_manager->AdvanceFocus(/*reverse=*/is_reverse);
-      // After focusing on the new cell the view should have scrolled already
-      // if needed, disable the scroll bar mode if the even list is showing.
-      if (event_list_view_)
-        scroll_view_->SetVerticalScrollBarMode(
-            views::ScrollView::ScrollBarMode::kDisabled);
 
-      const int current_height =
-          scroll_view_->GetVisibleRect().y() - PositionOfCurrentMonth();
-      calendar_view_controller_->set_expanded_row_index(
-          current_height / calendar_view_controller_->row_height());
+      // After focusing on the new cell the view should have scrolled already
+      // if needed, but there's an offset compared with scrolled by
+      // `ScrollOneRowWithAnimation`. Manually scroll the view then disable the
+      // scroll bar mode if the even list is showing.
+      if (event_list_view_) {
+        const int current_height =
+            scroll_view_->GetVisibleRect().y() - PositionOfCurrentMonth();
+        SetExpandedRowThenDisableScroll(
+            current_height / calendar_view_controller_->row_height());
+      }
 
       AdjustDateCellVoxBounds();
 
@@ -1552,6 +1534,20 @@
   }
 }
 
+void CalendarView::SetExpandedRowThenDisableScroll(int row_index) {
+  DCHECK(event_list_view_);
+  calendar_view_controller_->set_expanded_row_index(row_index);
+
+  const int row_height = calendar_view_controller_->GetExpandedRowIndex() *
+                         calendar_view_controller_->row_height();
+  scroll_view_->ScrollToPosition(
+      scroll_view_->vertical_scroll_bar(),
+      PositionOfCurrentMonth() + row_height + kExpandedCalendarPadding);
+
+  scroll_view_->SetVerticalScrollBarMode(
+      views::ScrollView::ScrollBarMode::kDisabled);
+}
+
 void CalendarView::OnContentsScrolled() {
   base::AutoReset<bool> set_is_scrolling(&is_calendar_view_scrolling_, true);
 
@@ -1627,8 +1623,7 @@
   scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(),
                                  PositionOfSelectedDate());
   // Clip the height to a bit more than the height of a row.
-  scroll_view_->ClipHeightTo(
-      0, calendar_view_controller_->GetRowHeightWithEventListView());
+  scroll_view_->ClipHeightTo(0, calendar_view_controller_->row_height());
 
   if (!should_months_animate_)
     months_animation_restart_timer_.Reset();
diff --git a/ash/system/time/calendar_view.h b/ash/system/time/calendar_view.h
index e67c147..a621b82 100644
--- a/ash/system/time/calendar_view.h
+++ b/ash/system/time/calendar_view.h
@@ -269,6 +269,10 @@
   // We only fetch events after we've "settled" on the current on-screen month.
   void OnScrollingSettledTimerFired();
 
+  // Sets `expanded_row_index_` and auto-scrolls the `scroll_view_` when
+  // `event_list_view_` is opened. After scrolling, disables the scroll bar.
+  void SetExpandedRowThenDisableScroll(int row_index);
+
   // ScrollView callback.
   void OnContentsScrolled();
 
diff --git a/ash/system/time/calendar_view_controller.cc b/ash/system/time/calendar_view_controller.cc
index 65dd2ae..f2c8ffaf 100644
--- a/ash/system/time/calendar_view_controller.cc
+++ b/ash/system/time/calendar_view_controller.cc
@@ -22,15 +22,6 @@
 
 namespace ash {
 
-namespace {
-
-// The percentage of a normal row height, which (percentage * row_height) will
-// be used as the `CalendarView` height when the `CalendarEventListView` is
-// expanded.
-constexpr float kExpandedCalendarViewHeightScale = 1.1;
-
-}  // namespace
-
 CalendarViewController::CalendarViewController()
     : currently_shown_date_(base::Time::Now()),
       calendar_open_time_(base::TimeTicks::Now()),
@@ -138,12 +129,6 @@
   return expanded_row_index_;
 }
 
-int CalendarViewController::GetRowHeightWithEventListView() const {
-  //`is_event_list_showing_` may not be true because this is called before the
-  // animation begins.
-  return kExpandedCalendarViewHeightScale * row_height_;
-}
-
 int CalendarViewController::GetTodayRowTopHeight() const {
   return (today_row_ - 1) * row_height_;
 }
diff --git a/ash/system/time/calendar_view_controller.h b/ash/system/time/calendar_view_controller.h
index 9d150a6..0171821 100644
--- a/ash/system/time/calendar_view_controller.h
+++ b/ash/system/time/calendar_view_controller.h
@@ -103,9 +103,6 @@
   // month.
   std::u16string GetPreviousMonthName();
 
-  // `row_height_` is expanded when the EventListView is shown.
-  int GetRowHeightWithEventListView() const;
-
   // Getters of the today's row position, top and bottom.
   int GetTodayRowTopHeight() const;
   int GetTodayRowBottomHeight() const;
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h
index c9c2d8b5..08e8f8b 100644
--- a/ash/test_shell_delegate.h
+++ b/ash/test_shell_delegate.h
@@ -56,6 +56,8 @@
   bool IsSessionRestoreInProgress() const override;
   void SetUpEnvironmentForLockedFullscreen(bool locked) override {}
   const GURL& GetLastCommittedURLForWindowIfAny(aura::Window* window) override;
+  void ForceSkipWarningUserOnClose(
+      const std::vector<aura::Window*>& windows) override {}
 
   void SetCanGoBack(bool can_go_back);
   void SetShouldWaitForTouchAck(bool should_wait_for_touch_ack);
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc
index 0c323164..164a25c 100644
--- a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc
@@ -77,8 +77,10 @@
   for (size_t i = 0; i < prominent_swatches.size(); ++i)
     prominent_colors[i] = prominent_swatches[i].color;
 
-  SkColor k_mean_color =
-      color_utils::CalculateKMeanColorOfBitmap(*resized_image.bitmap());
+  constexpr color_utils::HSL kNoBounds = {-1, -1, -1};
+  SkColor k_mean_color = color_utils::CalculateKMeanColorOfBitmap(
+      *resized_image.bitmap(), resized_image.height(), kNoBounds, kNoBounds,
+      /*find_closest=*/true);
 
   UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.Durations",
                       base::TimeTicks::Now() - start_time);
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc
index a7d052af..91da5f39 100644
--- a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc
@@ -198,19 +198,19 @@
 
 TEST_F(WallPaperColorCalculatorAsyncTest, ColorUpdatedOnSuccessfulCalculation) {
   std::vector<SkColor> colors = {kDefaultColor};
-  SkColor k_mean_color = kGray;
+  SkColor k_mean_color = kDefaultColor;
   calculator_->set_calculated_colors_for_test(
       WallpaperCalculatedColors(colors, k_mean_color));
 
   EXPECT_TRUE(calculator_->StartCalculation());
   EXPECT_EQ(kDefaultColor,
             calculator_->get_calculated_colors().prominent_colors[0]);
-  EXPECT_EQ(kGray, calculator_->get_calculated_colors().k_mean_color);
+  EXPECT_EQ(kDefaultColor, calculator_->get_calculated_colors().k_mean_color);
 
   task_runner_->RunUntilIdle();
   EXPECT_NE(kDefaultColor,
             calculator_->get_calculated_colors().prominent_colors[0]);
-  EXPECT_NE(kGray, calculator_->get_calculated_colors().k_mean_color);
+  EXPECT_EQ(kGray, calculator_->get_calculated_colors().k_mean_color);
 }
 
 TEST_F(WallPaperColorCalculatorAsyncTest,
diff --git a/ash/webui/OWNERS b/ash/webui/OWNERS
index 40e42be..2617462 100644
--- a/ash/webui/OWNERS
+++ b/ash/webui/OWNERS
@@ -1,7 +1,3 @@
-# Code is migrating here from //chromeos/components, so share owners.
-# See go/lacros-directory-migration
-file://chromeos/components/OWNERS
-
 file://ash/webui/PLATFORM_OWNERS
 
 # For horizontal changes, usually related to the WebUI toolchain. For any
diff --git a/ash/webui/PLATFORM_OWNERS b/ash/webui/PLATFORM_OWNERS
index 44e3cdf..99733d3 100644
--- a/ash/webui/PLATFORM_OWNERS
+++ b/ash/webui/PLATFORM_OWNERS
@@ -1,3 +1,12 @@
+achuith@chromium.org
+alemate@chromium.org
+chadduffin@chromium.org
+hidehiko@chromium.org
+jimmyxgong@chromium.org
+khorimoto@chromium.org
+xiyuan@chromium.org
+
+# For backend changes or toolchain changes.
 ortuno@chromium.org
 qjw@chromium.org
 dominicschulz@google.com
diff --git a/ash/webui/os_feedback_ui/backend/feedback_service_provider.cc b/ash/webui/os_feedback_ui/backend/feedback_service_provider.cc
index 300864af..ca7c630e 100644
--- a/ash/webui/os_feedback_ui/backend/feedback_service_provider.cc
+++ b/ash/webui/os_feedback_ui/backend/feedback_service_provider.cc
@@ -58,6 +58,10 @@
   feedback_delegate_->OpenMetricsDialog();
 }
 
+void FeedbackServiceProvider::OpenSystemInfoDialog() {
+  feedback_delegate_->OpenSystemInfoDialog();
+}
+
 void FeedbackServiceProvider::BindInterface(
     mojo::PendingReceiver<os_feedback_ui::mojom::FeedbackServiceProvider>
         receiver) {
diff --git a/ash/webui/os_feedback_ui/backend/feedback_service_provider.h b/ash/webui/os_feedback_ui/backend/feedback_service_provider.h
index ec69d66..3e751fb 100644
--- a/ash/webui/os_feedback_ui/backend/feedback_service_provider.h
+++ b/ash/webui/os_feedback_ui/backend/feedback_service_provider.h
@@ -35,6 +35,7 @@
   void OpenDiagnosticsApp() override;
   void OpenExploreApp() override;
   void OpenMetricsDialog() override;
+  void OpenSystemInfoDialog() override;
 
   void BindInterface(
       mojo::PendingReceiver<os_feedback_ui::mojom::FeedbackServiceProvider>
diff --git a/ash/webui/os_feedback_ui/backend/feedback_service_provider_unittest.cc b/ash/webui/os_feedback_ui/backend/feedback_service_provider_unittest.cc
index 905691e..8a474cf 100644
--- a/ash/webui/os_feedback_ui/backend/feedback_service_provider_unittest.cc
+++ b/ash/webui/os_feedback_ui/backend/feedback_service_provider_unittest.cc
@@ -63,6 +63,8 @@
   void OpenExploreApp() override {}
 
   void OpenMetricsDialog() override {}
+
+  void OpenSystemInfoDialog() override {}
 };
 
 class FeedbackServiceProviderTest : public testing::Test {
diff --git a/ash/webui/os_feedback_ui/backend/os_feedback_delegate.h b/ash/webui/os_feedback_ui/backend/os_feedback_delegate.h
index ccbac06..14ae718 100644
--- a/ash/webui/os_feedback_ui/backend/os_feedback_delegate.h
+++ b/ash/webui/os_feedback_ui/backend/os_feedback_delegate.h
@@ -45,6 +45,9 @@
   virtual void OpenExploreApp() = 0;
   // Open metrics dialog (which displays chrome://histograms).
   virtual void OpenMetricsDialog() = 0;
+  // Open system info dialog (which displays the system logs
+  // to be sent with the report if the user has opted in).
+  virtual void OpenSystemInfoDialog() = 0;
 };
 
 }  // namespace ash
diff --git a/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom b/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom
index 69ff697..022a1ea 100644
--- a/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom
+++ b/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom
@@ -143,4 +143,7 @@
   OpenExploreApp();
   // Open metrics dialog (which displays chrome://histograms).
   OpenMetricsDialog();
+  // Open system info dialog (which displays the system logs
+  // to be sent with the report if the user has opted in).
+  OpenSystemInfoDialog();
 };
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc
index e8444dd1..a0b2d80b 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.cc
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -56,6 +56,8 @@
       {"noMatchedResults", IDS_FEEDBACK_TOOL_NO_MATCHED_RESULTS},
       {"attachFilesLabel", IDS_FEEDBACK_TOOL_ATTACH_FILES_LABEL},
       {"attachScreenshotLabel", IDS_FEEDBACK_TOOL_SCREENSHOT_LABEL},
+      {"attachScreenshotCheckboxAriaLabel",
+       IDS_FEEDBACK_TOOL_ATTACH_SCREENSHOT_CHECKBOX_ARIA_LABEL},
       {"addFileLabel", IDS_FEEDBACK_TOOL_ADD_FILE_LABEL},
       {"replaceFileLabel", IDS_FEEDBACK_TOOL_REPLACE_FILE_LABEL},
       {"userEmailLabel", IDS_FEEDBACK_TOOL_USER_EMAIL_LABEL},
diff --git a/ash/webui/os_feedback_ui/resources/fake_feedback_service_provider.js b/ash/webui/os_feedback_ui/resources/fake_feedback_service_provider.js
index 0449eae..41568ad 100644
--- a/ash/webui/os_feedback_ui/resources/fake_feedback_service_provider.js
+++ b/ash/webui/os_feedback_ui/resources/fake_feedback_service_provider.js
@@ -42,6 +42,8 @@
       openExploreApp: 0,
       /** @type {number} */
       openMetricsDialog: 0,
+      /** @type {number} */
+      openSystemInfoDialog: 0,
     };
   }
 
@@ -163,4 +165,18 @@
   openMetricsDialog() {
     this.callCounts_.openMetricsDialog++;
   }
+
+  /**
+   * @return {number}
+   */
+  getOpenSystemInfoDialogCallCount() {
+    return this.callCounts_.openSystemInfoDialog;
+  }
+
+  /**
+   * @return {void}
+   */
+  openSystemInfoDialog() {
+    this.callCounts_.openSystemInfoDialog++;
+  }
 }
diff --git a/ash/webui/os_feedback_ui/resources/search_page.html b/ash/webui/os_feedback_ui/resources/search_page.html
index e1364b5..3f8fcafe 100644
--- a/ash/webui/os_feedback_ui/resources/search_page.html
+++ b/ash/webui/os_feedback_ui/resources/search_page.html
@@ -8,14 +8,15 @@
     background-color: var(--cros-textfield-background-color);
     border: none;
     border-radius: 4px;
+    box-sizing: border-box;
     color: var(--cros-text-color-primary);
     font-family: var(--feedback-roboto-font-family);
     font-size: 13px;
-    height: 162px;
+    height: 120px;
     line-height: 20px;
     padding: 10px;
     resize: none;
-    width: 514px;
+    width: 520px;
   }
 
   #descriptionText:focus {
@@ -49,6 +50,10 @@
     color: var(--google-red-600);
     font-weight: bold;
   }
+
+  #descriptionTitle {
+    margin: 0 0 6px 0;
+  }
 </style>
 <div id="container">
   <div id="header">
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.html b/ash/webui/os_feedback_ui/resources/share_data_page.html
index e9c0c11..d963101f 100644
--- a/ash/webui/os_feedback_ui/resources/share_data_page.html
+++ b/ash/webui/os_feedback_ui/resources/share_data_page.html
@@ -152,7 +152,7 @@
       <div id="attachFilesContainer">
         <!-- Attach a screenshot -->
         <div id="screenshotContainer" class="card-frame">
-          <cr-checkbox id="screenshotCheckbox" aria-labelledby="screenshotCheckLabel"
+          <cr-checkbox id="screenshotCheckbox"
               disabled="[[!hasScreenshot_(screenshotUrl)]]">
           </cr-checkbox>
           <label id="screenshotCheckLabel">[[i18n('attachScreenshotLabel')]]</label>
@@ -191,7 +191,7 @@
     <div id="shareDiagnosticData">
       <h2 id="shareDiagnosticDataLabel">[[i18n('shareDiagnosticDataLabel')]]</h2>
       <!-- URL -->
-      <div id="pageUrl" class="checkbox-field-container">
+      <div id="pageUrl" class="checkbox-field-container" hidden="[[!feedbackContext.pageUrl.url]]">
         <cr-checkbox id="pageUrlCheckbox" aria-labelledby="pageUrlLabel" checked></cr-checkbox>
         <label id="pageUrlLabel">[[i18n('sharePageUrlLabel')]]&nbsp;</label>
         <a href="[[feedbackContext.pageUrl.url]]" class="overflow-text" id="pageUrlText" target="_blank">
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.js b/ash/webui/os_feedback_ui/resources/share_data_page.js
index 4c9dd661..b2e3a57 100644
--- a/ash/webui/os_feedback_ui/resources/share_data_page.js
+++ b/ash/webui/os_feedback_ui/resources/share_data_page.js
@@ -80,6 +80,8 @@
     super.ready();
     this.setPrivacyNote_();
     this.setSysInfoCheckboxLabelAndAttributes_();
+    this.$.screenshotCheckbox.ariaLabel =
+        this.i18n('attachScreenshotCheckboxAriaLabel');
 
     // Set up event listener for email change to retarget |this| to be the
     // ShareDataPageElement's context.
@@ -149,12 +151,14 @@
    * @param {!Event} e
    * @protected
    */
-  handleOpenSysInfoDialog_(e) {
+  handleOpenSystemInfoDialog_(e) {
     // The default behavior of clicking on an anchor tag
     // with href="#" is a scroll to the top of the page.
     // This link opens a dialog, so we want to prevent
     // this default behavior.
     e.preventDefault();
+
+    this.feedbackServiceProvider_.openSystemInfoDialog();
   }
 
   /**
@@ -282,7 +286,7 @@
     // Setting href causes <a> tag to display as link.
     sysInfoLink.setAttribute('href', '#');
     sysInfoLink.addEventListener(
-        'click', (e) => void this.handleOpenSysInfoDialog_(e));
+        'click', (e) => void this.handleOpenSystemInfoDialog_(e));
 
     const histogramsLink = this.shadowRoot.querySelector('#histogramsLink');
     histogramsLink.setAttribute('href', '#');
diff --git a/ash/webui/sample_system_web_app_ui/BUILD.gn b/ash/webui/sample_system_web_app_ui/BUILD.gn
index f12d252f..1637556 100644
--- a/ash/webui/sample_system_web_app_ui/BUILD.gn
+++ b/ash/webui/sample_system_web_app_ui/BUILD.gn
@@ -28,6 +28,7 @@
     "//ash/webui/resources:sample_system_web_app_untrusted_resources",
     "//ash/webui/sample_system_web_app_ui/mojom:trusted",
     "//ash/webui/sample_system_web_app_ui/mojom:untrusted",
+    "//ash/webui/system_apps/public:system_web_app_config",
     "//content/public/browser",
     "//ui/webui",
   ]
diff --git a/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.cc b/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.cc
index 26b1b59..9185eb6 100644
--- a/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.cc
+++ b/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.cc
@@ -20,16 +20,6 @@
 
 namespace ash {
 
-SampleSystemWebAppUIConfig::SampleSystemWebAppUIConfig()
-    : WebUIConfig(content::kChromeUIScheme, kChromeUISampleSystemWebAppHost) {}
-
-SampleSystemWebAppUIConfig::~SampleSystemWebAppUIConfig() = default;
-
-std::unique_ptr<content::WebUIController>
-SampleSystemWebAppUIConfig::CreateWebUIController(content::WebUI* web_ui) {
-  return std::make_unique<SampleSystemWebAppUI>(web_ui);
-}
-
 SampleSystemWebAppUI::SampleSystemWebAppUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui) {
   auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
diff --git a/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.h b/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.h
index 8ecfeaf7..f623df0b 100644
--- a/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.h
+++ b/ash/webui/sample_system_web_app_ui/sample_system_web_app_ui.h
@@ -13,6 +13,8 @@
 
 #include "ash/webui/sample_system_web_app_ui/mojom/sample_system_web_app_ui.mojom.h"
 #include "ash/webui/sample_system_web_app_ui/sample_page_handler.h"
+#include "ash/webui/sample_system_web_app_ui/url_constants.h"
+#include "ash/webui/system_apps/public/system_web_app_ui_config.h"
 #include "content/public/browser/webui_config.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -21,14 +23,15 @@
 
 namespace ash {
 
-// The WebUIConfig for chrome://sample-system-web-app/.
-class SampleSystemWebAppUIConfig : public content::WebUIConfig {
- public:
-  SampleSystemWebAppUIConfig();
-  ~SampleSystemWebAppUIConfig() override;
+class SampleSystemWebAppUI;
 
-  std::unique_ptr<content::WebUIController> CreateWebUIController(
-      content::WebUI* web_ui) override;
+// The WebUIConfig for chrome://sample-system-web-app/.
+class SampleSystemWebAppUIConfig
+    : public SystemWebAppUIConfig<SampleSystemWebAppUI> {
+ public:
+  SampleSystemWebAppUIConfig()
+      : SystemWebAppUIConfig(kChromeUISampleSystemWebAppHost,
+                             SystemWebAppType::SAMPLE) {}
 };
 
 class SampleSystemWebAppUI : public ui::MojoWebUIController,
diff --git a/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.cc b/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.cc
index 09d71958..04adeb86 100644
--- a/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.cc
+++ b/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.cc
@@ -15,19 +15,6 @@
 
 namespace ash {
 
-UntrustedSampleSystemWebAppUIConfig::UntrustedSampleSystemWebAppUIConfig()
-    : WebUIConfig(content::kChromeUIUntrustedScheme,
-                  kChromeUIUntrustedSampleSystemWebAppHost) {}
-
-UntrustedSampleSystemWebAppUIConfig::~UntrustedSampleSystemWebAppUIConfig() =
-    default;
-
-std::unique_ptr<content::WebUIController>
-UntrustedSampleSystemWebAppUIConfig::CreateWebUIController(
-    content::WebUI* web_ui) {
-  return std::make_unique<UntrustedSampleSystemWebAppUI>(web_ui);
-}
-
 UntrustedSampleSystemWebAppUI::UntrustedSampleSystemWebAppUI(
     content::WebUI* web_ui)
     : ui::UntrustedWebUIController(web_ui) {
diff --git a/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.h b/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.h
index 5169459..b65d488 100644
--- a/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.h
+++ b/ash/webui/sample_system_web_app_ui/untrusted_sample_system_web_app_ui.h
@@ -6,6 +6,8 @@
 #define ASH_WEBUI_SAMPLE_SYSTEM_WEB_APP_UI_UNTRUSTED_SAMPLE_SYSTEM_WEB_APP_UI_H_
 
 #include "ash/webui/sample_system_web_app_ui/mojom/sample_system_web_app_untrusted_ui.mojom.h"
+#include "ash/webui/sample_system_web_app_ui/url_constants.h"
+#include "ash/webui/system_apps/public/system_web_app_ui_config.h"
 #include "content/public/browser/webui_config.h"
 #include "ui/webui/untrusted_web_ui_controller.h"
 
@@ -19,15 +21,17 @@
 
 namespace ash {
 
-class UntrustedSampleSystemWebAppUIConfig : public content::WebUIConfig {
- public:
-  UntrustedSampleSystemWebAppUIConfig();
-  ~UntrustedSampleSystemWebAppUIConfig() override;
+class UntrustedSampleSystemWebAppUI;
 
-  std::unique_ptr<content::WebUIController> CreateWebUIController(
-      content::WebUI* web_ui) override;
+class SampleSystemWebAppUntrustedUIConfig
+    : public SystemWebAppUntrustedUIConfig<UntrustedSampleSystemWebAppUI> {
+ public:
+  SampleSystemWebAppUntrustedUIConfig()
+      : SystemWebAppUntrustedUIConfig(kChromeUIUntrustedSampleSystemWebAppHost,
+                                      SystemWebAppType::SAMPLE) {}
 };
 
+// TODO(crbug.com/1345846): Rename to SampleSystemWebAppUntrustedUI.
 class UntrustedSampleSystemWebAppUI
     : public ui::UntrustedWebUIController,
       public mojom::sample_swa::UntrustedPageInterfacesFactory {
diff --git a/ash/webui/system_apps/public/BUILD.gn b/ash/webui/system_apps/public/BUILD.gn
new file mode 100644
index 0000000..84cf42c
--- /dev/null
+++ b/ash/webui/system_apps/public/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(crbug.com/1321984): system_web_app_type is currently used by non-ash
+# classes. Once SystemWebAppManager is ash-only we can add the assert.
+# assert(is_chromeos_ash)
+
+source_set("system_web_app_config") {
+  sources = [ "system_web_app_ui_config.h" ]
+  deps = [
+    ":system_web_app_type",
+    "//content/public/browser",
+    "//ui/webui",
+  ]
+}
+
+source_set("system_web_app_type") {
+  sources = [ "system_web_app_type.h" ]
+}
diff --git a/ash/webui/system_apps/public/system_web_app_type.h b/ash/webui/system_apps/public/system_web_app_type.h
new file mode 100644
index 0000000..ac2d0b47
--- /dev/null
+++ b/ash/webui/system_apps/public/system_web_app_type.h
@@ -0,0 +1,145 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_TYPE_H_
+#define ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_TYPE_H_
+
+namespace ash {
+
+// An enum that lists the different System Apps that exist. Can be used to
+// retrieve the App ID from the underlying Web App system.
+//
+// These values are persisted to the web_app database. Entries should not be
+// renumbered and numeric values should never be reused.
+//
+// When deprecating, comment out the entry so that it's not accidentally
+// re-used.
+enum class SystemWebAppType {
+  FILE_MANAGER = 1,
+  // TELEMETRY_DEPRECATED = 2,
+
+  // A sample System Web App to illustrate SWA development best practices, and
+  // various SWA platform features.
+  //
+  // This App is only enabled on non-official builds. You can find a brief SWA
+  // platform introduction (Google internal) at: http://go/system-web-apps.
+  //
+  // Source: //ash/webui/sample_system_web_app_ui/
+  // Contact: dominicshulz@google.com, ortuno@chromium.org
+  SAMPLE = 3,
+
+  SETTINGS = 4,
+  CAMERA = 5,
+  TERMINAL = 6,
+  MEDIA = 7,
+  HELP = 8,
+  PRINT_MANAGEMENT = 9,
+  SCANNING = 10,
+  DIAGNOSTICS = 11,
+  CONNECTIVITY_DIAGNOSTICS = 12,
+  ECHE = 13,
+  CROSH = 14,
+  PERSONALIZATION = 15,
+  SHORTCUT_CUSTOMIZATION = 16,
+
+  // SHIMLESS RMA Flow is SWA that provides step by step guides for the
+  // repair/RMA process.
+  //
+  // You can find information about this SWA at: http://go/shimless-ux.
+  //
+  // Source: //ash/webui/shimless_rma/
+  // Contact: cros-peripherals@google.com
+  SHIMLESS_RMA = 17,
+
+  // A System Web App that launches on Demo Mode startup, to display animated
+  // content that highlights various features of ChromeOS
+  //
+  // Currently this SWA is only enabled in unofficial builds while still under
+  // development. Prefer to file bugs to the internal Demo Mode component:
+  // b/components/812312
+  //
+  // Source: //ash/webui/demo_mode_app_ui/
+  // Contact: jacksontadie@google.com, drcrash@chromium.org
+  DEMO_MODE = 18,
+
+  // OS FEEDBACK is a SWA that provides step by step guides to submit a
+  // feedback report on Chrome OS.
+  //
+  // Source: //ash/webui/os_feedback_ui
+  // contact: cros-telemetry@google.com
+  OS_FEEDBACK = 19,
+
+  // Projector aka Screencast (go/projector-player-dd) aims to make it simple
+  // for teachers and students to record and share instructional videos on a
+  // Chromebook. This app enables teachers to create a library of
+  // custom-tailored instructional content that students can search and view at
+  // home.
+  //
+  // Source: //ash/webui/projector_app/
+  // Contact: cros-projector@google.com
+  // Buganizer component: b/components/1080013
+  // This app is only included in Chrome-branded builds. Non-official builds
+  // will have a mock page.
+  PROJECTOR = 20,
+
+  // OsUrlHandler is called by Lacros to show Ash internal chrome:// pages as
+  // applications to the user. Note that these pages are accessible to the user
+  // as os://<page> through search.
+  // contact: skuhne@google.com
+  OS_URL_HANDLER = 21,
+
+  // FIRMWARE UPDATE App is SWA that lets users update all their peripheral
+  // firmwares in one place.
+  // You can find information about this SWA at: http://go/fwupd-app.
+  // Source: //ash/webui/firmware_update/
+  // Contact: cros-peripherals@google.com
+  FIRMWARE_UPDATE = 22,
+
+  // OsFlags is called by Lacros to show the chrome://flags page as
+  // applications to the user. Note that this page is accessible to the user
+  // as os://flags through search.
+  // contact: skuhne@google.com
+  OS_FLAGS = 23,
+
+  // When adding a new System App, remember to:
+  //
+  // 1. Add a corresponding histogram suffix in WebAppSystemAppInternalName
+  //    (histograms.xml). The suffix name should match the App's
+  //    |internal_name|. This is for reporting per-app install results.
+  //
+  // 2. Add a corresponding proto enum entry (with the same numerical value) to
+  //    SystemWebAppDataProto in system_web_app_data.proto. This is for
+  //    identifying system apps during Chrome start-up (i.e. when
+  //    SystemWebAppManager hasn't finished synchronizing all apps).
+  //
+  // 3. Add a comment above the enum entry in this file. It should include a
+  //    description (what it does in one sentence), at least one email contact,
+  //    source location (if it's in chromium source tree), and other relevant
+  //    information.
+  //
+  //    Other relevant information should come in separate paragraphs after the
+  //    description. This can be anything useful for triaging or routing bugs.
+  //    For example, your team doesn't use chromium's bug tracker, the App is
+  //    only available on certain devices.
+  //
+  //    Source location should point to where the App's WebUIController is
+  //    defined. It doesn't have to include the complete source repository (e.g.
+  //    if the App is hosted in internal repositories).
+  //
+  // 4. Put a blank line after each enum (before next enum's comment).
+  //
+  // 5. Use ash::LaunchSystemWebAppAsync to launch your SWA (with the type
+  //    added above). This provides extra safety in edge cases (e.g. when in
+  //    incognito or guest sessions).
+  //
+  // 6. Update kMaxValue.
+  //
+  // 7. Have one of System Web App Platform owners review the CL.
+  //    See: //ash/webui/PLATFORM_OWNERS
+  kMaxValue = OS_FLAGS,
+};
+
+}  // namespace ash
+
+#endif  // ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_TYPE_H_
diff --git a/ash/webui/system_apps/public/system_web_app_ui_config.h b/ash/webui/system_apps/public/system_web_app_ui_config.h
new file mode 100644
index 0000000..3734981
--- /dev/null
+++ b/ash/webui/system_apps/public/system_web_app_ui_config.h
@@ -0,0 +1,94 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_UI_CONFIG_H_
+#define ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_UI_CONFIG_H_
+
+#include <memory>
+#include <string>
+
+#include "ash/webui/system_apps/public/system_web_app_type.h"
+#include "base/strings/string_piece.h"
+#include "content/public/browser/webui_config.h"
+#include "content/public/common/url_constants.h"
+#include "ui/webui/untrusted_web_ui_controller.h"
+
+namespace ash {
+
+namespace internal {
+
+// Internal base class that overrides IsWebUIEnabled. Separate from the
+// templated class because IsWebUIEnabled needs to be implemented in //chrome.
+class BaseSystemWebAppUIConfig : public content::WebUIConfig {
+ public:
+  BaseSystemWebAppUIConfig(SystemWebAppType swa_type,
+                           base::StringPiece scheme,
+                           base::StringPiece host)
+      : content::WebUIConfig(scheme, host), swa_type_(swa_type) {}
+
+  // Implemented in //chrome/browser/ash/system_web_apps/
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+
+ private:
+  SystemWebAppType swa_type_;
+};
+
+}  // namespace internal
+
+// Default WebUIConfig for the chrome:// component of System Web Apps. It
+// has an implementation of `CreateWebUIController()`, which returns a new
+// `T` and an implementation of `IsWebUIEnabled()` which returns true if
+// System Web Apps are enabled and `swa_type` is enabled.
+template <typename T>
+class SystemWebAppUIConfig : public internal::BaseSystemWebAppUIConfig {
+ public:
+  // Constructs a WebUIConfig for chrome://`host` and enables it if
+  // System Web Apps are enabled and `swa_type` is enabled.
+  SystemWebAppUIConfig(base::StringPiece host, SystemWebAppType swa_type)
+      : BaseSystemWebAppUIConfig(swa_type, content::kChromeUIScheme, host) {
+    static_assert(!std::is_base_of<ui::UntrustedWebUIController, T>::value,
+                  "Should only be used for chrome:// WebUIs. See "
+                  "SystemWebAppUntrustedUIConfig below for chrome-untrusted:// "
+                  "WebUIs.");
+  }
+
+  ~SystemWebAppUIConfig() override = default;
+
+  std::unique_ptr<content::WebUIController> CreateWebUIController(
+      content::WebUI* web_ui) override {
+    return std::make_unique<T>(web_ui);
+  }
+};
+
+// Default WebUIConfig for the chrome-untrusted:// component of System Web Apps.
+// It has an implementation of `CreateWebUIController()`, which returns a new
+// `T` and an implementation of `IsWebUIEnabled()` which returns true if
+// System Web Apps are enabled and `swa_type` is enabled.
+template <typename T>
+class SystemWebAppUntrustedUIConfig
+    : public internal::BaseSystemWebAppUIConfig {
+ public:
+  // Constructs a WebUIConfig for chrome://`host` and enables it if
+  // System Web Apps are enabled and `swa_type` is enabled.
+  SystemWebAppUntrustedUIConfig(base::StringPiece host,
+                                SystemWebAppType swa_type)
+      : BaseSystemWebAppUIConfig(swa_type,
+                                 content::kChromeUIUntrustedScheme,
+                                 host) {
+    static_assert(std::is_base_of<ui::UntrustedWebUIController, T>::value,
+                  "Should only be used for chrome-untrusted:// WebUIs. See "
+                  "SystemWebAppUIConfig above for chrome:// WebUIs.");
+  }
+
+  ~SystemWebAppUntrustedUIConfig() override = default;
+
+  std::unique_ptr<content::WebUIController> CreateWebUIController(
+      content::WebUI* web_ui) override {
+    return std::make_unique<T>(web_ui);
+  }
+};
+
+}  //  namespace ash
+
+#endif  // ASH_WEBUI_SYSTEM_APPS_PUBLIC_SYSTEM_WEB_APP_UI_CONFIG_H_
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc
index 7e2b3cd..5da23b14 100644
--- a/ash/wm/client_controlled_state.cc
+++ b/ash/wm/client_controlled_state.cc
@@ -81,7 +81,7 @@
     set_next_bounds_change_animation_type(kAnimationCrossFade);
     EnterNextState(window_state, next_state_type);
 
-    VLOG(1) << "Processing Pinned Transtion: event=" << event_type
+    VLOG(1) << "Processing Pinned Transition: event=" << event_type
             << ", state=" << old_state_type << "=>" << next_state_type
             << ", pinned=" << was_pinned << "=>" << window_state->IsPinned()
             << ", trusted pinned=" << was_trusted_pinned << "=>"
@@ -101,6 +101,9 @@
       UpdateWindowForTransitionEvents(window_state, next_state, event_type);
       break;
     }
+    case WM_EVENT_FLOAT:
+      // TODO(crbug.com/1346061): Implement this.
+      break;
     case WM_EVENT_RESTORE:
       UpdateWindowForTransitionEvents(
           window_state, window_state->GetRestoreWindowState(), event_type);
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc
index 1f1178dd..09109a64 100644
--- a/ash/wm/default_state.cc
+++ b/ash/wm/default_state.cc
@@ -368,6 +368,12 @@
   }
 
   const WMEventType type = event->type();
+  // Not all windows can be floated.
+  if (type == WM_EVENT_FLOAT &&
+      !FloatController::CanFloatWindowInClamshell(window_state->window())) {
+    return;
+  }
+
   if (type == WM_EVENT_SNAP_PRIMARY || type == WM_EVENT_SNAP_SECONDARY)
     HandleWindowSnapping(window_state, type);
 
@@ -633,13 +639,22 @@
 
     case WindowStateType::kMinimized:
       break;
+    case WindowStateType::kFloated: {
+      // TODO(shidi): This needs to be updated if we decide to have float window
+      // for overview mode.
+      // When a floated window is previously minimized, un-minimize will restore
+      // the float state with previous floated bounds, without re-calculating
+      // preferred bounds.
+      bounds_in_parent =
+          previous_state_type == WindowStateType::kMinimized
+              ? window->bounds()
+              : Shell::Get()
+                    ->float_controller()
+                    ->GetPreferredFloatWindowClamshellBounds(window);
+      break;
+    }
     case WindowStateType::kInactive:
     case WindowStateType::kAutoPositioned:
-    case WindowStateType::kFloated:
-      // TODO(crbug.com/1331078): Handle Float Size and Position requirement.
-      // Temporarily set to current bounds.
-      bounds_in_parent = window->bounds();
-      break;
     case WindowStateType::kPip:
       return;
   }
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index 4dfb22b..7f0e1515 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -1762,6 +1762,13 @@
 
   if (toast_id.empty() || (temporary_removed_desk_ &&
                            temporary_removed_desk_->toast_id() == toast_id)) {
+    DCHECK(temporary_removed_desk_ && temporary_removed_desk_->desk());
+    // We need to tell any browser windows that are still in
+    // `temporary_removed_desk_->desk()` to suppress warning the user before
+    // closing.
+    Shell::Get()->shell_delegate()->ForceSkipWarningUserOnClose(
+        temporary_removed_desk_->desk()->GetAllAppWindows());
+
     temporary_removed_desk_.reset();
   }
 }
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc
index 38318085..fd06072 100644
--- a/ash/wm/float/float_controller.cc
+++ b/ash/wm/float/float_controller.cc
@@ -4,6 +4,8 @@
 
 #include "ash/wm/float/float_controller.h"
 
+#include <algorithm>
+
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
@@ -22,7 +24,6 @@
 #include "ui/display/screen.h"
 
 namespace ash {
-
 namespace {
 
 // The ideal dimensions of a float window before factoring in its minimum size
@@ -147,6 +148,49 @@
 }
 
 // static
+gfx::Rect FloatController::GetPreferredFloatWindowClamshellBounds(
+    aura::Window* window) {
+  DCHECK(CanFloatWindowInClamshell(window));
+  auto* work_area_insets = WorkAreaInsets::ForWindow(window->GetRootWindow());
+  const gfx::Rect work_area = work_area_insets->user_work_area_bounds();
+
+  gfx::Rect preferred_bounds =
+      WindowState::Get(window)->HasRestoreBounds()
+          ? WindowState::Get(window)->GetRestoreBoundsInParent()
+          : window->bounds();
+
+  // Float bounds should not be smaller than min bounds.
+  const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
+  DCHECK_GE(preferred_bounds.height(), minimum_size.height());
+  DCHECK_GE(preferred_bounds.width(), minimum_size.width());
+
+  int preferred_width = std::min(preferred_bounds.width(),
+                                 work_area.width() - 2 * kFloatWindowPaddingDp);
+  int preferred_height =
+      std::min(preferred_bounds.height(),
+               work_area.height() - 2 * kFloatWindowPaddingDp);
+
+  gfx::Rect float_init_bounds(
+      work_area.width() - preferred_width - kFloatWindowPaddingDp,
+      work_area.height() - preferred_height - kFloatWindowPaddingDp,
+      preferred_width, preferred_height);
+
+  return float_init_bounds;
+}
+
+// static
+bool FloatController::CanFloatWindowInClamshell(aura::Window* window) {
+  const gfx::Rect work_area = WorkAreaInsets::ForWindow(window->GetRootWindow())
+                                  ->user_work_area_bounds();
+  const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
+  if (minimum_size.width() > work_area.width() - 2 * kFloatWindowPaddingDp ||
+      minimum_size.height() > work_area.height() - 2 * kFloatWindowPaddingDp) {
+    return false;
+  }
+  return true;
+}
+
+// static
 bool FloatController::CanFloatWindowInTablet(aura::Window* window) {
   auto* window_state = WindowState::Get(window);
   if (!window_state || !window_state->CanResize())
@@ -288,6 +332,11 @@
   ResetFloatedWindow();
   DCHECK(!float_window_);
   float_window_ = window;
+  // Save the window position auto-management status.
+  position_auto_managed_ = WindowState::Get(window)->GetWindowPositionManaged();
+  // Floated window position should not be auto-managed.
+  if (position_auto_managed_)
+    WindowState::Get(window)->SetWindowPositionManaged(false);
   float_window_observation_.Observe(float_window_);
   aura::Window* float_container =
       window->GetRootWindow()->GetChildById(kShellWindowId_FloatContainer);
@@ -302,9 +351,18 @@
 void FloatController::Unfloat(aura::Window* window) {
   if (window != float_window_)
     return;
-  //  Re-parent window to active desk container.
+  // When a window is moved in/out from active desk container to float
+  // container, it gets reparented and will use
+  // `pre_added_to_workspace_window_bounds_` to update it's bounds, here we
+  // update `pre_added_to_workspace_window_bounds_` as window is re-added to
+  // active desk container from float container.
+  WindowState::Get(window)->SetPreAddedToWorkspaceWindowBounds(
+      window->bounds());
+  // Re-parent window to active desk container.
   desks_util::GetActiveDeskContainerForRoot(float_window_->GetRootWindow())
       ->AddChild(float_window_);
+  // Reset the window position auto-managed status.
+  WindowState::Get(window)->SetWindowPositionManaged(position_auto_managed_);
   float_window_observation_.Reset();
   float_window_ = nullptr;
 
diff --git a/ash/wm/float/float_controller.h b/ash/wm/float/float_controller.h
index 36b222b..f2f648e 100644
--- a/ash/wm/float/float_controller.h
+++ b/ash/wm/float/float_controller.h
@@ -43,6 +43,12 @@
   // area when it is floated.
   static constexpr int kFloatWindowPaddingDp = 8;
 
+  // Returns float window bounds in clamshell mode.
+  static gfx::Rect GetPreferredFloatWindowClamshellBounds(aura::Window* window);
+
+  // Determines if a window can be floated in clamshell mode.
+  static bool CanFloatWindowInClamshell(aura::Window* window);
+
   // Determines if a window can be floated in tablet mode.
   static bool CanFloatWindowInTablet(aura::Window* window);
 
@@ -108,6 +114,10 @@
   // is floated.
   aura::Window* float_window_ = nullptr;
 
+  // When a window is floated, the window position should not be auto-managed.
+  // Use this value to reset the auto-managed state when unfloat a window.
+  bool position_auto_managed_ = false;
+
   // The corner a floated window should be magnetized to. It persists throughout
   // the session; if you drag a window to the bottom left and float another
   // window, that window will also be magnetized to the bottom left.
diff --git a/ash/wm/float/float_controller_unittest.cc b/ash/wm/float/float_controller_unittest.cc
index d93ac04..3fa734f 100644
--- a/ash/wm/float/float_controller_unittest.cc
+++ b/ash/wm/float/float_controller_unittest.cc
@@ -14,8 +14,13 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/overview/overview_test_util.h"
+#include "ash/wm/splitview/split_view_metrics_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "ash/wm/window_positioning_utils.h"
+#include "ash/wm/window_state.h"
+#include "ash/wm/work_area_insets.h"
 #include "base/test/scoped_feature_list.h"
+#include "chromeos/ui/base/window_state_type.h"
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
 #include "chromeos/ui/wm/features.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -113,6 +118,82 @@
   EXPECT_TRUE(maximized_window->layer()->GetAnimator()->is_animating());
 }
 
+// Test when float a window in clamshell mode, window will change to default
+// float bounds in certain conditions.
+TEST_F(WindowFloatTest, WindowFloatingResize) {
+  UpdateDisplay("800x600");
+  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  widget->SetBounds(gfx::Rect(0, 0, 200, 200));
+  FloatController* controller = Shell::Get()->float_controller();
+
+  // Float Maximized window.
+  widget->Maximize();
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+  gfx::Rect default_float_bounds =
+      controller->GetPreferredFloatWindowClamshellBounds(
+          widget->GetNativeWindow());
+  EXPECT_EQ(widget->GetWindowBoundsInScreen(), default_float_bounds);
+  // Unfloat.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+  EXPECT_TRUE(widget->IsMaximized());
+
+  // Float Full screen window.
+  widget->SetFullscreen(true);
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+  EXPECT_EQ(widget->GetWindowBoundsInScreen(), default_float_bounds);
+  // Unfloat.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+  // TODO(crbug.com/1330999): This should return to Fullscreen state after
+  // the change.
+
+  // Minimize floated window.
+  // Minimized window can't be floated, but when a floated window enter/exit
+  // minimized state, it remains floated.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+  gfx::Rect curr_bounds = widget->GetWindowBoundsInScreen();
+  widget->Minimize();
+  widget->Restore();
+  EXPECT_EQ(widget->GetWindowBoundsInScreen(), curr_bounds);
+  EXPECT_TRUE(WindowState::Get(widget->GetNativeWindow())->IsFloated());
+
+  // Float Snapped window.
+  // Create a snap enabled window.
+  auto window = CreateAppWindow(default_float_bounds, AppType::BROWSER);
+  AcceleratorControllerImpl* acc_controller =
+      Shell::Get()->accelerator_controller();
+
+  // Snap Left.
+  acc_controller->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_LEFT, {});
+  ASSERT_EQ(chromeos::WindowStateType::kPrimarySnapped,
+            WindowState::Get(window.get())->GetStateType());
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(WindowState::Get(window.get()));
+  EXPECT_EQ(window->bounds(), default_float_bounds);
+  // Unfloat.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  // Window back to snapped state.
+  ASSERT_EQ(chromeos::WindowStateType::kPrimarySnapped,
+            WindowState::Get(window.get())->GetStateType());
+
+  // Snap Right.
+  acc_controller->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_RIGHT, {});
+  ASSERT_EQ(chromeos::WindowStateType::kSecondarySnapped,
+            WindowState::Get(window.get())->GetStateType());
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(WindowState::Get(window.get()));
+  EXPECT_EQ(window->bounds(), default_float_bounds);
+  // Unfloat.
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  // Window back to snapped state.
+  ASSERT_EQ(chromeos::WindowStateType::kSecondarySnapped,
+            WindowState::Get(window.get())->GetStateType());
+}
+
 using TabletWindowFloatTest = WindowFloatTest;
 
 TEST_F(TabletWindowFloatTest, TabletClamshellTransition) {
@@ -164,8 +245,8 @@
 
   aura::test::TestWindowDelegate window_delegate;
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
-      &window_delegate, /*id=*/-1, gfx::Rect(300, 300)));
-  window_delegate.set_minimum_size(gfx::Size(600, 600));
+      &window_delegate, /*id=*/-1, gfx::Rect(850, 850)));
+  window_delegate.set_minimum_size(gfx::Size(500, 500));
   wm::ActivateWindow(window.get());
 
   PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index f3870de1e..970731e9 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -571,8 +571,10 @@
     return nullptr;
 
   const bool maximized = window_state->IsMaximized();
-  if (!window_state->IsNormalOrSnapped() && !maximized)
+  if (!maximized && !window_state->IsNormalOrSnapped() &&
+      !window_state->IsFloated()) {
     return nullptr;
+  }
 
   // TODO(https://crbug.com/1084695): Disable dragging maximized ARC windows
   // from the caption. This is because ARC does not currently handle setting
@@ -972,6 +974,11 @@
     return;
   }
 
+  // Drag/Resize a floated window won't change window restore bounds.
+  if (window_state()->IsFloated()) {
+    return;
+  }
+
   DCHECK(window_state()->IsNormalStateType());
   // The window was normal and stays normal. This is a user
   // resize/drag and so the current bounds should be maintained, clearing
diff --git a/base/bind_internal.h b/base/bind_internal.h
index f83c94c..44adafa 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -359,6 +359,17 @@
   using Type = R(Args...);
 };
 
+template <typename Callable, typename R, typename... Args>
+struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) noexcept> {
+  using Type = R(Args...);
+};
+
+template <typename Callable, typename R, typename... Args>
+struct ExtractCallableRunTypeImpl<Callable,
+                                  R (Callable::*)(Args...) const noexcept> {
+  using Type = R(Args...);
+};
+
 // Evaluated to RunType of the given callable type.
 // Example:
 //   auto f = [](int, char*) { return 0.1; };
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index 6844b67..78e3f363 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -319,6 +319,16 @@
   return 42;
 }
 
+class NoexceptFunctor {
+ public:
+  int operator()() noexcept { return 42; }
+};
+
+class ConstNoexceptFunctor {
+ public:
+  int operator()() noexcept { return 42; }
+};
+
 class BindTest : public ::testing::Test {
  public:
   BindTest() {
@@ -1734,6 +1744,8 @@
   EXPECT_EQ(
       42, base::BindOnce(&BindTest::ConstNoexceptMethod, base::Unretained(this))
               .Run());
+  EXPECT_EQ(42, base::BindOnce(NoexceptFunctor()).Run());
+  EXPECT_EQ(42, base::BindOnce(ConstNoexceptFunctor()).Run());
 }
 
 int PingPong(int* i_ptr) {
diff --git a/base/callback_unittest.cc b/base/callback_unittest.cc
index f3eca56..348761cc 100644
--- a/base/callback_unittest.cc
+++ b/base/callback_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/notreached.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/bind.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -676,7 +677,9 @@
 // function.
 class ClassWithAMethod {
  public:
-  void TheMethod() {}
+  void TheMethod() { method_called = true; }
+
+  bool method_called = false;
 };
 
 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnSameSequence) {
@@ -726,6 +729,24 @@
   // run.
 }
 
+TEST_F(CallbackTest, ThenAfterWeakPtr) {
+  ClassWithAMethod obj;
+  WeakPtrFactory<ClassWithAMethod> factory(&obj);
+  WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
+
+  // If the first callback of a chain is skipped due to InvalidateWeakPtrs(),
+  // the remaining callbacks should still run.
+  bool chained_closure_called = false;
+  OnceClosure closure =
+      BindOnce(&ClassWithAMethod::TheMethod, ptr)
+          .Then(BindLambdaForTesting(
+              [&chained_closure_called] { chained_closure_called = true; }));
+  factory.InvalidateWeakPtrs();
+  std::move(closure).Run();
+  EXPECT_FALSE(obj.method_called);
+  EXPECT_TRUE(chained_closure_called);
+}
+
 class CallbackOwner : public base::RefCounted<CallbackOwner> {
  public:
   explicit CallbackOwner(bool* deleted) {
diff --git a/base/trace_event/cfi_backtrace_android.cc b/base/trace_event/cfi_backtrace_android.cc
index 2539794..4112449 100644
--- a/base/trace_event/cfi_backtrace_android.cc
+++ b/base/trace_event/cfi_backtrace_android.cc
@@ -107,7 +107,7 @@
   uint16_t cfi_data;
 
   // Return the RA offset for the current unwind row.
-  uint16_t ra_offset() const { return cfi_data & kRAMask << kRAShift; }
+  uint16_t ra_offset() const { return (cfi_data & kRAMask) << kRAShift; }
 
   // Returns the CFA offset for the current unwind row.
   uint16_t cfa_offset() const { return cfi_data & kCFAMask; }
diff --git a/base/trace_event/cfi_backtrace_android_unittest.cc b/base/trace_event/cfi_backtrace_android_unittest.cc
index edcdb55..59c384d 100644
--- a/base/trace_event/cfi_backtrace_android_unittest.cc
+++ b/base/trace_event/cfi_backtrace_android_unittest.cc
@@ -18,9 +18,7 @@
 
 }  // namespace
 
-// TODO(https://crbug.com/1346002): Disabled since the test is borken on
-// test-n-phone, test-o-phone and android-arm-tests.
-TEST(CFIBacktraceAndroidTest, DISABLED_TestUnwinding) {
+TEST(CFIBacktraceAndroidTest, TestUnwinding) {
   auto* unwinder = CFIBacktraceAndroid::GetInitializedInstance();
   EXPECT_TRUE(unwinder->can_unwind_stack_frames());
   EXPECT_GT(unwinder->executable_start_addr(), 0u);
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 606cd98..b2476d2 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-9.20220720.1.1
+9.20220720.3.1
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 91872c8..c0b9ce25 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -19,7 +19,6 @@
 #include "cc/trees/occlusion.h"
 #include "cc/trees/task_runner_provider.h"
 #include "components/viz/client/client_resource_provider.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
 #include "media/base/video_frame.h"
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc
index 6a205ea4..dd0e14e 100644
--- a/cc/layers/video_layer_impl_unittest.cc
+++ b/cc/layers/video_layer_impl_unittest.cc
@@ -13,7 +13,6 @@
 #include "cc/trees/single_thread_proxy.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/quads/draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
 #include "components/viz/service/display/output_surface.h"
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc
index b57a730..9a4abe41 100644
--- a/cc/paint/paint_op_buffer_serializer.cc
+++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -142,8 +142,7 @@
                              SkClipOp::kDifference, false);
     SerializeOp(canvas, &inner_clip_op, nullptr, params);
   }
-  DrawColorOp clear_op(SkColor4f::FromColor(preamble.background_color),
-                       SkBlendMode::kSrc);
+  DrawColorOp clear_op(preamble.background_color, SkBlendMode::kSrc);
   SerializeOp(canvas, &clear_op, nullptr, params);
   RestoreToCount(canvas, 1, params);
 }
diff --git a/cc/paint/paint_op_buffer_serializer.h b/cc/paint/paint_op_buffer_serializer.h
index c1f2ac7c..b44825b 100644
--- a/cc/paint/paint_op_buffer_serializer.h
+++ b/cc/paint/paint_op_buffer_serializer.h
@@ -49,7 +49,7 @@
     // potentially being partially transparent, if post scaled).
     bool requires_clear = true;
     // If clearing is needed, the color to clear to.
-    SkColor background_color = SK_ColorTRANSPARENT;
+    SkColor4f background_color = SkColors::kTransparent;
   };
   // Serialize the buffer with a preamble. This function wraps the buffer in a
   // save/restore and includes any translations, scales, and clearing as
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index d8481bc..c14dc46 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -19,7 +19,6 @@
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
@@ -240,11 +239,16 @@
   solid_color_quad->SetNew(shared_state, rect, visible_rect, SkColors::kRed,
                            false);
 
+  // We add a TextureDrawQuad with is_stream_video set to true to cover related
+  // code paths.
   auto* stream_video_quad =
-      to_pass->CreateAndAppendDrawQuad<viz::StreamVideoDrawQuad>();
+      to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
   stream_video_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
-                            resource6, gfx::Size(), gfx::PointF(),
-                            gfx::PointF(1.f, 1.f));
+                            resource6, false, gfx::PointF(0.f, 0.f),
+                            gfx::PointF(1.f, 1.f), SkColors::kTransparent,
+                            vertex_opacity, false, false, false,
+                            gfx::ProtectedVideoType::kHardwareProtected);
+  stream_video_quad->is_stream_video = true;
 
   auto* texture_quad = to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
   texture_quad->SetNew(
@@ -417,11 +421,14 @@
   solid_color_quad->SetNew(shared_state, rect, visible_rect, SkColors::kRed,
                            false);
 
-  viz::StreamVideoDrawQuad* stream_video_quad =
-      to_pass->CreateAndAppendDrawQuad<viz::StreamVideoDrawQuad>();
+  viz::TextureDrawQuad* stream_video_quad =
+      to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
   stream_video_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
-                            mapped_resource6, gfx::Size(), gfx::PointF(),
-                            gfx::PointF(1.f, 1.f));
+                            mapped_resource6, false, gfx::PointF(0.f, 0.f),
+                            gfx::PointF(1.f, 1.f), SkColors::kTransparent,
+                            vertex_opacity, false, false, false,
+                            gfx::ProtectedVideoType::kHardwareProtected);
+  stream_video_quad->is_stream_video = true;
 
   viz::TextureDrawQuad* texture_quad =
       to_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 288d755..55acb61e 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1380,6 +1380,7 @@
     "javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java",
     "javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java",
     "javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java",
+    "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeUnitTest.java",
     "javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java",
     "javatests/src/org/chromium/chrome/browser/ntp/TitleUtilTest.java",
     "javatests/src/org/chromium/chrome/browser/tab/WebContentsStateBridgeTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 5c5420dfe..418d557 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -243,8 +243,8 @@
   "javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java",
   "javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java",
-  "javatests/src/org/chromium/chrome/browser/media/ui/MediaSessionTest.java",
   "javatests/src/org/chromium/chrome/browser/media/ui/FullscreenVideoPictureInPictureControllerTest.java",
+  "javatests/src/org/chromium/chrome/browser/media/ui/MediaSessionTest.java",
   "javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java",
   "javatests/src/org/chromium/chrome/browser/metrics/ChromiumAndroidLinkerMetricsTest.java",
   "javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java",
@@ -260,7 +260,6 @@
   "javatests/src/org/chromium/chrome/browser/net/connectivitydetector/ConnectivityDetectorTest.java",
   "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java",
   "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java",
-  "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeUnitTest.java",
   "javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java",
   "javatests/src/org/chromium/chrome/browser/notifications/channels/SiteChannelsManagerTest.java",
   "javatests/src/org/chromium/chrome/browser/ntp/FakeRecentlyClosedTabManager.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index ce80267..f2255718 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -90,7 +90,6 @@
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFormActionTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java",
-    "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInputActionIntegrationTest.java",
     "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInterruptIntegrationTest.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java
deleted file mode 100644
index e7d0c144..0000000
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxEndToEndTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.autofill_assistant;
-
-import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.startAutofillAssistant;
-import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition;
-
-import android.view.View;
-
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matcher;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.BitmapDrawableProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.ClientDimensionProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.ConfigBasedUrlProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.DrawableProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.InfoBoxProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.ShowInfoBoxProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto;
-import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto;
-import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.components.autofill_assistant.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/** Tests autofill assistant's show info box feature. */
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@RunWith(ChromeJUnit4ClassRunner.class)
-public class AutofillAssistantInfoBoxEndToEndTest {
-    private static final String TEST_PAGE = "form_target_website.html";
-    private static final String IMAGE_URL =
-            "https://www.gstatic.com/images/branding/product/2x/googleg_48dp.png";
-    private static final ClientDimensionProto DIMENSION =
-            ClientDimensionProto.newBuilder().setDp(150).build();
-    private static final ConfigBasedUrlProto MDPI_CONFIG =
-            ConfigBasedUrlProto.newBuilder().putUrl("mdpi", IMAGE_URL).build();
-
-    private static final ConfigBasedUrlProto DARK_MDPI_CONFIG =
-            ConfigBasedUrlProto.newBuilder().putUrl("night-mdpi", IMAGE_URL).build();
-
-    private static DrawableProto drawable(ConfigBasedUrlProto config) {
-        BitmapDrawableProto.Builder bitmapBuilder = BitmapDrawableProto.newBuilder();
-        bitmapBuilder.setConfigBasedUrl(config);
-        bitmapBuilder.setHeight(DIMENSION);
-        bitmapBuilder.setWidth(DIMENSION);
-        return DrawableProto.newBuilder().setBitmap(bitmapBuilder.build()).build();
-    }
-
-    private static ShowInfoBoxProto showInfoBox(DrawableProto drawable) {
-        return ShowInfoBoxProto.newBuilder()
-                .setInfoBox(InfoBoxProto.newBuilder().setDrawable(drawable))
-                .build();
-    }
-
-    private static ShowInfoBoxProto showInfoBox(String explanation) {
-        return ShowInfoBoxProto.newBuilder()
-                .setInfoBox(InfoBoxProto.newBuilder().setExplanation(explanation))
-                .build();
-    }
-
-    private static ShowInfoBoxProto showInfoBox(String explanation, DrawableProto drawable) {
-        return ShowInfoBoxProto.newBuilder()
-                .setInfoBox(
-                        InfoBoxProto.newBuilder().setExplanation(explanation).setDrawable(drawable))
-                .build();
-    }
-
-    private static ActionProto actionProto(ShowInfoBoxProto showInfoBox) {
-        return ActionProto.newBuilder().setShowInfoBox(showInfoBox).build();
-    }
-
-    private static AutofillAssistantTestScript testScript(ArrayList<ActionProto> list) {
-        return new AutofillAssistantTestScript(
-                SupportedScriptProto.newBuilder()
-                        .setPath(TEST_PAGE)
-                        .setPresentation(PresentationProto.newBuilder().setAutostart(true))
-                        .build(),
-                list);
-    }
-
-    private final CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
-
-    @Rule
-    public final TestRule mRulesChain = RuleChain.outerRule(mTestRule).around(
-            new AutofillAssistantCustomTabTestRule(mTestRule, TEST_PAGE));
-
-    private void runAutofillAssistant(AutofillAssistantTestScript script) {
-        AutofillAssistantTestService testService =
-                new AutofillAssistantTestService(Collections.singletonList(script));
-        startAutofillAssistant(mTestRule.getActivity(), testService);
-    }
-
-    private Matcher<View> getImageView() {
-        return withId(R.id.info_box_image);
-    }
-
-    private Matcher<View> getTextView() {
-        return withId(R.id.info_box_explanation);
-    }
-
-    @Test
-    @MediumTest
-    public void showInfoBoxShown_onlyText() throws Exception {
-        ArrayList<ActionProto> list = new ArrayList<>();
-        list.add(actionProto(showInfoBox("explanation")));
-
-        runAutofillAssistant(testScript(list));
-
-        waitUntilViewMatchesCondition(withText("explanation"), isCompletelyDisplayed());
-    }
-
-    @Test
-    @MediumTest
-    public void showInfoBoxShown_textAndImage() throws Exception {
-        ArrayList<ActionProto> list = new ArrayList<>();
-        list.add(actionProto(showInfoBox("explanation", drawable(MDPI_CONFIG))));
-
-        runAutofillAssistant(testScript(list));
-
-        waitUntilViewMatchesCondition(withText("explanation"), isCompletelyDisplayed());
-        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
-    }
-
-    @Test
-    @MediumTest
-    public void showInfoBoxShown_image() throws Exception {
-        ArrayList<ActionProto> list = new ArrayList<>();
-        list.add(actionProto(showInfoBox(drawable(MDPI_CONFIG))));
-
-        runAutofillAssistant(testScript(list));
-
-        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
-    }
-
-    @Test
-    @MediumTest
-    public void showInfoBoxShown_fallbacks() throws Exception {
-        ArrayList<ActionProto> list = new ArrayList<>();
-        list.add(actionProto(showInfoBox(drawable(DARK_MDPI_CONFIG))));
-
-        runAutofillAssistant(testScript(list));
-
-        waitUntilViewMatchesCondition(getImageView(), isDisplayed());
-    }
-}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
index 9ee6062..74e8fb2c 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java
@@ -20,7 +20,6 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Typeface;
 import android.support.test.InstrumentationRegistry;
-import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.test.filters.MediumTest;
@@ -36,7 +35,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.autofill_assistant.R;
-import org.chromium.components.autofill_assistant.generic_ui.AssistantDrawable;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBox;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBoxCoordinator;
 import org.chromium.components.autofill_assistant.infobox.AssistantInfoBoxModel;
@@ -46,7 +44,6 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class AutofillAssistantInfoBoxUiTest {
-    private static final AssistantDrawable sAssistantDrawable = AssistantDrawable.createFromIcon(1);
     @Rule
     public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
 
@@ -54,10 +51,6 @@
         return coordinator.getView().findViewById(R.id.info_box_explanation);
     }
 
-    private ImageView getImageView(AssistantInfoBoxCoordinator coordinator) {
-        return coordinator.getView().findViewById(R.id.info_box_image);
-    }
-
     private AssistantInfoBoxModel createModel() {
         return TestThreadUtils.runOnUiThreadBlockingNoException(AssistantInfoBoxModel::new);
     }
@@ -101,35 +94,20 @@
     /** Tests for an infobox with a message, but without an image. */
     @Test
     @MediumTest
-    public void testMessageNoImageLegacy() throws Exception {
-        testMessageNoImage(/*useLegacyImplementation=*/false);
-    }
-
-    /** Tests for an infobox with a message, but without an image. */
-    @Test
-    @MediumTest
     public void testMessageNoImage() throws Exception {
-        testMessageNoImage(/*useLegacyImplementation=*/true);
-    }
-
-    private void testMessageNoImage(boolean useLegacyImplementation) throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox(
-                null, "Message", /* useIntrinsicDimensions= */ useLegacyImplementation);
+        AssistantInfoBox infoBox = new AssistantInfoBox("", "Message");
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
         onView(is(coordinator.getView())).check(matches(isDisplayed()));
-        // Image should not be set.org.chromium.components.autofill_assistant.generic_ui
+        // Image should not be set.
         assertThat(getExplanationView(coordinator).getCompoundDrawables()[1], nullValue());
-        onView(is(getImageView(coordinator))).check(matches(not(isDisplayed())));
-
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
 
         // Test that info message supports typeface span.
-        AssistantInfoBox boldInfoBox = new AssistantInfoBox(
-                null, "<b>Message</b>", /* useIntrinsicDimensions= */ useLegacyImplementation);
+        AssistantInfoBox boldInfoBox = new AssistantInfoBox("", "<b>Message</b>");
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, boldInfoBox));
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
@@ -140,11 +118,10 @@
     /** Tests for an infobox with message and image. */
     @Test
     @MediumTest
-    public void testImageLegacy() throws Exception {
+    public void testImage() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox(
-                sAssistantDrawable, "Message", /* useIntrinsicDimensions= */ true);
+        AssistantInfoBox infoBox = new AssistantInfoBox("x", "Message");
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
@@ -154,42 +131,19 @@
         onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
     }
 
-    /** Tests for an infobox with message and image. */
-    @Test
-    @MediumTest
-    public void testImage() throws Exception {
-        AssistantInfoBoxModel model = createModel();
-        AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox = new AssistantInfoBox(
-                sAssistantDrawable, "Message", /* useIntrinsicDimensions= */ false);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
-        onView(is(getExplanationView(coordinator))).check(matches(isDisplayed()));
-        onView(is(getImageView(coordinator))).check(matches(isDisplayed()));
-        // Image should be set.
-        assertThat(getImageView(coordinator).getDrawable(), not(nullValue()));
-        onView(is(getExplanationView(coordinator))).check(matches(withText("Message")));
-    }
-
     @Test
     @MediumTest
     public void hideIfEmpty() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
 
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> model.set(AssistantInfoBoxModel.INFO_BOX,
-                                new AssistantInfoBox(
-                                        null, "Message", /* useIntrinsicDimensions= */ false)));
+        TestThreadUtils.runOnUiThreadBlocking(()
+                                                      -> model.set(AssistantInfoBoxModel.INFO_BOX,
+                                                              new AssistantInfoBox("", "Message")));
         onView(is(coordinator.getView())).check(matches(isDisplayed()));
 
         TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> model.set(AssistantInfoBoxModel.INFO_BOX,
-                                new AssistantInfoBox(
-                                        null, "", /* useIntrinsicDimensions= */ false)));
+                () -> model.set(AssistantInfoBoxModel.INFO_BOX, new AssistantInfoBox("", "")));
         onView(is(coordinator.getView())).check(matches(not(isDisplayed())));
     }
 
@@ -198,8 +152,7 @@
     public void hideIfNull() throws Exception {
         AssistantInfoBoxModel model = createModel();
         AssistantInfoBoxCoordinator coordinator = createCoordinator(model);
-        AssistantInfoBox infoBox =
-                new AssistantInfoBox(null, "Message", /* useIntrinsicDimensions= */ false);
+        AssistantInfoBox infoBox = new AssistantInfoBox("Message", "");
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantInfoBoxModel.INFO_BOX, infoBox));
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
index 29c83a52..2437a877 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -64,7 +64,9 @@
 import java.util.Arrays;
 import java.util.List;
 
-/** Instrumentation tests for autofill assistant UI. */
+/**
+ * Instrumentation tests for autofill assistant UI.
+ */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class AutofillAssistantUiTest {
     private String mTestPage;
@@ -193,9 +195,8 @@
                                         descriptionLine3,
                                         /* priceAttribution = */ "",
                                         /* userApprovalRequired= */ false,
-                                        /* highlightTitle= */ false,
-                                        /* highlightLine1= */ false,
-                                        /* highlightLine2 = */ false,
+                                        /* highlightTitle= */ false, /* highlightLine1= */
+                                        false, /* highlightLine2 = */ false,
                                         /* highlightLine3 = */ false,
                                         AutofillAssistantDetailsUiTest.NO_PLACEHOLDERS))));
         onView(withId(R.id.details_title))
@@ -226,8 +227,8 @@
                 ()
                         -> assistantCoordinator.getModel().getInfoBoxModel().set(
                                 AssistantInfoBoxModel.INFO_BOX,
-                                new AssistantInfoBox(null, infoBoxExplanation,
-                                        /*useIntrinsicDimensions=*/false)));
+                                new AssistantInfoBox(
+                                        /* imagePath = */ "", infoBoxExplanation)));
         TextView infoBoxExplanationView =
                 bottomSheetContent.findViewById(R.id.info_box_explanation);
         onView(is(infoBoxExplanationView)).check(matches(withText(infoBoxExplanation)));
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
index 8aaf09b0..45a29c3 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -165,6 +165,12 @@
     @Override
     public void hideDialog(boolean showAnimation) {
         mMediator.hideDialog(showAnimation);
+        mTabListCoordinator.postHiding();
+    }
+
+    @Override
+    public void prepareDialog() {
+        mTabListCoordinator.prepareTabGridDialogView();
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index e09afe2..e2589f394 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -73,6 +73,11 @@
         void hideDialog(boolean showAnimation);
 
         /**
+         * Prepare the TabGridDialog before show.
+         */
+        void prepareDialog();
+
+        /**
          * @return Whether or not the TabGridDialog consumed the event.
          */
         boolean handleBackPressed();
@@ -325,6 +330,7 @@
             updateDialog();
             updateDialogScrollPosition();
             mModel.set(TabGridPanelProperties.SCRIMVIEW_CLICK_RUNNABLE, mScrimClickRunnable);
+            mDialogController.prepareDialog();
             mModel.set(TabGridPanelProperties.IS_DIALOG_VISIBLE, true);
         } else {
             mModel.set(TabGridPanelProperties.IS_DIALOG_VISIBLE, false);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index df5f6ed..046dd41d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -87,6 +87,7 @@
     private boolean mIsInitialized;
     private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener;
     private OnLayoutChangeListener mListLayoutListener;
+    private boolean mLayoutListenerRegistered;
 
     /**
      * Construct a coordinator for UI that shows a list of tabs.
@@ -404,19 +405,30 @@
         if (mGlobalLayoutListener != null) {
             mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
         }
-        if (mListLayoutListener != null) {
-            mRecyclerView.addOnLayoutChangeListener(mListLayoutListener);
-        }
+        registerLayoutChangeListener();
         mRecyclerView.prepareTabSwitcherView();
         mMediator.prepareTabSwitcherView();
     }
 
+    private void registerLayoutChangeListener() {
+        if (mListLayoutListener != null) {
+            assert !mLayoutListenerRegistered;
+            mLayoutListenerRegistered = true;
+            mRecyclerView.addOnLayoutChangeListener(mListLayoutListener);
+        }
+    }
+
+    public void prepareTabGridDialogView() {
+        registerLayoutChangeListener();
+    }
+
     void postHiding() {
         if (mGlobalLayoutListener != null) {
             mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
         }
         if (mListLayoutListener != null) {
             mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener);
+            mLayoutListenerRegistered = false;
         }
         mRecyclerView.postHiding();
         mMediator.postHiding();
@@ -433,6 +445,7 @@
         }
         if (mListLayoutListener != null) {
             mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener);
+            mLayoutListenerRegistered = false;
         }
         mRecyclerView.setRecyclerListener(null);
     }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index 566c3ad..9fd8012 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -876,6 +876,8 @@
         assertThat(mModel.get(TabGridPanelProperties.ANIMATION_SOURCE_VIEW), equalTo(mView));
         // Dialog title should be updated.
         assertThat(mModel.get(TabGridPanelProperties.HEADER_TITLE), equalTo(DIALOG_TITLE2));
+        // Prepare dialog invoked.
+        verify(mDialogController).prepareDialog();
     }
 
     @Test
@@ -935,6 +937,8 @@
         assertThat(mModel.get(TabGridPanelProperties.ANIMATION_SOURCE_VIEW), equalTo(null));
         // Dialog title should be updated.
         assertThat(mModel.get(TabGridPanelProperties.HEADER_TITLE), equalTo(DIALOG_TITLE2));
+        // Prepare dialog invoked.
+        verify(mDialogController).prepareDialog();
     }
 
     @Test
diff --git a/chrome/android/java/res/layout/send_tab_to_self_feature_unavailable_prompt.xml b/chrome/android/java/res/layout/send_tab_to_self_feature_unavailable_prompt.xml
index 430122dc..a9ea20f 100644
--- a/chrome/android/java/res/layout/send_tab_to_self_feature_unavailable_prompt.xml
+++ b/chrome/android/java/res/layout/send_tab_to_self_feature_unavailable_prompt.xml
@@ -33,6 +33,7 @@
     android:text="@string/send_tab_to_self_share_activity_title"/>
 
   <TextView
+    android:id="@+id/empty_state_label"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:gravity="center"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
index 02f7954..acaa7cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
@@ -78,20 +78,6 @@
         int NONE = 7;
     }
 
-    // TODO(@vishwasuppoor): Reuse VirtualCardEnrollmentLinkType defined in
-    // virtual_card_enrollment_metrics.h (crbug.com/1318681).
-    // Constants used to log UMA "enum" histograms about the type of links clicked in mobile virtual
-    // card dialogs. Entries should not be renumbered and numeric values should never be reused.
-    @IntDef({VirtualCardDialogLink.EDUCATION_TEXT, VirtualCardDialogLink.GOOGLE_LEGAL_MESSAGE,
-            VirtualCardDialogLink.ISSUER_LEGAL_MESSAGE, VirtualCardDialogLink.NUM_ENTRIES})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface VirtualCardDialogLink {
-        int EDUCATION_TEXT = 0;
-        int GOOGLE_LEGAL_MESSAGE = 1;
-        int ISSUER_LEGAL_MESSAGE = 2;
-        int NUM_ENTRIES = 3;
-    }
-
     /**
      * Launches the Autofill help page on top of the current @{link android.app.Activity} and
      * current @{link Profile}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/VirtualCardEnrollmentDialogViewBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/VirtualCardEnrollmentDialogViewBridge.java
index 7cef2548..4eed55c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/VirtualCardEnrollmentDialogViewBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/VirtualCardEnrollmentDialogViewBridge.java
@@ -9,7 +9,6 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.autofill.settings.AutofillVirtualCardEnrollmentDialog;
 import org.chromium.chrome.browser.autofill.settings.VirtualCardEnrollmentFields;
-import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 
@@ -61,16 +60,6 @@
      */
     @CalledByNative
     private void showDialog() {
-        Callback<String> onEducationTextLinkClicked = url
-                -> mDelegate.onLinkClicked(
-                        url, VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK);
-        Callback<String> onGoogleLegalMessageLinkClicked = url
-                -> mDelegate.onLinkClicked(url,
-                        VirtualCardEnrollmentLinkType
-                                .VIRTUAL_CARD_ENROLLMENT_GOOGLE_PAYMENTS_TOS_LINK);
-        Callback<String> onIssuerLegalMessageLinkClicked = url
-                -> mDelegate.onLinkClicked(
-                        url, VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_ISSUER_TOS_LINK);
         Callback<Integer> resultHandler = dismissalCause -> {
             if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) {
                 mDelegate.onAccepted();
@@ -82,8 +71,7 @@
         };
         mDialog = new AutofillVirtualCardEnrollmentDialog(mWindowAndroid.getActivity().get(),
                 mWindowAndroid.getModalDialogManager(), mFields, mAcceptButtonText,
-                mDeclineButtonText, onEducationTextLinkClicked, onGoogleLegalMessageLinkClicked,
-                onIssuerLegalMessageLinkClicked, resultHandler);
+                mDeclineButtonText, mDelegate::onLinkClicked, resultHandler);
         mDialog.show();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
index 45db520..e7333ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
@@ -21,13 +21,13 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeStringConstants;
-import org.chromium.chrome.browser.autofill.AutofillUiUtils.VirtualCardDialogLink;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.payments.SettingsAutofillAndPaymentsObserver;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.components.autofill.VirtualCardEnrollmentState;
 import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
@@ -226,12 +226,13 @@
     private void showVirtualCardEnrollmentDialog(
             VirtualCardEnrollmentFields virtualCardEnrollmentFields,
             ModalDialogManager modalDialogManager) {
-        Callback<String> onEducationTextLinkClicked =
-                url -> onLinkClicked(url, VirtualCardDialogLink.EDUCATION_TEXT);
-        Callback<String> onGoogleLegalMessageLinkClicked =
-                url -> onLinkClicked(url, VirtualCardDialogLink.GOOGLE_LEGAL_MESSAGE);
-        Callback<String> onIssuerLegalMessageLinkClicked =
-                url -> onLinkClicked(url, VirtualCardDialogLink.ISSUER_LEGAL_MESSAGE);
+        AutofillVirtualCardEnrollmentDialog.LinkClickCallback onLinkClicked =
+                (url, virtualCardEnrollmentLinkType) -> {
+            RecordHistogram.recordEnumeratedHistogram(
+                    SETTINGS_PAGE_ENROLLMENT_HISTOGRAM_TEXT + ".LinkClicked",
+                    virtualCardEnrollmentLinkType, VirtualCardEnrollmentLinkType.MAX_VALUE + 1);
+            CustomTabActivity.showInfoPage(getActivity(), url);
+        };
         Callback<Integer> resultHandler = dismissalCause -> {
             if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) {
                 logSettingsPageEnrollmentDialogUserSelection(true);
@@ -250,8 +251,7 @@
                 getActivity(), modalDialogManager, virtualCardEnrollmentFields,
                 getActivity().getString(
                         R.string.autofill_virtual_card_enrollment_accept_button_label),
-                getActivity().getString(R.string.no_thanks), onEducationTextLinkClicked,
-                onGoogleLegalMessageLinkClicked, onIssuerLegalMessageLinkClicked, resultHandler);
+                getActivity().getString(R.string.no_thanks), onLinkClicked, resultHandler);
         dialog.show();
     }
 
@@ -271,13 +271,6 @@
         dialog.show();
     }
 
-    private void onLinkClicked(String url, @VirtualCardDialogLink int virtualCardDialogLink) {
-        RecordHistogram.recordEnumeratedHistogram(
-                SETTINGS_PAGE_ENROLLMENT_HISTOGRAM_TEXT + ".LinkClicked", virtualCardDialogLink,
-                VirtualCardDialogLink.NUM_ENTRIES);
-        CustomTabActivity.showInfoPage(getActivity(), url);
-    }
-
     private void removeLocalCopyViews() {
         ViewGroup parent = (ViewGroup) mClearLocalCopy.getParent();
         if (parent == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialog.java
index e1277e98..7b676b6a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialog.java
@@ -15,6 +15,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeStringConstants;
 import org.chromium.chrome.browser.autofill.AutofillUiUtils;
+import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
@@ -23,33 +24,34 @@
 
 /** Dialog shown to the user to enroll a credit card into the virtual card feature. */
 public class AutofillVirtualCardEnrollmentDialog {
+    /**
+     * The interface that implements the action to be performed when links are clicked.
+     */
+    @FunctionalInterface
+    public interface LinkClickCallback {
+        void call(String url, @VirtualCardEnrollmentLinkType int virtualCardEnrollmentLinkType);
+    }
+
     private final Context mContext;
     private final ModalDialogManager mModalDialogManager;
     private final VirtualCardEnrollmentFields mVirtualCardEnrollmentFields;
     private final String mAcceptButtonText;
     private final String mDeclineButtonText;
-    // TODO(@vishwasuppoor): Replace the 3 link click callbacks with a single callback after fixing
-    // crbug.com/1318681.
-    private final Callback<String> mOnEducationTextLinkClicked;
-    private final Callback<String> mOnGoogleLegalMessageLinkClicked;
-    private final Callback<String> mOnIssuerLegalMessageLinkClicked;
+    private final LinkClickCallback mOnLinkClicked;
     private final Callback<Integer> mResultHandler;
     private PropertyModel mDialogModel;
 
     public AutofillVirtualCardEnrollmentDialog(Context context,
             ModalDialogManager modalDialogManager,
             VirtualCardEnrollmentFields virtualCardEnrollmentFields, String acceptButtonText,
-            String declineButtonText, Callback<String> onEducationTextLinkClicked,
-            Callback<String> onGoogleLegalMessageLinkClicked,
-            Callback<String> onIssuerLegalMessageLinkClicked, Callback<Integer> resultHandler) {
+            String declineButtonText, LinkClickCallback onLinkClicked,
+            Callback<Integer> resultHandler) {
         mContext = context;
         mModalDialogManager = modalDialogManager;
         mVirtualCardEnrollmentFields = virtualCardEnrollmentFields;
         mAcceptButtonText = acceptButtonText;
         mDeclineButtonText = declineButtonText;
-        mOnEducationTextLinkClicked = onEducationTextLinkClicked;
-        mOnGoogleLegalMessageLinkClicked = onGoogleLegalMessageLinkClicked;
-        mOnIssuerLegalMessageLinkClicked = onIssuerLegalMessageLinkClicked;
+        mOnLinkClicked = onLinkClicked;
         mResultHandler = resultHandler;
     }
 
@@ -88,21 +90,31 @@
                 AutofillUiUtils.getSpannableStringWithClickableSpansToOpenLinksInCustomTabs(
                         mContext, R.string.autofill_virtual_card_enrollment_dialog_education_text,
                         ChromeStringConstants.AUTOFILL_VIRTUAL_CARD_ENROLLMENT_SUPPORT_URL,
-                        mOnEducationTextLinkClicked));
+                        url
+                        -> mOnLinkClicked.call(url,
+                                VirtualCardEnrollmentLinkType
+                                        .VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK)));
         virtualCardEducationTextView.setMovementMethod(LinkMovementMethod.getInstance());
 
         TextView googleLegalMessageTextView =
                 (TextView) customView.findViewById(R.id.google_legal_message);
         googleLegalMessageTextView.setText(AutofillUiUtils.getSpannableStringForLegalMessageLines(
                 mContext, mVirtualCardEnrollmentFields.getGoogleLegalMessages(),
-                /* underlineLinks= */ false, mOnGoogleLegalMessageLinkClicked));
+                /* underlineLinks= */ false,
+                url
+                -> mOnLinkClicked.call(url,
+                        VirtualCardEnrollmentLinkType
+                                .VIRTUAL_CARD_ENROLLMENT_GOOGLE_PAYMENTS_TOS_LINK)));
         googleLegalMessageTextView.setMovementMethod(LinkMovementMethod.getInstance());
 
         TextView issuerLegalMessageTextView =
                 (TextView) customView.findViewById(R.id.issuer_legal_message);
         issuerLegalMessageTextView.setText(AutofillUiUtils.getSpannableStringForLegalMessageLines(
                 mContext, mVirtualCardEnrollmentFields.getIssuerLegalMessages(),
-                /* underlineLinks= */ false, mOnIssuerLegalMessageLinkClicked));
+                /* underlineLinks= */ false,
+                url
+                -> mOnLinkClicked.call(url,
+                        VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_ISSUER_TOS_LINK)));
         issuerLegalMessageTextView.setMovementMethod(LinkMovementMethod.getInstance());
 
         ((TextView) customView.findViewById(R.id.credit_card_identifier))
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialog.java
index d79f318..d00d018 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialog.java
@@ -11,8 +11,8 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeStringConstants;
 import org.chromium.chrome.browser.autofill.AutofillUiUtils;
-import org.chromium.chrome.browser.autofill.AutofillUiUtils.VirtualCardDialogLink;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
@@ -60,8 +60,9 @@
                                         url -> {
                                             RecordHistogram.recordEnumeratedHistogram(
                                                     "Autofill.VirtualCard.SettingsPageUnenrollment.LinkClicked",
-                                                    VirtualCardDialogLink.EDUCATION_TEXT,
-                                                    VirtualCardDialogLink.NUM_ENTRIES);
+                                                    VirtualCardEnrollmentLinkType
+                                                            .VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK,
+                                                    VirtualCardEnrollmentLinkType.MAX_VALUE + 1);
                                             CustomTabActivity.showInfoPage(mContext, url);
                                         }))
                         .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
index 7c16922..124b94d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
@@ -55,7 +55,7 @@
             // navigations. Also handle chrome:// URLs if not already handled.
             mCurrentTabObserver = new CurrentTabObserver(tabSupplier, new EmptyTabObserver() {
                 @Override
-                public void onPageLoadFinished(Tab tab, GURL url) {
+                public void didFirstVisuallyNonEmptyPaint(Tab tab) {
                     if (tab != null) maybeShowContextualPageAction();
                 }
             }, this::activeTabChanged);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
index 588dcae9..978de65 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
@@ -59,7 +59,6 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.AutofillUiUtils.VirtualCardDialogLink;
 import org.chromium.chrome.browser.autofill.LegalMessageLine;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -68,6 +67,7 @@
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.components.autofill.VirtualCardEnrollmentState;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -279,7 +279,7 @@
         Assert.assertEquals(1,
                 mHistogramTester.getHistogramValueCount(
                         "Autofill.VirtualCard.SettingsPageEnrollment.LinkClicked",
-                        VirtualCardDialogLink.EDUCATION_TEXT));
+                        VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK));
         // Go back to the settings page.
         Espresso.pressBack();
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java
index affe3ec..3136194 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeStringConstants;
 import org.chromium.chrome.browser.autofill.LegalMessageLine;
+import org.chromium.components.autofill.VirtualCardEnrollmentLinkType;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
@@ -55,11 +56,7 @@
     @Mock
     private Callback<Integer> mResultHandlerMock;
     @Mock
-    private Callback<String> mOnEducationTextLinkClickedMock;
-    @Mock
-    private Callback<String> mOnGoogleLegalMessageLinkClickedMock;
-    @Mock
-    private Callback<String> mOnIssuerLegalMessageLinkClickedMock;
+    private AutofillVirtualCardEnrollmentDialog.LinkClickCallback mOnLinkClickedMock;
     private FakeModalDialogManager mModalDialogManager;
     private AutofillVirtualCardEnrollmentDialog mDialog;
     private VirtualCardEnrollmentFields mVirtualCardEnrollmentFields;
@@ -71,11 +68,10 @@
                 "card label", Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8));
         mVirtualCardEnrollmentFields.mGoogleLegalMessages.add(createLegalMessageLine("google"));
         mVirtualCardEnrollmentFields.mIssuerLegalMessages.add(createLegalMessageLine("issuer"));
-        mDialog = new AutofillVirtualCardEnrollmentDialog(
-                ApplicationProvider.getApplicationContext(), mModalDialogManager,
-                mVirtualCardEnrollmentFields, ACCEPT_BUTTON_TEXT, DECLINE_BUTTON_TEXT,
-                mOnEducationTextLinkClickedMock, mOnGoogleLegalMessageLinkClickedMock,
-                mOnIssuerLegalMessageLinkClickedMock, mResultHandlerMock);
+        mDialog =
+                new AutofillVirtualCardEnrollmentDialog(ApplicationProvider.getApplicationContext(),
+                        mModalDialogManager, mVirtualCardEnrollmentFields, ACCEPT_BUTTON_TEXT,
+                        DECLINE_BUTTON_TEXT, mOnLinkClickedMock, mResultHandlerMock);
         mDialog.show();
     }
 
@@ -126,8 +122,7 @@
         // Create a new AutofillVirtualCardEnrollmentDialog with Activity as the context instead.
         mDialog = new AutofillVirtualCardEnrollmentDialog(activity, mModalDialogManager,
                 mVirtualCardEnrollmentFields, ACCEPT_BUTTON_TEXT, DECLINE_BUTTON_TEXT,
-                mOnEducationTextLinkClickedMock, mOnGoogleLegalMessageLinkClickedMock,
-                mOnIssuerLegalMessageLinkClickedMock, mResultHandlerMock);
+                mOnLinkClickedMock, mResultHandlerMock);
         mDialog.show();
         // Make sure that the dialog was shown properly.
         assertThat(mModalDialogManager.getShownDialogModel()).isNotNull();
@@ -144,9 +139,11 @@
                 .isEqualTo("Learn more about virtual cards");
         // Click on the link. The callback doesn't use the view so it can be null.
         learnMoreSpan.onClick(null);
-        // Verify that the callback is called with url for learn more page.
-        verify(mOnEducationTextLinkClickedMock)
-                .onResult(ChromeStringConstants.AUTOFILL_VIRTUAL_CARD_ENROLLMENT_SUPPORT_URL);
+        // Verify that the callback is called with url for learn more page and enum type
+        // corresponding to the learn more link.
+        verify(mOnLinkClickedMock)
+                .call(ChromeStringConstants.AUTOFILL_VIRTUAL_CARD_ENROLLMENT_SUPPORT_URL,
+                        VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK);
     }
 
     @Test
@@ -157,8 +154,7 @@
         // Create a new AutofillVirtualCardEnrollmentDialog with Activity as the context instead.
         mDialog = new AutofillVirtualCardEnrollmentDialog(activity, mModalDialogManager,
                 mVirtualCardEnrollmentFields, ACCEPT_BUTTON_TEXT, DECLINE_BUTTON_TEXT,
-                mOnEducationTextLinkClickedMock, mOnGoogleLegalMessageLinkClickedMock,
-                mOnIssuerLegalMessageLinkClickedMock, mResultHandlerMock);
+                mOnLinkClickedMock, mResultHandlerMock);
         mDialog.show();
         // Make sure that the dialog was shown properly.
         assertThat(mModalDialogManager.getShownDialogModel()).isNotNull();
@@ -175,8 +171,12 @@
                 .isEqualTo("oo");
         // Click on the link. The callback doesn't use the view so it can be null.
         googleSpan.onClick(null);
-        // Verify that the callback is called with LEGAL_MESSAGE_URL.
-        verify(mOnGoogleLegalMessageLinkClickedMock).onResult(LEGAL_MESSAGE_URL);
+        // Verify that the callback is called with LEGAL_MESSAGE_URL and enum type corresponding to
+        // Google legal message lines.
+        verify(mOnLinkClickedMock)
+                .call(LEGAL_MESSAGE_URL,
+                        VirtualCardEnrollmentLinkType
+                                .VIRTUAL_CARD_ENROLLMENT_GOOGLE_PAYMENTS_TOS_LINK);
     }
 
     @Test
@@ -187,8 +187,7 @@
         // Create a new AutofillVirtualCardEnrollmentDialog with Activity as the context instead.
         mDialog = new AutofillVirtualCardEnrollmentDialog(activity, mModalDialogManager,
                 mVirtualCardEnrollmentFields, ACCEPT_BUTTON_TEXT, DECLINE_BUTTON_TEXT,
-                mOnEducationTextLinkClickedMock, mOnGoogleLegalMessageLinkClickedMock,
-                mOnIssuerLegalMessageLinkClickedMock, mResultHandlerMock);
+                mOnLinkClickedMock, mResultHandlerMock);
         mDialog.show();
         // Make sure that the dialog was shown properly.
         assertThat(mModalDialogManager.getShownDialogModel()).isNotNull();
@@ -205,8 +204,11 @@
                 .isEqualTo("ss");
         // Click on the link. The callback doesn't use the view so it can be null.
         issuerSpan.onClick(null);
-        // Verify that the callback is called with LEGAL_MESSAGE_URL.
-        verify(mOnIssuerLegalMessageLinkClickedMock).onResult(LEGAL_MESSAGE_URL);
+        // Verify that the callback is called with LEGAL_MESSAGE_URL and enum type corresponding to
+        // issuer legal message lines.
+        verify(mOnLinkClickedMock)
+                .call(LEGAL_MESSAGE_URL,
+                        VirtualCardEnrollmentLinkType.VIRTUAL_CARD_ENROLLMENT_ISSUER_TOS_LINK);
     }
 
     private SpannableString getSpannableStringForViewFromCurrentDialog(int textViewId) {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ef64588..b00742a 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3456,7 +3456,7 @@
           Certificate Signature Value
         </message>
         <message name="IDS_CERT_DETAILS_EXPORT_CERTIFICATE" desc="The label of the button to export the selected certificate">
-          E&amp;xport...
+          E&amp;xport selected certificate...
         </message>
 
         <message translateable="false" name="IDS_CERT_OID_AVA_COMMON_NAME" desc="">
@@ -12885,10 +12885,10 @@
       You have Chrome's strongest security against dangerous websites, downloads and extensions
     </message>
     <message name="IDS_TAILORED_SECURITY_DISABLED_DIALOG_MAIN_TEXT" desc="Title shown in the tab dialog when the account tailored security setting changes for a consented primary account">
-      You're getting standard security protection. To get more protection against dangerous websites, downloads, and extensions, turn on Enhanced Safe Browsing.
+      You're getting standard security protection. To get more protection against dangerous websites, downloads, and extensions, turn on Enhanced Safe Browsing in Chrome settings.
     </message>
-    <message name="IDS_TAILORED_SECURITY_DIALOG_ACCEPT_BUTTON" desc="The text on the accept button in the tab dialog when the account tailored security setting changes for a consented primary account">
-      OK
+    <message name="IDS_TAILORED_SECURITY_DISABLED_DIALOG_ACCEPT_BUTTON" desc="The text on the accept button in the tab modal dialog when the account tailored security setting is disabled for a consented primary account">
+      Got it
     </message>
     <message name="IDS_TAILORED_SECURITY_DIALOG_SETTINGS_BUTTON" desc="The text on the cancel button in the tab dialog when the account tailored security setting changes for a consented primary account">
       Chrome settings
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1
new file mode 100644
index 0000000..cc44c34
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CERT_DETAILS_EXPORT_CERTIFICATE.png.sha1
@@ -0,0 +1 @@
+55a7a3c61cd9fa7ff8bf31be3214cb615ac6d55d
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DIALOG_ACCEPT_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DIALOG_ACCEPT_BUTTON.png.sha1
deleted file mode 100644
index e9cd9d9..0000000
--- a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DIALOG_ACCEPT_BUTTON.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5f09b467c8915ab1506bf046ed01ce83b0b14b8f
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_ACCEPT_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_ACCEPT_BUTTON.png.sha1
new file mode 100644
index 0000000..a89132b1
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_ACCEPT_BUTTON.png.sha1
@@ -0,0 +1 @@
+b27ac30163139310f5991fdcf01fa9d9f68a2452
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_MAIN_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_MAIN_TEXT.png.sha1
index 9579270..e934af5b 100644
--- a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_MAIN_TEXT.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_DISABLED_DIALOG_MAIN_TEXT.png.sha1
@@ -1 +1 @@
-d7929629b0ef0c1ebec1d37d39cda7a226320496
\ No newline at end of file
+67635fba25320fef00650785314526a83d3dacb3
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9fbe0572..e4f8295a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1261,20 +1261,6 @@
     "predictors/resource_prefetch_predictor.h",
     "predictors/resource_prefetch_predictor_tables.cc",
     "predictors/resource_prefetch_predictor_tables.h",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc",
-    "prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h",
-    "prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc",
-    "prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h",
-    "prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc",
-    "prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h",
-    "prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc",
-    "prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h",
-    "prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc",
-    "prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h",
     "prefetch/pref_names.cc",
     "prefetch/pref_names.h",
     "prefetch/prefetch_headers.cc",
@@ -1370,6 +1356,20 @@
     "preloading/chrome_preloading.h",
     "preloading/navigation_ablation_throttle.cc",
     "preloading/navigation_ablation_throttle.h",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc",
+    "preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc",
+    "preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h",
     "preloading/prerender/prerender_manager.cc",
     "preloading/prerender/prerender_manager.h",
     "preloading/prerender/prerender_utils.cc",
@@ -2470,6 +2470,8 @@
   # to the stub which is not implemented.
   if (is_chromeos_ash) {
     sources += [ "net/net_error_diagnostics_dialog_chromeos.cc" ]
+  } else if (is_chromeos_lacros) {
+    sources += [ "net/net_error_diagnostics_dialog_lacros.cc" ]
   } else if (is_win) {
     sources += [ "net/net_error_diagnostics_dialog_win.cc" ]
   } else {
@@ -4029,8 +4031,8 @@
       "policy/managed_account_policy_handler.h",
       "policy/webhid_device_policy_handler.cc",
       "policy/webhid_device_policy_handler.h",
-      "prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc",
-      "prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h",
+      "preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc",
+      "preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h",
       "process_singleton_modal_dialog_lock.cc",
       "process_singleton_modal_dialog_lock.h",
       "process_singleton_startup_lock.cc",
@@ -5471,6 +5473,8 @@
       "lacros/metrics_reporting_observer.h",
       "lacros/net/lacros_extension_proxy_tracker.cc",
       "lacros/net/lacros_extension_proxy_tracker.h",
+      "lacros/net/network_change_manager_bridge.cc",
+      "lacros/net/network_change_manager_bridge.h",
       "lacros/net/network_settings_translation.h",
       "lacros/net/network_settings_translation_crosapi.cc",
       "lacros/net/network_settings_translation_net_proxy.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b1f8ecf..2e82088 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -374,6 +374,22 @@
      gl::kANGLEImplementationMetalName}};
 #endif
 
+#if BUILDFLAG(IS_WIN)
+const FeatureEntry::FeatureParam kDXGIWaitableSwapChain1Frame = {
+    "DXGIWaitableSwapChainMaxQueuedFrames", "1"};
+
+const FeatureEntry::FeatureParam kDXGIWaitableSwapChain2Frames = {
+    "DXGIWaitableSwapChainMaxQueuedFrames", "2"};
+
+const FeatureEntry::FeatureParam kDXGIWaitableSwapChain3Frames = {
+    "DXGIWaitableSwapChainMaxQueuedFrames", "3"};
+
+const FeatureEntry::FeatureVariation kDXGIWaitableSwapChainVariations[] = {
+    {"Max 1 Frame", &kDXGIWaitableSwapChain1Frame, 1, nullptr},
+    {"Max 2 Frames", &kDXGIWaitableSwapChain2Frames, 1, nullptr},
+    {"Max 3 Frames", &kDXGIWaitableSwapChain3Frames, 1, nullptr}};
+#endif
+
 #if BUILDFLAG(IS_LINUX)
 const FeatureEntry::Choice kOzonePlatformHintRuntimeChoices[] = {
     {flag_descriptions::kOzonePlatformHintChoiceDefault, "", ""},
@@ -3867,6 +3883,15 @@
         kOsWin,
         FEATURE_VALUE_TYPE(media::kMediaFoundationClearPlayback),
     },
+    {
+        "enable-waitable-swap-chain",
+        flag_descriptions::kUseWaitableSwapChainName,
+        flag_descriptions::kUseWaitableSwapChainDescription,
+        kOsWin,
+        FEATURE_WITH_PARAMS_VALUE_TYPE(features::kDXGIWaitableSwapChain,
+                                       kDXGIWaitableSwapChainVariations,
+                                       "DXGIWaitableSwapChain"),
+    },
 #endif
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     {
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
index b40f2e6..c065d734 100644
--- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc
+++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -166,7 +166,7 @@
   input_.set_prevent_inline_autocomplete(prevent_inline_autocomplete);
   input_.set_prefer_keyword(prefer_keyword);
   input_.set_allow_exact_keyword_match(allow_exact_keyword_match);
-  input_.set_want_asynchronous_matches(want_asynchronous_matches);
+  input_.set_omit_asynchronous_matches(!want_asynchronous_matches);
   autocomplete_controller_->Start(input_);
 }
 
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index c9b51adb..58de298a 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -32,8 +32,8 @@
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
diff --git a/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc b/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
index 73bbc698..03ca64d9 100644
--- a/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
+++ b/chrome/browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc
@@ -24,7 +24,7 @@
 #include "chrome/test/base/chromeos/ash_browser_test_starter.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "content/public/test/browser_test.h"
 #include "ui/base/models/simple_menu_model.h"
 
@@ -173,7 +173,7 @@
       InstallWebApp("https://example.org/", apps::WindowMode::kBrowser);
   EXPECT_EQ(ash::ShelfModel::Get()->ItemIndexByAppID(app_id), -1);
   AppServiceProxy()->Launch(app_id, /*event_flags=*/0,
-                            apps::mojom::LaunchSource::kFromAppListGrid);
+                            apps::LaunchSource::kFromAppListGrid);
   AppInstanceWaiter(AppServiceProxy()->InstanceRegistry(), app_id)
       .AwaitRunning();
   EXPECT_NE(ash::ShelfModel::Get()->ItemIndexByAppID(app_id), -1);
@@ -238,7 +238,7 @@
   const web_app::AppId app_id =
       InstallWebApp("https://example.org/", apps::WindowMode::kBrowser);
   AppServiceProxy()->Launch(app_id, /*event_flags=*/0,
-                            apps::mojom::LaunchSource::kFromAppListGrid);
+                            apps::LaunchSource::kFromAppListGrid);
   AppInstanceWaiter(AppServiceProxy()->InstanceRegistry(), app_id)
       .AwaitRunning();
   EXPECT_NE(ash::ShelfModel::Get()->ItemIndexByAppID(app_id), -1);
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index bfa5d32..b6cf888b 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -44,7 +44,7 @@
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/profile_network_context_service_factory.h"
 #include "chrome/browser/pdf/pdf_extension_test_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
diff --git a/chrome/browser/apps/intent_helper/intent_picker_internal.cc b/chrome/browser/apps/intent_helper/intent_picker_internal.cc
index 299c62a..51cd648 100644
--- a/chrome/browser/apps/intent_helper/intent_picker_internal.cc
+++ b/chrome/browser/apps/intent_helper/intent_picker_internal.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/apps/intent_helper/page_transition_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc b/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc
index cabbac30..9a8b2d3 100644
--- a/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc
+++ b/chrome/browser/apps/platform_apps/platform_app_navigation_redirector.cc
@@ -7,7 +7,7 @@
 #include "apps/launcher.h"
 #include "base/bind.h"
 #include "base/logging.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 87e4acd..46a5f163 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -213,6 +213,8 @@
     "arc/arc_migration_constants.h",
     "arc/arc_migration_guide_notification.cc",
     "arc/arc_migration_guide_notification.h",
+    "arc/arc_mount_provider.cc",
+    "arc/arc_mount_provider.h",
     "arc/arc_optin_uma.cc",
     "arc/arc_optin_uma.h",
     "arc/arc_support_host.cc",
diff --git a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
index eeb8c45..7b389d9a 100644
--- a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
+++ b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
+#include "components/services/app_service/public/cpp/features.h"
 
 namespace ash {
 namespace android_sms {
@@ -45,11 +47,19 @@
 
 void AndroidSmsAppManagerImpl::PwaDelegate::OpenApp(Profile* profile,
                                                     const std::string& app_id) {
-  apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-      app_id,
-      apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
-                          false /* preferred_containner */),
-      apps::mojom::LaunchSource::kFromChromeInternal);
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+        app_id,
+        apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
+                            false /* preferred_containner */),
+        apps::LaunchSource::kFromChromeInternal);
+  } else {
+    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+        app_id,
+        apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
+                            false /* preferred_containner */),
+        apps::mojom::LaunchSource::kFromChromeInternal);
+  }
 }
 
 bool AndroidSmsAppManagerImpl::PwaDelegate::TransferItemAttributes(
diff --git a/chrome/browser/ash/arc/arc_mount_provider.cc b/chrome/browser/ash/arc/arc_mount_provider.cc
new file mode 100644
index 0000000..85d7070
--- /dev/null
+++ b/chrome/browser/ash/arc/arc_mount_provider.cc
@@ -0,0 +1,52 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/arc_mount_provider.h"
+
+#include "ash/components/arc/arc_util.h"
+#include "ash/strings/grit/ash_strings.h"
+#include "chrome/browser/ash/guest_os/public/types.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace arc {
+
+namespace {
+
+constexpr uint32_t kVsockPort = 7780;
+
+}  // namespace
+
+ArcMountProvider::ArcMountProvider(Profile* profile, int cid)
+    : profile_(profile), cid_(cid) {}
+
+ArcMountProvider::~ArcMountProvider() = default;
+
+// GuestOsMountProvider overrides
+Profile* ArcMountProvider::profile() {
+  return profile_;
+}
+
+std::string ArcMountProvider::DisplayName() {
+  return l10n_util::GetStringUTF8(IDS_ASH_SCREEN_CAPTURE_SAVE_TO_ANDROID_FILES);
+}
+
+guest_os::GuestId ArcMountProvider::GuestId() {
+  return {guest_os::VmType::ARCVM, kArcVmName, ""};
+}
+
+guest_os::VmType ArcMountProvider::vm_type() {
+  return guest_os::VmType::ARCVM;
+}
+
+void ArcMountProvider::Prepare(PrepareCallback callback) {
+  std::move(callback).Run(true, cid_, kVsockPort, base::FilePath());
+}
+
+std::unique_ptr<guest_os::GuestOsFileWatcher>
+ArcMountProvider::CreateFileWatcher(base::FilePath mount_path,
+                                    base::FilePath relative_path) {
+  return nullptr;
+}
+
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/arc_mount_provider.h b/chrome/browser/ash/arc/arc_mount_provider.h
new file mode 100644
index 0000000..34d31101
--- /dev/null
+++ b/chrome/browser/ash/arc/arc_mount_provider.h
@@ -0,0 +1,53 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_ARC_ARC_MOUNT_PROVIDER_H_
+#define CHROME_BROWSER_ASH_ARC_ARC_MOUNT_PROVIDER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_mount_provider.h"
+
+namespace guest_os {
+class GuestOsFileWatcher;
+}
+
+namespace arc {
+
+// This class is responsible for mounting the sshfs version of Play files mount.
+class ArcMountProvider : public guest_os::GuestOsMountProvider {
+ public:
+  ArcMountProvider(Profile* profile, int cid);
+
+  ArcMountProvider(const ArcMountProvider&) = delete;
+  ArcMountProvider& operator=(const ArcMountProvider&) = delete;
+
+  ~ArcMountProvider() override;
+
+  // GuestOsMountProvider overrides
+  Profile* profile() override;
+  std::string DisplayName() override;
+  guest_os::GuestId GuestId() override;
+  guest_os::VmType vm_type() override;
+
+  std::unique_ptr<guest_os::GuestOsFileWatcher> CreateFileWatcher(
+      base::FilePath mount_path,
+      base::FilePath relative_path) override;
+
+ protected:
+  // GuestOsMountProvider override. Make sure Arc is running, then get
+  // address info e.g. cid and vsock port.
+  void Prepare(PrepareCallback callback) override;
+
+ private:
+  Profile* const profile_;
+  const int cid_;
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate its weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<ArcMountProvider> weak_ptr_factory_{this};
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_ASH_ARC_ARC_MOUNT_PROVIDER_H_
diff --git a/chrome/browser/ash/arc/arc_mount_provider_unittest.cc b/chrome/browser/ash/arc/arc_mount_provider_unittest.cc
new file mode 100644
index 0000000..8943507
--- /dev/null
+++ b/chrome/browser/ash/arc/arc_mount_provider_unittest.cc
@@ -0,0 +1,21 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+class ArcMountProviderTest : public testing::Test {
+ public:
+  ArcMountProviderTest() = default;
+
+  ArcMountProviderTest(const ArcMountProviderTest&) = delete;
+  ArcMountProviderTest& operator=(const ArcMountProviderTest&) = delete;
+
+  ~ArcMountProviderTest() override = default;
+};
+
+TEST_F(ArcMountProviderTest, ConstructDestruct) {}
+
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
index 927eb92..cbba3f1 100644
--- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
+++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager.cc
@@ -271,6 +271,7 @@
   it->second->UnRegisterEventRewriter();
   RemoveDisplayOverlayController();
   RemoveObserverFromInputMethod();
+  it->second->NotifyTextInputState(false);
   registered_top_level_window_ = nullptr;
 }
 
diff --git a/chrome/browser/ash/arc/input_overlay/touch_injector.cc b/chrome/browser/ash/arc/input_overlay/touch_injector.cc
index 57fcd41..88035ae 100644
--- a/chrome/browser/ash/arc/input_overlay/touch_injector.cc
+++ b/chrome/browser/ash/arc/input_overlay/touch_injector.cc
@@ -462,7 +462,7 @@
       CleanupTouchEvents();
       display_overlay_controller_->SetDisplayMode(DisplayMode::kPreMenu);
     }
-    return DiscardEvent(continuation);
+    return SendEvent(continuation, &event);
   } else if (display_mode_ == DisplayMode::kPreMenu) {
     if (event.IsKeyEvent()) {
       auto* key_event = event.AsKeyEvent();
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.cc b/chrome/browser/ash/arc/session/arc_session_manager.cc
index 1679615e..132f78a4 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager.cc
@@ -34,6 +34,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/ash/arc/arc_demo_mode_delegate_impl.h"
 #include "chrome/browser/ash/arc/arc_migration_guide_notification.h"
+#include "chrome/browser/ash/arc/arc_mount_provider.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/ash/arc/arc_support_host.h"
 #include "chrome/browser/ash/arc/arc_ui_availability_reporter.h"
@@ -44,6 +45,7 @@
 #include "chrome/browser/ash/arc/policy/arc_android_management_checker.h"
 #include "chrome/browser/ash/arc/policy/arc_policy_util.h"
 #include "chrome/browser/ash/arc/session/arc_provisioning_result.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_service.h"
 #include "chrome/browser/ash/login/demo_mode/demo_resources.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/policy/handlers/powerwash_requirements_checker.h"
@@ -648,7 +650,7 @@
           apps_util::CreateIntentForActivity(
               kPlayStoreActivity, kInitialStartParam, kCategoryLauncher),
           false /* deferred_launch_allowed */, display::kInvalidDisplayId,
-          apps::mojom::LaunchSource::kFromChromeInternal);
+          apps::LaunchSource::kFromChromeInternal);
     }
 
     prefs->ClearPref(prefs::kArcProvisioningInitiatedFromOobe);
@@ -938,15 +940,33 @@
 void ArcSessionManager::OnVmStarted(
     const vm_tools::concierge::VmStartedSignal& vm_signal) {
   // When an ARCVM starts, store the vm info.
-  if (vm_signal.name() == kArcVmName)
+  if (vm_signal.name() == kArcVmName) {
     vm_info_ = vm_signal.vm_info();
+
+    if (base::FeatureList::IsEnabled(kEnableVirtioBlkForData)) {
+      arcvm_mount_provider_id_ =
+          absl::optional<guest_os::GuestOsMountProviderRegistry::Id>(
+              guest_os::GuestOsService::GetForProfile(profile())
+                  ->MountProviderRegistry()
+                  ->Register(std::make_unique<ArcMountProvider>(
+                      profile(), vm_info_->cid())));
+    }
+  }
 }
 
 void ArcSessionManager::OnVmStopped(
     const vm_tools::concierge::VmStoppedSignal& vm_signal) {
   // When an ARCVM stops, clear the stored vm info.
-  if (vm_signal.name() == kArcVmName)
+  if (vm_signal.name() == kArcVmName) {
     vm_info_ = absl::nullopt;
+
+    if (arcvm_mount_provider_id_.has_value()) {
+      guest_os::GuestOsService::GetForProfile(profile())
+          ->MountProviderRegistry()
+          ->Unregister(*arcvm_mount_provider_id_);
+      arcvm_mount_provider_id_.reset();
+    }
+  }
 }
 
 const absl::optional<vm_tools::concierge::VmInfo>&
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.h b/chrome/browser/ash/arc/session/arc_session_manager.h
index 75001d8..fea2167 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.h
+++ b/chrome/browser/ash/arc/session/arc_session_manager.h
@@ -20,6 +20,7 @@
 #include "chrome/browser/ash/arc/session/adb_sideloading_availability_delegate_impl.h"
 #include "chrome/browser/ash/arc/session/arc_app_id_provider_impl.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_mount_provider_registry.h"
 #include "chrome/browser/ash/policy/arc/android_management_client.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
@@ -494,6 +495,9 @@
 
   std::unique_ptr<ArcDlcInstaller> arc_dlc_installer_;
 
+  absl::optional<guest_os::GuestOsMountProviderRegistry::Id>
+      arcvm_mount_provider_id_;
+
   // Must be the last member.
   base::WeakPtrFactory<ArcSessionManager> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
index 2aab90ac..2f3f589 100644
--- a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper.cc
@@ -18,7 +18,9 @@
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_update.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "components/services/app_service/public/cpp/instance_update.h"
 #include "components/services/app_service/public/cpp/types_util.h"
@@ -98,9 +100,15 @@
 }
 
 void AppServiceWrapper::LaunchApp(const std::string& app_service_id) {
-  GetAppProxy()->Launch(app_service_id, ui::EF_NONE,
-                        apps::mojom::LaunchSource::kFromParentalControls,
-                        apps::MakeWindowInfo(display::kDefaultDisplayId));
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    GetAppProxy()->Launch(
+        app_service_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
+        std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
+  } else {
+    GetAppProxy()->Launch(app_service_id, ui::EF_NONE,
+                          apps::mojom::LaunchSource::kFromParentalControls,
+                          apps::MakeWindowInfo(display::kDefaultDisplayId));
+  }
 }
 
 std::vector<AppId> AppServiceWrapper::GetInstalledApps() const {
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index e1d89403..584926f 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -151,6 +151,8 @@
     "move_migrator.h",
     "native_theme_service_ash.cc",
     "native_theme_service_ash.h",
+    "network_change_ash.cc",
+    "network_change_ash.h",
     "network_settings_service_ash.cc",
     "network_settings_service_ash.h",
     "network_settings_translation.h",
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index 242447a6..9012c39 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -63,6 +63,7 @@
 #include "chrome/browser/ash/crosapi/message_center_ash.h"
 #include "chrome/browser/ash/crosapi/metrics_reporting_ash.h"
 #include "chrome/browser/ash/crosapi/native_theme_service_ash.h"
+#include "chrome/browser/ash/crosapi/network_change_ash.h"
 #include "chrome/browser/ash/crosapi/network_settings_service_ash.h"
 #include "chrome/browser/ash/crosapi/networking_attributes_ash.h"
 #include "chrome/browser/ash/crosapi/networking_private_ash.h"
@@ -205,6 +206,7 @@
       metrics_reporting_ash_(registry->CreateMetricsReportingAsh(
           g_browser_process->metrics_service())),
       native_theme_service_ash_(std::make_unique<NativeThemeServiceAsh>()),
+      network_change_ash_(std::make_unique<NetworkChangeAsh>()),
       networking_attributes_ash_(std::make_unique<NetworkingAttributesAsh>()),
       networking_private_ash_(std::make_unique<NetworkingPrivateAsh>()),
       network_settings_service_ash_(std::make_unique<NetworkSettingsServiceAsh>(
@@ -449,6 +451,11 @@
   native_theme_service_ash_->BindReceiver(std::move(receiver));
 }
 
+void CrosapiAsh::BindNetworkChange(
+    mojo::PendingReceiver<crosapi::mojom::NetworkChange> receiver) {
+  network_change_ash_->BindReceiver(std::move(receiver));
+}
+
 void CrosapiAsh::BindSelectFile(
     mojo::PendingReceiver<mojom::SelectFile> receiver) {
   select_file_ash_->BindReceiver(std::move(receiver));
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index 2c0497b..1dbb117 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -69,6 +69,7 @@
 class MessageCenterAsh;
 class MetricsReportingAsh;
 class NativeThemeServiceAsh;
+class NetworkChangeAsh;
 class NetworkingAttributesAsh;
 class NetworkingPrivateAsh;
 class PolicyServiceAsh;
@@ -213,6 +214,8 @@
       mojo::PendingReceiver<mojom::MetricsReporting> receiver) override;
   void BindNativeThemeService(
       mojo::PendingReceiver<mojom::NativeThemeService> receiver) override;
+  void BindNetworkChange(
+      mojo::PendingReceiver<mojom::NetworkChange> receiver) override;
   void BindNetworkingAttributes(
       mojo::PendingReceiver<mojom::NetworkingAttributes> receiver) override;
   void BindNetworkingPrivate(
@@ -456,6 +459,7 @@
   std::unique_ptr<MessageCenterAsh> message_center_ash_;
   std::unique_ptr<MetricsReportingAsh> metrics_reporting_ash_;
   std::unique_ptr<NativeThemeServiceAsh> native_theme_service_ash_;
+  std::unique_ptr<NetworkChangeAsh> network_change_ash_;
   std::unique_ptr<NetworkingAttributesAsh> networking_attributes_ash_;
   std::unique_ptr<NetworkingPrivateAsh> networking_private_ash_;
   std::unique_ptr<NetworkSettingsServiceAsh> network_settings_service_ash_;
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index 6cb54be..97d57b7 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -80,6 +80,7 @@
 #include "chromeos/crosapi/mojom/login_state.mojom.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "chromeos/crosapi/mojom/metrics_reporting.mojom.h"
+#include "chromeos/crosapi/mojom/network_change.mojom.h"
 #include "chromeos/crosapi/mojom/network_settings_service.mojom.h"
 #include "chromeos/crosapi/mojom/networking_attributes.mojom.h"
 #include "chromeos/crosapi/mojom/networking_private.mojom.h"
@@ -233,7 +234,7 @@
   return {T::Uuid_, T::Version_};
 }
 
-static_assert(crosapi::mojom::Crosapi::Version_ == 87,
+static_assert(crosapi::mojom::Crosapi::Version_ == 88,
               "If you add a new crosapi, please add it to "
               "kInterfaceVersionEntries below.");
 
@@ -292,6 +293,7 @@
     MakeInterfaceVersionEntry<crosapi::mojom::MessageCenter>(),
     MakeInterfaceVersionEntry<crosapi::mojom::MetricsReporting>(),
     MakeInterfaceVersionEntry<crosapi::mojom::NativeThemeService>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::NetworkChange>(),
     MakeInterfaceVersionEntry<crosapi::mojom::NetworkingAttributes>(),
     MakeInterfaceVersionEntry<crosapi::mojom::NetworkingPrivate>(),
     MakeInterfaceVersionEntry<crosapi::mojom::NetworkSettingsService>(),
diff --git a/chrome/browser/ash/crosapi/network_change_ash.cc b/chrome/browser/ash/crosapi/network_change_ash.cc
new file mode 100644
index 0000000..9908587
--- /dev/null
+++ b/chrome/browser/ash/crosapi/network_change_ash.cc
@@ -0,0 +1,27 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/network_change_ash.h"
+
+#include "chrome/browser/ash/network_change_manager_client.h"
+
+namespace crosapi {
+
+NetworkChangeAsh::NetworkChangeAsh() = default;
+NetworkChangeAsh::~NetworkChangeAsh() = default;
+
+void NetworkChangeAsh::BindReceiver(
+    mojo::PendingReceiver<mojom::NetworkChange> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void NetworkChangeAsh::AddObserver(
+    mojo::PendingRemote<crosapi::mojom::NetworkChangeObserver> observer) {
+  auto* client = ash::NetworkChangeManagerClient::GetInstance();
+  // NetworkChangeManagerClient might be not set for testing.
+  if (client)
+    client->AddLacrosNetworkChangeObserver(std::move(observer));
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/network_change_ash.h b/chrome/browser/ash/crosapi/network_change_ash.h
new file mode 100644
index 0000000..baec780
--- /dev/null
+++ b/chrome/browser/ash/crosapi/network_change_ash.h
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_NETWORK_CHANGE_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_NETWORK_CHANGE_ASH_H_
+
+#include "chromeos/crosapi/mojom/network_change.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace crosapi {
+
+// Ash-side implementation of NetworkChange interface.
+class NetworkChangeAsh : public mojom::NetworkChange {
+ public:
+  NetworkChangeAsh();
+  NetworkChangeAsh(const NetworkChangeAsh&) = delete;
+  NetworkChangeAsh& operator=(const NetworkChangeAsh&) = delete;
+  ~NetworkChangeAsh() override;
+
+  void BindReceiver(mojo::PendingReceiver<mojom::NetworkChange> receiver);
+
+  // crosapi::mojom::NetworkChange:
+  void AddObserver(mojo::PendingRemote<crosapi::mojom::NetworkChangeObserver>
+                       manager) override;
+
+ private:
+  // This class supports any number of connections.
+  mojo::ReceiverSet<mojom::NetworkChange> receivers_;
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_NETWORK_CHANGE_ASH_H_
diff --git a/chrome/browser/ash/network_change_manager_client.cc b/chrome/browser/ash/network_change_manager_client.cc
index b89eeef..d41b0b52 100644
--- a/chrome/browser/ash/network_change_manager_client.cc
+++ b/chrome/browser/ash/network_change_manager_client.cc
@@ -7,20 +7,27 @@
 #include "base/bind.h"
 #include "chromeos/ash/components/network/network_event_log.h"
 #include "chromeos/ash/components/network/network_state.h"
+#include "chromeos/crosapi/mojom/network_change.mojom.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/common/network_service_util.h"
-#include "net/base/network_change_notifier.h"
 #include "net/base/network_change_notifier_posix.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 
 namespace ash {
 
+namespace {
+NetworkChangeManagerClient* g_network_change_manager_client = nullptr;
+}
+
 NetworkChangeManagerClient::NetworkChangeManagerClient(
     net::NetworkChangeNotifierPosix* network_change_notifier)
     : connection_type_(net::NetworkChangeNotifier::GetConnectionType()),
       connection_subtype_(net::NetworkChangeNotifier::GetConnectionSubtype()),
       network_change_notifier_(network_change_notifier) {
+  DCHECK(!g_network_change_manager_client);
+  g_network_change_manager_client = this;
+
   PowerManagerClient::Get()->AddObserver(this);
 
   network_state_handler_observer_.Observe(
@@ -36,6 +43,13 @@
 
 NetworkChangeManagerClient::~NetworkChangeManagerClient() {
   PowerManagerClient::Get()->RemoveObserver(this);
+  DCHECK_EQ(g_network_change_manager_client, this);
+  g_network_change_manager_client = nullptr;
+}
+
+// static
+NetworkChangeManagerClient* NetworkChangeManagerClient::GetInstance() {
+  return g_network_change_manager_client;
 }
 
 void NetworkChangeManagerClient::SuspendDone(base::TimeDelta sleep_duration) {
@@ -64,6 +78,22 @@
                   connection_subtype_);
 }
 
+void NetworkChangeManagerClient::AddLacrosNetworkChangeObserver(
+    mojo::PendingRemote<crosapi::mojom::NetworkChangeObserver> observer) {
+  mojo::Remote<crosapi::mojom::NetworkChangeObserver> remote(
+      std::move(observer));
+
+  // Tell the observer what the current connection type is.
+  remote->OnNetworkChanged(
+      /*dns_changed=*/false, /*ip_address_changed=*/false,
+      /*connection_type_changed=*/true,
+      crosapi::mojom::ConnectionType(connection_type_),
+      /*connection_subtype_changed=*/true,
+      crosapi::mojom::ConnectionSubtype(connection_subtype_));
+
+  lacros_network_change_observers_.Add(std::move(remote));
+}
+
 void NetworkChangeManagerClient::ConnectToNetworkChangeManager() {
   if (network_change_manager_.is_bound())
     network_change_manager_.reset();
@@ -209,7 +239,17 @@
         connection_subtype_changed,
         network::mojom::ConnectionSubtype(connection_subtype));
   }
+
+  // Notify NetworkChangeObserver in Lacros if exists.
+  for (auto& observer : lacros_network_change_observers_) {
+    observer->OnNetworkChanged(
+        dns_changed, ip_address_changed, connection_type_changed,
+        crosapi::mojom::ConnectionType(connection_type),
+        connection_subtype_changed,
+        crosapi::mojom::ConnectionSubtype(connection_subtype));
+  }
 }
+
 // static
 net::NetworkChangeNotifier::ConnectionType
 NetworkChangeManagerClient::ConnectionTypeFromShill(
diff --git a/chrome/browser/ash/network_change_manager_client.h b/chrome/browser/ash/network_change_manager_client.h
index 4acf510..ac6cd49 100644
--- a/chrome/browser/ash/network_change_manager_client.h
+++ b/chrome/browser/ash/network_change_manager_client.h
@@ -13,9 +13,14 @@
 #include "chromeos/ash/components/network/network_state_handler_observer.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/mojom/network_change_manager.mojom.h"
 
+namespace crosapi::mojom {
+class NetworkChangeObserver;
+}
+
 namespace net {
 class NetworkChangeNotifierPosix;
 }
@@ -38,6 +43,9 @@
 
   ~NetworkChangeManagerClient() override;
 
+  // Returns NetworkChangeManagerClient instance.
+  static NetworkChangeManagerClient* GetInstance();
+
   // PowerManagerClient::Observer overrides.
   void SuspendDone(base::TimeDelta sleep_duration) override;
 
@@ -45,6 +53,10 @@
   void DefaultNetworkChanged(
       const chromeos::NetworkState* default_network) override;
 
+  // Adds Lacros NetworkChangeObserver.
+  void AddLacrosNetworkChangeObserver(
+      mojo::PendingRemote<crosapi::mojom::NetworkChangeObserver> observer);
+
  private:
   friend class NetworkChangeManagerClientUpdateTest;
   FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest,
@@ -109,6 +121,8 @@
 
   net::NetworkChangeNotifierPosix* network_change_notifier_;
   mojo::Remote<network::mojom::NetworkChangeManager> network_change_manager_;
+  mojo::RemoteSet<crosapi::mojom::NetworkChangeObserver>
+      lacros_network_change_observers_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/note_taking_helper.cc b/chrome/browser/ash/note_taking_helper.cc
index 0e45e36..33a9ff4 100644
--- a/chrome/browser/ash/note_taking_helper.cc
+++ b/chrome/browser/ash/note_taking_helper.cc
@@ -49,9 +49,11 @@
 #include "chrome/common/pref_names.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/prefs/pref_service.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/features.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/types_util.h"
@@ -217,8 +219,13 @@
         ConvertIntentToMojomIntent(apps_util::CreateCreateNoteIntent()),
         apps::mojom::LaunchSource::kFromShelf);
   } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-        app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromShelf);
+    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+      apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+          app_id, ui::EF_NONE, apps::LaunchSource::kFromShelf);
+    } else {
+      apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+          app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromShelf);
+    }
   }
 
   return NoteTakingHelper::LaunchResult::WEB_APP_SUCCESS;
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
index 63cc7bd..16939d2 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/os_feedback/os_feedback_screenshot_manager.h"
@@ -239,6 +240,18 @@
 }
 
 void ChromeOsFeedbackDelegate::OpenMetricsDialog() {
+  OpenWebDialog(GURL(chrome::kChromeUIHistogramsURL));
+}
+
+void ChromeOsFeedbackDelegate::OpenSystemInfoDialog() {
+  // TODO(http://b/239701119): Make the sys_info.html page a separate WebUI.
+  // For now, use the old Feedback tool's sys_info.html.
+  GURL systemInfoUrl =
+      GURL(base::StrCat({chrome::kChromeUIFeedbackURL, "html/sys_info.html"}));
+  OpenWebDialog(systemInfoUrl);
+}
+
+void ChromeOsFeedbackDelegate::OpenWebDialog(GURL url) {
   Browser* feedback_browser = ash::FindSystemWebAppBrowser(
       profile_, ash::SystemWebAppType::OS_FEEDBACK);
 
@@ -247,7 +260,7 @@
   views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
 
   ChildWebDialog* child_dialog = new ChildWebDialog(
-      profile_, widget, GURL(chrome::kChromeUIHistogramsURL),
+      profile_, widget, url,
       /*title=*/std::u16string(),
       /*modal_type=*/ui::MODAL_TYPE_NONE, /*dialog_width=*/640,
       /*dialog_height=*/400, /*can_resize=*/true,
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
index 5fc4251..0661663 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
@@ -44,9 +44,11 @@
   void OpenDiagnosticsApp() override;
   void OpenExploreApp() override;
   void OpenMetricsDialog() override;
+  void OpenSystemInfoDialog() override;
 
  private:
   void OnSendFeedbackDone(SendReportCallback callback, bool status);
+  void OpenWebDialog(GURL url);
 
   // TODO(xiangdongkong): make sure the profile_ cannot be destroyed while
   // operations are pending.
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
index 00fd0e77..121e9b8 100644
--- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
+++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
@@ -122,6 +122,34 @@
     EXPECT_EQ(SendReportStatus::kSuccess, future.Get());
   }
 
+  Browser* LaunchFeedbackAppAndGetBrowser() {
+    // Install system apps, namely the Feedback App.
+    ash::SystemWebAppManager::GetForTest(browser()->profile())
+        ->InstallSystemAppsForTesting();
+
+    GURL feedback_url_ = GURL(ash::kChromeUIOSFeedbackUrl);
+
+    // Initialize NavigationObserver to start watching for navigation events.
+    // NavigationObserver is necessary to avoid crash on opening dialog,
+    // because we need to wait for the Feedback app to finish launching
+    // before opening the metrics dialog.
+    content::TestNavigationObserver navigation_observer(feedback_url_);
+    navigation_observer.StartWatchingNewWebContents();
+
+    // Launch the feedback app.
+    ui_test_utils::SendToOmniboxAndSubmit(browser(), feedback_url_.spec());
+
+    // Wait for the Feedback app to launch.
+    navigation_observer.Wait();
+
+    Browser* feedback_browser = ash::FindSystemWebAppBrowser(
+        browser()->profile(), ash::SystemWebAppType::OS_FEEDBACK);
+
+    EXPECT_NE(feedback_browser, nullptr);
+
+    return feedback_browser;
+  }
+
   scoped_refptr<base::RefCountedMemory> CreateFakePngData() {
     const unsigned char kData[] = {12, 11, 99};
     return base::MakeRefCounted<base::RefCountedBytes>(kData, std::size(kData));
@@ -320,29 +348,7 @@
 // Test that the Metrics (Histograms) dialog opens
 // when OpenMetricsDialog is invoked.
 IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, OpenMetricsDialog) {
-  // Install system apps, namely the Feedback App.
-  ash::SystemWebAppManager::GetForTest(browser()->profile())
-      ->InstallSystemAppsForTesting();
-
-  GURL feedback_url_ = GURL(ash::kChromeUIOSFeedbackUrl);
-
-  // Initialize NavigationObserver to start watching for navigation events.
-  // NavigationObserver is necessary to avoid crash on opening dialog,
-  // because we need to wait for the Feedback app to finish launching
-  // before opening the metrics dialog.
-  content::TestNavigationObserver navigation_observer(feedback_url_);
-  navigation_observer.StartWatchingNewWebContents();
-
-  // Launch the feedback app.
-  ui_test_utils::SendToOmniboxAndSubmit(browser(), feedback_url_.spec());
-
-  // Wait for the Feedback app to launch.
-  navigation_observer.Wait();
-
-  Browser* feedback_browser = ash::FindSystemWebAppBrowser(
-      browser()->profile(), ash::SystemWebAppType::OS_FEEDBACK);
-
-  EXPECT_NE(feedback_browser, nullptr);
+  Browser* feedback_browser = LaunchFeedbackAppAndGetBrowser();
 
   gfx::NativeWindow feedback_window =
       feedback_browser->window()->GetNativeWindow();
@@ -364,4 +370,29 @@
   EXPECT_EQ(owned_widgets_post_dialog.size(), 1);
 }
 
+// Test that the SystemInfo (Histograms) dialog opens
+// when OpenSystemInfoDialog is invoked.
+IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, OpenSystemInfoDialog) {
+  Browser* feedback_browser = LaunchFeedbackAppAndGetBrowser();
+
+  gfx::NativeWindow feedback_window =
+      feedback_browser->window()->GetNativeWindow();
+
+  std::set<views::Widget*> owned_widgets_pre_dialog;
+  views::Widget::GetAllOwnedWidgets(feedback_window, &owned_widgets_pre_dialog);
+
+  EXPECT_EQ(owned_widgets_pre_dialog.size(), 0);
+
+  // Initialize the delegate.
+  ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile());
+
+  feedback_delegate_.OpenSystemInfoDialog();
+
+  std::set<views::Widget*> owned_widgets_post_dialog;
+  views::Widget::GetAllOwnedWidgets(feedback_window,
+                                    &owned_widgets_post_dialog);
+
+  EXPECT_EQ(owned_widgets_post_dialog.size(), 1);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
index e5f5a16..b35e41c 100644
--- a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
+++ b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
@@ -1530,14 +1530,12 @@
   // Start the platform app, causing it to open a window.
   run_loop_ = std::make_unique<base::RunLoop>();
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
-  proxy->FlushMojoCallsForTesting();
   proxy->Launch(app->id(),
                 apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
                                     false /* preferred_containner */),
-                apps::mojom::LaunchSource::kFromChromeInternal,
-                apps::MakeWindowInfo(
+                apps::LaunchSource::kFromChromeInternal,
+                std::make_unique<apps::WindowInfo>(
                     display::Screen::GetScreen()->GetPrimaryDisplay().id()));
-  proxy->FlushMojoCallsForTesting();
   run_loop_->Run();
   EXPECT_EQ(1U, app_window_registry->app_windows().size());
 
diff --git a/chrome/browser/ash/system_web_apps/BUILD.gn b/chrome/browser/ash/system_web_apps/BUILD.gn
index 228ce159..5629d9c 100644
--- a/chrome/browser/ash/system_web_apps/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/BUILD.gn
@@ -8,6 +8,7 @@
 
 source_set("system_web_apps") {
   sources = [
+    "chrome_system_web_app_ui_config.cc",
     "system_web_app_background_task.cc",
     "system_web_app_background_task.h",
     "system_web_app_manager.cc",
@@ -31,6 +32,7 @@
     "//ash/webui/personalization_app",
     "//ash/webui/shimless_rma",
     "//ash/webui/shortcut_customization_ui",
+    "//ash/webui/system_apps/public:system_web_app_config",
     "//base",
     "//chrome/browser:browser_process",
     "//chrome/browser/ash/system_web_apps/types",
diff --git a/chrome/browser/ash/system_web_apps/chrome_system_web_app_ui_config.cc b/chrome/browser/ash/system_web_apps/chrome_system_web_app_ui_config.cc
new file mode 100644
index 0000000..b83fa15
--- /dev/null
+++ b/chrome/browser/ash/system_web_apps/chrome_system_web_app_ui_config.cc
@@ -0,0 +1,18 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/webui/system_apps/public/system_web_app_ui_config.h"
+#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
+
+namespace ash::internal {
+bool BaseSystemWebAppUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  auto* swa_manager = ash::SystemWebAppManager::Get(
+      Profile::FromBrowserContext(browser_context));
+  if (!swa_manager)
+    return false;
+
+  return swa_manager->IsAppEnabled(swa_type_);
+}
+}  // namespace ash::internal
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
index fbdbf58..f3f4120 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
@@ -219,26 +219,27 @@
           std::string(kInstallResultHistogramName) + ".Profiles." +
           web_app::GetProfileCategoryForLogging(profile)),
       pref_service_(profile_->GetPrefs()) {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
-    // Always update in tests.
-    update_policy_ = UpdatePolicy::kAlwaysUpdate;
-
-    // Populate with real system apps if the test asks for it.
-    if (base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps))
-      system_app_delegates_ = CreateSystemWebApps(profile_);
-
-    return;
-  }
+  // Always create delegates because many System Web App WebUIs are disabled
+  // when the delegate is not present and we need them in tests. Tests can
+  // override the list of delegates with SetSystemAppsForTesting().
+  system_app_delegates_ = CreateSystemWebApps(profile_);
 
 #if defined(OFFICIAL_BUILD)
-  // Official builds should trigger updates whenever the version number changes.
-  update_policy_ = UpdatePolicy::kOnVersionChange;
+  const bool is_official = true;
 #else
-  // Dev builds should update every launch.
-  update_policy_ = UpdatePolicy::kAlwaysUpdate;
+  const bool is_official = false;
 #endif
+  const bool is_test =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType);
 
-  system_app_delegates_ = CreateSystemWebApps(profile_);
+  if (is_test || !is_official) {
+    // Tests and non-official builds should always update.
+    update_policy_ = UpdatePolicy::kAlwaysUpdate;
+  } else {
+    // Official builds should trigger updates whenever the version number
+    // changes.
+    update_policy_ = UpdatePolicy::kOnVersionChange;
+  }
 }
 
 SystemWebAppManager::~SystemWebAppManager() {
@@ -400,6 +401,13 @@
     return;
   }
 
+  // In tests, only install System Web Apps if `InstallSystemAppsForTesting()`
+  // or `SetSystemAppsForTesting()` has been called.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType) &&
+      skip_app_installation_in_test_) {
+    install_options_list.clear();
+  }
+
   externally_managed_app_manager_->SynchronizeInstalledApps(
       std::move(install_options_list),
       web_app::ExternalInstallSource::kSystemInstalled,
@@ -415,7 +423,7 @@
 void SystemWebAppManager::InstallSystemAppsForTesting() {
   on_apps_synchronized_ = std::make_unique<base::OneShotEvent>();
   on_tasks_started_ = std::make_unique<base::OneShotEvent>();
-  system_app_delegates_ = CreateSystemWebApps(profile_);
+  skip_app_installation_in_test_ = false;
   Start();
 
   // Wait for the System Web Apps to install.
@@ -546,6 +554,7 @@
 
 void SystemWebAppManager::SetSystemAppsForTesting(
     SystemWebAppDelegateMap system_apps) {
+  skip_app_installation_in_test_ = false;
   system_app_delegates_ = std::move(system_apps);
 }
 
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager.h b/chrome/browser/ash/system_web_apps/system_web_app_manager.h
index 240c180..b67ea8d 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager.h
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager.h
@@ -247,6 +247,11 @@
 
   UpdatePolicy update_policy_;
 
+  // We skip app installation in tests by default. Tests can trigger
+  // installation by calling `InstallSystemAppsForTesting()` or
+  // `SetSystemAppsForTesting()`.
+  bool skip_app_installation_in_test_ = true;
+
   SystemWebAppDelegateMap system_app_delegates_;
 
   const raw_ptr<PrefService> pref_service_;
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
index 71585bba..1782db8 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
@@ -1139,16 +1139,6 @@
   }
   ~SystemWebAppManagerInstallAllAppsBrowserTest() override = default;
 
-  // Don't use WaitForTestSystemAppInstall in this test, because it artificially
-  // resets the OnAppsSynchronized signal, and starts a new synchronize request.
-  void WaitForSystemAppsSynchronized() {
-    base::RunLoop run_loop;
-    SystemWebAppManager::Get(browser()->profile())
-        ->on_apps_synchronized()
-        .Post(FROM_HERE, run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
  private:
   base::test::ScopedFeatureList features_;
 };
@@ -1163,7 +1153,7 @@
                        BasicConsistencyCheck) {
   // Wait for apps to install before performing assertions, otherwise the test
   // might flake. See https://crbug.com/1286600#c6.
-  WaitForSystemAppsSynchronized();
+  GetManager().InstallSystemAppsForTesting();
 
   const auto& app_map = GetManager().system_app_delegates();
   ASSERT_GT(app_map.size(), 0U);
@@ -1237,13 +1227,13 @@
 
 IN_PROC_BROWSER_TEST_P(SystemWebAppManagerInstallAllAppsBrowserTest,
                        PRE_Upgrade) {
-  WaitForSystemAppsSynchronized();
+  GetManager().InstallSystemAppsForTesting();
   EXPECT_GE(GetManager().system_app_delegates().size(),
             GetManager().GetAppIds().size());
 }
 
 IN_PROC_BROWSER_TEST_P(SystemWebAppManagerInstallAllAppsBrowserTest, Upgrade) {
-  WaitForSystemAppsSynchronized();
+  GetManager().InstallSystemAppsForTesting();
   const auto& app_ids = GetManager().GetAppIds();
 
   EXPECT_EQ(GetManager().system_app_delegates().size(), app_ids.size());
diff --git a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
index 10f5815..2788b2d 100644
--- a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
+++ b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
@@ -48,10 +48,6 @@
   if (maybe_installation_) {
     maybe_installation_->WaitForAppInstall();
   } else {
-    // Avoid recreating system apps in tests since AppBrowserController keeps a
-    // reference to SystemWebAppDelegates.
-    if (!GetManager().system_app_delegates().empty())
-      return;
     GetManager().InstallSystemAppsForTesting();
   }
 
diff --git a/chrome/browser/ash/system_web_apps/types/BUILD.gn b/chrome/browser/ash/system_web_apps/types/BUILD.gn
index c3781e5..349d8d7 100644
--- a/chrome/browser/ash/system_web_apps/types/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/types/BUILD.gn
@@ -35,4 +35,10 @@
     "//ui/base",
     "//url",
   ]
+
+  public_deps = [
+    # TODO(crbug.com/1321984): Move to deps when users of system_web_app_type.
+    # are migrated to include the new location.
+    "//ash/webui/system_apps/public:system_web_app_type",
+  ]
 }
diff --git a/chrome/browser/ash/system_web_apps/types/system_web_app_type.h b/chrome/browser/ash/system_web_apps/types/system_web_app_type.h
index 4ad2cde..2c8400e5 100644
--- a/chrome/browser/ash/system_web_apps/types/system_web_app_type.h
+++ b/chrome/browser/ash/system_web_apps/types/system_web_app_type.h
@@ -5,141 +5,9 @@
 #ifndef CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TYPES_SYSTEM_WEB_APP_TYPE_H_
 #define CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TYPES_SYSTEM_WEB_APP_TYPE_H_
 
-namespace ash {
+#include "ash/webui/system_apps/public/system_web_app_type.h"
 
-// An enum that lists the different System Apps that exist. Can be used to
-// retrieve the App ID from the underlying Web App system.
-//
-// These values are persisted to the web_app database. Entries should not be
-// renumbered and numeric values should never be reused.
-//
-// When deprecating, comment out the entry so that it's not accidentally
-// re-used.
-enum class SystemWebAppType {
-  FILE_MANAGER = 1,
-  // TELEMETRY_DEPRECATED = 2,
-
-  // A sample System Web App to illustrate SWA development best practices, and
-  // various SWA platform features.
-  //
-  // This App is only enabled on non-official builds. You can find a brief SWA
-  // platform introduction (Google internal) at: http://go/system-web-apps.
-  //
-  // Source: //ash/webui/sample_system_web_app_ui/
-  // Contact: dominicshulz@google.com, ortuno@chromium.org
-  SAMPLE = 3,
-
-  SETTINGS = 4,
-  CAMERA = 5,
-  TERMINAL = 6,
-  MEDIA = 7,
-  HELP = 8,
-  PRINT_MANAGEMENT = 9,
-  SCANNING = 10,
-  DIAGNOSTICS = 11,
-  CONNECTIVITY_DIAGNOSTICS = 12,
-  ECHE = 13,
-  CROSH = 14,
-  PERSONALIZATION = 15,
-  SHORTCUT_CUSTOMIZATION = 16,
-
-  // SHIMLESS RMA Flow is SWA that provides step by step guides for the
-  // repair/RMA process.
-  //
-  // You can find information about this SWA at: http://go/shimless-ux.
-  //
-  // Source: //ash/webui/shimless_rma/
-  // Contact: cros-peripherals@google.com
-  SHIMLESS_RMA = 17,
-
-  // A System Web App that launches on Demo Mode startup, to display animated
-  // content that highlights various features of ChromeOS
-  //
-  // Currently this SWA is only enabled in unofficial builds while still under
-  // development. Prefer to file bugs to the internal Demo Mode component:
-  // b/components/812312
-  //
-  // Source: //ash/webui/demo_mode_app_ui/
-  // Contact: jacksontadie@google.com, drcrash@chromium.org
-  DEMO_MODE = 18,
-
-  // OS FEEDBACK is a SWA that provides step by step guides to submit a
-  // feedback report on Chrome OS.
-  //
-  // Source: //ash/webui/os_feedback_ui
-  // contact: cros-telemetry@google.com
-  OS_FEEDBACK = 19,
-
-  // Projector aka Screencast (go/projector-player-dd) aims to make it simple
-  // for teachers and students to record and share instructional videos on a
-  // Chromebook. This app enables teachers to create a library of
-  // custom-tailored instructional content that students can search and view at
-  // home.
-  //
-  // Source: //ash/webui/projector_app/
-  // Contact: cros-projector@google.com
-  // Buganizer component: b/components/1080013
-  // This app is only included in Chrome-branded builds. Non-official builds
-  // will have a mock page.
-  PROJECTOR = 20,
-
-  // OsUrlHandler is called by Lacros to show Ash internal chrome:// pages as
-  // applications to the user. Note that these pages are accessible to the user
-  // as os://<page> through search.
-  // contact: skuhne@google.com
-  OS_URL_HANDLER = 21,
-
-  // FIRMWARE UPDATE App is SWA that lets users update all their peripheral
-  // firmwares in one place.
-  // You can find information about this SWA at: http://go/fwupd-app.
-  // Source: //ash/webui/firmware_update/
-  // Contact: cros-peripherals@google.com
-  FIRMWARE_UPDATE = 22,
-
-  // OsFlags is called by Lacros to show the chrome://flags page as
-  // applications to the user. Note that this page is accessible to the user
-  // as os://flags through search.
-  // contact: skuhne@google.com
-  OS_FLAGS = 23,
-
-  // When adding a new System App, remember to:
-  //
-  // 1. Add a corresponding histogram suffix in WebAppSystemAppInternalName
-  //    (histograms.xml). The suffix name should match the App's
-  //    |internal_name|. This is for reporting per-app install results.
-  //
-  // 2. Add a corresponding proto enum entry (with the same numerical value) to
-  //    SystemWebAppDataProto in system_web_app_data.proto. This is for
-  //    identifying system apps during Chrome start-up (i.e. when
-  //    SystemWebAppManager hasn't finished synchronizing all apps).
-  //
-  // 3. Add a comment above the enum entry in this file. It should include a
-  //    description (what it does in one sentence), at least one email contact,
-  //    source location (if it's in chromium source tree), and other relevant
-  //    information.
-  //
-  //    Other relevant information should come in separate paragraphs after the
-  //    description. This can be anything useful for triaging or routing bugs.
-  //    For example, your team doesn't use chromium's bug tracker, the App is
-  //    only available on certain devices.
-  //
-  //    Source location should point to where the App's WebUIController is
-  //    defined. It doesn't have to include the complete source repository (e.g.
-  //    if the App is hosted in internal repositories).
-  //
-  // 4. Put a blank line after each enum (before next enum's comment).
-  //
-  // 5. Use ash::LaunchSystemWebAppAsync to launch your SWA (with the type
-  //    added above). This provides extra safety in edge cases (e.g. when in
-  //    incognito or guest sessions).
-  //
-  // 6. Update kMaxValue.
-  //
-  // 7. Have one of System Web App Platform owners review the CL.
-  //    See: //ash/webui/PLATFORM_OWNERS
-  kMaxValue = OS_FLAGS,
-};
-
-}  // namespace ash
+// TODO(crbug.com/1321984): Files that includes this file to the new location
+// once the new location is decided.
 
 #endif  // CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TYPES_SYSTEM_WEB_APP_TYPE_H_
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc
index c2d99c7..a7b5435 100644
--- a/chrome/browser/autocomplete/autocomplete_browsertest.cc
+++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -149,7 +149,7 @@
         u"chrome", metrics::OmniboxEventProto::NTP,
         ChromeAutocompleteSchemeClassifier(browser()->profile()));
     input.set_prevent_inline_autocomplete(true);
-    input.set_want_asynchronous_matches(false);
+    input.set_omit_asynchronous_matches(true);
     autocomplete_controller->Start(input);
 
     EXPECT_TRUE(autocomplete_controller->done());
diff --git a/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc b/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc
index c14f1c1..2e236e8 100644
--- a/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc
+++ b/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc
@@ -73,7 +73,8 @@
     const std::u16string& remaining_input) {
   DCHECK(template_url);
 
-  if (input.want_asynchronous_matches()) {
+  bool want_asynchronous_matches = !input.omit_asynchronous_matches();
+  if (want_asynchronous_matches) {
     std::string extension_id = template_url->GetExtensionId();
     if (extension_id != current_keyword_extension_id_)
       MaybeEndExtensionKeywordMode();
@@ -92,7 +93,7 @@
       matches()->push_back(extension_suggest_matches_[i]);
       matches()->back().relevance = matches()->front().relevance - (i + 1);
     }
-  } else if (input.want_asynchronous_matches()) {
+  } else if (want_asynchronous_matches) {
     extension_suggest_last_input_ = input;
     extension_suggest_matches_.clear();
 
@@ -103,7 +104,7 @@
             base::UTF16ToUTF8(remaining_input), current_input_id_))
       set_done(false);
   }
-  return input.want_asynchronous_matches();
+  return want_asynchronous_matches;
 }
 
 void KeywordExtensionsDelegateImpl::EnterExtensionKeywordMode(
diff --git a/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc b/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc
index 88ae10b3..23f65167 100644
--- a/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_navigation_throttle.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/browser_switcher/browser_switcher_service.h"
 #include "chrome/browser/browser_switcher/browser_switcher_service_factory.h"
 #include "chrome/browser/browser_switcher/browser_switcher_sitelist.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/navigation_interception/intercept_navigation_throttle.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index b5d2fccc..1f020ea 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -56,12 +56,12 @@
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/permissions/permission_actions_history_factory.h"
 #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_service.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_service_factory.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.cc
index a1c4ba52..975ba6c 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/web_history_service_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 186ba4c..942a164 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -23,8 +23,8 @@
 #include "chrome/browser/navigation_predictor/navigation_predictor.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/predictors/network_hints_handler_impl.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8ca7aa7..d4afb0f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -86,9 +86,6 @@
 #include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
 #include "chrome/browser/plugins/plugin_utils.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
 #include "chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h"
 #include "chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.h"
@@ -100,6 +97,9 @@
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader.h"
 #include "chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader_interceptor.h"
 #include "chrome/browser/preloading/navigation_ablation_throttle.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
 #include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 39393eff..b932474c 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2731,6 +2731,7 @@
     "../ash/arc/app_shortcuts/arc_app_shortcuts_request_unittest.cc",
     "../ash/arc/arc_demo_mode_delegate_impl_unittest.cc",
     "../ash/arc/arc_migration_guide_notification_unittest.cc",
+    "../ash/arc/arc_mount_provider_unittest.cc",
     "../ash/arc/arc_support_host_unittest.cc",
     "../ash/arc/arc_ui_availability_reporter_unittest.cc",
     "../ash/arc/arc_util_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 9adcf5b..72d48cc 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -4589,7 +4589,7 @@
 // AutotestPrivateInstallPWAForCurrentURL
 ///////////////////////////////////////////////////////////////////////////////
 
-// Used to notify when when a certain URL contains a WPA.
+// Used to notify when when a certain URL contains a PWA.
 class AutotestPrivateInstallPWAForCurrentURLFunction::PWABannerObserver
     : public webapps::AppBannerManager::Observer {
  public:
@@ -4646,7 +4646,7 @@
   webapps::AppBannerManager* app_banner_manager_;
 };
 
-// Used to notify when a WPA is installed.
+// Used to notify when a PWA is installed.
 class AutotestPrivateInstallPWAForCurrentURLFunction::PWAInstallManagerObserver
     : public web_app::WebAppInstallManagerObserver {
  public:
@@ -4654,8 +4654,9 @@
       Profile* profile,
       base::OnceCallback<void(const web_app::AppId&)> callback)
       : callback_(std::move(callback)) {
-    observation_.Observe(
-        &web_app::WebAppProvider::GetForTest(profile)->install_manager());
+    auto* provider = web_app::WebAppProvider::GetForWebApps(profile);
+    if (provider)
+      observation_.Observe(&provider->install_manager());
   }
 
   PWAInstallManagerObserver(const PWAInstallManagerObserver&) = delete;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index 2dfc2c7..1d35cbe 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -649,14 +649,26 @@
     return RespondNow(
         Error("GetSizeStats: volume with ID * not found", params->volume_id));
 
-  // For fusebox volumes, get the underlying (aka original) volume.
+  // For fusebox volumes, get the underlying (aka regular) volume.
   const auto fusebox = base::StringPiece(file_manager::util::kFuseBox);
   if (base::StartsWith(volume->file_system_type(), fusebox)) {
-    auto volume_id = params->volume_id.substr(fusebox.length());
+    std::string volume_id = params->volume_id;
+
+    if (volume->type() == file_manager::VOLUME_TYPE_MTP) {
+      volume_id = volume_id.substr(fusebox.length());
+    } else if (volume->type() == file_manager::VOLUME_TYPE_PROVIDED) {
+      // NB: FileManagerPrivate.GetSizeStats is not called by files app JS
+      // because regular PROVIDED volumes do not support size stats.
+      volume_manager->ConvertFuseBoxFSPVolumeIdToFSPIfNeeded(&volume_id);
+    } else {
+      // TODO(crbug.com/1292825): add VOLUME_TYPE_DOCUMENTS_PROVIDER.
+    }
+
     volume = volume_manager->FindVolumeById(volume_id);
-    if (!volume.get())
+    if (!volume.get()) {
       return RespondNow(
           Error("GetSizeStats: volume with ID * not found", volume_id));
+    }
   }
 
   if (volume->type() == file_manager::VOLUME_TYPE_MTP) {
diff --git a/chrome/browser/download/bubble/download_bubble_controller.h b/chrome/browser/download/bubble/download_bubble_controller.h
index ae08ecd..e563f747 100644
--- a/chrome/browser/download/bubble/download_bubble_controller.h
+++ b/chrome/browser/download/bubble/download_bubble_controller.h
@@ -91,7 +91,7 @@
 
   // Returns the DownloadDisplayController. Should always return a valid
   // controller.
-  DownloadDisplayController* display_controller_for_testing() {
+  DownloadDisplayController* GetDownloadDisplayController() {
     return display_controller_;
   }
 
diff --git a/chrome/browser/download/bubble/download_bubble_controller_unittest.cc b/chrome/browser/download/bubble/download_bubble_controller_unittest.cc
index bd19654c..b710c714 100644
--- a/chrome/browser/download/bubble/download_bubble_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_controller_unittest.cc
@@ -44,9 +44,9 @@
 
 class MockDownloadDisplayController : public DownloadDisplayController {
  public:
-  MockDownloadDisplayController(Profile* profile,
+  MockDownloadDisplayController(Browser* browser,
                                 DownloadBubbleUIController* bubble_controller)
-      : DownloadDisplayController(nullptr, profile, bubble_controller) {}
+      : DownloadDisplayController(nullptr, browser, bubble_controller) {}
   void MaybeShowButtonWhenCreated() override {}
   MOCK_METHOD1(OnNewItem, void(bool));
   MOCK_METHOD2(OnUpdatedItem, void(bool, bool));
@@ -110,7 +110,7 @@
     controller_ = std::make_unique<DownloadBubbleUIController>(browser_.get());
     display_controller_ =
         std::make_unique<NiceMock<MockDownloadDisplayController>>(
-            profile_, controller_.get());
+            browser_.get(), controller_.get());
     controller_->set_manager_for_testing(manager_);
   }
 
@@ -382,7 +382,7 @@
         std::make_unique<DownloadBubbleUIController>(incognito_browser_.get());
     incognito_display_controller_ =
         std::make_unique<NiceMock<MockDownloadDisplayController>>(
-            incognito_profile_, incognito_controller_.get());
+            incognito_browser_.get(), incognito_controller_.get());
   }
 
   void TearDown() override {
diff --git a/chrome/browser/download/bubble/download_display_controller.cc b/chrome/browser/download/bubble/download_display_controller.cc
index 239acabd..8a25d6f 100644
--- a/chrome/browser/download/bubble/download_display_controller.cc
+++ b/chrome/browser/download/bubble/download_display_controller.cc
@@ -11,7 +11,12 @@
 #include "chrome/browser/download/bubble/download_icon_state.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/download/download_item_mode.h"
+#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h"
+#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
+#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
 #include "components/offline_items_collection/core/offline_item.h"
 #include "components/offline_items_collection/core/offline_item_state.h"
 
@@ -24,7 +29,8 @@
 constexpr base::TimeDelta kToolbarIconVisibilityTimeInterval = base::Hours(24);
 
 // The amount of time for the toolbar icon to stay active after a download is
-// completed.
+// completed. If the download completed while full screen, the timer is started
+// after user comes out of the full screen.
 constexpr base::TimeDelta kToolbarIconActiveTimeInterval = base::Minutes(1);
 
 // From the button UI's perspective, whether the download is considered in
@@ -42,14 +48,37 @@
   return model->GetState() == download::DownloadItem::IN_PROGRESS;
 }
 
+bool HasDeepScanningDownload(
+    std::vector<std::unique_ptr<DownloadUIModel>>& all_models) {
+  for (const auto& model : all_models) {
+    if (model->GetDangerType() ==
+            download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING &&
+        model->GetState() != download::DownloadItem::CANCELLED) {
+      return true;
+    }
+  }
+  return false;
+}
+
+int InProgressDownloadCount(
+    std::vector<std::unique_ptr<DownloadUIModel>>& all_models) {
+  int in_progress_count = 0;
+  for (const auto& model : all_models) {
+    if (IsModelInProgress(model.get())) {
+      in_progress_count++;
+    }
+  }
+  return in_progress_count;
+}
 }  // namespace
 
 DownloadDisplayController::DownloadDisplayController(
     DownloadDisplay* display,
-    Profile* profile,
+    Browser* browser,
     DownloadBubbleUIController* bubble_controller)
     : display_(display),
-      download_manager_(profile->GetDownloadManager()),
+      browser_(browser),
+      download_manager_(browser_->profile()->GetDownloadManager()),
       download_notifier_(download_manager_, this),
       bubble_controller_(bubble_controller) {
   bubble_controller_->InitOfflineItems(
@@ -61,9 +90,20 @@
 DownloadDisplayController::~DownloadDisplayController() = default;
 
 void DownloadDisplayController::OnNewItem(bool show_details) {
-  UpdateToolbarButtonState();
+  std::vector<std::unique_ptr<DownloadUIModel>> all_models =
+      bubble_controller_->GetAllItemsToDisplay();
+  UpdateToolbarButtonState(all_models);
   if (show_details) {
-    display_->ShowDetails();
+    if (browser_->window()->IsFullscreen()) {
+      browser_->exclusive_access_manager()
+          ->context()
+          ->UpdateExclusiveAccessExitBubbleContent(
+              GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED,
+              ExclusiveAccessBubbleHideCallback(),
+              /*force_update=*/false);
+    } else {
+      display_->ShowDetails();
+    }
   }
 }
 
@@ -71,10 +111,17 @@
                                               bool show_details_if_done) {
   if (is_done) {
     ScheduleToolbarDisappearance(kToolbarIconVisibilityTimeInterval);
-    if (show_details_if_done)
-      display_->ShowDetails();
+    if (show_details_if_done) {
+      if (browser_->window()->IsFullscreen()) {
+        download_completed_while_fullscreen_ = true;
+      } else {
+        display_->ShowDetails();
+      }
+    }
   }
-  UpdateToolbarButtonState();
+  std::vector<std::unique_ptr<DownloadUIModel>> all_models =
+      bubble_controller_->GetAllItemsToDisplay();
+  UpdateToolbarButtonState(all_models);
 }
 
 void DownloadDisplayController::OnRemovedItem(const ContentId& id) {
@@ -86,7 +133,7 @@
     HideToolbarButton();
     return;
   }
-  UpdateToolbarButtonState();
+  UpdateToolbarButtonState(all_models);
 }
 
 void DownloadDisplayController::OnManagerGoingDown(
@@ -124,26 +171,33 @@
   }
 }
 
-void DownloadDisplayController::UpdateToolbarButtonState() {
-  int in_progress_count = 0;
-  bool has_deep_scanning_download = false;
+void DownloadDisplayController::ListenToFullScreenChanges() {
+  observation_.Observe(
+      browser_->exclusive_access_manager()->fullscreen_controller());
+}
+
+void DownloadDisplayController::OnFullscreenStateChanged() {
+  if (browser_->window()->IsFullscreen())
+    return;
 
   std::vector<std::unique_ptr<DownloadUIModel>> all_models =
       bubble_controller_->GetAllItemsToDisplay();
+  UpdateToolbarButtonState(all_models);
+  int in_progress_count = InProgressDownloadCount(all_models);
+  if (in_progress_count > 0) {
+    display_->ShowDetails();
+  }
+}
+
+void DownloadDisplayController::UpdateToolbarButtonState(
+    std::vector<std::unique_ptr<DownloadUIModel>>& all_models) {
   if (all_models.empty()) {
     HideToolbarButton();
     return;
   }
-  for (const auto& model : all_models) {
-    if (model->GetDangerType() ==
-            download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING &&
-        model->GetState() != download::DownloadItem::CANCELLED) {
-      has_deep_scanning_download = true;
-    }
-    if (IsModelInProgress(model.get())) {
-      in_progress_count++;
-    }
-  }
+  int in_progress_count = InProgressDownloadCount(all_models);
+  bool has_deep_scanning_download = HasDeepScanningDownload(all_models);
+
   if (in_progress_count > 0) {
     ShowToolbarButton();
     icon_info_.icon_state = DownloadIconState::kProgress;
@@ -155,6 +209,11 @@
             GetLastCompleteTime(bubble_controller_->GetOfflineItems()))) {
       icon_info_.is_active = true;
       ScheduleToolbarInactive(kToolbarIconActiveTimeInterval);
+    } else if (!browser_->window()->IsFullscreen() &&
+               download_completed_while_fullscreen_) {
+      icon_info_.is_active = true;
+      ScheduleToolbarInactive(kToolbarIconActiveTimeInterval);
+      download_completed_while_fullscreen_ = false;
     } else {
       icon_info_.is_active = false;
     }
@@ -240,12 +299,12 @@
 
 DownloadDisplayController::ProgressInfo
 DownloadDisplayController::GetProgress() {
-  DownloadDisplayController::ProgressInfo progress_info;
+  ProgressInfo progress_info;
+  std::vector<std::unique_ptr<DownloadUIModel>> all_models =
+      bubble_controller_->GetAllItemsToDisplay();
   int64_t received_bytes = 0;
   int64_t total_bytes = 0;
 
-  std::vector<std::unique_ptr<DownloadUIModel>> all_models =
-      bubble_controller_->GetAllItemsToDisplay();
   for (const auto& model : all_models) {
     if (IsModelInProgress(model.get())) {
       ++progress_info.download_count;
@@ -263,6 +322,5 @@
     progress_info.progress_percentage =
         base::ClampFloor(received_bytes * 100.0 / total_bytes);
   }
-
   return progress_info;
 }
diff --git a/chrome/browser/download/bubble/download_display_controller.h b/chrome/browser/download/bubble/download_display_controller.h
index 0329551..0bc2e50 100644
--- a/chrome/browser/download/bubble/download_display_controller.h
+++ b/chrome/browser/download/bubble/download_display_controller.h
@@ -8,6 +8,8 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/download/bubble/download_icon_state.h"
 #include "chrome/browser/download/offline_item_model.h"
+#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
+#include "chrome/browser/ui/exclusive_access/fullscreen_observer.h"
 #include "components/download/content/public/all_download_item_notifier.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 #include "components/offline_items_collection/core/offline_content_provider.h"
@@ -16,7 +18,6 @@
 class DownloadManager;
 }  // namespace content
 
-class Profile;
 class DownloadBubbleUIController;
 
 namespace base {
@@ -31,10 +32,11 @@
 // future OfflineItems include regular Download on Desktop platforms,
 // we can remove AllDownloadItemNotifier::Observer.
 class DownloadDisplayController
-    : public download::AllDownloadItemNotifier::Observer {
+    : public download::AllDownloadItemNotifier::Observer,
+      public FullscreenObserver {
  public:
   DownloadDisplayController(DownloadDisplay* display,
-                            Profile* profile,
+                            Browser* browser,
                             DownloadBubbleUIController* bubble_controller);
   DownloadDisplayController(const DownloadDisplayController&) = delete;
   DownloadDisplayController& operator=(const DownloadDisplayController&) =
@@ -84,6 +86,14 @@
   // details are already hidden.
   void HideBubble();
 
+  // Start listening to full screen changes. This is separate from the
+  // constructor as the exclusive access manager is constructed after
+  // BrowserWindow.
+  void ListenToFullScreenChanges();
+
+  // FullScreenObserver
+  void OnFullscreenStateChanged() override;
+
   // Returns the DownloadDisplay. Should always return a valid display.
   DownloadDisplay* download_display_for_testing() { return display_; }
 
@@ -114,7 +124,8 @@
 
   // Based on the information from `download_manager_`, updates the icon state
   // of the `display_`.
-  void UpdateToolbarButtonState();
+  void UpdateToolbarButtonState(
+      std::vector<std::unique_ptr<DownloadUIModel>>& all_models);
   // Asks `display_` to make the download icon inactive.
   void UpdateDownloadIconToInactive();
 
@@ -133,11 +144,15 @@
 
   // The pointer is created in ToolbarView and owned by ToolbarView.
   raw_ptr<DownloadDisplay> const display_;
+  raw_ptr<Browser> browser_;
+  base::ScopedObservation<FullscreenController, FullscreenObserver>
+      observation_{this};
   raw_ptr<content::DownloadManager> download_manager_;
   download::AllDownloadItemNotifier download_notifier_;
   base::OneShotTimer icon_disappearance_timer_;
   base::OneShotTimer icon_inactive_timer_;
   IconInfo icon_info_;
+  bool download_completed_while_fullscreen_ = false;
   // DownloadDisplayController and DownloadBubbleUIController have the same
   // lifetime. Both are owned, constructed together, and destructed together by
   // DownloadToolbarButtonView. If one is valid, so is the other.
diff --git a/chrome/browser/download/bubble/download_display_controller_unittest.cc b/chrome/browser/download/bubble/download_display_controller_unittest.cc
index 643804c2..aa7c0f14 100644
--- a/chrome/browser/download/bubble/download_display_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_display_controller_unittest.cc
@@ -15,6 +15,8 @@
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -107,6 +109,54 @@
 
 }  // namespace
 
+class DownloadDisplayControllerTest;
+
+// A test browser window that can toggle fullscreen state.
+class TestBrowserWindowWithFullscreen : public TestBrowserWindow,
+                                        ExclusiveAccessContext {
+ public:
+  explicit TestBrowserWindowWithFullscreen(DownloadDisplayControllerTest* test)
+      : test_(test) {}
+
+  TestBrowserWindowWithFullscreen(const TestBrowserWindowWithFullscreen&) =
+      delete;
+  TestBrowserWindowWithFullscreen& operator=(
+      const TestBrowserWindowWithFullscreen&) = delete;
+
+  ~TestBrowserWindowWithFullscreen() override = default;
+
+  // TestBrowserWindow overrides:
+  bool ShouldHideUIForFullscreen() const override { return fullscreen_; }
+  bool IsFullscreen() const override { return fullscreen_; }
+  void EnterFullscreen(const GURL& url,
+                       ExclusiveAccessBubbleType type,
+                       int64_t display_id) override {
+    fullscreen_ = true;
+  }
+  void ExitFullscreen() override { fullscreen_ = false; }
+  bool IsToolbarShowing() const override { return toolbar_showing_; }
+  bool IsLocationBarVisible() const override { return true; }
+
+  ExclusiveAccessContext* GetExclusiveAccessContext() override { return this; }
+
+  // Exclusive access interface:
+  Profile* GetProfile() override;
+  content::WebContents* GetActiveWebContents() override;
+  void UpdateExclusiveAccessExitBubbleContent(
+      const GURL& url,
+      ExclusiveAccessBubbleType bubble_type,
+      ExclusiveAccessBubbleHideCallback bubble_first_hide_callback,
+      bool force_update) override {}
+  bool IsExclusiveAccessBubbleDisplayed() const override { return false; }
+  void OnExclusiveAccessUserInput() override {}
+  bool CanUserExitFullscreen() const override { return true; }
+
+ private:
+  bool fullscreen_ = false;
+  bool toolbar_showing_ = false;
+  raw_ptr<DownloadDisplayControllerTest> test_;
+};
+
 class DownloadDisplayControllerTest : public testing::Test {
  public:
   DownloadDisplayControllerTest()
@@ -131,7 +181,7 @@
         ->SetDownloadManagerDelegateForTesting(std::move(delegate));
 
     display_ = std::make_unique<FakeDownloadDisplay>();
-    window_ = std::make_unique<TestBrowserWindow>();
+    window_ = std::make_unique<TestBrowserWindowWithFullscreen>(this);
     Browser::CreateParams params(profile_, true);
     params.type = Browser::TYPE_NORMAL;
     params.window = window_.get();
@@ -140,7 +190,7 @@
         std::make_unique<FakeDownloadBubbleUIController>(browser_.get());
     bubble_controller_->set_manager_for_testing(manager_.get());
     controller_ = std::make_unique<DownloadDisplayController>(
-        display_.get(), profile_, bubble_controller_.get());
+        display_.get(), browser_.get(), bubble_controller_.get());
     controller_->set_manager_for_testing(manager_.get());
     display_->SetController(controller_.get());
   }
@@ -154,6 +204,8 @@
     controller_.reset();
   }
 
+  Browser* browser() { return browser_.get(); }
+
  protected:
   NiceMock<content::MockDownloadManager>& manager() { return *manager_.get(); }
   download::MockDownloadItem& item(size_t index) { return *items_[index]; }
@@ -310,10 +362,18 @@
   std::unique_ptr<FakeDownloadBubbleUIController> bubble_controller_;
   TestingProfileManager testing_profile_manager_;
   raw_ptr<Profile> profile_;
-  std::unique_ptr<TestBrowserWindow> window_;
+  std::unique_ptr<TestBrowserWindowWithFullscreen> window_;
   std::unique_ptr<Browser> browser_;
 };
 
+Profile* TestBrowserWindowWithFullscreen::GetProfile() {
+  return test_->browser()->profile();
+}
+
+content::WebContents* TestBrowserWindowWithFullscreen::GetActiveWebContents() {
+  return test_->browser()->tab_strip_model()->GetActiveWebContents();
+}
+
 TEST_F(DownloadDisplayControllerTest, GetProgressItemsInProgress) {
   InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
                    download::DownloadItem::IN_PROGRESS);
@@ -604,7 +664,7 @@
   DownloadPrefs::FromDownloadManager(&manager())
       ->SetLastCompleteTime(current_time - base::Hours(25));
 
-  DownloadDisplayController controller(&display(), profile(),
+  DownloadDisplayController controller(&display(), browser(),
                                        &bubble_controller());
   EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false,
                                  /*icon_state=*/DownloadIconState::kComplete,
@@ -619,7 +679,7 @@
   DownloadPrefs::FromDownloadManager(&manager())
       ->SetLastCompleteTime(current_time - base::Hours(23));
 
-  DownloadDisplayController controller(&display(), profile(),
+  DownloadDisplayController controller(&display(), browser(),
                                        &bubble_controller());
   // The initial state should not display details.
   EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
@@ -641,7 +701,7 @@
   DownloadPrefs::FromDownloadManager(&manager())
       ->SetLastCompleteTime(current_time - base::Hours(23));
 
-  DownloadDisplayController controller(&display(), profile(),
+  DownloadDisplayController controller(&display(), browser(),
                                        &bubble_controller());
   // Although the last complete time is set, the download display is not shown
   // because the download item list is empty. This can happen if the download
@@ -652,7 +712,7 @@
 }
 
 TEST_F(DownloadDisplayControllerTest, InitialState_NoLastDownload) {
-  DownloadDisplayController controller(&display(), profile(),
+  DownloadDisplayController controller(&display(), browser(),
                                        &bubble_controller());
   EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false,
                                  /*icon_state=*/DownloadIconState::kComplete,
@@ -688,3 +748,66 @@
                                  /*icon_state=*/DownloadIconState::kProgress,
                                  /*is_active=*/true));
 }
+
+TEST_F(DownloadDisplayControllerTest,
+       Fullscreen_ShowsDetailsForInProgressOnExitFullscreen) {
+  chrome::ToggleFullscreenMode(browser());
+  EXPECT_TRUE(browser()->window()->IsFullscreen());
+  controller().OnFullscreenStateChanged();
+  InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                   download::DownloadItem::IN_PROGRESS);
+  // Do not show bubble for in-progress download in full screen mode.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kProgress,
+                                 /*is_active=*/true));
+
+  chrome::ToggleFullscreenMode(browser());
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+  controller().OnFullscreenStateChanged();
+  // Show bubble for in-progress download when exiting full screen mode.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true,
+                                 /*icon_state=*/DownloadIconState::kProgress,
+                                 /*is_active=*/true));
+}
+
+TEST_F(DownloadDisplayControllerTest,
+       Fullscreen_ShowsIconForCompletedOnExitFullscreen) {
+  chrome::ToggleFullscreenMode(browser());
+  EXPECT_TRUE(browser()->window()->IsFullscreen());
+  controller().OnFullscreenStateChanged();
+  InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                   download::DownloadItem::IN_PROGRESS);
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kProgress,
+                                 /*is_active=*/true));
+
+  UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE,
+                     download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+                     /*show_details_if_done=*/true);
+  // While the bubble does not pop up, and the toolbar not shown, the icon
+  // state is still updated. So |is_active| should be true for one minute after
+  // completed download.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/true));
+
+  task_environment_.FastForwardBy(base::Minutes(1));
+  // The display is still showing but the state has changed to inactive.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/false));
+
+  chrome::ToggleFullscreenMode(browser());
+  EXPECT_FALSE(browser()->window()->IsFullscreen());
+  controller().OnFullscreenStateChanged();
+  // On exiting full screen, show download icon as active for 1 minute.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/true));
+
+  task_environment_.FastForwardBy(base::Minutes(1));
+  // The display is still showing but the state has changed to inactive.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/false));
+}
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 183254b0..3641c27f 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -538,7 +538,7 @@
 bool IsDownloadSurfaceVisible(BrowserWindow* window) {
   return base::FeatureList::IsEnabled(safe_browsing::kDownloadBubble)
              ? window->GetDownloadBubbleUIController()
-                   ->display_controller_for_testing()
+                   ->GetDownloadDisplayController()
                    ->download_display_for_testing()
                    ->IsShowingDetails()
              : window->IsDownloadShelfVisible();
diff --git a/chrome/browser/engagement/site_engagement_service_factory.cc b/chrome/browser/engagement/site_engagement_service_factory.cc
index b79d8cc..c8e979e 100644
--- a/chrome/browser/engagement/site_engagement_service_factory.cc
+++ b/chrome/browser/engagement/site_engagement_service_factory.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/engagement/history_aware_site_engagement_service.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 1f9e4952..bfbd95d 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -26,7 +26,7 @@
 #include "chrome/browser/extensions/activity_log/counting_policy.h"
 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 54a30c9..3ed2be12 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/extensions/activity_log/activity_log_task_runner.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 1006390..bcb2992 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -114,6 +114,10 @@
     "Each extension may have at most one "
     "onDeterminingFilename listener between all of its renderer execution "
     "contexts.";
+const char kUiDisabled[] = "Another extension has disabled the download UI";
+const char kUiPermission[] =
+    "downloads.setUiOptions requires the "
+    "\"downloads.ui\" permission";
 const char kUnexpectedDeterminer[] = "Unexpected determineFilename call";
 const char kUserGesture[] = "User gesture required";
 
@@ -441,7 +445,7 @@
 
 // Set |manager| to the on-record DownloadManager, and |incognito_manager| to
 // the off-record DownloadManager if one exists and is requested via
-// |include_incognito|. This should work regardless of whether |profile| is
+// |include_incognito|. This should work regardless of whether |context| is
 // original or incognito.
 void GetManagers(content::BrowserContext* context,
                  bool include_incognito,
@@ -459,6 +463,40 @@
   }
 }
 
+// Set |service| to the on-record DownloadCoreService, |incognito_service| to
+// the off-record DownloadCoreService if one exists and is requested via
+// |include_incognito|. This should work regardless of whether |context| is
+// original or incognito.
+void GetDownloadCoreServices(content::BrowserContext* context,
+                             bool include_incognito,
+                             DownloadCoreService** service,
+                             DownloadCoreService** incognito_service) {
+  DownloadManager* manager = nullptr;
+  DownloadManager* incognito_manager = nullptr;
+  GetManagers(context, include_incognito, &manager, &incognito_manager);
+  if (manager) {
+    *service = DownloadCoreServiceFactory::GetForBrowserContext(
+        manager->GetBrowserContext());
+  }
+  if (incognito_manager) {
+    *incognito_service = DownloadCoreServiceFactory::GetForBrowserContext(
+        incognito_manager->GetBrowserContext());
+  }
+}
+
+void MaybeSetShelfEnabled(DownloadCoreService* service,
+                          DownloadCoreService* incognito_service,
+                          const Extension* extension,
+                          bool enabled) {
+  if (service) {
+    service->GetExtensionEventRouter()->SetShelfEnabled(extension, enabled);
+  }
+  if (incognito_service) {
+    incognito_service->GetExtensionEventRouter()->SetShelfEnabled(extension,
+                                                                  enabled);
+  }
+}
+
 DownloadItem* GetDownload(content::BrowserContext* context,
                           bool include_incognito,
                           int id) {
@@ -490,6 +528,7 @@
   DOWNLOADS_FUNCTION_SHOW_DEFAULT_FOLDER = 13,
   DOWNLOADS_FUNCTION_SET_SHELF_ENABLED = 14,
   DOWNLOADS_FUNCTION_DETERMINE_FILENAME = 15,
+  DOWNLOADS_FUNCTION_SET_UI_OPTIONS = 16,
   // Insert new values here, not at the beginning.
   DOWNLOADS_FUNCTION_LAST
 };
@@ -1462,24 +1501,13 @@
   }
 
   RecordApiFunctions(DOWNLOADS_FUNCTION_SET_SHELF_ENABLED);
-  DownloadManager* manager = NULL;
-  DownloadManager* incognito_manager = NULL;
-  GetManagers(browser_context(), include_incognito_information(), &manager,
-              &incognito_manager);
-  DownloadCoreService* service = NULL;
-  DownloadCoreService* incognito_service = NULL;
-  if (manager) {
-    service = DownloadCoreServiceFactory::GetForBrowserContext(
-        manager->GetBrowserContext());
-    service->GetExtensionEventRouter()->SetShelfEnabled(extension(),
-                                                        params->enabled);
-  }
-  if (incognito_manager) {
-    incognito_service = DownloadCoreServiceFactory::GetForBrowserContext(
-        incognito_manager->GetBrowserContext());
-    incognito_service->GetExtensionEventRouter()->SetShelfEnabled(
-        extension(), params->enabled);
-  }
+  DownloadCoreService* service = nullptr;
+  DownloadCoreService* incognito_service = nullptr;
+  GetDownloadCoreServices(browser_context(), include_incognito_information(),
+                          &service, &incognito_service);
+
+  MaybeSetShelfEnabled(service, incognito_service, extension(),
+                       params->enabled);
 
   BrowserList* browsers = BrowserList::GetInstance();
   if (browsers) {
@@ -1496,14 +1524,60 @@
   }
 
   if (params->enabled &&
-      ((manager && !service->IsShelfEnabled()) ||
-       (incognito_manager && !incognito_service->IsShelfEnabled()))) {
+      ((service && !service->IsShelfEnabled()) ||
+       (incognito_service && !incognito_service->IsShelfEnabled()))) {
     return RespondNow(Error(download_extension_errors::kShelfDisabled));
   }
 
   return RespondNow(NoArguments());
 }
 
+DownloadsSetUiOptionsFunction::DownloadsSetUiOptionsFunction() = default;
+
+DownloadsSetUiOptionsFunction::~DownloadsSetUiOptionsFunction() = default;
+
+ExtensionFunction::ResponseAction DownloadsSetUiOptionsFunction::Run() {
+  std::unique_ptr<downloads::SetUiOptions::Params> params(
+      downloads::SetUiOptions::Params::Create(args()));
+  EXTENSION_FUNCTION_VALIDATE(params.get());
+  const downloads::UiOptions& options = params->options;
+  if (!extension()->permissions_data()->HasAPIPermission(
+          APIPermissionID::kDownloadsUi)) {
+    return RespondNow(Error(download_extension_errors::kUiPermission));
+  }
+
+  RecordApiFunctions(DOWNLOADS_FUNCTION_SET_UI_OPTIONS);
+  DownloadCoreService* service = nullptr;
+  DownloadCoreService* incognito_service = nullptr;
+  GetDownloadCoreServices(browser_context(), include_incognito_information(),
+                          &service, &incognito_service);
+
+  MaybeSetShelfEnabled(service, incognito_service, extension(),
+                       options.enabled);
+
+  BrowserList* browsers = BrowserList::GetInstance();
+  if (browsers) {
+    for (auto* browser : *browsers) {
+      DownloadCoreService* current_service =
+          DownloadCoreServiceFactory::GetForBrowserContext(browser->profile());
+      if (((current_service == service) ||
+           (current_service == incognito_service)) &&
+          browser->window()->IsDownloadShelfVisible() &&
+          !current_service->IsShelfEnabled()) {
+        browser->window()->GetDownloadShelf()->Close();
+      }
+    }
+  }
+
+  if (options.enabled &&
+      ((service && !service->IsShelfEnabled()) ||
+       (incognito_service && !incognito_service->IsShelfEnabled()))) {
+    return RespondNow(Error(download_extension_errors::kUiDisabled));
+  }
+
+  return RespondNow(NoArguments());
+}
+
 DownloadsGetFileIconFunction::DownloadsGetFileIconFunction()
     : icon_extractor_(new DownloadFileIconExtractorImpl()) {}
 
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.h b/chrome/browser/extensions/api/downloads/downloads_api.h
index 994116d87..e5d2eac 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.h
+++ b/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -299,6 +299,21 @@
   ~DownloadsSetShelfEnabledFunction() override;
 };
 
+class DownloadsSetUiOptionsFunction : public ExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("downloads.setUiOptions", DOWNLOADS_SETUIOPTIONS)
+  DownloadsSetUiOptionsFunction();
+
+  DownloadsSetUiOptionsFunction(const DownloadsSetUiOptionsFunction&) = delete;
+  DownloadsSetUiOptionsFunction& operator=(
+      const DownloadsSetUiOptionsFunction&) = delete;
+
+  ResponseAction Run() override;
+
+ protected:
+  ~DownloadsSetUiOptionsFunction() override;
+};
+
 class DownloadsGetFileIconFunction : public ExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("downloads.getFileIcon", DOWNLOADS_GETFILEICON)
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index d75876c..7f2546a 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -4599,6 +4599,21 @@
 // TODO(benjhayden) Test that the shelf is shown for download() both with and
 // without a WebContents.
 
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
+                       DownloadExtensionTest_SetUiOptions) {
+  LoadExtension("downloads_split");
+  EXPECT_TRUE(RunFunction(new DownloadsSetUiOptionsFunction(),
+                          R"([{"enabled": false}])"));
+  EXPECT_FALSE(DownloadCoreServiceFactory::GetForBrowserContext(
+                   current_browser()->profile())
+                   ->IsShelfEnabled());
+  EXPECT_TRUE(RunFunction(new DownloadsSetUiOptionsFunction(),
+                          R"([{"enabled": true}])"));
+  EXPECT_TRUE(DownloadCoreServiceFactory::GetForBrowserContext(
+                  current_browser()->profile())
+                  ->IsShelfEnabled());
+}
+
 void OnDangerPromptCreated(DownloadDangerPrompt* prompt) {
   prompt->InvokeActionForTesting(DownloadDangerPrompt::ACCEPT);
 }
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index 8a1f73b..f4ba614 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -74,7 +74,7 @@
 bool IsDownloadSurfaceVisible(BrowserWindow* window) {
   return base::FeatureList::IsEnabled(safe_browsing::kDownloadBubble)
              ? window->GetDownloadBubbleUIController()
-                   ->display_controller_for_testing()
+                   ->GetDownloadDisplayController()
                    ->download_display_for_testing()
                    ->IsShowingDetails()
              : window->IsDownloadShelfVisible();
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 2f5f7a7..b2095ffc 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
 #include "components/sessions/core/session_id.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 8963be93..fd805ae 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -14,6 +14,7 @@
 #include "ash/public/cpp/keyboard/keyboard_switches.h"
 #include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "base/bind.h"
+#include "base/check.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
@@ -527,15 +528,15 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
 
-  std::unique_ptr<base::DictionaryValue> results(new base::DictionaryValue());
-  results->SetStringKey("layout", GetKeyboardLayout());
+  base::Value::Dict results;
+  results.Set("layout", GetKeyboardLayout());
 
   // TODO(bshe): Consolidate a11y, hotrod and normal mode into a mode enum. See
   // crbug.com/529474.
-  results->SetBoolKey("a11ymode",
-                      keyboard_client->IsEnableFlagSet(
-                          keyboard::KeyboardEnableFlag::kAccessibilityEnabled));
-  results->SetBoolKey("hotrodmode", g_hotrod_keyboard_enabled);
+  results.Set("a11ymode",
+              keyboard_client->IsEnableFlagSet(
+                  keyboard::KeyboardEnableFlag::kAccessibilityEnabled));
+  results.Set("hotrodmode", g_hotrod_keyboard_enabled);
   base::Value features(base::Value::Type::LIST);
 
   keyboard::KeyboardConfig config = keyboard_client->GetKeyboardConfig();
@@ -598,20 +599,22 @@
                           base::FeatureList::IsEnabled(
                               chromeos::features::kAutocorrectParamsTuning)));
 
-  results->SetKey("features", std::move(features));
+  results.Set("features", std::move(features));
 
   std::move(on_settings_callback).Run(std::move(results));
 }
 
 void ChromeVirtualKeyboardDelegate::DispatchConfigChangeEvent(
-    std::unique_ptr<base::DictionaryValue> settings) {
+    absl::optional<base::Value::Dict> settings) {
+  DCHECK(settings);
+
   EventRouter* router = GetRouterForEventName(
       browser_context_, keyboard_api::OnKeyboardConfigChanged::kEventName);
   if (!router)
     return;
 
   base::Value::List event_args;
-  event_args.Append(base::Value::FromUniquePtrValue(std::move(settings)));
+  event_args.Append(base::Value(std::move(*settings)));
 
   auto event = std::make_unique<extensions::Event>(
       extensions::events::VIRTUAL_KEYBOARD_PRIVATE_ON_KEYBOARD_CONFIG_CHANGED,
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
index be06f05..12cd15fe 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.h
@@ -9,9 +9,11 @@
 
 #include "ash/public/cpp/clipboard_history_controller.h"
 #include "base/memory/weak_ptr.h"
+#include "base/values.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
 #include "extensions/common/api/virtual_keyboard.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace media {
 class AudioSystem;
@@ -80,8 +82,7 @@
 
   void OnHasInputDevices(OnKeyboardSettingsCallback on_settings_callback,
                          bool has_audio_input_devices);
-  void DispatchConfigChangeEvent(
-      std::unique_ptr<base::DictionaryValue> settings);
+  void DispatchConfigChangeEvent(absl::optional<base::Value::Dict> settings);
 
   content::BrowserContext* browser_context_;
   std::unique_ptr<media::AudioSystem> audio_system_;
diff --git a/chrome/browser/extensions/user_host_restrictions_browsertest.cc b/chrome/browser/extensions/user_host_restrictions_browsertest.cc
index ec3ce56..9b1b875 100644
--- a/chrome/browser/extensions/user_host_restrictions_browsertest.cc
+++ b/chrome/browser/extensions/user_host_restrictions_browsertest.cc
@@ -515,4 +515,32 @@
           non_user_permitted_site, extension_misc::kUnknownTabId, nullptr));
 }
 
+IN_PROC_BROWSER_TEST_P(UserHostRestrictionsBrowserTest,
+                       UserPermittedSitesAndChromeFavicon) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
+  // Note: MV2 extension because chrome://favicon is removed in MV3 (yay!).
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Test Extension",
+           "version": "0.1",
+           "manifest_version": 2,
+           "permissions": ["<all_urls>"]
+         })";
+
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+
+  const GURL favicon_url("chrome://favicon/http://example.com");
+  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
+
+  WithholdExtensionPermissions(*extension);
+  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
+
+  AddUserPermittedSite(GURL("https://allowed.example"));
+  EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index a68ab19..f71d4dd8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3062,6 +3062,11 @@
     "expiry_milestone": 110
   },
   {
+    "name": "enable-waitable-swap-chain",
+    "owners": [ "alex.forrence@gmail.com", "sunnyps" ],
+    "expiry_milestone": 120
+  },
+  {
     "name": "enable-web-authentication-cable-disco-creds",
     "owners": [ "chrome-webauthn@google.com" ],
     "expiry_milestone": 112
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8f4448b7..9ab3e1ca4 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4210,6 +4210,14 @@
 const char kUseAngleD3D9[] = "D3D9";
 const char kUseAngleD3D11on12[] = "D3D11on12";
 
+const char kUseWaitableSwapChainName[] = "Use waitable swap chains";
+const char kUseWaitableSwapChainDescription[] =
+    "Use waitable swap chains to reduce presentation latency (effective only "
+    "Windows 8.1 or later). If enabled, specify the maximum number of frames "
+    "that can be queued, ranging from 1-3. 1 has the lowest delay but is most "
+    "likely to drop frames, while 3 has the highest delay but is least likely "
+    "to drop frames.";
+
 const char kUseWinrtMidiApiName[] = "Use Windows Runtime MIDI API";
 const char kUseWinrtMidiApiDescription[] =
     "Use Windows Runtime MIDI API for WebMIDI (effective only on Windows 10 or "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 5a12fa6..22e27599 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2404,6 +2404,9 @@
 extern const char kUseAngleD3D9[];
 extern const char kUseAngleD3D11on12[];
 
+extern const char kUseWaitableSwapChainName[];
+extern const char kUseWaitableSwapChainDescription[];
+
 extern const char kUseWinrtMidiApiName[];
 extern const char kUseWinrtMidiApiDescription[];
 
diff --git a/chrome/browser/font_prewarmer_tab_helper.cc b/chrome/browser/font_prewarmer_tab_helper.cc
index 3931a4e2..af9eead 100644
--- a/chrome/browser/font_prewarmer_tab_helper.cc
+++ b/chrome/browser/font_prewarmer_tab_helper.cc
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history_clusters/history_clusters_tab_helper.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/common/font_prewarmer.mojom.h"
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
index 9edcfb9..64f2b597 100644
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -9,7 +9,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history_clusters/history_clusters_tab_helper.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "components/history/content/browser/history_context_helper.h"
diff --git a/chrome/browser/history_clusters/java/res/values/dimens.xml b/chrome/browser/history_clusters/java/res/values/dimens.xml
index e9749d9..1659a38 100644
--- a/chrome/browser/history_clusters/java/res/values/dimens.xml
+++ b/chrome/browser/history_clusters/java/res/values/dimens.xml
@@ -5,4 +5,6 @@
 
 <resources>
     <dimen name="visit_item_remove_button_lateral_padding">18dp</dimen>
+    <dimen name="related_search_chip_list_chip_spacing">4dp</dimen>
+    <dimen name="related_search_chip_list_side_padding">16dp</dimen>
 </resources>
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersRelatedSearchesChipLayout.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersRelatedSearchesChipLayout.java
index 5dc7ed7..b789835 100644
--- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersRelatedSearchesChipLayout.java
+++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersRelatedSearchesChipLayout.java
@@ -35,6 +35,10 @@
         super.onFinishInflate();
 
         mChipsCoordinator = new ChipsCoordinator(getContext(), mChipList);
+        mChipsCoordinator.setSpaceItemDecoration(
+                getResources().getDimensionPixelSize(R.dimen.related_search_chip_list_chip_spacing),
+                getResources().getDimensionPixelSize(
+                        R.dimen.related_search_chip_list_side_padding));
         addView(mChipsCoordinator.getView());
     }
 
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
index 4ddbbd1..851b8a56 100644
--- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
+++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/lacros/lacros_file_system_provider.h"
 #include "chrome/browser/lacros/lacros_memory_pressure_evaluator.h"
 #include "chrome/browser/lacros/launcher_search/search_controller_lacros.h"
+#include "chrome/browser/lacros/net/network_change_manager_bridge.h"
 #include "chrome/browser/lacros/screen_orientation_delegate_lacros.h"
 #include "chrome/browser/lacros/standalone_browser_test_controller.h"
 #include "chrome/browser/lacros/sync/sync_explicit_passphrase_client_lacros.h"
@@ -114,6 +115,8 @@
       std::make_unique<DownloadControllerClientLacros>();
   file_system_provider_ = std::make_unique<LacrosFileSystemProvider>();
   kiosk_session_service_ = std::make_unique<KioskSessionServiceLacros>();
+  network_change_manager_bridge_ =
+      std::make_unique<NetworkChangeManagerBridge>();
   screen_orientation_delegate_ =
       std::make_unique<ScreenOrientationDelegateLacros>();
   search_controller_ = std::make_unique<crosapi::SearchControllerLacros>();
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h
index 08e1e5b..2c29a72 100644
--- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h
+++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h
@@ -23,6 +23,7 @@
 class LacrosFileSystemProvider;
 class KioskSessionServiceLacros;
 class FieldTrialObserver;
+class NetworkChangeManagerBridge;
 class QuickAnswersController;
 class StandaloneBrowserTestController;
 class SyncExplicitPassphraseClientLacros;
@@ -87,6 +88,9 @@
   // Sends lacros installation status of force-installed extensions to ash.
   std::unique_ptr<ForceInstalledTrackerLacros> force_installed_tracker_;
 
+  // Receives and handles network change status.
+  std::unique_ptr<NetworkChangeManagerBridge> network_change_manager_bridge_;
+
   // Sends lacros load/unload events of Vpn extensions to ash.
   std::unique_ptr<VpnExtensionTrackerLacros> vpn_extension_tracker_;
 
diff --git a/chrome/browser/lacros/net/network_change_manager_bridge.cc b/chrome/browser/lacros/net/network_change_manager_bridge.cc
new file mode 100644
index 0000000..ba8b2859
--- /dev/null
+++ b/chrome/browser/lacros/net/network_change_manager_bridge.cc
@@ -0,0 +1,145 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/lacros/net/network_change_manager_bridge.h"
+
+#include "base/bind.h"
+#include "chromeos/lacros/lacros_service.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/network_service_util.h"
+#include "net/base/network_change_notifier_posix.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+
+// Check ConnectionType and ConnectionSubtype values are the same for
+// network::mojom and crosapi::mojom.
+#define STATIC_ASSERT_CONNECTION_TYPE(v)                 \
+  static_assert(static_cast<int>(crosapi::mojom::v) ==   \
+                    static_cast<int>(network::mojom::v), \
+                "mismatching enums: " #v)
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_UNKNOWN);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_ETHERNET);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_WIFI);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_2G);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_3G);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_4G);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_NONE);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_BLUETOOTH);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_5G);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionType::CONNECTION_LAST);
+
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_UNKNOWN);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_NONE);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_OTHER);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_GSM);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_IDEN);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_CDMA);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_1XRTT);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_GPRS);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_EDGE);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_UMTS);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_EVDO_REV_0);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_EVDO_REV_A);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_HSPA);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_EVDO_REV_B);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_HSDPA);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_HSUPA);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_EHRPD);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_HSPAP);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_LTE);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_LTE_ADVANCED);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_BLUETOOTH_1_2);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_BLUETOOTH_2_1);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_BLUETOOTH_3_0);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_BLUETOOTH_4_0);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_ETHERNET);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_FAST_ETHERNET);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_GIGABIT_ETHERNET);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_10_GIGABIT_ETHERNET);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_WIFI_B);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_WIFI_G);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_WIFI_N);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_WIFI_AC);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_WIFI_AD);
+STATIC_ASSERT_CONNECTION_TYPE(ConnectionSubtype::SUBTYPE_LAST);
+
+NetworkChangeManagerBridge::NetworkChangeManagerBridge()
+    : network_change_notifier_(static_cast<net::NetworkChangeNotifierPosix*>(
+          content::GetNetworkChangeNotifier())) {
+  auto* lacros_service = chromeos::LacrosService::Get();
+  // If NetworkChange crosapi is not supported, fallback to use
+  // NetworkChangeNotifierLinux instead.
+  if (!lacros_service->IsAvailable<crosapi::mojom::NetworkChange>())
+    return;
+
+  if (content::IsOutOfProcessNetworkService())
+    ConnectToNetworkChangeManager();
+
+  lacros_service->GetRemote<crosapi::mojom::NetworkChange>()->AddObserver(
+      receiver_.BindNewPipeAndPassRemoteWithVersion());
+}
+
+NetworkChangeManagerBridge::~NetworkChangeManagerBridge() = default;
+
+void NetworkChangeManagerBridge::OnNetworkChanged(
+    bool dns_changed,
+    bool ip_address_changed,
+    bool connection_type_changed,
+    crosapi::mojom::ConnectionType new_connection_type,
+    bool connection_subtype_changed,
+    crosapi::mojom::ConnectionSubtype new_connection_subtype) {
+  // If `test_notifications_only_` is set for registered notifier, skip
+  // notifying.
+  if (network_change_notifier_->IsTestNotificationsOnly())
+    return;
+
+  DCHECK(network_change_notifier_);
+  if (ip_address_changed)
+    network_change_notifier_->OnIPAddressChanged();
+  if (dns_changed)
+    network_change_notifier_->OnDNSChanged();
+  if (connection_type_changed)
+    network_change_notifier_->OnConnectionChanged(
+        net::NetworkChangeNotifier::ConnectionType(new_connection_type));
+  if (connection_type_changed || connection_subtype_changed) {
+    network_change_notifier_->OnConnectionSubtypeChanged(
+        net::NetworkChangeNotifier::ConnectionType(new_connection_type),
+        net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype));
+  }
+
+  if (network_change_manager_) {
+    network_change_manager_->OnNetworkChanged(
+        dns_changed, ip_address_changed, connection_type_changed,
+        network::mojom::ConnectionType(new_connection_type),
+        connection_subtype_changed,
+        network::mojom::ConnectionSubtype(new_connection_subtype));
+  }
+
+  // Update cached values.
+  connection_type_ =
+      net::NetworkChangeNotifier::ConnectionType(new_connection_type);
+  connection_subtype_ =
+      net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype);
+}
+
+void NetworkChangeManagerBridge::ConnectToNetworkChangeManager() {
+  if (network_change_manager_.is_bound())
+    network_change_manager_.reset();
+
+  content::GetNetworkService()->GetNetworkChangeManager(
+      network_change_manager_.BindNewPipeAndPassReceiver());
+  network_change_manager_.set_disconnect_handler(base::BindOnce(
+      &NetworkChangeManagerBridge::ReconnectToNetworkChangeManager,
+      base::Unretained(this)));
+}
+
+void NetworkChangeManagerBridge::ReconnectToNetworkChangeManager() {
+  ConnectToNetworkChangeManager();
+
+  network_change_manager_->OnNetworkChanged(
+      /*dns_changed=*/false, /*ip_address_changed=*/false,
+      /*connection_type_changed=*/true,
+      network::mojom::ConnectionType(connection_type_),
+      /*connection_subtype_changed=*/true,
+      network::mojom::ConnectionSubtype(connection_subtype_));
+}
diff --git a/chrome/browser/lacros/net/network_change_manager_bridge.h b/chrome/browser/lacros/net/network_change_manager_bridge.h
new file mode 100644
index 0000000..58718569
--- /dev/null
+++ b/chrome/browser/lacros/net/network_change_manager_bridge.h
@@ -0,0 +1,57 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_LACROS_NET_NETWORK_CHANGE_MANAGER_BRIDGE_H_
+#define CHROME_BROWSER_LACROS_NET_NETWORK_CHANGE_MANAGER_BRIDGE_H_
+
+#include "chromeos/crosapi/mojom/network_change.mojom.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/network_change_notifier.h"
+#include "services/network/public/mojom/network_change_manager.mojom.h"
+
+namespace net {
+class NetworkChangeNotifierPosix;
+}
+
+// Passes NetworkChange status given from Ash to NetworkChangeNotifier in
+// browser process and NetworkChangeManager in NetworkService process.
+// This class only runs on browser process.
+class NetworkChangeManagerBridge
+    : public crosapi::mojom::NetworkChangeObserver {
+ public:
+  NetworkChangeManagerBridge();
+
+  NetworkChangeManagerBridge(const NetworkChangeManagerBridge&) = delete;
+  NetworkChangeManagerBridge& operator=(const NetworkChangeManagerBridge&) =
+      delete;
+
+  ~NetworkChangeManagerBridge() override;
+
+  // crosapi::mojom::NetworkChangeObserver
+  void OnNetworkChanged(
+      bool dns_changed,
+      bool ip_address_changed,
+      bool connection_type_changed,
+      crosapi::mojom::ConnectionType new_connection_type,
+      bool connection_subtype_changed,
+      crosapi::mojom::ConnectionSubtype new_connection_subtype) override;
+
+ private:
+  void ConnectToNetworkChangeManager();
+  void ReconnectToNetworkChangeManager();
+
+  net::NetworkChangeNotifier::ConnectionType connection_type_ =
+      net::NetworkChangeNotifier::CONNECTION_NONE;
+  net::NetworkChangeNotifier::ConnectionSubtype connection_subtype_ =
+      net::NetworkChangeNotifier::SUBTYPE_NONE;
+
+  const raw_ptr<net::NetworkChangeNotifierPosix> network_change_notifier_;
+  mojo::Remote<network::mojom::NetworkChangeManager> network_change_manager_;
+
+  // Receives mojo messages from ash-chrome.
+  mojo::Receiver<crosapi::mojom::NetworkChangeObserver> receiver_{this};
+};
+
+#endif  // CHROME_BROWSER_LACROS_NET_NETWORK_CHANGE_MANAGER_BRIDGE_H_
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
index dda9d41..889f36c1 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -22,7 +22,7 @@
 #include "chrome/browser/lookalikes/lookalike_url_controller_client.h"
 #include "chrome/browser/lookalikes/lookalike_url_service.h"
 #include "chrome/browser/lookalikes/lookalike_url_tab_storage.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/reputation/reputation_service.h"
 #include "components/lookalikes/core/features.h"
@@ -413,18 +413,16 @@
 
   LookalikeUrlMatchType match_type =
       first_is_lookalike ? first_match_type : last_match_type;
-  if (match_type == LookalikeUrlMatchType::kCharacterSwapSiteEngagement ||
-      match_type == LookalikeUrlMatchType::kCharacterSwapTop500) {
+
+  // TODO(crbug.com/1344981): Once the Combo Squatting heuristic is fully
+  // launched, this console message should be removed.
+  if (match_type == LookalikeUrlMatchType::kComboSquatting) {
     GURL lookalike_url = first_is_lookalike ? first_url : last_url;
 
     navigation_handle()->GetRenderFrameHost()->AddMessageToConsole(
         blink::mojom::ConsoleMessageLevel::kWarning,
-        base::StringPrintf(
-            "Chrome has determined that %s could be fake or fraudulent.\n\n"
-            "Future Chrome versions will show a warning on this domain name. "
-            "If you believe this is shown in error please visit "
-            "https://g.co/chrome/lookalike-warnings",
-            lookalike_url.host().c_str()));
+        lookalikes::GetConsoleMessage(lookalike_url,
+                                      /*is_new_heuristic=*/true));
   }
 
   RecordUMAFromMatchType(match_type);
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
index 49e26c1f..8fb435d4 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -842,13 +842,7 @@
   // Advance clock to force a fetch of new engaged sites list.
   test_clock()->Advance(base::Hours(1));
 
-  content::WebContents* tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  content::WebContentsConsoleObserver console_observer(tab);
-  console_observer.SetPattern("Chrome has determined that*character-wsap.com*");
-
   TestInterstitialNotShown(browser(), kNavigatedUrl);
-  console_observer.Wait();
 
   histograms.ExpectTotalCount(lookalikes::kHistogramName, 1);
   histograms.ExpectBucketCount(
diff --git a/chrome/browser/media/media_engagement_browsertest.cc b/chrome/browser/media/media_engagement_browsertest.cc
index 90f95eb0..a88e012 100644
--- a/chrome/browser/media/media_engagement_browsertest.cc
+++ b/chrome/browser/media/media_engagement_browsertest.cc
@@ -20,9 +20,9 @@
 #include "chrome/browser/media/media_engagement_contents_observer.h"
 #include "chrome/browser/media/media_engagement_preloaded_list.h"
 #include "chrome/browser/media/media_engagement_service.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/media/media_engagement_service.cc b/chrome/browser/media/media_engagement_service.cc
index d324357..df634ca90 100644
--- a/chrome/browser/media/media_engagement_service.cc
+++ b/chrome/browser/media/media_engagement_service.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/media/media_engagement_contents_observer.h"
 #include "chrome/browser/media/media_engagement_score.h"
 #include "chrome/browser/media/media_engagement_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc
index 7726ef6..6b9521d 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h"
 #include "chrome/browser/page_load_metrics/observers/page_anchors_metrics_observer.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
index 33d71e6..a160946 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/navigation_predictor/navigation_predictor.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/net/errorpage_browsertest.cc b/chrome/browser/net/errorpage_browsertest.cc
index 6683c14..96a0ac18 100644
--- a/chrome/browser/net/errorpage_browsertest.cc
+++ b/chrome/browser/net/errorpage_browsertest.cc
@@ -620,7 +620,7 @@
   // Verify that the expected error page is being displayed.
   ExpectDisplayingErrorPage(incognito_browser, net::ERR_NAME_NOT_RESOLVED);
 
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
+#if !BUILDFLAG(IS_CHROMEOS)
   // Can't currently show the diagnostics in incognito on any platform but
   // ChromeOS.
   EXPECT_FALSE(WebContentsCanShowDiagnosticsTool(
diff --git a/chrome/browser/net/net_error_diagnostics_dialog_lacros.cc b/chrome/browser/net/net_error_diagnostics_dialog_lacros.cc
new file mode 100644
index 0000000..2ce0af2
--- /dev/null
+++ b/chrome/browser/net/net_error_diagnostics_dialog_lacros.cc
@@ -0,0 +1,23 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/net_error_diagnostics_dialog.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "content/public/browser/web_contents.h"
+
+bool CanShowNetworkDiagnosticsDialog(content::WebContents* web_contents) {
+  // The ChromeOS network diagnostics dialog can be shown in incognito and guest
+  // profiles since it does not log the referring URL.
+  return true;
+}
+
+void ShowNetworkDiagnosticsDialog(content::WebContents* web_contents,
+                                  const std::string& failed_url) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+
+  chrome::ShowConnectivityDiagnosticsApp(profile);
+}
diff --git a/chrome/browser/net/net_export_helper.cc b/chrome/browser/net/net_export_helper.cc
index ef76c7d..b54287a 100644
--- a/chrome/browser/net/net_export_helper.cc
+++ b/chrome/browser/net/net_export_helper.cc
@@ -9,7 +9,7 @@
 
 #include "base/values.h"
 #include "build/build_config.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "extensions/buildflags/buildflags.h"
diff --git a/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc b/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc
index 52b6b60..3843412 100644
--- a/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc
+++ b/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc
@@ -22,8 +22,8 @@
 #include "chrome/browser/optimization_guide/browser_test_util.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
diff --git a/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc b/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc
index 94b1724..bd3c1fd 100644
--- a/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/optimization_guide/chrome_hints_manager.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "components/optimization_guide/core/hints_fetcher.h"
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
index ebcd095..973f5d5 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/history_clusters/history_clusters_tab_helper.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 8b50b16..d88ad64 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -32,9 +32,9 @@
 #include "chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index 8fba39c..acf2aa3 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -41,7 +41,7 @@
 #include "chrome/browser/page_load_metrics/observers/third_party_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_memory_tracker_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
diff --git a/chrome/browser/performance_manager/observers/page_load_metrics_observer.cc b/chrome/browser/performance_manager/observers/page_load_metrics_observer.cc
index c27d4046..558507a 100644
--- a/chrome/browser/performance_manager/observers/page_load_metrics_observer.cc
+++ b/chrome/browser/performance_manager/observers/page_load_metrics_observer.cc
@@ -6,7 +6,7 @@
 
 #include "base/metrics/histogram_functions.h"
 #include "build/build_config.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.cc b/chrome/browser/predictors/autocomplete_action_predictor.cc
index f544b10..14f2ebe 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor.cc
+++ b/chrome/browser/predictors/autocomplete_action_predictor.cc
@@ -20,9 +20,9 @@
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
 #include "chrome/browser/predictors/predictor_database.h"
 #include "chrome/browser/predictors/predictor_database_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
 #include "chrome/browser/preloading/chrome_preloading.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/preloading/prerender/prerender_manager.h"
 #include "chrome/browser/preloading/prerender/prerender_utils.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/predictors/loading_predictor_browsertest.cc b/chrome/browser/predictors/loading_predictor_browsertest.cc
index b8e535a7..fe83c8c 100644
--- a/chrome/browser/predictors/loading_predictor_browsertest.cc
+++ b/chrome/browser/predictors/loading_predictor_browsertest.cc
@@ -34,7 +34,7 @@
 #include "chrome/browser/predictors/predictors_enums.h"
 #include "chrome/browser/predictors/predictors_features.h"
 #include "chrome/browser/predictors/predictors_switches.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.cc b/chrome/browser/predictors/loading_predictor_tab_helper.cc
index fb5872c..b85fb70 100644
--- a/chrome/browser/predictors/loading_predictor_tab_helper.cc
+++ b/chrome/browser/predictors/loading_predictor_tab_helper.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/predictors/predictors_enums.h"
 #include "chrome/browser/predictors/predictors_features.h"
 #include "chrome/browser/predictors/predictors_switches.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/google/core/common/google_util.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
diff --git a/chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.cc b/chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.cc
index 2b6b2ff..914f6b4 100644
--- a/chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.cc
@@ -6,10 +6,10 @@
 
 #include "chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_container.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_params.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc
index e93434b..49fe1e2 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc
@@ -31,7 +31,6 @@
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/profile_network_context_service_factory.h"
 #include "chrome/browser/policy/policy_test_utils.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_prober.h"
@@ -44,6 +43,7 @@
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_test_utils.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/certificate_reporting_test_utils.h"
 #include "chrome/browser/ssl/security_state_tab_helper.h"
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc
index 3dac2ca..d93fdfd 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/data_saver/data_saver.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_headers.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h"
@@ -35,6 +34,7 @@
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_service_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_subresource_manager.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_type.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/google/core/common/google_util.h"
 #include "components/language/core/browser/pref_names.h"
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor.cc
index 68a8d19..8691fd7a 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor.cc
@@ -10,7 +10,6 @@
 #include "base/callback.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_from_string_url_loader.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_prober.h"
@@ -19,6 +18,7 @@
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_service_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_subresource_manager.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetched_mainframe_response_container.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor_unittest.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor_unittest.cc
index 508f7a0..524bdbfa 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor_unittest.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_url_loader_interceptor_unittest.cc
@@ -8,9 +8,9 @@
 
 #include "base/command_line.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetched_mainframe_response_container.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/DIR_METADATA b/chrome/browser/preloading/prefetch/no_state_prefetch/DIR_METADATA
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/DIR_METADATA
rename to chrome/browser/preloading/prefetch/no_state_prefetch/DIR_METADATA
diff --git a/chrome/browser/prefetch/no_state_prefetch/OWNERS b/chrome/browser/preloading/prefetch/no_state_prefetch/OWNERS
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/OWNERS
rename to chrome/browser/preloading/prefetch/no_state_prefetch/OWNERS
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
similarity index 89%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
index 9d98bba..6b43e0c 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/task_manager/web_contents_tags.h"
 #include "chrome/browser/ui/tab_helpers.h"
 #include "chrome/common/chrome_render_frame.mojom.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h
similarity index 79%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h
index cad7c11..b4a595c 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h
@@ -1,8 +1,8 @@
 // Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
 
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents_delegate.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -37,4 +37,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_CONTENTS_DELEGATE_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc
similarity index 90%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc
index d28925e..184c41c6 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
 
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h
similarity index 77%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h
index f17d125d..6f2209fc 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
 
 #include "base/memory/raw_ptr.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager_delegate.h"
@@ -37,4 +37,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_MANAGER_DELEGATE_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc
similarity index 72%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc
index db4ddc7..d08e9b36 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_link_manager.h"
 #include "content/public/browser/browser_context.h"
 
diff --git a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h
similarity index 70%
rename from chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h
index 5795990f9..0dc024f 100644
--- a/chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_processor_impl_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
 
 #include "components/no_state_prefetch/browser/no_state_prefetch_processor_impl_delegate.h"
 
@@ -28,4 +28,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_CHROME_NO_STATE_PREFETCH_PROCESSOR_IMPL_DELEGATE_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
similarity index 90%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
index 98ddf2d..19898e8 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_link_manager.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h
similarity index 77%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h
index 588b16b..dd04fb8 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -37,4 +37,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_LINK_MANAGER_FACTORY_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc
similarity index 92%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc
index d1351fe..c2002d30 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 
 #include "base/trace_event/trace_event.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/predictors/predictor_database_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_service_factory.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h
similarity index 81%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h
index bfe8cf0b..2f8d696 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
 
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -44,4 +44,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_MANAGER_FACTORY_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc
similarity index 92%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc
index 2593a01..becab6a 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h
similarity index 83%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h
index 6d4fdaf..2dee91fc 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
 
 #include "content/public/browser/navigation_throttle.h"
 
@@ -41,4 +41,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
similarity index 87%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
index e3b20f8..1e949c03 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/page.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h
similarity index 79%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h
index 22a67c1..bd0c5b1 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
 
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -34,4 +34,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_NO_STATE_PREFETCH_TAB_HELPER_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc
similarity index 99%
rename from chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc
index 2ae54dd..833c82d 100644
--- a/chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc
@@ -26,9 +26,9 @@
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/loading_test_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_manager_delegate.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
similarity index 99%
rename from chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
index 2918b49..b8454a1 100644
--- a/chrome/browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
@@ -27,8 +27,8 @@
 #include "chrome/browser/history/history_test_utils.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.cc
similarity index 98%
rename from chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc
rename to chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.cc
index d4f6fff5..4e803bc8 100644
--- a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.cc
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.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 "chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h"
 
 #include <memory>
 #include <set>
@@ -16,7 +16,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h
similarity index 97%
rename from chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h
rename to chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h
index 03c2c372..97482fd 100644
--- a/chrome/browser/prefetch/no_state_prefetch/prerender_test_utils.h
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
-#define CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
 
 #include <functional>
 #include <map>
@@ -20,7 +20,7 @@
 #include "base/synchronization/lock.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
@@ -384,4 +384,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_NO_STATE_PREFETCH_PRERENDER_TEST_UTILS_H_
diff --git a/chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/OWNERS b/chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/OWNERS
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/OWNERS
rename to chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/OWNERS
diff --git a/chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/default.css b/chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/default.css
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/default.css
rename to chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/default.css
diff --git a/chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/index.html b/chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/index.html
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/index.html
rename to chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/index.html
diff --git a/chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/prerender.js b/chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/prerender.js
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/prerender.js
rename to chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/prerender.js
diff --git a/chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/prerender_test_server.py b/chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/prerender_test_server.py
similarity index 100%
rename from chrome/browser/prefetch/no_state_prefetch/tools/prerender_test_server/prerender_test_server.py
rename to chrome/browser/preloading/prefetch/no_state_prefetch/tools/prerender_test_server/prerender_test_server.py
diff --git a/chrome/browser/prefetch/zero_suggest_prefetch/DIR_METADATA b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/DIR_METADATA
similarity index 100%
rename from chrome/browser/prefetch/zero_suggest_prefetch/DIR_METADATA
rename to chrome/browser/preloading/prefetch/zero_suggest_prefetch/DIR_METADATA
diff --git a/chrome/browser/prefetch/zero_suggest_prefetch/OWNERS b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/OWNERS
similarity index 100%
rename from chrome/browser/prefetch/zero_suggest_prefetch/OWNERS
rename to chrome/browser/preloading/prefetch/zero_suggest_prefetch/OWNERS
diff --git a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc
similarity index 96%
rename from chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc
rename to chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc
index 4d31023..0e7f4d8 100644
--- a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc
+++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.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 "chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
 
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h
similarity index 81%
rename from chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h
rename to chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h
index 1ea221c..9f6cf50c 100644
--- a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h
+++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
-#define CHROME_BROWSER_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
+#ifndef CHROME_BROWSER_PRELOADING_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
+#define CHROME_BROWSER_PRELOADING_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
 
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -37,4 +37,4 @@
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 };
 
-#endif  // CHROME_BROWSER_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
+#endif  // CHROME_BROWSER_PRELOADING_PREFETCH_ZERO_SUGGEST_PREFETCH_ZERO_SUGGEST_PREFETCH_TAB_HELPER_H_
diff --git a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
similarity index 97%
rename from chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
rename to chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
index dfcf2a7..b1ee8bf6 100644
--- a/chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
+++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
@@ -7,7 +7,7 @@
 #include "base/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/test/scoped_feature_list.h"
-#include "chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index ebea7cd..27aff48 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -71,9 +71,9 @@
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/predictor_database_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefs/pref_metrics_service.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/privacy/privacy_metrics_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index b2512e7..b1a3fc0 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -71,11 +71,11 @@
 #include "chrome/browser/policy/profile_policy_connector_builder.h"
 #include "chrome/browser/policy/schema_registry_service.h"
 #include "chrome/browser/policy/schema_registry_service_builder.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/prefs/profile_pref_store_manager.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/privacy/privacy_metrics_service_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
index 78982fd..517b4ea 100644
--- a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
+++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
 #include "components/no_state_prefetch/browser/prerender_histograms.h"
 #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/reputation/reputation_web_contents_observer.cc b/chrome/browser/reputation/reputation_web_contents_observer.cc
index 2eca5725..9fb11485 100644
--- a/chrome/browser/reputation/reputation_web_contents_observer.cc
+++ b/chrome/browser/reputation/reputation_web_contents_observer.cc
@@ -308,11 +308,8 @@
   if (!called_from_visibility_check) {
     web_contents()->GetPrimaryMainFrame()->AddMessageToConsole(
         blink::mojom::ConsoleMessageLevel::kWarning,
-        base::StringPrintf(
-            "Chrome has determined that %s could be fake or fraudulent.\n\n"
-            "If you believe this is shown in error please visit "
-            "https://g.co/chrome/lookalike-warnings",
-            result.url.host().c_str()));
+        lookalikes::GetConsoleMessage(result.url,
+                                      /*is_new_heuristic=*/false));
   }
 
   if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker.cc b/chrome/browser/resource_coordinator/tab_load_tracker.cc
index dc95cd9..e8f4782c 100644
--- a/chrome/browser/resource_coordinator/tab_load_tracker.cc
+++ b/chrome/browser/resource_coordinator/tab_load_tracker.cc
@@ -10,7 +10,7 @@
 #include "base/containers/contains.h"
 #include "base/observer_list.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
 #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
index 7e8ace2..9b1fe33 100644
--- a/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_load_tracker_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/process/kill.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
diff --git a/chrome/browser/resources/chromeos/OWNERS b/chrome/browser/resources/chromeos/OWNERS
index 4df5c77..fd2a5d3 100644
--- a/chrome/browser/resources/chromeos/OWNERS
+++ b/chrome/browser/resources/chromeos/OWNERS
@@ -1,9 +1,3 @@
 file://ash/webui/PLATFORM_OWNERS
 
-achuith@chromium.org
-alemate@chromium.org
-hidehiko@chromium.org
-khorimoto@chromium.org
-xiyuan@chromium.org
-
 per-file drive_internals*=file://ui/file_manager/OWNERS
diff --git a/chrome/browser/resources/chromeos/notification_tester/form_constants.js b/chrome/browser/resources/chromeos/notification_tester/form_constants.js
index 344f7e4..849f240 100644
--- a/chrome/browser/resources/chromeos/notification_tester/form_constants.js
+++ b/chrome/browser/resources/chromeos/notification_tester/form_constants.js
@@ -242,6 +242,7 @@
   originURL: '',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.SYSTEM_COMPONENT,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'none',
   richDataNeverTimeout: false,
@@ -268,6 +269,7 @@
   originURL: '',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.SYSTEM_COMPONENT,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'chromium_logo_large_png',
   richDataSmallImage: 'none',
   richDataNeverTimeout: false,
@@ -293,6 +295,7 @@
   originURL: '',
   notificationType: NotificationType.NOTIFICATION_TYPE_PROGRESS,
   notifierType: NotifierType.SYSTEM_COMPONENT,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'none',
   richDataNeverTimeout: false,
@@ -318,6 +321,7 @@
   originURL: '',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.SYSTEM_COMPONENT,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'kProductIcon',
   richDataNeverTimeout: false,
@@ -343,6 +347,7 @@
   originURL: 'https://testurl.xyz',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.WEB_PAGE,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'kProductIcon',
   richDataNeverTimeout: false,
@@ -364,6 +369,7 @@
   originURL: 'https://testurl.xyz',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.WEB_PAGE,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'kProductIcon',
   richDataNeverTimeout: false,
@@ -385,6 +391,7 @@
   originURL: 'https://testurl.xyz',
   notificationType: NotificationType.NOTIFICATION_TYPE_SIMPLE,
   notifierType: NotifierType.WEB_PAGE,
+  warningLevel: SystemNotificationWarningLevel.NORMAL,
   richDataImage: 'none',
   richDataSmallImage: 'kProductIcon',
   richDataNeverTimeout: false,
diff --git a/chrome/browser/resources/extensions/site_permissions_by_site.html b/chrome/browser/resources/extensions/site_permissions_by_site.html
index 6d6e83b..deed7ad 100644
--- a/chrome/browser/resources/extensions/site_permissions_by_site.html
+++ b/chrome/browser/resources/extensions/site_permissions_by_site.html
@@ -21,7 +21,8 @@
     </div>
     <div id="site-groups">
       <template is="dom-repeat" items="[[siteGroups_]]">
-        <site-permissions-site-group data="[[item]]">
+        <site-permissions-site-group data="[[item]]" delegate="[[delegate]]"
+            list-index="[[index]]">
         </site-permissions-site-group>
       </template>
     </div>
diff --git a/chrome/browser/resources/extensions/site_permissions_by_site.ts b/chrome/browser/resources/extensions/site_permissions_by_site.ts
index ba8f948..d2b4e29e 100644
--- a/chrome/browser/resources/extensions/site_permissions_by_site.ts
+++ b/chrome/browser/resources/extensions/site_permissions_by_site.ts
@@ -45,9 +45,15 @@
   private siteGroups_: chrome.developerPrivate.SiteGroup[];
 
   override ready() {
-    // TODO(crbug.com/1253673): Observe for changes in user specified sites and
-    // extension host permissions.
+    // TODO(crbug.com/1253673): Observe for changes in extension host
+    // permissions.
     super.ready();
+    this.refreshUserAndExtensionSites_();
+    this.delegate.getUserSiteSettingsChangedTarget().addListener(
+        this.refreshUserAndExtensionSites_.bind(this));
+  }
+
+  private refreshUserAndExtensionSites_() {
     this.delegate.getUserAndExtensionSitesByEtld().then(sites => {
       this.siteGroups_ = sites;
     });
diff --git a/chrome/browser/resources/extensions/site_permissions_site_group.html b/chrome/browser/resources/extensions/site_permissions_site_group.html
index 71aecd7..470bbe2 100644
--- a/chrome/browser/resources/extensions/site_permissions_site_group.html
+++ b/chrome/browser/resources/extensions/site_permissions_site_group.html
@@ -1,7 +1,7 @@
 <style include="cr-shared-style cr-icons shared-style">
   #etld-row {
     align-items: center;
-    border-bottom: var(--cr-separator-line);
+    /* border-bottom: var(--cr-separator-line); */
     display: flex;
     height: var(--cr-section-two-line-min-height);
   }
@@ -25,7 +25,7 @@
 
   .site-row {
     align-items: center;
-    border-bottom: var(--cr-separator-line);
+    /* border-top: var(--cr-separator-line); */
     display: flex;
     height: var(--cr-section-min-height);
   }
@@ -48,7 +48,7 @@
     flex-shrink: 0;
   }
 </style>
-<div id="etld-row">
+<div id="etld-row" class$="[[getClassForIndex_(listIndex)]]">
   <div class="site-favicon"
       style$="background-image:[[getEtldOrSiteFaviconUrl_(data)]]"></div>
   <div id="etld-and-subtext">
@@ -60,16 +60,32 @@
         expanded="{{expanded_}}">
     </cr-expand-button>
   </template>
+  <template is="dom-if" if="[[!isExpandable_]]">
+    <cr-icon-button class="subpage-arrow" id="edit-one-site-button"
+        on-click="onEditSiteClick_">
+    </cr-icon-button>
+  </template>
 </div>
 <div id="sites-list" hidden$="[[!expanded_]]">
   <template is="dom-repeat" items="[[data.sites]]">
-    <div class="site-row">
+    <div class="site-row hr">
       <div class="site-favicon"
           style$="background-image:[[getFaviconUrl_(item.site)]]"></div>
       <div class="site-and-subtext">
         <span class="site">[[item.site]]</span>
         <span class="site-subtext">[[getSiteSubtext_(item.siteList)]]</span>
       </div>
+      <cr-icon-button class="subpage-arrow" on-click="onEditSiteInListClick_">
+      </cr-icon-button>
     </div>
   </template>
 </div>
+
+<template is="dom-if" if="[[showEditSitePermissionsDialog_]]" restamp>
+  <site-permissions-edit-permissions-dialog
+      delegate="[[delegate]]"
+      site="[[siteToEdit_.site]]"
+      original-site-set="[[siteToEdit_.siteList]]"
+      on-close="onEditSitePermissionsDialogClose_">
+  </site-permissions-edit-permissions-dialog>
+</template>
diff --git a/chrome/browser/resources/extensions/site_permissions_site_group.ts b/chrome/browser/resources/extensions/site_permissions_site_group.ts
index 7c77e76..d5009ec 100644
--- a/chrome/browser/resources/extensions/site_permissions_site_group.ts
+++ b/chrome/browser/resources/extensions/site_permissions_site_group.ts
@@ -9,11 +9,14 @@
 import './strings.m.js';
 import './shared_style.css.js';
 import './shared_vars.css.js';
+import './site_permissions_edit_permissions_dialog.js';
 
+import {assert} from 'chrome://resources/js/assert_ts.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './site_permissions_site_group.html.js';
+import {SiteSettingsDelegate} from './site_settings_mixin.js';
 import {getFaviconUrl} from './url_util.js';
 
 export interface SitePermissionsSiteGroupElement {
@@ -35,6 +38,12 @@
   static get properties() {
     return {
       data: Object,
+      delegate: Object,
+
+      listIndex: {
+        type: Number,
+        value: -1,
+      },
 
       expanded_: {
         type: Boolean,
@@ -45,12 +54,26 @@
         type: Boolean,
         computed: 'computeIsExpandable_(data.sites)',
       },
+
+      showEditSitePermissionsDialog_: {
+        type: Boolean,
+        value: false,
+      },
+
+      siteToEdit_: {
+        type: Object,
+        value: null,
+      },
     };
   }
 
   data: chrome.developerPrivate.SiteGroup;
+  delegate: SiteSettingsDelegate;
+  listIndex: number;
   private expanded_: boolean;
   private isExpandable_: boolean;
+  private showEditSitePermissionsDialog_: boolean;
+  private siteToEdit_: chrome.developerPrivate.SiteInfo|null;
 
   private getEtldOrSiteFaviconUrl_(): string {
     return getFaviconUrl(this.getDisplayUrl_());
@@ -64,6 +87,10 @@
     return this.data.sites.length > 1;
   }
 
+  private getClassForIndex_(): string {
+    return this.listIndex > 0 ? 'hr' : '';
+  }
+
   private getDisplayUrl_(): string {
     return this.data.sites.length === 1 ? this.data.sites[0].site :
                                           this.data.etldPlusOne;
@@ -94,6 +121,23 @@
             'permittedSites' :
             'restrictedSites');
   }
+
+  private onEditSiteClick_() {
+    this.siteToEdit_ = this.data.sites[0];
+    this.showEditSitePermissionsDialog_ = true;
+  }
+
+  private onEditSiteInListClick_(
+      e: DomRepeatEvent<chrome.developerPrivate.SiteInfo>) {
+    this.siteToEdit_ = e.model.item;
+    this.showEditSitePermissionsDialog_ = true;
+  }
+
+  private onEditSitePermissionsDialogClose_() {
+    this.showEditSitePermissionsDialog_ = false;
+    assert(this.siteToEdit_, 'Site To Edit');
+    this.siteToEdit_ = null;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 9a1d37d..b6d81b84 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -63,19 +63,15 @@
 preprocess_if_expr("preprocess") {
   defines = chrome_grit_defines
   out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = ts_files
+  in_files = ts_files + html_files + icons_html_files + css_files
 }
 
 preprocess_if_expr("preprocess_generated") {
   defines = chrome_grit_defines
-  deps = [
-    ":css_wrapper_files",
-    ":css_wrapper_files_old",
-    ":html_wrapper_files",
-  ]
+  deps = [ ":css_wrapper_files_old" ]
   in_folder = target_gen_dir
   out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = html_wrapper_files + css_wrapper_files + css_wrapper_files_old
+  in_files = css_wrapper_files_old
 }
 
 grit("resources") {
@@ -123,11 +119,19 @@
 }
 
 html_to_wrapper("html_wrapper_files") {
+  deps = [ ":preprocess" ]
+  in_folder = "$target_gen_dir/$preprocess_folder"
+  out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = html_files + icons_html_files
+  minify = optimize_webui
 }
 
 css_to_wrapper("css_wrapper_files") {
+  deps = [ ":preprocess" ]
+  in_folder = "$target_gen_dir/$preprocess_folder"
+  out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = css_files
+  minify = optimize_webui
 }
 
 ts_library("build_ts") {
@@ -166,6 +170,8 @@
   }
 
   extra_deps = [
+    ":css_wrapper_files",
+    ":html_wrapper_files",
     ":preprocess",
     ":preprocess_generated",
   ]
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.ts b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
index 27bca158..119e82d 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.ts
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
 import '../controls/settings_toggle_button.js';
 import '../settings_page/settings_animated_pages.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 // <if expr="not is_macosx and not chromeos_ash">
 import './captions_subpage.js';
 import '../settings_page/settings_subpage.js';
diff --git a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
index 5b0d047..1f85c6a 100644
--- a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
+++ b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
@@ -10,7 +10,7 @@
 
 import '//resources/cr_elements/shared_style_css.m.js';
 import '../controls/settings_slider.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './live_caption_section.js';
 
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
index 096084a8..5d2b0f76 100644
--- a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
+++ b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
@@ -12,7 +12,7 @@
 
 import '//resources/cr_elements/shared_style_css.m.js';
 import '../controls/settings_toggle_button.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {WebUIListenerMixin} from '//resources/js/web_ui_listener_mixin.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/about_page/about_page.ts b/chrome/browser/resources/settings/about_page/about_page.ts
index abfc284..73dee008 100644
--- a/chrome/browser/resources/settings/about_page/about_page.ts
+++ b/chrome/browser/resources/settings/about_page/about_page.ts
@@ -14,7 +14,7 @@
 // </if>
 import '../settings_page/settings_section.js';
 import '../settings_page_styles.css.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
index 89d1a6b3..3aaa68c 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
+++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../controls/settings_slider.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../controls/settings_dropdown_menu.js';
 
 import {SliderTick} from 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_page.ts
index 56f3cd9..ab535b2a 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.ts
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.ts
@@ -13,7 +13,7 @@
 import '../controls/settings_toggle_button.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import './home_url_input.js';
 import '../controls/settings_dropdown_menu.js';
diff --git a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts
index f05dcc09..ac77926ed 100644
--- a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import '../controls/settings_textarea.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.ts b/chrome/browser/resources/settings/autofill_page/autofill_page.ts
index e80758fb..7c2a10e 100644
--- a/chrome/browser/resources/settings/autofill_page/autofill_page.ts
+++ b/chrome/browser/resources/settings/autofill_page/autofill_page.ts
@@ -12,7 +12,7 @@
 import '../prefs/prefs.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.ts b/chrome/browser/resources/settings/autofill_page/autofill_section.ts
index 5f3bc09..399e3f8 100644
--- a/chrome/browser/resources/settings/autofill_page/autofill_section.ts
+++ b/chrome/browser/resources/settings/autofill_page/autofill_section.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../controls/extension_controlled_indicator.js';
 import '../controls/settings_toggle_button.js';
 import '../prefs/prefs.js';
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts
index 0856ec2..1527c0e 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import '../i18n_setup.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
index 450a816..9fe61bd 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../i18n_setup.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './passwords_shared.css.js';
 
 import {I18nMixin} from '//resources/js/i18n_mixin.js';
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.ts b/chrome/browser/resources/settings/autofill_page/password_check.ts
index e4e499a..e1727af 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check.ts
@@ -4,7 +4,7 @@
 
 import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
index 6da3bfa5..a15aade 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/cr_icons_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import './passwords_shared.css.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
index a660b17..dc7f059 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_icons_css.m.js';
 import 'chrome://resources/js/action_link.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 import './passwords_shared.css.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
index b547f6c..94b03859 100644
--- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/cr_icons_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import './passwords_shared.css.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_list_item.ts
index 6d1e70c1..369f7abd3 100644
--- a/chrome/browser/resources/settings/autofill_page/password_list_item.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_list_item.ts
@@ -11,7 +11,7 @@
 
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_icons_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 import './passwords_shared.css.js';
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.ts b/chrome/browser/resources/settings/autofill_page/password_view.ts
index 78b860db..083d136 100644
--- a/chrome/browser/resources/settings/autofill_page/password_view.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_view.ts
@@ -15,7 +15,7 @@
 // <if expr="chromeos_ash or chromeos_lacros">
 import '../controls/password_prompt_dialog.js';
 // </if>
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './password_edit_dialog.js';
 import './password_remove_dialog.js';
 import './passwords_shared.css.js';
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts b/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts
index 89688226..78ca39a 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts
+++ b/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts
@@ -13,7 +13,7 @@
 
 import './passwords_list_handler.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './avatar_icon.js';
 import './passwords_shared.css.js';
 import './password_list_item.js';
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts
index ab924e8..6512b2d 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/paper-progress/paper-progress.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
 import {microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.ts b/chrome/browser/resources/settings/autofill_page/passwords_section.ts
index c9194af..8219278 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_section.ts
+++ b/chrome/browser/resources/settings/autofill_page/passwords_section.ts
@@ -22,7 +22,7 @@
 // </if>
 import '../controls/settings_toggle_button.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 import './password_list_item.js';
 import './passwords_list_handler.js';
diff --git a/chrome/browser/resources/settings/autofill_page/payments_list.ts b/chrome/browser/resources/settings/autofill_page/payments_list.ts
index c058c60..afe3a5b 100644
--- a/chrome/browser/resources/settings/autofill_page/payments_list.ts
+++ b/chrome/browser/resources/settings/autofill_page/payments_list.ts
@@ -8,7 +8,7 @@
  */
 
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './credit_card_list_entry.js';
 import './passwords_shared.css.js';
 import './upi_id_list_entry.js';
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.ts b/chrome/browser/resources/settings/autofill_page/payments_section.ts
index 50bf046..c637368 100644
--- a/chrome/browser/resources/settings/autofill_page/payments_section.ts
+++ b/chrome/browser/resources/settings/autofill_page/payments_section.ts
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../controls/settings_toggle_button.js';
 import '../prefs/prefs.js';
 import './credit_card_edit_dialog.js';
diff --git a/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts b/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts
index c529e6a0..016f037 100644
--- a/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts
+++ b/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts
@@ -10,9 +10,10 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../i18n_setup.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './upi_id_list_entry.html.js';
 
 class SettingsUpiIdListEntryElement extends PolymerElement {
diff --git a/chrome/browser/resources/settings/autofill_page/virtual_card_unenroll_dialog.ts b/chrome/browser/resources/settings/autofill_page/virtual_card_unenroll_dialog.ts
index 264c0b9..f5d387b3 100644
--- a/chrome/browser/resources/settings/autofill_page/virtual_card_unenroll_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/virtual_card_unenroll_dialog.ts
@@ -12,11 +12,12 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './virtual_card_unenroll_dialog.html.js';
 
 declare global {
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts
index c0383f16..b69acb9 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts
@@ -14,7 +14,7 @@
 import '../controls/controlled_button.js';
 import '../controls/settings_checkbox.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts
index 3922c3cb..4cb2523 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts
@@ -4,7 +4,7 @@
 
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 2fa6c17..4097281 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -467,7 +467,7 @@
     "relaunch_mixin.js",
     "setting_id_param_util.js",
     "settings_page_styles.css.js",
-    "settings_shared_css.js",
+    "settings_shared.css.js",
     "settings_vars.css.js",
   ]
 
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js
index 30ead9c..7e51bb5 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import './text_with_tooltip.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
index 24f851d..67ea169 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
index 6c45aad..b5f378f 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
@@ -14,7 +14,7 @@
 import '../../prefs/prefs.js';
 import '../../controls/settings_radio_group.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js
index 1cb9c299..4a70d8f 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js
@@ -10,7 +10,7 @@
 import './art_album_dialog.js';
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js
index 692da0b2..827a0e2 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js
@@ -8,7 +8,7 @@
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js
index d76630c..71c65bd 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js
@@ -9,7 +9,7 @@
 
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js
index c5fdc706..5c6ca9d 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js
index b338fde8..480c39a3 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.js b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.js
index ddd519f..a77d83d9 100644
--- a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.js
+++ b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {FocusRowBehavior, FocusRowBehaviorInterface} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.js
index 7546cc4..d60e44f 100644
--- a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.js
+++ b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.js
@@ -16,7 +16,7 @@
 import '../../prefs/prefs.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './bluetooth_subpage.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
index b6927178..27c62742 100644
--- a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
 import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './bluetooth_device_list_item.js';
 
 import {BluetoothUiSurface, recordBluetoothUiSurfaceMetrics, recordUserInitiatedReconnectionAttemptDuration} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_metrics_utils.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/bruschetta_subpage.js b/chrome/browser/resources/settings/chromeos/crostini_page/bruschetta_subpage.js
index afb8c87..8aa5515 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/bruschetta_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/bruschetta_subpage.js
@@ -9,7 +9,7 @@
  */
 
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb.js
index c1ff6fa..ec5fde87 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import './crostini_arc_adb_confirmation_dialog.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.js
index 0e91fb7..0af1b19 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_confirmation_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_confirmation_dialog.js
index a8ff9d0c..03a61e2 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_confirmation_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_confirmation_dialog.js
@@ -14,7 +14,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js
index 46103989..787b9014 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
index 48ea003..f5160b3 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_export_import.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_export_import.js
index b1545bd..4739b557 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_export_import.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_export_import.js
@@ -10,7 +10,7 @@
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import './crostini_import_confirmation_dialog.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js
index e2eb23df..50be5da 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import './crostini_extra_containers_create_dialog.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers_create_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers_create_dialog.js
index 54f430ec..f29c8ba 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers_create_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers_create_dialog.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_import_confirmation_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_import_confirmation_dialog.js
index 91f0d0f1..4d5153b 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_import_confirmation_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_import_confirmation_dialog.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.js
index 60d12b7..08112a3 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../guest_os/guest_os_shared_paths.js';
 import '../guest_os/guest_os_shared_usb_devices.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.js
index 3b322af2..f9ab6cf 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.js
@@ -16,7 +16,7 @@
 import '../../controls/settings_toggle_button.js';
 import '../../settings_page/settings_section.js';
 import '../../settings_page_styles.css.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.js
index 37cf5f0..319c50e 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../guest_os/guest_os_container_select.js';
 
 import {html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
index e890ad0..a79c62f 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../../controls/settings_toggle_button.js';
 import './crostini_confirmation_dialog.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './crostini_disk_resize_dialog.js';
 import './crostini_disk_resize_confirmation_dialog.js';
 import './crostini_port_forwarding.js';
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.js b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.js
index 79d3a870..d473eb11 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.js
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
 import '../../controls/settings_toggle_button.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './date_time_types.js';
 import './timezone_selector.js';
 import './timezone_subpage.js';
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.js b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.js
index c84a9d64..edee172 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.js
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.js
@@ -6,7 +6,7 @@
  * @fileoverview 'timezone-selector' is the time zone selector dropdown.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../controls/settings_dropdown_menu.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.js b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.js
index 41dea75..5ee019d 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.js
@@ -9,7 +9,7 @@
 import '../../controls/controlled_radio_button.js';
 import '../../controls/settings_radio_group.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './timezone_selector.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/audio.js b/chrome/browser/resources/settings/chromeos/device_page/audio.js
index 230db8d..2a41316 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/audio.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/audio.js
@@ -4,7 +4,7 @@
 
 import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
 import '../../icons.html.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page.js b/chrome/browser/resources/settings/chromeos/device_page/device_page.js
index 0d3f74e..dfce905 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page.js
@@ -18,7 +18,7 @@
 import '../../prefs/prefs.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/display.js b/chrome/browser/resources/settings/chromeos/device_page/display.js
index 6ad01efc..ed1c7c1 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/display.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/display.js
@@ -18,7 +18,7 @@
 import './display_overscan_dialog.js';
 import '../settings_scheduler_slider/settings_scheduler_slider.js';
 import '../../controls/settings_slider.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import '../../controls/settings_dropdown_menu.js';
 import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/display_layout.js b/chrome/browser/resources/settings/chromeos/device_page/display_layout.js
index 878d31f..d05b2cc 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/display_layout.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/display_layout.js
@@ -9,7 +9,7 @@
  */
 
 import 'chrome://resources/polymer/v3_0/paper-styles/shadow.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {IronResizableBehavior} from 'chrome://resources/polymer/v3_0/iron-resizable-behavior/iron-resizable-behavior.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/display_overscan_dialog.js b/chrome/browser/resources/settings/chromeos/device_page/display_overscan_dialog.js
index fe17194..6f487f61 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/display_overscan_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/display_overscan_dialog.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.js b/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
index 4c32d8c..0749d6a 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.js
@@ -6,7 +6,7 @@
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../controls/settings_dropdown_menu.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/pointers.js b/chrome/browser/resources/settings/chromeos/device_page/pointers.js
index f6f19f6..3230a37 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/pointers.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/pointers.js
@@ -12,7 +12,7 @@
 import '../../controls/settings_radio_group.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/power.js b/chrome/browser/resources/settings/chromeos/device_page/power.js
index 9558a113..4923671 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/power.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/power.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/storage.js b/chrome/browser/resources/settings/chromeos/device_page/storage.js
index db4e50d1..d9e8fd7 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/storage.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/storage.js
@@ -9,7 +9,7 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import './storage_external.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/storage_external.js b/chrome/browser/resources/settings/chromeos/device_page/storage_external.js
index aff3b4df..45b19a7 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/storage_external.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/storage_external.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './storage_external_entry.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/storage_external_entry.js b/chrome/browser/resources/settings/chromeos/device_page/storage_external_entry.js
index d4ba1152..d0ee12a 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/storage_external_entry.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/storage_external_entry.js
@@ -9,7 +9,7 @@
  * the storage's uuid will be saved to a preference.
  */
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/stylus.js b/chrome/browser/resources/settings/chromeos/device_page/stylus.js
index 7f087d9e..cb677bc 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/stylus.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/stylus.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/js/action_link.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
index 10cad0a..ae964bc 100644
--- a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
+++ b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
@@ -13,7 +13,7 @@
 import '../../controls/settings_toggle_button.js';
 import '../../prefs/prefs.js';
 import '../../prefs/pref_util.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_container_select.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_container_select.js
index 961a3a4..85de4c9 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_container_select.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_container_select.js
@@ -7,7 +7,7 @@
  * user to select a target container from a list stored in prefs.
  */
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
index bfc8df07..a166c369 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_paths.js
@@ -9,7 +9,7 @@
 
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
index 1dcff7a..b58df5b 100644
--- a/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
+++ b/chrome/browser/resources/settings/chromeos/guest_os/guest_os_shared_usb_devices.js
@@ -9,7 +9,7 @@
  */
 
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_roaming_toggle_button.js b/chrome/browser/resources/settings/chromeos/internet_page/cellular_roaming_toggle_button.js
index e84725d4d..1402ef1c 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_roaming_toggle_button.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/cellular_roaming_toggle_button.js
@@ -10,7 +10,7 @@
  */
 
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.js b/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.js
index d322cb4..8431515 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.js
@@ -9,7 +9,7 @@
 import 'chrome://resources/cr_components/chromeos/cellular_setup/cellular_setup.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CellularSetupDelegate} from 'chrome://resources/cr_components/chromeos/cellular_setup/cellular_setup_delegate.m.js';
 import {CellularSetupPageName} from 'chrome://resources/cr_components/chromeos/cellular_setup/cellular_types.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_menu.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_menu.js
index 171e6a7..8df05ed0 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_menu.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_menu.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {ESimManagerListenerBehavior, ESimManagerListenerBehaviorInterface} from 'chrome://resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.m.js';
 import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/cr_components/chromeos/network/mojo_interface_provider.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js
index 25a294c..2646363 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
 import 'chrome://resources/cr_elements/icons.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './internet_shared_css.js';
 
 import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
index dd26e014..e55c52e 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
@@ -20,7 +20,7 @@
 import '../../prefs/prefs.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './cellular_setup_dialog.js';
 import './internet_detail_menu.js';
 import './internet_detail_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js
index 66d5c46e..ea0678d 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 const template = document.createElement('template');
 template.innerHTML = `
 <dom-module id="internet-shared" assetpath="chrome://resources/">{__html_template__}</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js
index 27504633..1da7166 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_subpage.js
@@ -18,7 +18,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../os_settings_icons_css.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './cellular_networks_list.js';
 import './network_always_on_vpn.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js b/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js
index c1e8401..0658046 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js
index 497ec74..b4284a0 100644
--- a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js
+++ b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './kerberos_add_account_dialog.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_add_account_dialog.js b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_add_account_dialog.js
index 308cd0e..41ee93c 100644
--- a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_add_account_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_add_account_dialog.js
@@ -17,7 +17,7 @@
 import 'chrome://resources/js/action_link.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../../controls/settings_textarea.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_page.js b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_page.js
index 5356e40..b385442c 100644
--- a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_page.js
+++ b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_page.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './kerberos_accounts.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
index f7744e70..e702320 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
index 24700bf..fb8fa90 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
index dd7cbdf..50109fe 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
@@ -9,7 +9,7 @@
 import '../../controls/password_prompt_dialog.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../nearby_share_page/nearby_share_subpage.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './multidevice_feature_toggle.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
index 09457ebd..f8e9ecbc02 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js
@@ -17,7 +17,7 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import './multidevice_screen_lock_subpage.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
index 40daea6..ee668c7b 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_radio_button.js
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js';
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrRadioButtonBehavior, CrRadioButtonBehaviorInterface} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js
index 2559ee1..151bb04 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js
@@ -6,7 +6,7 @@
 import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
 import './multidevice_feature_toggle.js';
 import './multidevice_radio_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
index 8b9594f..cc0b15b 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import './multidevice_combined_setup_item.js';
 import './multidevice_feature_item.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
index 9e626c2..ce721ebb 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
@@ -13,7 +13,7 @@
  * and the other to a Learn More page for Phone Hub.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
index 4d19e76..071dff4 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
@@ -20,7 +20,7 @@
 import './multidevice_feature_item.js';
 import './multidevice_task_continuation_disabled_link.js';
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
index 5fadf7f..83382a9 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
@@ -12,7 +12,7 @@
  */
 
 import 'chrome://resources/cr_components/chromeos/network/network_icon.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import './multidevice_feature_item.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
index 9dae1d2..6d2c0b6 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js
@@ -12,7 +12,7 @@
  * and the other to a Learn More page for Wifi Sync.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
index 10b527c9..b2568b1 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.js
@@ -18,7 +18,7 @@
 import './multidevice_feature_item.js';
 import './multidevice_wifi_sync_disabled_link.js';
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js
index 7475e0e..1545343 100644
--- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../../controls/settings_toggle_button.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './nearby_share_contact_visibility_dialog.js';
 import './nearby_share_device_name_dialog.js';
 import './nearby_share_data_usage_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.js
index 78f577e..f6d5d76f 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/audio_and_captions_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/change_dictation_locale_dialog.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/change_dictation_locale_dialog.js
index 76448f8..bbaafa8 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/change_dictation_locale_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/change_dictation_locale_dialog.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {afterNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.js
index 07b6449..a5b892f7 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.js
index 8c76038..d8a8dbf 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.js
index e9227b6ed..9a994349 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
index 85ff8bb..e7510a7 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.js
index 77eccc22..50f573b 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page.js
@@ -12,7 +12,7 @@
 import '../../controls/settings_toggle_button.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './manage_a11y_page.js';
 import './text_to_speech_page.js';
 import './display_and_magnification_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_setup_guide_warning_dialog.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_setup_guide_warning_dialog.js
index 78df08c..40880ef 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_setup_guide_warning_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_setup_guide_warning_dialog.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
index 53943564..d17d7e66 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_subpage.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import '../../controls/settings_slider.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './switch_access_action_assignment_dialog.js';
 import './switch_access_setup_guide_dialog.js';
 import './switch_access_setup_guide_warning_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.js
index 84a5081a..9eeea7e 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.js
@@ -10,7 +10,7 @@
 
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage.js
index 1fe9ed1e..50e48d4 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import '../../controls/settings_slider.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.js b/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.js
index 419b7d2..d92a304 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
 import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.js b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.js
index 62b86f94..cfdc6dfe 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './channel_switcher_dialog.js';
 import './consumer_auto_update_toggle_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.js b/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.js
index 5d161e8..94dda78 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
 import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
index 975fc620..95e9936d 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
@@ -13,7 +13,7 @@
 import '../../settings_page/settings_section.js';
 import '../../settings_page/settings_subpage.js';
 import '../../settings_page_styles.css.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../os_icons.js';
 import '../os_reset_page/os_powerwash_dialog.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js b/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
index 029206d4..dd28293 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
index ef8914b..057ddb5 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js
index 94c3a9ed..41b0b09f 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js
@@ -8,7 +8,7 @@
 import './chrome_app_detail_view.js';
 import './plugin_vm_page/plugin_vm_detail_view.js';
 import './borealis_page/borealis_detail_view.js';
-import '../../../settings_shared_css.js';
+import '../../../settings_shared.css.js';
 
 import {AppManagementUserAction, AppType} from 'chrome://resources/cr_components/app_management/constants.js';
 import {getSelectedApp, recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
index 752df2e..e6332d63 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_management_page.js
@@ -6,7 +6,7 @@
 
 import './api_listener.js';
 import './main_view.js';
-import '../../../settings_shared_css.js';
+import '../../../settings_shared.css.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
index 4cc9a2a..e5e4abb 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
@@ -13,8 +13,8 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
+import '../../settings_shared.css.js';
 import '../guest_os/guest_os_shared_usb_devices.js';
 import '../guest_os/guest_os_shared_paths.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js
index 0f690d96..8491920d0 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js
@@ -7,7 +7,7 @@
  * Settings dialog is used to change a Bluetooth device nickname.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 
 import {getDeviceName} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_utils.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js
index 7a134e5..e008595b 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js
@@ -8,7 +8,7 @@
  * only be called when a device exist.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
 import './os_bluetooth_change_device_name_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
index c3b1df0..36d7653 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
@@ -7,7 +7,7 @@
  * Settings subpage for managing Bluetooth properties and devices.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './os_paired_bluetooth_list.js';
 import './settings_fast_pair_toggle.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.js
index 78abce5a..e24bb7b 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.js
@@ -10,7 +10,7 @@
 
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_page/settings_animated_pages.js';
 import './os_bluetooth_devices_subpage.js';
 import './os_bluetooth_summary.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js
index df615d7..ef2f6fd 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js
@@ -7,7 +7,7 @@
  * Settings subpage for managing Bluetooth saved devices.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.js
index d3f98c12..33577c4 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.js
@@ -8,7 +8,7 @@
  * its connected devices.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js
index 6de61d8d..933477d 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js
@@ -8,7 +8,7 @@
  * information.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage.js';
 
 import {BatteryType} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_types.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.js
index c11cd8fde..cb399aa8 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.js
@@ -7,7 +7,7 @@
  * UI element for displaying paired Bluetooth devices.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './os_paired_bluetooth_list_item.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js
index 74f67cc..fe0fe970 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js
@@ -8,7 +8,7 @@
  * Bluetooth device.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.js b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.js
index ede08c8..a166dde 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.js
@@ -10,7 +10,7 @@
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './smb_shares_page.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.js b/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.js
index ab40ee4..59e285b 100644
--- a/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.js
@@ -8,7 +8,7 @@
 import 'chrome://resources/js/action_link.js';
 import 'chrome://resources/cr_elements/action_link_css.m.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js
index 57f72fcf..7abf496 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_items_dialog.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import './cr_checkbox_with_policy.js';
 import './shared_style.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrScrollableBehavior, CrScrollableBehaviorInterface} from 'chrome://resources/cr_elements/cr_scrollable_behavior.m.js';
 import {FindShortcutBehavior, FindShortcutBehaviorInterface} from 'chrome://resources/cr_elements/find_shortcut_behavior.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.js b/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.js
index d9d23d8..9bf8d60c 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.js
@@ -15,7 +15,7 @@
 import './shared_style.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './languages.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrScrollableBehavior, CrScrollableBehaviorInterface} from 'chrome://resources/cr_elements/cr_scrollable_behavior.m.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
index 04b2f2b9..bbe3ea8 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
@@ -8,7 +8,7 @@
  */
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
index 332ff0a..795f0e9 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
@@ -17,7 +17,7 @@
 import './os_edit_dictionary_page.js';
 import '../keyboard_shortcut_banner/keyboard_shortcut_banner.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_page/settings_animated_pages.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.js
index b1bfe0e..5f51de8a 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.js
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-a11y-keys/iron-a11y-keys.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
index 4381f43..4df921e 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
@@ -20,7 +20,7 @@
 import './os_add_languages_dialog.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
index f009354..4217fe2 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
@@ -17,7 +17,7 @@
 import './languages.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
index a2fd91c..092572a 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
@@ -9,7 +9,7 @@
 
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
index f5d4bb2..2c0b9a08 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {getImage} from 'chrome://resources/js/icon.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
index 113d97d..3f0f82f 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
 import './setup_fingerprint_dialog.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
index 2f5297f..90db919 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
@@ -23,7 +23,7 @@
 import './setup_pin_dialog.js';
 import './pin_autosubmit_dialog.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import '../multidevice_page/multidevice_smartlock_item.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
index ad7c1985..3763d386 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
@@ -18,7 +18,7 @@
 import '../../people_page/sync_page.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './account_manager.js';
 import './fingerprint_list.js';
 import './lock_screen.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
index 5960dead..7df6d89 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
@@ -6,7 +6,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js
index 12def23..b1815697 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.js
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/js/assert.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.js
index f4b940e..73c153a 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.js
@@ -6,7 +6,7 @@
 import 'chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.m.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/setup_pin_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/setup_pin_dialog.js
index 03c430bc..6549a39 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/setup_pin_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/setup_pin_dialog.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.m.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/user_list.js b/chrome/browser/resources/settings/chromeos/os_people_page/user_list.js
index 3f52da03..3251ce1a 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/user_list.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/user_list.js
@@ -17,7 +17,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/users_add_user_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/users_add_user_dialog.js
index 78126df..f3a4669 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/users_add_user_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/users_add_user_dialog.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
index 2b3b7224..8428e8aa 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/action_link_css.m.js';
 import 'chrome://resources/js/action_link.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './user_list.js';
 import './users_add_user_dialog.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js
index 15218676..a83a275 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import './cups_printers_entry.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js
index 044cd4e..2876e5f2 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js
@@ -8,7 +8,7 @@
  */
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import './cups_printers_entry.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js
index 53e890a..83ecd895 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 const template = document.createElement('template');
 template.innerHTML = `
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js
index 781232f..37aec9b 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js
@@ -8,7 +8,7 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {FocusRowBehavior, FocusRowBehaviorInterface} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js
index ccad5f08..4803b57 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import './cups_printers_entry.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js b/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js
index d93e31d9..c9314f5 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js
@@ -4,7 +4,7 @@
 
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './cups_printers.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/os_privacy_page.js b/chrome/browser/resources/settings/chromeos/os_privacy_page/os_privacy_page.js
index e36877c..5d68d4a 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/os_privacy_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/os_privacy_page.js
@@ -14,7 +14,7 @@
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
 import './peripheral_data_access_protection_dialog.js';
 import '../../controls/settings_toggle_button.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_page/settings_subpage.js';
 import '../os_people_page/users_page.js';
 import '../../settings_page/settings_animated_pages.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_protection_dialog.js b/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_protection_dialog.js
index 7b44ec02..da07fa0 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_protection_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/peripheral_data_access_protection_dialog.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/polymer/v3_0/paper-progress/paper-progress.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/smart_privacy_page.js b/chrome/browser/resources/settings/chromeos/os_privacy_page/smart_privacy_page.js
index 2d3773fd..64536e5 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/smart_privacy_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/smart_privacy_page.js
@@ -13,7 +13,7 @@
 import '../../controls/extension_controlled_indicator.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.js b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.js
index 5cbb172d..cab7f7b 100644
--- a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.js
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './os_powerwash_dialog_esim_item.js';
 
 import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog_esim_item.js b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog_esim_item.js
index fb1bb73..5e69a18 100644
--- a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog_esim_item.js
+++ b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog_esim_item.js
@@ -7,7 +7,7 @@
  * 'os-settings-powerwash-dialog-esim-item' is an item showing details of an
  * installed eSIM profile shown in a list in the device reset dialog.
  */
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.js b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.js
index 200ddc8d..6cd6c8911 100644
--- a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.js
@@ -15,7 +15,7 @@
 import '../../controls/extension_controlled_indicator.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import '../google_assistant_page/google_assistant_page.js';
 import './search_subpage.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_selection_dialog.js b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_selection_dialog.js
index e7ca66e4..8f0e0d0 100644
--- a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_selection_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_selection_dialog.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/search_engine.js b/chrome/browser/resources/settings/chromeos/os_search_page/search_engine.js
index 0562464..84086e54 100644
--- a/chrome/browser/resources/settings/chromeos/os_search_page/search_engine.js
+++ b/chrome/browser/resources/settings/chromeos/os_search_page/search_engine.js
@@ -17,7 +17,7 @@
 import '../../controls/settings_toggle_button.js';
 import '../../prefs/prefs.js';
 import '../../prefs/pref_util.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.js b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.js
index 2b016ce..34f66e2 100644
--- a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.js
@@ -15,7 +15,7 @@
 import '../../controls/settings_toggle_button.js';
 import '../../prefs/prefs.js';
 import '../../prefs/pref_util.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 import 'chrome://resources/cr_components/localized_link/localized_link.js';
 import './search_engine.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js
index 2539c42d..85376aac 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js
@@ -14,7 +14,7 @@
 import '../os_about_page/os_about_page.js';
 import '../os_settings_page/os_settings_page.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
index 8d30b7a..48e2da0 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../os_icons.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
index 821ca8a..dc8bc2b5 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
@@ -7,7 +7,7 @@
  */
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../os_icons.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_settings_search_box.js b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_settings_search_box.js
index 20fc1d4..c447c310 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_settings_search_box.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_settings_search_box.js
@@ -10,7 +10,7 @@
 import 'chrome://resources/js/cr/ui/focus_row.m.js';
 import 'chrome://resources/polymer/v3_0/iron-dropdown/iron-dropdown.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
index 265345008..81164921 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
@@ -18,7 +18,7 @@
 import '../os_settings_menu/os_settings_menu.js';
 import '../os_settings_main/os_settings_main.js';
 import '../os_toolbar/os_toolbar.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import '../../prefs/prefs.js';
 import '../../settings_vars.css.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
index b8ae4385..ed73dce5 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/change_picture.js b/chrome/browser/resources/settings/chromeos/personalization_page/change_picture.js
index 0265161..ae16c5b 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/change_picture.js
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/change_picture.js
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/chromeos/cr_picture/cr_picture_list.js';
 import 'chrome://resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {CrPicture} from 'chrome://resources/cr_elements/chromeos/cr_picture/cr_picture_types.js';
 import {isEncodedPngDataUrlAnimated} from 'chrome://resources/cr_elements/chromeos/cr_picture/png.js';
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js
index 2384e43f..2ea729d 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js
@@ -12,7 +12,7 @@
 import './change_picture.js';
 import '../../settings_page/settings_animated_pages.js';
 import '../../settings_page/settings_subpage.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/settings_scheduler_slider/settings_scheduler_slider.js b/chrome/browser/resources/settings/chromeos/settings_scheduler_slider/settings_scheduler_slider.js
index 8cbdad5..a26a3a8 100644
--- a/chrome/browser/resources/settings/chromeos/settings_scheduler_slider/settings_scheduler_slider.js
+++ b/chrome/browser/resources/settings/chromeos/settings_scheduler_slider/settings_scheduler_slider.js
@@ -8,7 +8,7 @@
  * start and end times.
  */
 
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
 import {IronResizableBehavior} from 'chrome://resources/polymer/v3_0/iron-resizable-behavior/iron-resizable-behavior.js';
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
index b8f484a..ee19480a 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
@@ -18,7 +18,7 @@
 import './installed_app_checkbox.js';
 import '../controls/settings_checkbox.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts
index e97a644..2da47bda 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts
@@ -10,10 +10,11 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './history_deletion_dialog.html.js';
 
 export interface SettingsHistoryDeletionDialogElement {
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts
index fd8c201..3fd4b17 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts
index 3859251..95395b1 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts
@@ -10,10 +10,11 @@
  */
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './passwords_deletion_dialog.html.js';
 
 export interface SettingsPasswordsDeletionDialogElement {
diff --git a/chrome/browser/resources/settings/controls/controlled_button.ts b/chrome/browser/resources/settings/controls/controlled_button.ts
index dde4dd2..9c6cbee 100644
--- a/chrome/browser/resources/settings/controls/controlled_button.ts
+++ b/chrome/browser/resources/settings/controls/controlled_button.ts
@@ -5,11 +5,11 @@
 import '//resources/cr_elements/cr_button/cr_button.m.js';
 import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
 import '//resources/cr_elements/shared_vars_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './controlled_button.html.js';
 
+import {getTemplate} from './controlled_button.html.js';
 import {CrPolicyPrefMixin} from './cr_policy_pref_mixin.js';
 import {PrefControlMixin} from './pref_control_mixin.js';
 
diff --git a/chrome/browser/resources/settings/controls/controlled_radio_button.ts b/chrome/browser/resources/settings/controls/controlled_radio_button.ts
index e343096..7e38e07 100644
--- a/chrome/browser/resources/settings/controls/controlled_radio_button.ts
+++ b/chrome/browser/resources/settings/controls/controlled_radio_button.ts
@@ -5,7 +5,7 @@
 import '//resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js';
 import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
 import '//resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrRadioButtonBehavior} from '//resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js';
 import {assert} from '//resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts b/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts
index f2d4f5ed..c641d49 100644
--- a/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts
+++ b/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts
@@ -4,7 +4,7 @@
 
 import '//resources/cr_elements/cr_button/cr_button.m.js';
 import '../i18n_setup.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert} from '//resources/js/assert_ts.js';
 import {loadTimeData} from '//resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/settings/controls/password_prompt_dialog.ts b/chrome/browser/resources/settings/controls/password_prompt_dialog.ts
index e924787..504c31059 100644
--- a/chrome/browser/resources/settings/controls/password_prompt_dialog.ts
+++ b/chrome/browser/resources/settings/controls/password_prompt_dialog.ts
@@ -23,11 +23,12 @@
 import '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import '//resources/cr_elements/cr_input/cr_input.m.js';
 import '//resources/cr_elements/shared_style_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.m.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './password_prompt_dialog.html.js';
 
 interface SettingsPasswordPromptDialogElement {
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.ts b/chrome/browser/resources/settings/controls/settings_checkbox.ts
index e339fbe..abcabe6 100644
--- a/chrome/browser/resources/settings/controls/settings_checkbox.ts
+++ b/chrome/browser/resources/settings/controls/settings_checkbox.ts
@@ -8,7 +8,7 @@
  */
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts b/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
index b653071..94b70ee 100644
--- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
+++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
@@ -13,7 +13,7 @@
  */
 import '//resources/cr_elements/md_select_css.m.js';
 import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {assert} from '//resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/controls/settings_radio_group.ts b/chrome/browser/resources/settings/controls/settings_radio_group.ts
index ce40094..47b6760 100644
--- a/chrome/browser/resources/settings/controls/settings_radio_group.ts
+++ b/chrome/browser/resources/settings/controls/settings_radio_group.ts
@@ -14,7 +14,7 @@
  */
 import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
 import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.ts b/chrome/browser/resources/settings/controls/settings_toggle_button.ts
index 404fca1..d329d5c 100644
--- a/chrome/browser/resources/settings/controls/settings_toggle_button.ts
+++ b/chrome/browser/resources/settings/controls/settings_toggle_button.ts
@@ -10,7 +10,7 @@
 import '//resources/cr_elements/cr_toggle/cr_toggle.m.js';
 import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js';
 import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrToggleElement} from '//resources/cr_elements/cr_toggle/cr_toggle.m.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts b/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts
index 8239935..8780c59 100644
--- a/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts
+++ b/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.ts b/chrome/browser/resources/settings/downloads_page/downloads_page.ts
index 439759f..c877741f 100644
--- a/chrome/browser/resources/settings/downloads_page/downloads_page.ts
+++ b/chrome/browser/resources/settings/downloads_page/downloads_page.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../controls/controlled_button.js';
 import '../controls/settings_toggle_button.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
 import {listenOnce} from 'chrome://resources/js/util.m.js';
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts
index 9797243c..fa51ff0 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts
+++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts
@@ -34,13 +34,13 @@
  */
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './incompatible_application_item.html.js';
 
+import {getTemplate} from './incompatible_application_item.html.js';
 import {ActionTypes, IncompatibleApplicationsBrowserProxy, IncompatibleApplicationsBrowserProxyImpl} from './incompatible_applications_browser_proxy.js';
 
 const IncompatibleApplicationItemElementBase = I18nMixin(PolymerElement);
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts
index f11503f8..75094e0 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts
+++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './incompatible_application_item.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts b/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts
index b3694d8e..bc41dc3e 100644
--- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts
+++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_search_field/cr_search_field.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
@@ -20,6 +20,7 @@
 import {CrSearchFieldElement} from 'chrome://resources/cr_elements/cr_search_field/cr_search_field.js';
 import {FindShortcutMixin, FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './add_languages_dialog.html.js';
 
 export interface SettingsAddLanguagesDialogElement {
diff --git a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts
index a10f0b38..77cb79ed 100644
--- a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts
+++ b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts
@@ -14,7 +14,7 @@
 import 'chrome://resources/polymer/v3_0/iron-a11y-keys/iron-a11y-keys.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.ts b/chrome/browser/resources/settings/languages_page/languages_page.ts
index 0e2d3d86..995dcb94 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.ts
+++ b/chrome/browser/resources/settings/languages_page/languages_page.ts
@@ -27,7 +27,7 @@
  // <if expr="not chromeos_ash">
  import '../relaunch_confirmation_dialog.js';
  // </if>
- import '../settings_shared_css.js';
+ import '../settings_shared.css.js';
  import '../settings_vars.css.js';
 
  import {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js';
diff --git a/chrome/browser/resources/settings/languages_page/spell_check_page.ts b/chrome/browser/resources/settings/languages_page/spell_check_page.ts
index c6821f55..e998c4d 100644
--- a/chrome/browser/resources/settings/languages_page/spell_check_page.ts
+++ b/chrome/browser/resources/settings/languages_page/spell_check_page.ts
@@ -27,7 +27,7 @@
 import '../icons.html.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 // <if expr="not is_macosx">
 import './edit_dictionary_page.js';
diff --git a/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts b/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts
index b5bae26..f1f81fd 100644
--- a/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts
+++ b/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts
@@ -13,7 +13,7 @@
 import '../controls/settings_radio_group.js';
 import './startup_urls_page.js';
 import '../i18n_setup.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts
index cae5b95..e7512fa 100644
--- a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts
+++ b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts
index 192c0dc1..5f33697 100644
--- a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts
+++ b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js';
@@ -20,8 +20,8 @@
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {FocusRowBehavior} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './startup_url_entry.html.js';
 
+import {getTemplate} from './startup_url_entry.html.js';
 import {StartupPageInfo, StartupUrlsPageBrowserProxyImpl} from './startup_urls_page_browser_proxy.js';
 
 /**
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts
index 2c72d146..2ee49b5 100644
--- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts
+++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import '../controls/extension_controlled_indicator.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './startup_url_dialog.js';
 
 import {CrScrollableBehavior} from 'chrome://resources/cr_elements/cr_scrollable_behavior.m.js';
diff --git a/chrome/browser/resources/settings/people_page/manage_profile.ts b/chrome/browser/resources/settings/people_page/manage_profile.ts
index bfff28a..9763b78 100644
--- a/chrome/browser/resources/settings/people_page/manage_profile.ts
+++ b/chrome/browser/resources/settings/people_page/manage_profile.ts
@@ -13,7 +13,7 @@
 import 'chrome://resources/cr_components/customize_themes/customize_themes.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/paper-styles/shadow.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js';
 
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
diff --git a/chrome/browser/resources/settings/people_page/people_page.ts b/chrome/browser/resources/settings/people_page/people_page.ts
index a344560..1550b1f 100644
--- a/chrome/browser/resources/settings/people_page/people_page.ts
+++ b/chrome/browser/resources/settings/people_page/people_page.ts
@@ -20,7 +20,7 @@
 import '../icons.html.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 // <if expr="chromeos_ash">
 import {convertImageSequenceToPng} from 'chrome://resources/cr_elements/chromeos/cr_picture/png.js';
diff --git a/chrome/browser/resources/settings/people_page/signout_dialog.ts b/chrome/browser/resources/settings/people_page/signout_dialog.ts
index 2ba5e79b..87432f59 100644
--- a/chrome/browser/resources/settings/people_page/signout_dialog.ts
+++ b/chrome/browser/resources/settings/people_page/signout_dialog.ts
@@ -14,7 +14,7 @@
 import '//resources/cr_elements/shared_vars_css.m.js';
 import '//resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {WebUIListenerMixin} from '//resources/js/web_ui_listener_mixin.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.ts b/chrome/browser/resources/settings/people_page/sync_account_control.ts
index bbeb0e35..16368e0 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.ts
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.ts
@@ -16,7 +16,7 @@
 import './profile_info_browser_proxy.js';
 import '../icons.html.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrButtonElement} from '//resources/cr_elements/cr_button/cr_button.m.js';
 import {assert} from '//resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.ts b/chrome/browser/resources/settings/people_page/sync_controls.ts
index 4e98ea2..759b87d 100644
--- a/chrome/browser/resources/settings/people_page/sync_controls.ts
+++ b/chrome/browser/resources/settings/people_page/sync_controls.ts
@@ -10,7 +10,7 @@
 import '//resources/cr_elements/shared_style_css.m.js';
 import '//resources/cr_elements/shared_vars_css.m.js';
 import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert} from '//resources/js/assert_ts.js';
 import {WebUIListenerMixin} from '//resources/js/web_ui_listener_mixin.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts
index 61651cf..34b9b74 100644
--- a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts
+++ b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts
@@ -7,7 +7,7 @@
 import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
 import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
 import '//resources/cr_elements/shared_style_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.m.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_page.ts b/chrome/browser/resources/settings/people_page/sync_page.ts
index c699c43..72f2395 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.ts
+++ b/chrome/browser/resources/settings/people_page/sync_page.ts
@@ -17,7 +17,7 @@
 import './sync_account_control.js';
 import './sync_encryption_options.js';
 import '../privacy_page/personalization_options.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 // <if expr="not chromeos_ash">
 import '//resources/cr_elements/cr_toast/cr_toast.js';
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
index cfd3ade..9aef1c8 100644
--- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
+++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
@@ -6,11 +6,12 @@
 import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrExpandButtonElement} from 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.m.js';
 import {CrRadioButtonBehavior} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './collapse_radio_button.html.js';
 
 export interface SettingsCollapseRadioButtonElement {
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.ts b/chrome/browser/resources/settings/privacy_page/cookies_page.ts
index d2a4ea2b..04f6ffe 100644
--- a/chrome/browser/resources/settings/privacy_page/cookies_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/cookies_page.ts
@@ -14,7 +14,7 @@
 import '../controls/settings_toggle_button.js';
 import '../icons.html.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_settings/site_list.js';
 import './collapse_radio_button.js';
 import './do_not_track_toggle.js';
diff --git a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts
index b946d45..1baf13b 100644
--- a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts
+++ b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts
@@ -4,7 +4,7 @@
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../controls/settings_toggle_button.js';
 
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.ts b/chrome/browser/resources/settings/privacy_page/personalization_options.ts
index 2f59c97..ccc1481 100644
--- a/chrome/browser/resources/settings/privacy_page/personalization_options.ts
+++ b/chrome/browser/resources/settings/privacy_page/personalization_options.ts
@@ -15,7 +15,7 @@
 // <if expr="not chromeos_ash">
 import '../relaunch_confirmation_dialog.js';
 // </if>
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 // <if expr="not chromeos_ash">
 import '//resources/cr_elements/cr_toast/cr_toast.js';
 
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
index bf7ad39d..f03c0e4 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_description_item.ts
@@ -9,9 +9,10 @@
  */
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './privacy_guide_description_item.html.js';
 
 export class PrivacyGuideDescriptionItemElement extends PolymerElement {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.ts
index ee2233b..2943970 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import './privacy_guide_page.js';
 
 import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_fragment_shared.css b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_fragment_shared.css
index df2ab55a..4722a27 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_fragment_shared.css
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_fragment_shared.css
@@ -6,7 +6,7 @@
  * #type=style
  * #import=chrome://resources/cr_elements/shared_style_css.m.js
  * #import=chrome://resources/cr_elements/shared_vars_css.m.js
- * #import=../../settings_shared_css.js
+ * #import=../../settings_shared.css.js
  * #include=cr-shared-style settings-shared
  * #css_wrapper_metadata_end */
 
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
index 4fd3ea3..7d141421 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import '../../prefs/prefs.js';
-import '../../settings_shared_css.js';
+import '../../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
 import './privacy_guide_clear_on_exit_fragment.js';
 import './privacy_guide_completion_fragment.js';
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_page.ts
index 87f7141..5081302b 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.ts
@@ -18,7 +18,7 @@
 import '../site_settings/site_data_details_subpage.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './privacy_guide/privacy_guide_dialog.js';
 
 import {CrLinkRowElement} from 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
diff --git a/chrome/browser/resources/settings/privacy_page/secure_dns.ts b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
index 37dd7b8..0882e65 100644
--- a/chrome/browser/resources/settings/privacy_page/secure_dns.ts
+++ b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
@@ -19,7 +19,7 @@
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import '../controls/settings_toggle_button.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './secure_dns_input.js';
 
 import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
index a786cdc..bf9e1d66 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
@@ -17,7 +17,7 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 import '../i18n_setup.js';
 
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts
index f152018d7..53bdd224 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts
@@ -13,7 +13,7 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 import '../i18n_setup.js';
 import './security_keys_pin_field.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts b/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts
index 4abd34f..fb9d43e 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts
@@ -6,7 +6,7 @@
  * @fileoverview An element that lists phones usable as security keys,
     optionally with a drop-down menu for editing or deleting them.
  */
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
 
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts b/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts
index e951d7a..d9c73478 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts
@@ -6,7 +6,7 @@
  * @fileoverview A settings subpage that allows the user to see and manage the
     set of phones that are usable as security keys.
  */
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts
index 5cad053..b9bf3f2 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts
@@ -9,14 +9,14 @@
 
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
-
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './security_keys_pin_field.html.js';
 
 /**
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts
index b15a58e..bb543c4 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts
index c9015c0a..3b76ba0c 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts
@@ -14,7 +14,7 @@
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts
index 0367120b..db3091f77 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts
@@ -7,7 +7,7 @@
  * containing operations on security keys.
  */
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './security_keys_credential_management_dialog.js';
 import './security_keys_bio_enroll_dialog.js';
 import './security_keys_set_pin_dialog.js';
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.ts b/chrome/browser/resources/settings/privacy_page/security_page.ts
index 01e2c06..b46fca26 100644
--- a/chrome/browser/resources/settings/privacy_page/security_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/security_page.ts
@@ -11,7 +11,7 @@
 import '../controls/settings_toggle_button.js';
 import '../icons.html.js';
 import '../prefs/prefs.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './disable_safebrowsing_dialog.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.ts b/chrome/browser/resources/settings/reset_page/reset_page.ts
index b14adb3..1e824ae2 100644
--- a/chrome/browser/resources/settings/reset_page/reset_page.ts
+++ b/chrome/browser/resources/settings/reset_page/reset_page.ts
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 import '../settings_page/settings_animated_pages.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './reset_profile_dialog.js';
 // <if expr="_google_chrome and is_win">
 import '../chrome_cleanup_page/chrome_cleanup_page.js';
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts
index d777ed5..fa110714 100644
--- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts
@@ -16,7 +16,7 @@
 import 'chrome://resources/js/action_link.js';
 import 'chrome://resources/cr_elements/action_link_css.m.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
index e469d94f..c697291d 100644
--- a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
+++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
@@ -14,11 +14,12 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './safety_check_child.html.js';
 
 /**
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts
index a04b925..c1df1691 100644
--- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts
+++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './safety_check_extensions_child.js';
 import './safety_check_passwords_child.js';
 import './safety_check_safe_browsing_child.js';
diff --git a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts
index 41e7a371..8b04d3f 100644
--- a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts
+++ b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts
@@ -9,7 +9,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import './search_engine_entry.css.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts
index 4ced27e..da525cf 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts
+++ b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../controls/extension_controlled_indicator.js';
 import './search_engine_entry.css.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
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 1696aa4..3c72013 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
@@ -7,7 +7,7 @@
  * list of search engines.
  */
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import './search_engine_entry.js';
 
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts b/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts
index f7d26b1..be19d9b 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts
@@ -17,7 +17,7 @@
 import './search_engine_edit_dialog.js';
 import './search_engines_list.js';
 import './omnibox_extension_entry.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
diff --git a/chrome/browser/resources/settings/search_page/search_page.ts b/chrome/browser/resources/settings/search_page/search_page.ts
index 9da0afb..0ab8f983 100644
--- a/chrome/browser/resources/settings/search_page/search_page.ts
+++ b/chrome/browser/resources/settings/search_page/search_page.ts
@@ -15,7 +15,7 @@
 import '../i18n_setup.js';
 import '../settings_page/settings_animated_pages.js';
 import '../settings_page/settings_subpage.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni
index 15112bc..55bfd93 100644
--- a/chrome/browser/resources/settings/settings.gni
+++ b/chrome/browser/resources/settings/settings.gni
@@ -321,6 +321,7 @@
 # Files that are passed as input to css_to_wrapper().
 css_files = [
   "settings_page_styles.css",
+  "settings_shared.css",
   "settings_vars.css",
 
   # subfolder files
@@ -337,7 +338,4 @@
 }
 
 # CSS/HTML wrapper files that are not auto-generated yet.
-css_wrapper_files_old = [
-  "settings_shared_css.ts",
-  "privacy_sandbox/icons.ts",
-]
+css_wrapper_files_old = [ "privacy_sandbox/icons.ts" ]
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.ts b/chrome/browser/resources/settings/settings_main/settings_main.ts
index f51ef2f..7c61a24 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.ts
+++ b/chrome/browser/resources/settings/settings_main/settings_main.ts
@@ -16,7 +16,7 @@
 import '../basic_page/basic_page.js';
 import '../prefs/prefs.js';
 import '../search_settings.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.ts b/chrome/browser/resources/settings/settings_menu/settings_menu.ts
index 00181b17..cb3a3fb 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.ts
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.ts
@@ -14,7 +14,7 @@
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
 import 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {IronSelectorElement} from 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
diff --git a/chrome/browser/resources/settings/settings_page/settings_subpage.ts b/chrome/browser/resources/settings/settings_page/settings_subpage.ts
index 86ae58f3d..965525f9 100644
--- a/chrome/browser/resources/settings/settings_page/settings_subpage.ts
+++ b/chrome/browser/resources/settings/settings_page/settings_subpage.ts
@@ -13,7 +13,7 @@
 import '//resources/cr_elements/icons.m.js';
 import '//resources/cr_elements/shared_style_css.m.js';
 import '//resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {CrSearchFieldElement} from '//resources/cr_elements/cr_search_field/cr_search_field.js';
diff --git a/chrome/browser/resources/settings/settings_shared.css b/chrome/browser/resources/settings/settings_shared.css
new file mode 100644
index 0000000..084ffccc
--- /dev/null
+++ b/chrome/browser/resources/settings/settings_shared.css
@@ -0,0 +1,383 @@
+/* Copyright 2022 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* #css_wrapper_metadata_start
+ * #type=style
+ * #import=//resources/cr_elements/shared_style_css.m.js
+ * #import=//resources/cr_elements/shared_vars_css.m.js
+ * #import=//resources/cr_elements/search_highlight_style.css.js
+ * #import=./settings_vars.css.js
+<if expr='not chromeos_ash'>
+ * #include=cr-shared-style search-highlight-style
+</if>
+<if expr='chromeos_ash'>
+ * #import=//resources/cr_elements/chromeos/cros_color_overrides.m.js
+ * #include=cr-shared-style search-highlight-style cros-color-overrides
+</if>
+ * #css_wrapper_metadata_end */
+
+/* Common styles for Material Design settings. */
+
+/* Prevent action-links from being selected to avoid accidental
+ * selection when trying to click it. */
+a[is=action-link] {
+  user-select: none;
+}
+
+/* Use <h2> as the "sub-header" mentioned in the UX design docs. */
+h2 {
+  align-items: center;
+  align-self: flex-start;
+  color: var(--cr-secondary-text-color);
+  display: flex;
+  font-size: inherit;
+  font-weight: 500;
+  margin: 0;
+  padding-bottom: 12px;
+  padding-top: 32px;
+}
+
+iron-icon {
+  flex-shrink: 0;  /* Prevent distortion of icons in cramped UI. */
+}
+
+iron-icon.policy {
+  margin-inline-end: var(--cr-controlled-by-spacing);
+}
+
+iron-list {
+  /* Text selection in an iron-list is problematic because the items are
+   * reused. The result is the selection happens somewhat arbitrarily.
+   * Add a |risk-selection| attribute to enabled selection in an
+   * iron-list. */
+  user-select: none;
+}
+
+iron-list[risk-selection] {
+  /* On short lists where selection is likely desired, we'll risk having
+   * text selection enabled. If the list is short enough that items are
+   * not actually reused, the bugs with selection are not evident. */
+  user-select: text;
+}
+
+.separator + cr-icon-button {
+  margin-inline-start: var(--cr-icon-ripple-margin);
+}
+
+/* Special case for buttons inside of toggle-buttons. */
+.settings-box settings-toggle-button cr-button:last-of-type {
+  margin-inline-end: 16px;
+}
+
+/* Space out multiple buttons in the same row. */
+.settings-box cr-button + cr-button,
+.settings-box cr-button + controlled-button,
+.settings-box controlled-button + controlled-button,
+.settings-box controlled-button + cr-button {
+  margin-inline-start: 8px;
+}
+
+span ~ a {
+  margin-inline-start: var(--cr-subsequent-anchors-of-span-margin, 4px);
+}
+
+a[href] {
+  color: var(--cr-link-color);
+  text-decoration: none;
+}
+
+/* For elements that are simple out-links but don't look like anchors. */
+.inherit-color {
+  color: inherit !important;
+}
+
+.primary-toggle {
+  color: var(--cr-secondary-text-color);
+  font-weight: 500;
+}
+
+.primary-toggle[checked] {
+  color: var(--google-blue-500);
+}
+
+collapse-radio-button,
+controlled-radio-button,
+cr-radio-button {
+  min-height: var(--settings-row-min-height);
+}
+
+cr-radio-group {
+  width: 100%;
+}
+
+cr-radio-group:focus {
+  /* TODO(dbeam): why is this here? It looks weird and I'm not sure how to
+   * actually trigger it with mouse/keyboard/screenreader. */
+  background-color: var(--google-grey-300);
+  outline: none;
+}
+
+@media (prefers-color-scheme: dark) {
+  cr-radio-group:focus {
+    background-color: var(--google-grey-800);
+  }
+}
+
+/* See also: .no-min-width below. */
+.text-elide {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* By default, flexbox children have min-width calculated to be the width
+ * of the content. However, in some cases we might want to allow the
+ * width to be smaller than the content (i.e. for long text to ellipsis).
+ * In such cases this class should be applied.
+ * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=1108514#c5) */
+.no-min-width {
+  min-width: 0;
+}
+
+.header-aligned-button {
+  margin-top: 12px;  /* Align cr-button with <h2>. */
+}
+
+.link-wrapper {
+  align-items: center;
+  display: flex;
+  flex-grow: 1;
+}
+
+/* A list-frame is an outer container for list-items. It is intended to be
+ * outside of a settings-box. A list-frame is likely to follow a
+ * settings box. */
+.list-frame {
+  display: block;
+  padding-block-end: 0;
+  padding-block-start: 0;
+  padding-inline-end: var(--cr-section-padding);
+  padding-inline-start: var(--cr-section-indent-padding);
+}
+
+/* A list-item is intended to be contained within a list-frame. The list
+ * frame will set up the initial start margin. */
+.list-item {
+  align-items: center;
+  display: flex;
+  min-height: var(--settings-row-min-height);
+  padding: 0;
+}
+
+/* A thin separator line under a list item. */
+.list-item.underbar {
+  border-bottom: var(--cr-separator-line);
+}
+
+.list-item.selected {
+  font-weight: 500;
+}
+
+/* The middle part (horizontally) of a list item. */
+.list-item .middle {
+  flex: 1;
+  margin: 8px 16px;
+}
+
+/* The start (left in LTR) part (horizontally) of a list item. */
+.list-item > .start {
+  flex: 1;
+}
+
+.list-item > label span[disabled] {
+  opacity: var(--settings-disabled-opacity);
+}
+
+/* This button has no ink ripple. */
+.list-button[is='action-link'] {
+  align-items: center;
+  display: flex;
+  flex: 1;
+  font-weight: 500;
+  min-height: inherit;
+}
+
+/* Link buttons use FocusOutlineManager to only show outlines when focus
+ * was triggered by keyboard. */
+:host-context(html:not(.focus-outline-visible))
+    .list-button[is='action-link'] {
+  outline: none;
+}
+
+/* A row with two lines of text. Often the lower line will be .secondary.
+ */
+.two-line {
+  min-height: var(--settings-row-two-line-min-height);
+}
+
+/* A settings-box is a horizontal row of text or controls within a
+ * setting section (page or subpage). */
+.settings-box {
+  align-items: center;
+  border-top: var(--cr-separator-line);
+  display: flex;
+  min-height: var(--cr-section-min-height);
+  padding: 0 var(--cr-section-padding);
+}
+
+.settings-box.no-padding {
+  padding: 0;
+}
+
+.settings-box.no-padding .margin-matches-padding {
+  margin: 0 var(--cr-section-padding);
+}
+
+.settings-box.no-padding > .link-wrapper {
+  padding: 0 var(--cr-section-padding);
+}
+
+.settings-box.two-line {
+  min-height: var(--settings-row-two-line-min-height);
+}
+
+.settings-box-text {
+  box-sizing: border-box;
+  padding-bottom: var(--cr-section-vertical-padding);
+  padding-top: var(--cr-section-vertical-padding);
+}
+
+/* We use an explicit tag to remove the top border, rather than a
+ * :first-of-type modifier. This is a conscious choice, please consult
+ * with dbeam@ or dschuyler@ prior to changing it. */
+.settings-box.first,
+.settings-box.continuation {
+  border-top: none;
+}
+
+h2.first {
+  padding-top: 0;
+}
+
+.settings-box.block {
+  display: block;
+}
+
+/* A start-aligned column. */
+.single-column {
+  align-items: flex-start;
+  flex-direction: column;
+  justify-content: center;
+}
+
+/* A settings-box with no height other than the separator line. */
+.settings-box.line-only {
+  min-height: 0;
+}
+
+/* A settings-box that is embedded in another settings-box (e.g. a control
+ * that is associated with a toggle button). */
+.settings-box.embedded {
+  padding-inline-start: var(--cr-section-indent-padding);
+}
+
+/* The lower line of text in a two-line row. */
+/* TODO: Remove and merge with .cr-secondary-text. */
+.secondary {
+  color: var(--cr-secondary-text-color);
+  font-weight: 400;
+}
+
+/* The |:empty| CSS selector only works when there is no whitespace.
+ * E.g. <div>[[foo]]</div> will be |:empty| when foo === ""; and
+ * <div> [[foo]] </div> will not be |:empty| when foo === "". Ensure there
+ * is no extra whitespace when the contents of .secondary may be "".
+ */
+.secondary:empty {
+  margin: 0;
+}
+
+/* The middle part (horizontally) of a row. */
+.settings-box .middle {
+  align-items: center;
+  flex: auto;
+  padding-inline-start: 16px;
+}
+
+.settings-box .middle.two-line,
+.settings-box .start.two-line {
+  display: flex;
+}
+
+/* The start (left in LTR) part (horizontally) of a row. */
+.settings-box .start {
+  align-items: center;
+  flex: auto;
+}
+
+/* For grouping elements with common flex options. */
+.settings-row {
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+  max-width: 100%;
+  min-width: 0;  /* Workaround for text elision in sub-elements. */
+}
+
+.no-outline {
+  background: none;
+  outline: none;
+}
+
+/* Prevent icon-button's ripples from fighting with potential scrollbars.
+ * Also apply to all iron-lists to align the buttons across them all.*/
+[scrollable],
+iron-list,
+.list-item {
+  --cr-icon-button-margin-end: 0;
+}
+
+/* Helper for a list frame to automatically avoid the separator line. */
+.vertical-list > *:not(:first-of-type) {
+  border-top: var(--cr-separator-line);
+}
+
+/* The separator a vertical line like a horizontal rule <hr> tag, but goes
+ * the other way. An example is near the |sign out| button on the People
+ * settings. */
+.separator {
+  border-inline-start: var(--cr-separator-line);
+  flex-shrink: 0;
+  /* Match cr-button's default height. */
+  height: 32px;
+  margin: 0 16px;
+}
+
+.settings-box.no-padding > .link-wrapper ~ .separator {
+  margin: 0;
+}
+
+.column-header {
+  color: var(--cr-secondary-text-color);
+  font-size: inherit;
+  font-weight: 400;
+}
+
+/* Error message that appears in a toast to indicate the success or
+ * failure of an operation. An example is when adding a printer. */
+.error-message {
+  color: white;
+  font: 13px;
+  padding-bottom: 15px;
+  padding-top: 15px;
+  text-align: center;
+  white-space: normal;
+}
+
+/* URLs should always be displayed using a LTR embedding - see
+ * https://url.spec.whatwg.org/#url-rendering. */
+.url-directionality {
+  direction: ltr;
+  unicode-bidi: embed;
+}
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
deleted file mode 100644
index 8bb8745..0000000
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ /dev/null
@@ -1,371 +0,0 @@
-  <!-- Common styles for Material Design settings. -->
-  <template>
-    <style include="cr-shared-style search-highlight-style
-<if expr='chromeos_ash'>
-          cros-color-overrides
-</if>
-    ">
-      /* Prevent action-links from being selected to avoid accidental
-       * selection when trying to click it. */
-      a[is=action-link] {
-        user-select: none;
-      }
-
-      /* Use <h2> as the "sub-header" mentioned in the UX design docs. */
-      h2 {
-        align-items: center;
-        align-self: flex-start;
-        color: var(--cr-secondary-text-color);
-        display: flex;
-        font-size: inherit;
-        font-weight: 500;
-        margin: 0;
-        padding-bottom: 12px;
-        padding-top: 32px;
-      }
-
-      iron-icon {
-        flex-shrink: 0;  /* Prevent distortion of icons in cramped UI. */
-      }
-
-      iron-icon.policy {
-        margin-inline-end: var(--cr-controlled-by-spacing);
-      }
-
-      iron-list {
-        /* Text selection in an iron-list is problematic because the items are
-         * reused. The result is the selection happens somewhat arbitrarily.
-         * Add a |risk-selection| attribute to enabled selection in an
-         * iron-list. */
-        user-select: none;
-      }
-
-      iron-list[risk-selection] {
-        /* On short lists where selection is likely desired, we'll risk having
-         * text selection enabled. If the list is short enough that items are
-         * not actually reused, the bugs with selection are not evident. */
-        user-select: text;
-      }
-
-      .separator + cr-icon-button {
-        margin-inline-start: var(--cr-icon-ripple-margin);
-      }
-
-      /* Special case for buttons inside of toggle-buttons. */
-      .settings-box settings-toggle-button cr-button:last-of-type {
-        margin-inline-end: 16px;
-      }
-
-      /* Space out multiple buttons in the same row. */
-      .settings-box cr-button + cr-button,
-      .settings-box cr-button + controlled-button,
-      .settings-box controlled-button + controlled-button,
-      .settings-box controlled-button + cr-button {
-        margin-inline-start: 8px;
-      }
-
-      span ~ a {
-        margin-inline-start: var(--cr-subsequent-anchors-of-span-margin, 4px);
-      }
-
-      a[href] {
-        color: var(--cr-link-color);
-        text-decoration: none;
-      }
-
-      /* For elements that are simple out-links but don't look like anchors. */
-      .inherit-color {
-        color: inherit !important;
-      }
-
-      .primary-toggle {
-        color: var(--cr-secondary-text-color);
-        font-weight: 500;
-      }
-
-      .primary-toggle[checked] {
-        color: var(--google-blue-500);
-      }
-
-      collapse-radio-button,
-      controlled-radio-button,
-      cr-radio-button {
-        min-height: var(--settings-row-min-height);
-      }
-
-      cr-radio-group {
-        width: 100%;
-      }
-
-      cr-radio-group:focus {
-        /* TODO(dbeam): why is this here? It looks weird and I'm not sure how to
-         * actually trigger it with mouse/keyboard/screenreader. */
-        background-color: var(--google-grey-300);
-        outline: none;
-      }
-
-      @media (prefers-color-scheme: dark) {
-        cr-radio-group:focus {
-          background-color: var(--google-grey-800);
-        }
-      }
-
-      /* See also: .no-min-width below. */
-      .text-elide {
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-      }
-
-      /* By default, flexbox children have min-width calculated to be the width
-       * of the content. However, in some cases we might want to allow the
-       * width to be smaller than the content (i.e. for long text to ellipsis).
-       * In such cases this class should be applied.
-       * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=1108514#c5) */
-      .no-min-width {
-        min-width: 0;
-      }
-
-      .header-aligned-button {
-        margin-top: 12px;  /* Align cr-button with <h2>. */
-      }
-
-      .link-wrapper {
-        align-items: center;
-        display: flex;
-        flex-grow: 1;
-      }
-
-      /* A list-frame is an outer container for list-items. It is intended to be
-       * outside of a settings-box. A list-frame is likely to follow a
-       * settings box. */
-      .list-frame {
-        display: block;
-        padding-block-end: 0;
-        padding-block-start: 0;
-        padding-inline-end: var(--cr-section-padding);
-        padding-inline-start: var(--cr-section-indent-padding);
-      }
-
-      /* A list-item is intended to be contained within a list-frame. The list
-       * frame will set up the initial start margin. */
-      .list-item {
-        align-items: center;
-        display: flex;
-        min-height: var(--settings-row-min-height);
-        padding: 0;
-      }
-
-      /* A thin separator line under a list item. */
-      .list-item.underbar {
-        border-bottom: var(--cr-separator-line);
-      }
-
-      .list-item.selected {
-        font-weight: 500;
-      }
-
-      /* The middle part (horizontally) of a list item. */
-      .list-item .middle {
-        flex: 1;
-        margin: 8px 16px;
-      }
-
-      /* The start (left in LTR) part (horizontally) of a list item. */
-      .list-item > .start {
-        flex: 1;
-      }
-
-      .list-item > label span[disabled] {
-        opacity: var(--settings-disabled-opacity);
-      }
-
-      /* This button has no ink ripple. */
-      .list-button[is='action-link'] {
-        align-items: center;
-        display: flex;
-        flex: 1;
-        font-weight: 500;
-        min-height: inherit;
-      }
-
-      /* Link buttons use FocusOutlineManager to only show outlines when focus
-       * was triggered by keyboard. */
-      :host-context(html:not(.focus-outline-visible))
-          .list-button[is='action-link'] {
-        outline: none;
-      }
-
-      /* A row with two lines of text. Often the lower line will be .secondary.
-       */
-      .two-line {
-        min-height: var(--settings-row-two-line-min-height);
-      }
-
-      /* A settings-box is a horizontal row of text or controls within a
-       * setting section (page or subpage). */
-      .settings-box {
-        align-items: center;
-        border-top: var(--cr-separator-line);
-        display: flex;
-        min-height: var(--cr-section-min-height);
-        padding: 0 var(--cr-section-padding);
-      }
-
-      .settings-box.no-padding {
-        padding: 0;
-      }
-
-      .settings-box.no-padding .margin-matches-padding {
-        margin: 0 var(--cr-section-padding);
-      }
-
-      .settings-box.no-padding > .link-wrapper {
-        padding: 0 var(--cr-section-padding);
-      }
-
-      .settings-box.two-line {
-        min-height: var(--settings-row-two-line-min-height);
-      }
-
-      .settings-box-text {
-        box-sizing: border-box;
-        padding-bottom: var(--cr-section-vertical-padding);
-        padding-top: var(--cr-section-vertical-padding);
-      }
-
-      /* We use an explicit tag to remove the top border, rather than a
-       * :first-of-type modifier. This is a conscious choice, please consult
-       * with dbeam@ or dschuyler@ prior to changing it. */
-      .settings-box.first,
-      .settings-box.continuation {
-        border-top: none;
-      }
-
-      h2.first {
-        padding-top: 0;
-      }
-
-      .settings-box.block {
-        display: block;
-      }
-
-      /* A start-aligned column. */
-      .single-column {
-        align-items: flex-start;
-        flex-direction: column;
-        justify-content: center;
-      }
-
-      /* A settings-box with no height other than the separator line. */
-      .settings-box.line-only {
-        min-height: 0;
-      }
-
-      /* A settings-box that is embedded in another settings-box (e.g. a control
-       * that is associated with a toggle button). */
-      .settings-box.embedded {
-        padding-inline-start: var(--cr-section-indent-padding);
-      }
-
-      /* The lower line of text in a two-line row. */
-      /* TODO: Remove and merge with .cr-secondary-text. */
-      .secondary {
-        color: var(--cr-secondary-text-color);
-        font-weight: 400;
-      }
-
-      /* The |:empty| CSS selector only works when there is no whitespace.
-       * E.g. <div>[[foo]]</div> will be |:empty| when foo === ""; and
-       * <div> [[foo]] </div> will not be |:empty| when foo === "". Ensure there
-       * is no extra whitespace when the contents of .secondary may be "".
-       */
-      .secondary:empty {
-        margin: 0;
-      }
-
-      /* The middle part (horizontally) of a row. */
-      .settings-box .middle {
-        align-items: center;
-        flex: auto;
-        padding-inline-start: 16px;
-      }
-
-      .settings-box .middle.two-line,
-      .settings-box .start.two-line {
-        display: flex;
-      }
-
-      /* The start (left in LTR) part (horizontally) of a row. */
-      .settings-box .start {
-        align-items: center;
-        flex: auto;
-      }
-
-      /* For grouping elements with common flex options. */
-      .settings-row {
-        align-items: center;
-        display: flex;
-        flex-direction: row;
-        max-width: 100%;
-        min-width: 0;  /* Workaround for text elision in sub-elements. */
-      }
-
-      .no-outline {
-        background: none;
-        outline: none;
-      }
-
-      /* Prevent icon-button's ripples from fighting with potential scrollbars.
-       * Also apply to all iron-lists to align the buttons across them all.*/
-      [scrollable],
-      iron-list,
-      .list-item {
-        --cr-icon-button-margin-end: 0;
-      }
-
-      /* Helper for a list frame to automatically avoid the separator line. */
-      .vertical-list > *:not(:first-of-type) {
-        border-top: var(--cr-separator-line);
-      }
-
-      /* The separator a vertical line like a horizontal rule <hr> tag, but goes
-       * the other way. An example is near the |sign out| button on the People
-       * settings. */
-      .separator {
-        border-inline-start: var(--cr-separator-line);
-        flex-shrink: 0;
-        /* Match cr-button's default height. */
-        height: 32px;
-        margin: 0 16px;
-      }
-
-      .settings-box.no-padding > .link-wrapper ~ .separator {
-        margin: 0;
-      }
-
-      .column-header {
-        color: var(--cr-secondary-text-color);
-        font-size: inherit;
-        font-weight: 400;
-      }
-
-      /* Error message that appears in a toast to indicate the success or
-       * failure of an operation. An example is when adding a printer. */
-      .error-message {
-        color: white;
-        font: 13px;
-        padding-bottom: 15px;
-        padding-top: 15px;
-        text-align: center;
-        white-space: normal;
-      }
-
-      /* URLs should always be displayed using a LTR embedding - see
-       * https://url.spec.whatwg.org/#url-rendering. */
-      .url-directionality {
-        direction: ltr;
-        unicode-bidi: embed;
-      }
-    </style>
-  </template>
diff --git a/chrome/browser/resources/settings/settings_shared_css.ts b/chrome/browser/resources/settings/settings_shared_css.ts
deleted file mode 100644
index fcf166a3..0000000
--- a/chrome/browser/resources/settings/settings_shared_css.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// <if expr="chromeos_ash">
-import '//resources/cr_elements/chromeos/cros_color_overrides.m.js';
-// </if>
-import '//resources/cr_elements/search_highlight_style.css.js';
-import '//resources/cr_elements/shared_vars_css.m.js';
-import '//resources/cr_elements/shared_style_css.m.js';
-import './settings_vars.css.js';
-
-const styleMod = document.createElement('dom-module');
-styleMod.innerHTML = `{__html_template__}`;
-styleMod.register('settings-shared');
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.ts b/chrome/browser/resources/settings/settings_ui/settings_ui.ts
index 1e851e3..892e7f6 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.ts
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.ts
@@ -20,7 +20,7 @@
 import '../icons.html.js';
 import '../settings_main/settings_main.js';
 import '../settings_menu/settings_menu.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {CrContainerShadowMixin, CrContainerShadowMixinInterface} from 'chrome://resources/cr_elements/cr_container_shadow_mixin.js';
diff --git a/chrome/browser/resources/settings/site_settings/add_site_dialog.ts b/chrome/browser/resources/settings/site_settings/add_site_dialog.ts
index c1d5de0..c7a3f30d 100644
--- a/chrome/browser/resources/settings/site_settings/add_site_dialog.ts
+++ b/chrome/browser/resources/settings/site_settings/add_site_dialog.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.ts b/chrome/browser/resources/settings/site_settings/all_sites.ts
index 2d6e5d796..43055aa 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.ts
+++ b/chrome/browser/resources/settings/site_settings/all_sites.ts
@@ -15,7 +15,7 @@
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './all_sites_icons.html.js';
 import './clear_storage_dialog_shared.css.js';
 import './site_entry.js';
diff --git a/chrome/browser/resources/settings/site_settings/category_default_setting.ts b/chrome/browser/resources/settings/site_settings/category_default_setting.ts
index 3d61376..306b0300 100644
--- a/chrome/browser/resources/settings/site_settings/category_default_setting.ts
+++ b/chrome/browser/resources/settings/site_settings/category_default_setting.ts
@@ -35,7 +35,7 @@
  * is launched.
  */
 import '../controls/settings_toggle_button.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js';
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
diff --git a/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts b/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts
index a482e70..158c19c 100644
--- a/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts
+++ b/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts
@@ -10,7 +10,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 import './chooser_exception_list_entry.js';
 
@@ -19,8 +19,8 @@
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {PaperTooltipElement} from 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './chooser_exception_list.html.js';
 
+import {getTemplate} from './chooser_exception_list.html.js';
 import {ChooserType, ContentSettingsTypes} from './constants.js';
 import {SiteSettingsMixin} from './site_settings_mixin.js';
 import {ChooserException, RawChooserException, SiteException} from './site_settings_prefs_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts b/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts
index 8e2dd93..55f6799 100644
--- a/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts
@@ -11,12 +11,12 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './site_list_entry.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './chooser_exception_list_entry.html.js';
 
+import {getTemplate} from './chooser_exception_list_entry.html.js';
 import {ChooserException} from './site_settings_prefs_browser_proxy.js';
 
 export interface ChooserExceptionListEntryElement {
diff --git a/chrome/browser/resources/settings/site_settings/media_picker.ts b/chrome/browser/resources/settings/site_settings/media_picker.ts
index 63fa031f..0ca7cccf 100644
--- a/chrome/browser/resources/settings/site_settings/media_picker.ts
+++ b/chrome/browser/resources/settings/site_settings/media_picker.ts
@@ -8,7 +8,7 @@
  * default camera/microphone.
  */
 import 'chrome://resources/cr_elements/md_select_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
diff --git a/chrome/browser/resources/settings/site_settings/pdf_documents.ts b/chrome/browser/resources/settings/site_settings/pdf_documents.ts
index efc49b6a..0439e07 100644
--- a/chrome/browser/resources/settings/site_settings/pdf_documents.ts
+++ b/chrome/browser/resources/settings/site_settings/pdf_documents.ts
@@ -9,9 +9,10 @@
  */
 
 import '../controls/settings_toggle_button.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {getTemplate} from './pdf_documents.html.js';
 
 class SettingsPdfDocumentsElement extends PolymerElement {
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts
index 502c4c3..0e967a3 100644
--- a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts
+++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts
@@ -19,13 +19,13 @@
 import '../controls/settings_toggle_button.js';
 import '../prefs/prefs.js';
 import '../privacy_page/collapse_radio_button.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getTemplate} from './protocol_handlers.html.js';
 
+import {getTemplate} from './protocol_handlers.html.js';
 import {SiteSettingsMixin} from './site_settings_mixin.js';
 
 export type HandlerEntry = {
diff --git a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts
index 20b4556..8b4ed48 100644
--- a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts
+++ b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts
@@ -7,7 +7,7 @@
  * 'settings-category-default-radio-group' is the polymer element for showing
  * a certain category under Site Settings.
  */
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../controls/settings_radio_group.js';
 import '../privacy_page/collapse_radio_button.js';
 
diff --git a/chrome/browser/resources/settings/site_settings/site_data.ts b/chrome/browser/resources/settings/site_settings/site_data.ts
index 54f2754..44ec086 100644
--- a/chrome/browser/resources/settings/site_settings/site_data.ts
+++ b/chrome/browser/resources/settings/site_settings/site_data.ts
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './site_data_entry.js';
 
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts
index f0dae16b..f87d517 100644
--- a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts
+++ b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts
@@ -7,7 +7,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {WebUIListenerMixin, WebUIListenerMixinInterface} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.ts b/chrome/browser/resources/settings/site_settings/site_data_entry.ts
index 1673a542..b037bde 100644
--- a/chrome/browser/resources/settings/site_settings/site_data_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/site_data_entry.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {FocusRowBehavior} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_details.ts b/chrome/browser/resources/settings/site_settings/site_details.ts
index a2075a0..22890df 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.ts
+++ b/chrome/browser/resources/settings/site_settings/site_details.ts
@@ -18,7 +18,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './all_sites_icons.html.js';
 import './clear_storage_dialog_shared.css.js';
 import './site_details_permission.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.ts b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
index a8062bb..591f062 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.ts
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
@@ -9,7 +9,7 @@
  */
 import 'chrome://resources/cr_elements/md_select_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../settings_vars.css.js';
 import '../i18n_setup.js';
 
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.ts b/chrome/browser/resources/settings/site_settings/site_entry.ts
index 7ec9d0d9..4e7233e3 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/site_entry.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_list.ts b/chrome/browser/resources/settings/site_settings/site_list.ts
index 063d0b53..bcb865e 100644
--- a/chrome/browser/resources/settings/site_settings/site_list.ts
+++ b/chrome/browser/resources/settings/site_settings/site_list.ts
@@ -15,7 +15,7 @@
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './add_site_dialog.js';
 import './edit_exception_dialog.js';
 import './site_list_entry.js';
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.ts b/chrome/browser/resources/settings/site_settings/site_list_entry.ts
index c552df6..0c8403e 100644
--- a/chrome/browser/resources/settings/site_settings/site_list_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/site_list_entry.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/site_settings/zoom_levels.ts b/chrome/browser/resources/settings/site_settings/zoom_levels.ts
index 7d5865e..47466b5 100644
--- a/chrome/browser/resources/settings/site_settings/zoom_levels.ts
+++ b/chrome/browser/resources/settings/site_settings/zoom_levels.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../site_favicon.js';
 
 import {ListPropertyUpdateMixin} from 'chrome://resources/js/list_property_update_mixin.js';
diff --git a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
index 93bc48f..b436741 100644
--- a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
+++ b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 
 import {CrTooltipIconElement} from 'chrome://resources/cr_elements/policy/cr_tooltip_icon.m.js';
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
index 9371e82..703c6c6 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
@@ -5,7 +5,7 @@
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
 import 'chrome://resources/cr_elements/icons.m.js';
 import '../icons.html.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import '../i18n_setup.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
index af1c286c..bbeb79f 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
@@ -12,7 +12,7 @@
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 import './recent_site_permissions.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/system_page/system_page.ts b/chrome/browser/resources/settings/system_page/system_page.ts
index 55a07844..5c1ddc2 100644
--- a/chrome/browser/resources/settings/system_page/system_page.ts
+++ b/chrome/browser/resources/settings/system_page/system_page.ts
@@ -17,7 +17,7 @@
 // <if expr="not chromeos_ash">
 import '../relaunch_confirmation_dialog.js';
 // </if>
-import '../settings_shared_css.js';
+import '../settings_shared.css.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chrome/browser/resources/signin/profile_picker/BUILD.gn
index f661c4f..432508c 100644
--- a/chrome/browser/resources/signin/profile_picker/BUILD.gn
+++ b/chrome/browser/resources/signin/profile_picker/BUILD.gn
@@ -3,130 +3,83 @@
 # found in the LICENSE file.
 
 import("//build/config/chromeos/ui_mode.gni")
-import("//chrome/common/features.gni")
-import("//tools/grit/grit_rule.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/polymer/css_to_wrapper.gni")
-import("//tools/polymer/html_to_wrapper.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
-import("../../tools/optimize_webui.gni")
-import("profile_picker.gni")
+import("//chrome/browser/resources/tools/build_webui.gni")
+import("//ui/webui/webui_features.gni")
 
 assert(!is_chromeos_ash)
 
-preprocess_folder = "preprocessed"
-
-if (optimize_webui) {
-  build_manifest = "build_manifest.json"
-
-  optimize_webui("build") {
-    host = "profile-picker"
-    js_module_in_files = [
-      "profile_picker.js",
-      "lazy_load.js",
-    ]
-    input = rebase_path("$target_gen_dir/tsc", root_build_dir)
-    out_manifest = "$target_gen_dir/$build_manifest"
-    js_out_files = [
-      "profile_picker.rollup.js",
-      "lazy_load.rollup.js",
-      "shared.rollup.js",
-    ]
-
-    deps = [ ":build_ts" ]
-    excludes = [
-      "chrome://resources/js/cr.m.js",
-      "chrome://resources/mojo/mojo/public/js/bindings.js",
-      "chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js",
-    ]
-  }
-}
-
-preprocess_if_expr("preprocess") {
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = ts_files
-}
-
-preprocess_if_expr("preprocess_generated") {
-  deps = [
-    ":css_wrapper_files",
-    ":html_wrapper_files",
-  ]
-  in_folder = target_gen_dir
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = html_wrapper_files + css_wrapper_files
-}
-
-css_to_wrapper("css_wrapper_files") {
-  in_files = css_files
-}
-
-html_to_wrapper("html_wrapper_files") {
-  in_files = html_files
-}
-
-grit("resources") {
-  defines = chrome_grit_defines
-
-  # These arguments are needed since the grd is generated at build time.
-  enable_input_discovery_for_gn_analyze = false
-  source = "$target_gen_dir/profile_picker_resources.grd"
-  deps = [ ":build_grd" ]
-
-  outputs = [
-    "grit/profile_picker_resources.h",
-    "grit/profile_picker_resources_map.cc",
-    "grit/profile_picker_resources_map.h",
-    "profile_picker_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chrome"
-}
-
-ts_library("build_ts") {
-  root_dir = "$target_gen_dir/$preprocess_folder"
-  out_dir = "$target_gen_dir/tsc"
-  composite = true
-  tsconfig_base = "tsconfig_base.json"
-  in_files = ts_files + css_wrapper_files + html_wrapper_files
-  definitions = [
-    "//tools/typescript/definitions/chrome_send.d.ts",
-    "//tools/typescript/definitions/metrics_private.d.ts",
-  ]
-
-  deps = [
-    "//third_party/polymer/v3_0:library",
-    "//ui/webui/resources:library",
-    "//ui/webui/resources/cr_components/customize_themes:build_ts",
-  ]
-  extra_deps = [
-    ":preprocess",
-    ":preprocess_generated",
-  ]
-}
-
-generate_grd("build_grd") {
+build_webui("build") {
   grd_prefix = "profile_picker"
-  out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
-  input_files = [
+
+  static_files = [
     "profile_picker.html",
     "images/left_banner_image.svg",
     "images/right_banner_image.svg",
     "images/dark_mode_left_banner_image.svg",
     "images/dark_mode_right_banner_image.svg",
   ]
-  input_files_base_dir = rebase_path(".", "//")
 
-  if (optimize_webui) {
-    deps = [ ":build" ]
-    manifest_files = [ "$target_gen_dir/$build_manifest" ]
-    resource_path_rewrites = [
+  web_component_files = [
+    "profile_card_menu.ts",
+    "profile_card.ts",
+    "profile_creation_flow/local_profile_customization.ts",
+    "profile_creation_flow/profile_type_choice.ts",
+    "profile_picker_app.ts",
+    "profile_picker_main_view.ts",
+    "profile_switch.ts",
+  ]
+
+  if (is_chromeos_lacros) {
+    web_component_files +=
+        [ "profile_creation_flow/account_selection_lacros.ts" ]
+  }
+
+  non_web_component_files = [
+    "ensure_lazy_loaded.ts",
+    "icons.ts",
+    "lazy_load.ts",
+    "manage_profiles_browser_proxy.ts",
+    "navigation_mixin.ts",
+    "policy_helper.ts",
+    "profile_picker.ts",
+  ]
+
+  css_files = [
+    "profile_creation_flow/profile_creation_shared.css",
+    "profile_picker_shared.css",
+  ]
+
+  ts_composite = true
+  ts_definitions = [
+    "//tools/typescript/definitions/chrome_send.d.ts",
+    "//tools/typescript/definitions/metrics_private.d.ts",
+  ]
+  ts_deps = [
+    "//third_party/polymer/v3_0:library",
+    "//ui/webui/resources:library",
+    "//ui/webui/resources/cr_components/customize_themes:build_ts",
+  ]
+
+  optimize = optimize_webui
+  if (optimize) {
+    optimize_webui_host = "profile-picker"
+    optimize_webui_in_files = [
+      "profile_picker.js",
+      "lazy_load.js",
+    ]
+    optimize_webui_out_files = [
+      "profile_picker.rollup.js",
+      "lazy_load.rollup.js",
+      "shared.rollup.js",
+    ]
+    optimize_webui_excludes = [
+      "chrome://resources/js/cr.m.js",
+      "chrome://resources/mojo/mojo/public/js/bindings.js",
+      "chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js",
+    ]
+    optimize_webui_resource_paths_rewrites = [
       "profile_picker.rollup.js|profile_picker.js",
       "lazy_load.rollup.js|lazy_load.js",
     ]
-  } else {
-    deps = [ ":build_ts" ]
-    manifest_files =
-        filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
   }
 }
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker.gni b/chrome/browser/resources/signin/profile_picker/profile_picker.gni
deleted file mode 100644
index e1178e8..0000000
--- a/chrome/browser/resources/signin/profile_picker/profile_picker.gni
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/chromeos/ui_mode.gni")
-
-non_web_component_files = [
-  "ensure_lazy_loaded.ts",
-  "icons.ts",
-  "lazy_load.ts",
-  "manage_profiles_browser_proxy.ts",
-  "navigation_mixin.ts",
-  "policy_helper.ts",
-  "profile_picker.ts",
-]
-
-# Files holding a Polymer element definition AND have an equivalent .html file.
-web_component_files = [
-  "profile_card_menu.ts",
-  "profile_card.ts",
-  "profile_creation_flow/local_profile_customization.ts",
-  "profile_creation_flow/profile_type_choice.ts",
-  "profile_picker_app.ts",
-  "profile_picker_main_view.ts",
-  "profile_switch.ts",
-]
-
-if (is_chromeos_lacros) {
-  web_component_files += [ "profile_creation_flow/account_selection_lacros.ts" ]
-}
-
-# Files that are passed as input to html_to_wrapper().
-html_files = []
-foreach(f, web_component_files) {
-  html_files += [ string_replace(f, ".ts", ".html") ]
-}
-
-# Files that are generated by html_to_wrapper().
-html_wrapper_files = []
-foreach(f, html_files) {
-  html_wrapper_files += [ f + ".ts" ]
-}
-
-ts_files = non_web_component_files + web_component_files
-
-# Files that are passed as input to css_to_wrapper().
-css_files = [
-  "profile_creation_flow/profile_creation_shared.css",
-  "profile_picker_shared.css",
-]
-
-# Files that are generated by css_to_wrapper().
-css_wrapper_files = []
-foreach(f, css_files) {
-  css_wrapper_files += [ f + ".ts" ]
-}
diff --git a/chrome/browser/resources/tools/build_webui.gni b/chrome/browser/resources/tools/build_webui.gni
index dd8ed8d..3f5bee5 100644
--- a/chrome/browser/resources/tools/build_webui.gni
+++ b/chrome/browser/resources/tools/build_webui.gni
@@ -154,12 +154,15 @@
 
     if (!composite) {
       visibility = [
-        ":build",
+        ":build_bundle",
         ":build_grd",
       ]
     }
 
-    tsconfig_base = "tsconfig_base.json"
+    if (!defined(invoker.ts_use_local_config) || invoker.ts_use_local_config) {
+      tsconfig_base = "tsconfig_base.json"
+    }
+
     in_files = ts_files
 
     extra_deps = [ ":preprocess" ]
@@ -200,15 +203,15 @@
   }
 
   if (optimize) {
-    build_manifest = "build_manifest.json"
+    bundle_manifest = "bundle_manifest.json"
 
-    optimize_webui("build") {
+    optimize_webui("build_bundle") {
       visibility = [ ":build_grd" ]
       host = invoker.optimize_webui_host
       input = rebase_path(tsc_dir, root_build_dir)
       js_out_files = invoker.optimize_webui_out_files
       js_module_in_files = invoker.optimize_webui_in_files
-      out_manifest = "$target_gen_dir/$build_manifest"
+      out_manifest = "$target_gen_dir/$bundle_manifest"
       excludes = invoker.optimize_webui_excludes
 
       deps = [
@@ -227,8 +230,8 @@
     input_files_base_dir = rebase_path(".", "//")
 
     if (optimize) {
-      deps = [ ":build" ]
-      manifest_files = [ "$target_gen_dir/$build_manifest" ]
+      deps = [ ":build_bundle" ]
+      manifest_files = [ "$target_gen_dir/$bundle_manifest" ]
       resource_path_rewrites = invoker.optimize_webui_resource_paths_rewrites
     } else {
       deps = [ ":build_ts" ]
diff --git a/chrome/browser/resources/webui_js_error/BUILD.gn b/chrome/browser/resources/webui_js_error/BUILD.gn
index 6675f56..8e978fc 100644
--- a/chrome/browser/resources/webui_js_error/BUILD.gn
+++ b/chrome/browser/resources/webui_js_error/BUILD.gn
@@ -2,73 +2,26 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//chrome/browser/resources/tools/optimize_webui.gni")
-import("//chrome/common/features.gni")
-import("//tools/grit/grit_rule.gni")
-import("//tools/grit/preprocess_if_expr.gni")
-import("//tools/typescript/ts_library.gni")
-import("//ui/webui/resources/tools/generate_grd.gni")
+import("//chrome/browser/resources/tools/build_webui.gni")
 import("//ui/webui/webui_features.gni")
 
 assert(is_linux || is_chromeos)
 
-preprocess_folder = "preprocessed"
-
-if (optimize_webui) {
-  build_manifest = "build_manifest.json"
-  optimize_webui("build") {
-    host = "webuijserror"
-    input = rebase_path("$target_gen_dir/tsc", root_build_dir)
-    deps = [ ":build_ts" ]
-    js_module_in_files = [ "webui_js_error.js" ]
-    js_out_files = [ "webui_js_error.rollup.js" ]
-    out_manifest = "$target_gen_dir/$build_manifest"
-  }
-}
-
-preprocess_if_expr("preprocess") {
-  in_folder = "."
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  in_files = [ "webui_js_error.ts" ]
-}
-
-grit("resources") {
-  defines = chrome_grit_defines
-
-  # These arguments are needed since the grd is generated at build time.
-  enable_input_discovery_for_gn_analyze = false
-  source = "$target_gen_dir/webui_js_error_resources.grd"
-  deps = [ ":build_grd" ]
-
-  outputs = [
-    "grit/webui_js_error_resources.h",
-    "grit/webui_js_error_resources_map.cc",
-    "grit/webui_js_error_resources_map.h",
-    "webui_js_error_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chrome"
-}
-
-ts_library("build_ts") {
-  root_dir = "$target_gen_dir/$preprocess_folder"
-  out_dir = "$target_gen_dir/tsc"
-  in_files = [ "webui_js_error.ts" ]
-  deps = [ "//ui/webui/resources:library" ]
-  extra_deps = [ ":preprocess" ]
-}
-
-generate_grd("build_grd") {
-  input_files = [ "webui_js_error.html" ]
-  input_files_base_dir = rebase_path(".", "//")
-  if (optimize_webui) {
-    deps = [ ":build" ]
-    resource_path_rewrites = [ "webui_js_error.rollup.js|webui_js_error.js" ]
-    manifest_files = [ "$target_gen_dir/$build_manifest" ]
-  } else {
-    deps = [ ":build_ts" ]
-    manifest_files =
-        filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
-  }
+build_webui("build") {
   grd_prefix = "webui_js_error"
-  out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
+  static_files = [ "webui_js_error.html" ]
+  non_web_component_files = [ "webui_js_error.ts" ]
+
+  ts_use_local_config = false
+  ts_deps = [ "//ui/webui/resources:library" ]
+
+  optimize = optimize_webui
+  if (optimize) {
+    optimize_webui_host = "webuijserror"
+    optimize_webui_in_files = [ "webui_js_error.js" ]
+    optimize_webui_out_files = [ "webui_js_error.rollup.js" ]
+    optimize_webui_excludes = []
+    optimize_webui_resource_paths_rewrites =
+        [ "webui_js_error.rollup.js|webui_js_error.js" ]
+  }
 }
diff --git a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
index 2ea458d4..71a46dd 100644
--- a/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
+++ b/chrome/browser/safe_browsing/chrome_ui_manager_delegate.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/interstitials/enterprise_util.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/chrome_ping_manager_factory.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc b/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc
index 19b7f86..8d1517ce 100644
--- a/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc
+++ b/chrome/browser/safe_browsing/delayed_warning_navigation_throttle.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/safe_browsing/delayed_warning_navigation_throttle.h"
 
 #include "base/feature_list.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/safe_browsing/user_interaction_observer.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
 #include "components/safe_browsing/core/common/features.h"
diff --git a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
index ea4a5bce..ed0273d 100644
--- a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
+++ b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
@@ -9,7 +9,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/android/customtabs/client_data_header_web_contents_observer.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/safe_browsing/user_interaction_observer.h"
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NoTargetDeviceBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NoTargetDeviceBottomSheetContent.java
index d3aadc85..89970b07 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NoTargetDeviceBottomSheetContent.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NoTargetDeviceBottomSheetContent.java
@@ -8,6 +8,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.TextView;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -30,6 +31,8 @@
         mContentView = (ViewGroup) LayoutInflater.from(context).inflate(
                 R.layout.send_tab_to_self_feature_unavailable_prompt, null);
         if (isPromoFeatureEnabled) {
+            TextView label = (TextView) mContentView.findViewById(R.id.empty_state_label);
+            label.setText(R.string.send_tab_to_self_android_no_target_device_label);
             mContentView.findViewById(R.id.manage_account_devices_link).setVisibility(View.VISIBLE);
         }
         // TODO(crbug.com/1298185): This is cumulating both signed-out and single device users.
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfBottomSheetRenderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfBottomSheetRenderTest.java
index 55e2413..7e4c5b19 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfBottomSheetRenderTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfBottomSheetRenderTest.java
@@ -52,6 +52,7 @@
     public final RenderTestRule mRenderTestRule =
             RenderTestRule.Builder.withPublicCorpus()
                     .setBugComponent(RenderTestRule.Component.UI_BROWSER_SHARING)
+                    .setRevision(1)
                     .build();
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
index 48bc177..b2a9b2d 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
@@ -219,7 +219,8 @@
             default:
                 // Report an error, but fall back to a default value.
                 // Use this to detect missing new cases.
-                assert false : "Unknown page classification: " + pageClass;
+                // TODO(crbug.com/1314765): This assert fails persistently on tablets.
+                // assert false : "Unknown page classification: " + pageClass;
                 break;
         }
 
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java
index c1ca7e0c..1f265faa 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java
@@ -103,7 +103,7 @@
     @Rule
     public final RenderTestRule mRenderTestRule =
             RenderTestRule.Builder.withPublicCorpus()
-                    .setRevision(4)
+                    .setRevision(5)
                     .setBugComponent(RenderTestRule.Component.SERVICES_SIGN_IN)
                     .build();
 
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 3b5d13b..2161713c 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2906,7 +2906,7 @@
         Sign in to this site and Chrome with your Google Account.
       </message>
       <message name="IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE_FOR_SEND_TAB_TO_SELF" desc="The subtitle for the account picker bottom sheet that tells the user what happens if the button 'Continue as John Doe' is clicked, when send-tab-to-self triggered the UI.">
-        You can send tabs between devices that are signed in with the same Google Account
+        To send this tab to another device, sign in to Chrome on both devices
       </message>
       <message name="IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SIGNIN_TITLE" desc="The title of the account picker bottom sheet tells that the user is in the process of signing in with their Google Account">
         Signing in...
@@ -4619,6 +4619,9 @@
       <message name="IDS_SEND_TAB_TO_SELF_WHEN_SIGNED_IN_UNAVAILABLE" desc="Instructions for the user to enable the feature when it's currently unavailable.">
         You can send tabs between devices that are signed in with the same Google Account
       </message>
+      <message name="IDS_SEND_TAB_TO_SELF_ANDROID_NO_TARGET_DEVICE_LABEL" desc="Text shown when a user with no available target devices attempts to use send-tab-to-self.">
+        To send this tab to another device, sign in to Chrome there
+      </message>
 
 
       <!-- Sharing -->
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SEND_TAB_TO_SELF_ANDROID_NO_TARGET_DEVICE_LABEL.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SEND_TAB_TO_SELF_ANDROID_NO_TARGET_DEVICE_LABEL.png.sha1
new file mode 100644
index 0000000..0faa463
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SEND_TAB_TO_SELF_ANDROID_NO_TARGET_DEVICE_LABEL.png.sha1
@@ -0,0 +1 @@
+3870296faa35b22f10eea66500c8c52777aa7e0b
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE_FOR_SEND_TAB_TO_SELF.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE_FOR_SEND_TAB_TO_SELF.png.sha1
index d9430e95..517fb687 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE_FOR_SEND_TAB_TO_SELF.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE_FOR_SEND_TAB_TO_SELF.png.sha1
@@ -1 +1 @@
-c4c066c2c7e796fe537cdaf1d031c6ac266c9bb8
\ No newline at end of file
+b1d4c5ab74e41b39ae6b12a62a6ffe38a737c16b
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
index 61f294f..e1c69a3 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
@@ -197,7 +197,9 @@
             mButtonData.setButtonSpec(new ButtonSpec(receivedButtonSpec.getDrawable(),
                     wrapClickListener(receivedButtonSpec.getOnClickListener(),
                             receivedButtonSpec.getButtonVariant()),
-                    mMenuHandler, receivedButtonSpec.getContentDescriptionResId(),
+                    // Use menu handler only with static actions.
+                    receivedButtonSpec.isDynamicAction() ? null : mMenuHandler,
+                    receivedButtonSpec.getContentDescriptionResId(),
                     receivedButtonSpec.getSupportsTinting(),
                     receivedButtonSpec.getIPHCommandBuilder(),
                     receivedButtonSpec.getButtonVariant(),
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
index 1325d6f..457dda4 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
@@ -6,6 +6,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -103,6 +104,8 @@
     @Mock
     private ButtonDataProvider mNewTabButtonController;
     @Mock
+    private ButtonDataProvider mPriceTrackingButtonController;
+    @Mock
     private ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
     @Mock
     private Tab mTab;
@@ -270,6 +273,65 @@
                 .launchSettingsActivity(activity, AdaptiveToolbarPreferenceFragment.class);
     }
 
+    @Test
+    @SmallTest
+    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
+    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
+    public void testShowDynamicAction() {
+        Activity activity = Robolectric.setupActivity(Activity.class);
+        SettingsLauncher settingsLauncher = mock(SettingsLauncher.class);
+
+        AdaptiveToolbarStatePredictor.setSegmentationResultsForTesting(
+                new Pair<>(true, AdaptiveToolbarButtonVariant.NEW_TAB));
+
+        AdaptiveButtonActionMenuCoordinator menuCoordinator =
+                mock(AdaptiveButtonActionMenuCoordinator.class);
+
+        doReturn(new OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View view) {
+                Assert.fail("This long click listener shouldn't be invoked.");
+                return false;
+            }
+        })
+                .when(menuCoordinator)
+                .createOnLongClickListener(any());
+
+        AdaptiveToolbarButtonController adaptiveToolbarButtonController =
+                new AdaptiveToolbarButtonController(activity, settingsLauncher,
+                        mActivityLifecycleDispatcher, menuCoordinator, mAndroidPermissionDelegate,
+                        SharedPreferencesManager.getInstance());
+        adaptiveToolbarButtonController.addButtonVariant(
+                AdaptiveToolbarButtonVariant.PRICE_TRACKING, mPriceTrackingButtonController);
+        ButtonDataObserver observer = mock(ButtonDataObserver.class);
+        adaptiveToolbarButtonController.addObserver(observer);
+        adaptiveToolbarButtonController.onFinishNativeInitialization();
+
+        mButtonData.setCanShow(true);
+        mButtonData.setEnabled(true);
+        mButtonData.setButtonSpec(makeButtonSpec(AdaptiveToolbarButtonVariant.PRICE_TRACKING));
+        when(mPriceTrackingButtonController.get(any())).thenReturn(mButtonData);
+        View view = mock(View.class);
+        when(view.getContext()).thenReturn(activity);
+
+        adaptiveToolbarButtonController.showDynamicAction(
+                AdaptiveToolbarButtonVariant.PRICE_TRACKING);
+
+        // Button data should have change twice, first on native initialization and then after
+        // showing the dynamic action.
+        verify(observer, times(2)).buttonDataChanged(true);
+        Assert.assertEquals(mPriceTrackingButtonController,
+                adaptiveToolbarButtonController.getSingleProviderForTesting());
+
+        ButtonSpec buttonSpec = adaptiveToolbarButtonController.get(mTab).getButtonSpec();
+        Assert.assertEquals(
+                AdaptiveToolbarButtonVariant.PRICE_TRACKING, buttonSpec.getButtonVariant());
+        Assert.assertTrue(buttonSpec.isDynamicAction());
+        // Dynamic actions should have no long click handlers.
+        Assert.assertNull(buttonSpec.getOnLongClickListener());
+        adaptiveToolbarButtonController.destroy();
+    }
+
     private AdaptiveToolbarButtonController buildController() {
         AdaptiveToolbarButtonController adaptiveToolbarButtonController =
                 new AdaptiveToolbarButtonController(mock(Activity.class),
diff --git a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
index 4f1693c..a2a9b3880 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
@@ -383,6 +383,10 @@
 
   // Show the launcher.
   client->ShowAppList();
+  if (ash::features::IsProductivityLauncherEnabled()) {
+    ash::AppListTestApi().WaitForBubbleWindow(
+        /*wait_for_opening_animation=*/false);
+  }
 
   AppListModelUpdater* model_updater = test::GetModelUpdater(client);
   ASSERT_TRUE(model_updater);
@@ -401,8 +405,7 @@
       "chrome-extension://mgndgikekgjfcpckkfioiadnlibdjbkf/";
 
   // Search by title and the app must present in the results.
-  model_updater->UpdateSearchBox(base::ASCIIToUTF16(app_title),
-                                 true /* initiated_by_user */);
+  ash::AppListTestApi().SimulateSearch(base::UTF8ToUTF16(app_title));
   ASSERT_TRUE(search_controller->FindSearchResult(app_result_id));
 
   // Expect that the browser window is not minimized.
@@ -591,8 +594,8 @@
   EXPECT_FALSE(search_controller->GetResultByTitleForTest(title));
 
   // Now a search finds the extension.
-  model_updater->UpdateSearchBox(base::ASCIIToUTF16(title),
-                                 true /* initiated_by_user */);
+  ash::AppListTestApi().SimulateSearch(base::UTF8ToUTF16(title));
+
   EXPECT_TRUE(search_controller->GetResultByTitleForTest(title));
 
   // Uninstall the extension.
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
index 3fb2565..6c7dac3d 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ui/app_list/app_service/app_service_context_menu.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/mojom/types.mojom-shared.h"
 
 namespace {
@@ -203,7 +204,7 @@
       return;
     }
   }
-  Launch(event_flags, apps::mojom::LaunchSource::kFromAppListGrid);
+  Launch(event_flags, apps::LaunchSource::kFromAppListGrid);
 }
 
 const char* AppServiceAppItem::GetItemType() const {
@@ -224,7 +225,7 @@
 }
 
 void AppServiceAppItem::ExecuteLaunchCommand(int event_flags) {
-  Launch(event_flags, apps::mojom::LaunchSource::kFromAppListGridContextMenu);
+  Launch(event_flags, apps::LaunchSource::kFromAppListGridContextMenu);
 
   // TODO(crbug.com/826982): drop the if, and call MaybeDismissAppList
   // unconditionally?
@@ -253,11 +254,19 @@
 }
 
 void AppServiceAppItem::Launch(int event_flags,
-                               apps::mojom::LaunchSource launch_source) {
+                               apps::LaunchSource launch_source) {
   ResetIsNewInstall();
-  apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
-      id(), event_flags, launch_source,
-      apps::MakeWindowInfo(GetController()->GetAppListDisplayId()));
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
+        id(), event_flags, launch_source,
+        std::make_unique<apps::WindowInfo>(
+            GetController()->GetAppListDisplayId()));
+  } else {
+    apps::AppServiceProxyFactory::GetForProfile(profile())->Launch(
+        id(), event_flags,
+        apps::ConvertLaunchSourceToMojomLaunchSource(launch_source),
+        apps::MakeWindowInfo(GetController()->GetAppListDisplayId()));
+  }
 }
 
 void AppServiceAppItem::CallLoadIcon(bool allow_placeholder_icon) {
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_item.h b/chrome/browser/ui/app_list/app_service/app_service_app_item.h
index b546a84..99e6e6a 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_item.h
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_item.h
@@ -11,10 +11,10 @@
 #include "base/time/time.h"
 #include "chrome/browser/ui/app_list/app_context_menu_delegate.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
+#include "components/services/app_service/public/cpp/app_launch_util.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/icon_types.h"
-#include "components/services/app_service/public/mojom/types.mojom-forward.h"
 
 // An app list item provided by the app service.
 class AppServiceAppItem : public ChromeAppListItem,
@@ -49,7 +49,7 @@
   // Resets the `is_new_install` property and records metrics.
   void ResetIsNewInstall();
 
-  void Launch(int event_flags, apps::mojom::LaunchSource launch_source);
+  void Launch(int event_flags, apps::LaunchSource launch_source);
 
   void CallLoadIcon(bool allow_placeholder_icon);
   void OnLoadIcon(apps::IconValuePtr icon_value);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
index 2382c9c..22aa7303 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "ui/events/event_constants.h"
 
 ArcAppLauncher::ArcAppLauncher(content::BrowserContext* context,
@@ -18,7 +19,7 @@
                                apps::mojom::IntentPtr launch_intent,
                                bool deferred_launch_allowed,
                                int64_t display_id,
-                               apps::mojom::LaunchSource launch_source)
+                               apps::LaunchSource launch_source)
     : context_(context),
       app_id_(app_id),
       launch_intent_(std::move(launch_intent)),
@@ -122,12 +123,20 @@
   Observe(nullptr);
 
   if (launch_intent_) {
-    proxy->LaunchAppWithIntent(app_id_, ui::EF_NONE, std::move(launch_intent_),
-                               launch_source_,
-                               apps::MakeWindowInfo(display_id_));
+    proxy->LaunchAppWithIntent(
+        app_id_, ui::EF_NONE, std::move(launch_intent_),
+        apps::ConvertLaunchSourceToMojomLaunchSource(launch_source_),
+        apps::MakeWindowInfo(display_id_));
   } else {
-    proxy->Launch(app_id_, ui::EF_NONE, launch_source_,
-                  apps::MakeWindowInfo(display_id_));
+    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+      proxy->Launch(app_id_, ui::EF_NONE, launch_source_,
+                    std::make_unique<apps::WindowInfo>(display_id_));
+    } else {
+      proxy->Launch(
+          app_id_, ui::EF_NONE,
+          apps::ConvertLaunchSourceToMojomLaunchSource(launch_source_),
+          apps::MakeWindowInfo(display_id_));
+    }
   }
 
   app_launched_ = true;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.h b/chrome/browser/ui/app_list/arc/arc_app_launcher.h
index 0385210..89ca768 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_launcher.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.h
@@ -12,6 +12,7 @@
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.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/mojom/types.mojom.h"
@@ -30,7 +31,7 @@
                  apps::mojom::IntentPtr launch_intent,
                  bool deferred_launch_allowed,
                  int64_t display_id,
-                 apps::mojom::LaunchSource launch_source);
+                 apps::LaunchSource launch_source);
 
   ArcAppLauncher(const ArcAppLauncher&) = delete;
   ArcAppLauncher& operator=(const ArcAppLauncher&) = delete;
@@ -71,7 +72,7 @@
   // Flag indicating that ARC app was launched.
   bool app_launched_ = false;
   // Enum that indicates what type of metric to record to UMA on launch.
-  apps::mojom::LaunchSource launch_source_;
+  apps::LaunchSource launch_source_;
 };
 
 #endif  // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_LAUNCHER_H_
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index f705771..cd5341c 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -79,6 +79,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/test/fake_intent_helper_instance.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"
@@ -3110,13 +3111,13 @@
   {
     ArcAppLauncher launcher1(profile(), id1, nullptr, false,
                              display::kInvalidDisplayId,
-                             apps::mojom::LaunchSource::kFromChromeInternal);
+                             apps::LaunchSource::kFromChromeInternal);
     EXPECT_FALSE(launcher1.app_launched());
     EXPECT_TRUE(prefs->HasObserver(&launcher1));
 
     ArcAppLauncher launcher3(profile(), id3, nullptr, false,
                              display::kInvalidDisplayId,
-                             apps::mojom::LaunchSource::kFromChromeInternal);
+                             apps::LaunchSource::kFromChromeInternal);
     EXPECT_FALSE(launcher1.app_launched());
     EXPECT_TRUE(prefs->HasObserver(&launcher1));
     EXPECT_FALSE(launcher3.app_launched());
@@ -3146,7 +3147,7 @@
         app2.activity, arc::kInitialStartParam, arc::kCategoryLauncher);
     ArcAppLauncher launcher2(profile(), id2, std::move(launch_intent2), false,
                              display::kInvalidDisplayId,
-                             apps::mojom::LaunchSource::kFromChromeInternal);
+                             apps::LaunchSource::kFromChromeInternal);
     EXPECT_TRUE(launcher2.app_launched());
     EXPECT_FALSE(prefs->HasObserver(&launcher2));
   }
@@ -3168,7 +3169,7 @@
 
   ArcAppLauncher launcher(profile(), app_id, nullptr, false,
                           display::kInvalidDisplayId,
-                          apps::mojom::LaunchSource::kFromChromeInternal);
+                          apps::LaunchSource::kFromChromeInternal);
   EXPECT_FALSE(launcher.app_launched());
 
   // Register app, however it is suspended.
@@ -3574,12 +3575,12 @@
   // Launch when app is registered and ready.
   ArcAppLauncher launcher1(profile(), id1, nullptr, false,
                            display::kInvalidDisplayId,
-                           apps::mojom::LaunchSource::kFromChromeInternal);
+                           apps::LaunchSource::kFromChromeInternal);
 
   // Launch when app is registered.
   ArcAppLauncher launcher2(profile(), id2, nullptr, true,
                            display::kInvalidDisplayId,
-                           apps::mojom::LaunchSource::kFromChromeInternal);
+                           apps::LaunchSource::kFromChromeInternal);
 
   EXPECT_FALSE(launcher1.app_launched());
 
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
index fbd7b81..f9f2544 100644
--- a/chrome/browser/ui/app_list/search/app_service_app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -28,7 +28,9 @@
 #include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "components/favicon/core/large_icon_service.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_update.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -206,9 +208,15 @@
     }
   }
 
-  proxy->Launch(app_id(), event_flags,
-                apps::ConvertLaunchSourceToMojomLaunchSource(launch_source),
-                apps::MakeWindowInfo(controller()->GetAppListDisplayId()));
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    proxy->Launch(app_id(), event_flags, launch_source,
+                  std::make_unique<apps::WindowInfo>(
+                      controller()->GetAppListDisplayId()));
+  } else {
+    proxy->Launch(app_id(), event_flags,
+                  apps::ConvertLaunchSourceToMojomLaunchSource(launch_source),
+                  apps::MakeWindowInfo(controller()->GetAppListDisplayId()));
+  }
 }
 
 // TODO(crbug.com/1258415): Remove this method when the productivity launcher is
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
index bbec465..9644237 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
@@ -20,6 +20,8 @@
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/components/string_matching/tokenized_string_match.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -267,8 +269,13 @@
 void KeyboardShortcutResult::Open(int event_flags) {
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile_);
-  proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
-                apps::mojom::LaunchSource::kFromAppListQuery, nullptr);
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
+                  apps::LaunchSource::kFromAppListQuery, nullptr);
+  } else {
+    proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
+                  apps::mojom::LaunchSource::kFromAppListQuery, nullptr);
+  }
 }
 
 double KeyboardShortcutResult::CalculateRelevance(
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc
index 3a87fc78..99c7c8b8 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -69,6 +69,7 @@
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -365,8 +366,13 @@
   apps::AppServiceProxy* proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile);
   DCHECK(proxy);
-  proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
-                ui::EF_NONE, apps::mojom::LaunchSource::kFromKeyboard);
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
+                  ui::EF_NONE, apps::LaunchSource::kFromKeyboard);
+  } else {
+    proxy->Launch(ash::calculator_app::GetInstalledCalculatorAppId(profile),
+                  ui::EF_NONE, apps::mojom::LaunchSource::kFromKeyboard);
+  }
 }
 
 void ChromeNewWindowClient::OpenFileManager() {
@@ -387,10 +393,19 @@
       return;
     }
 
-    proxy->Launch(update.AppId(),
-                  apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                                      /*prefer_container=*/true),
-                  apps::mojom::LaunchSource::kFromKeyboard);
+    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+      proxy->Launch(
+          update.AppId(),
+          apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
+                              /*prefer_container=*/true),
+          apps::LaunchSource::kFromKeyboard);
+    } else {
+      proxy->Launch(
+          update.AppId(),
+          apps::GetEventFlags(WindowOpenDisposition::NEW_FOREGROUND_TAB,
+                              /*prefer_container=*/true),
+          apps::mojom::LaunchSource::kFromKeyboard);
+    }
   };
 
   bool result = proxy->AppRegistryCache().ForOneApp(
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index c39ef789..67530d8 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -40,7 +40,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
@@ -342,3 +341,14 @@
 version_info::Channel ChromeShellDelegate::GetChannel() {
   return chrome::GetChannel();
 }
+
+void ChromeShellDelegate::ForceSkipWarningUserOnClose(
+    const std::vector<aura::Window*>& windows) {
+  for (aura::Window* window : windows) {
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForNativeWindow(window);
+    if (browser_view) {
+      browser_view->browser()->set_force_skip_warning_user_on_close(true);
+    }
+  }
+}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 97714bb..6e909de6 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -63,6 +63,8 @@
   static void ResetDisableLoggingRedirectForTesting();
   const GURL& GetLastCommittedURLForWindowIfAny(aura::Window* window) override;
   version_info::Channel GetChannel() override;
+  void ForceSkipWarningUserOnClose(
+      const std::vector<aura::Window*>& windows) override;
 };
 
 #endif  // CHROME_BROWSER_UI_ASH_CHROME_SHELL_DELEGATE_H_
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc b/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc
index 8416825..e32c7e20 100644
--- a/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc
@@ -352,10 +352,18 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_P(ProjectorClientManagedTest,
+                       PRE_DisableThenEnablePolicy) {
+  auto* profile = browser()->profile();
+  // By the time the test runs, SystemWebAppManager already marked the app as
+  // disabled because the policy is not set. This PRE step, sets the policy so
+  // that the app is correctly enabled when the actual test runs.
+  profile->GetPrefs()->SetBoolean(GetPolicy(), true);
+}
+
 // Prevents a regression to b/230779397.
 IN_PROC_BROWSER_TEST_P(ProjectorClientManagedTest, DisableThenEnablePolicy) {
   auto* profile = browser()->profile();
-  profile->GetPrefs()->SetBoolean(GetPolicy(), true);
   SystemWebAppManager::GetForTest(profile)->InstallSystemAppsForTesting();
 
   client()->OpenProjectorApp();
diff --git a/chrome/browser/ui/ash/shelf/arc_playstore_shortcut_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/arc_playstore_shortcut_shelf_item_controller.cc
index afec76e..0776730 100644
--- a/chrome/browser/ui/ash/shelf/arc_playstore_shortcut_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/arc_playstore_shortcut_shelf_item_controller.cc
@@ -37,7 +37,7 @@
         std::make_unique<ArcAppLauncher>(
             ChromeShelfController::instance()->profile(), arc::kPlayStoreAppId,
             nullptr /* launch_intent */, true /* deferred_launch_allowed */,
-            display_id, apps::mojom::LaunchSource::kFromShelf);
+            display_id, apps::LaunchSource::kFromShelf);
     // ArcAppLauncher may launch Play Store in case it exists already. In this
     // case this instance of ArcPlaystoreShortcutShelfItemController may be
     // deleted. If Play Store does not exist at this moment, then let
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
index 0607c59..091ce0f 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
@@ -3082,19 +3082,10 @@
 class FilesSystemWebAppPinnedTest : public ShelfPlatformAppBrowserTest {
  public:
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {ash::features::kFilesSWA, ash::features::kEnableAllSystemWebApps}, {});
+    scoped_feature_list_.InitAndEnableFeature(ash::features::kFilesSWA);
     ShelfPlatformAppBrowserTest::SetUp();
   }
 
-  void WaitForSystemAppsSynchronized() {
-    base::RunLoop run_loop;
-    ash::SystemWebAppManager::Get(browser()->profile())
-        ->on_apps_synchronized()
-        .Post(FROM_HERE, run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
@@ -3110,7 +3101,8 @@
                                  std::move(policy_value));
 
   // Ensure shelf is updated.
-  WaitForSystemAppsSynchronized();
+  ash::SystemWebAppManager::Get(browser()->profile())
+      ->InstallSystemAppsForTesting();
   web_app::WebAppProvider::GetForTest(browser()->profile())
       ->install_manager()
       .NotifyWebAppInstalledWithOsHooks(file_manager::kFileManagerSwaAppId);
diff --git a/chrome/browser/ui/ash/system_tray_client_impl.cc b/chrome/browser/ui/ash/system_tray_client_impl.cc
index 834396b..2cbe575 100644
--- a/chrome/browser/ui/ash/system_tray_client_impl.cc
+++ b/chrome/browser/ui/ash/system_tray_client_impl.cc
@@ -68,6 +68,7 @@
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/ash/components/network/tether_constants.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "components/user_manager/user_manager.h"
@@ -609,8 +610,13 @@
     return;
   }
 
-  apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
-      app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromParentalControls);
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+        app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
+  } else {
+    apps::AppServiceProxyFactory::GetForProfile(profile)->Launch(
+        app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromParentalControls);
+  }
 }
 
 void SystemTrayClientImpl::ShowSettingsSimUnlock() {
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index bcf8873..e882e46e 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -47,6 +47,8 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/devtools/devtools_toggle_action.h"
 #include "chrome/browser/devtools/devtools_window.h"
+#include "chrome/browser/download/bubble/download_bubble_controller.h"
+#include "chrome/browser/download/bubble/download_display_controller.h"
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/extensions/browser_extension_window_controller.h"
@@ -558,6 +560,12 @@
   exclusive_access_manager_ = std::make_unique<ExclusiveAccessManager>(
       window_->GetExclusiveAccessContext());
 
+  if (window_->GetDownloadBubbleUIController()) {
+    window_->GetDownloadBubbleUIController()
+        ->GetDownloadDisplayController()
+        ->ListenToFullScreenChanges();
+  }
+
   BrowserList::AddBrowser(this);
 }
 
@@ -828,10 +836,11 @@
 
 Browser::WarnBeforeClosingResult Browser::MaybeWarnBeforeClosing(
     Browser::WarnBeforeClosingCallback warn_callback) {
-  // If the browser can close right away (there are no pending downloads we need
-  // to prompt about) then there's no need to warn. In the future, we might need
-  // to check other conditions as well.
-  if (CanCloseWithInProgressDownloads())
+  // If the browser can close right away (we've indicated that we want to skip
+  // before-unload handlers by setting `force_skip_warning_user_on_close_` to
+  // true or there are no pending downloads we need to prompt about) then
+  // there's no need to warn.
+  if (force_skip_warning_user_on_close_ || CanCloseWithInProgressDownloads())
     return WarnBeforeClosingResult::kOkToClose;
 
   DCHECK(!warn_before_closing_callback_)
@@ -841,6 +850,11 @@
 }
 
 bool Browser::ShouldCloseWindow() {
+  // If `force_skip_warning_user_` is true, then we should immediately
+  // return true.
+  if (force_skip_warning_user_on_close_)
+    return true;
+
   // If the user needs to see one or more warnings, hold off closing the
   // browser.
   const WarnBeforeClosingResult result = MaybeWarnBeforeClosing(base::BindOnce(
@@ -870,12 +884,14 @@
 
 bool Browser::ShouldRunUnloadListenerBeforeClosing(
     content::WebContents* web_contents) {
-  return unload_controller_.ShouldRunUnloadEventsHelper(web_contents);
+  return !force_skip_warning_user_on_close_ &&
+         unload_controller_.ShouldRunUnloadEventsHelper(web_contents);
 }
 
 bool Browser::RunUnloadListenerBeforeClosing(
     content::WebContents* web_contents) {
-  return unload_controller_.RunUnloadEventsHelper(web_contents);
+  return !force_skip_warning_user_on_close_ &&
+         unload_controller_.RunUnloadEventsHelper(web_contents);
 }
 
 void Browser::SetWindowUserTitle(const std::string& user_title) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 64eeec3..c9e2f4c 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -387,6 +387,14 @@
     return creation_source_ == CreationSource::kSessionRestore;
   }
 
+  // Tells the browser whether it should skip showing any dialogs that ask the
+  // user to confirm that they want to close the browser when it is being
+  // closed.
+  void set_force_skip_warning_user_on_close(
+      bool force_skip_warning_user_on_close) {
+    force_skip_warning_user_on_close_ = force_skip_warning_user_on_close;
+  }
+
   // Accessors ////////////////////////////////////////////////////////////////
 
   const CreateParams& create_params() const { return create_params_; }
@@ -1291,6 +1299,9 @@
 
   WarnBeforeClosingCallback warn_before_closing_callback_;
 
+  // Tells if the browser should skip warning the user when closing the window.
+  bool force_skip_warning_user_on_close_ = false;
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   std::unique_ptr<extensions::ExtensionBrowserWindowHelper>
       extension_browser_window_helper_;
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index 4563f887..36244f0 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -21,8 +21,8 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "chrome/browser/signin/signin_promo.h"
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
index e6d406f6..59b7e11 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
@@ -47,6 +47,7 @@
       case EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION:
         return l10n_util::GetStringUTF16(
             IDS_FULLSCREEN_UNKNOWN_EXTENSION_TRIGGERED_FULLSCREEN);
+      case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
       case EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE:
         NOTREACHED();
         return std::u16string();
@@ -70,6 +71,7 @@
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION:
       return l10n_util::GetStringFUTF16(
           IDS_FULLSCREEN_EXTENSION_TRIGGERED_FULLSCREEN, host);
+    case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE:
       NOTREACHED();
       return std::u16string();
@@ -86,6 +88,7 @@
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION:
+    case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE:
       NOTREACHED();  // No button in this case.
       return std::u16string();
@@ -103,6 +106,7 @@
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION:
+    case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE:
       NOTREACHED();  // No button in this case.
       return std::u16string();
@@ -129,6 +133,9 @@
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION:
       return l10n_util::GetStringFUTF16(
           IDS_FULLSCREEN_PRESS_ESC_TO_EXIT_MOUSELOCK, accelerator);
+    case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
+      return l10n_util::GetStringFUTF16(IDS_FULLSCREEN_PRESS_TO_SEE_DOWNLOADS,
+                                        accelerator);
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE:
       NOTREACHED();
       return std::u16string();
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h
index b134ce3..7302111 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h
@@ -30,7 +30,10 @@
 
   // For browser fullscreen mode.
   EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION,
-  EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION
+  EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION,
+
+  // To notify user that a download has started.
+  EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED
 };
 
 namespace exclusive_access_bubble {
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
index 0aa2212..e28c9ff 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
@@ -150,6 +150,7 @@
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION:
     case EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION:
+    case EXCLUSIVE_ACCESS_BUBBLE_TYPE_DOWNLOAD_STARTED:
       // Only fullscreen in effect.
       fullscreen = true;
       break;
diff --git a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc
index 24b7639..ef364ff 100644
--- a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc
+++ b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc
@@ -135,15 +135,8 @@
   // keyboard lock hook can interfere with it.
   // Turn off Paint Holding because the content used in the test does not paint
   // anything and we do not want to wait for the timeout.
-  // TODO(crbug.com/1327775): Currently, the download bubble pops open on new
-  // and completed downloads, which takes away focus, and unlocks the keyboard.
-  // The lock returns when the user brings the focus back to the page.
-  // However DownloadNavigationDoesNotUnlock does not pass because of the lost
-  // focus. We want to implement transient notification for Download Bubble in
-  // full screen mode to prevent taking away focus from the page.
   scoped_feature_list_.InitWithFeatures(
-      {}, {features::kSystemKeyboardLock, blink::features::kPaintHolding,
-           safe_browsing::kDownloadBubble});
+      {}, {features::kSystemKeyboardLock, blink::features::kPaintHolding});
 }
 
 void KeyboardLockInteractiveBrowserTest::SetUpOnMainThread() {
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc
index f6bf84a..53f4eafa 100644
--- a/chrome/browser/ui/login/login_handler.cc
+++ b/chrome/browser/ui/login/login_handler.cc
@@ -18,7 +18,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
-#include "chrome/browser/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
diff --git a/chrome/browser/ui/side_search/side_search_side_contents_helper.cc b/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
index c7ad3d9..b9614ff1 100644
--- a/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
+++ b/chrome/browser/ui/side_search/side_search_side_contents_helper.cc
@@ -161,6 +161,10 @@
   has_loaded_url_ = true;
 }
 
+content::WebContents* SideSearchSideContentsHelper::GetTabWebContents() {
+  return delegate_->GetTabWebContents();
+}
+
 void SideSearchSideContentsHelper::SetDelegate(Delegate* delegate) {
   DCHECK(!delegate_);
   delegate_ = delegate;
diff --git a/chrome/browser/ui/side_search/side_search_side_contents_helper.h b/chrome/browser/ui/side_search/side_search_side_contents_helper.h
index ef462ea..b8d4f46 100644
--- a/chrome/browser/ui/side_search/side_search_side_contents_helper.h
+++ b/chrome/browser/ui/side_search/side_search_side_contents_helper.h
@@ -49,6 +49,9 @@
     virtual content::WebContents* OpenURLFromTab(
         content::WebContents* source,
         const content::OpenURLParams& params);
+
+    // Get the WebContents of the associated tab.
+    virtual content::WebContents* GetTabWebContents() = 0;
   };
 
   // Will call MaybeRecordMetricsPerJourney().
@@ -81,6 +84,9 @@
   // necessary. Also calls MaybeRecordMetricsPerJourney().
   void LoadURL(const GURL& url);
 
+  // Get the WebContents of the associated tab.
+  content::WebContents* GetTabWebContents();
+
   // Called to set the tab contents associated with this side panel contents.
   // The tab contents will always outlive this helper and its associated side
   // contents.
diff --git a/chrome/browser/ui/side_search/side_search_side_contents_helper_unittest.cc b/chrome/browser/ui/side_search/side_search_side_contents_helper_unittest.cc
index 1352c17..29232dd 100644
--- a/chrome/browser/ui/side_search/side_search_side_contents_helper_unittest.cc
+++ b/chrome/browser/ui/side_search/side_search_side_contents_helper_unittest.cc
@@ -41,6 +41,7 @@
     last_search_url_ = url;
   }
   void SidePanelProcessGone() override {}
+  content::WebContents* GetTabWebContents() override { return nullptr; }
 
   const GURL& tab_contents_url() const { return tab_contents_url_; }
 
diff --git a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
index acb791f..58e0171 100644
--- a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
+++ b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
@@ -58,6 +58,10 @@
   return delegate_ ? delegate_->HandleKeyboardEvent(source, event) : false;
 }
 
+content::WebContents* SideSearchTabContentsHelper::GetTabWebContents() {
+  return web_contents();
+}
+
 content::WebContents* SideSearchTabContentsHelper::OpenURLFromTab(
     content::WebContents* source,
     const content::OpenURLParams& params) {
diff --git a/chrome/browser/ui/side_search/side_search_tab_contents_helper.h b/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
index 5f0a9e4..b4f4616 100644
--- a/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
+++ b/chrome/browser/ui/side_search/side_search_tab_contents_helper.h
@@ -72,6 +72,7 @@
   content::WebContents* OpenURLFromTab(
       content::WebContents* source,
       const content::OpenURLParams& params) override;
+  content::WebContents* GetTabWebContents() override;
 
   // content::WebContentsObserver:
   void DidStartNavigation(
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index e004d33..52acbc75 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -58,9 +58,9 @@
 #include "chrome/browser/permissions/last_tab_standing_tracker_tab_helper.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/loading_predictor_tab_helper.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
-#include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h"
 #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/reputation/reputation_web_contents_observer.h"
@@ -162,7 +162,7 @@
 #else
 #include "chrome/browser/accuracy_tips/accuracy_service_factory.h"
 #include "chrome/browser/banners/app_banner_manager_desktop.h"
-#include "chrome/browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
+#include "chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h"
 #include "chrome/browser/tab_contents/form_interaction_tab_helper.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/intent_picker_tab_helper.h"
diff --git a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
index dc41a3e..62ebbfc7 100644
--- a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
@@ -61,7 +61,7 @@
   // Wait until we're done with everything else before creating `controller_`
   // since it can call `Show()` synchronously.
   controller_ = std::make_unique<DownloadDisplayController>(
-      this, browser_->profile(), bubble_controller_.get());
+      this, browser_, bubble_controller_.get());
 }
 
 DownloadToolbarButtonView::~DownloadToolbarButtonView() {
diff --git a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.cc b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.cc
index 5f2c20e..be25f0bf 100644
--- a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.cc
+++ b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.cc
@@ -6,6 +6,6 @@
 
 #include <algorithm>
 
-int SystemMenuInsertionDelegateWin::GetInsertionIndex(HMENU native_menu) {
-  return std::max(0, GetMenuItemCount(native_menu) - 1);
+size_t SystemMenuInsertionDelegateWin::GetInsertionIndex(HMENU native_menu) {
+  return static_cast<size_t>(std::max(1, GetMenuItemCount(native_menu)) - 1);
 }
diff --git a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h
index c4eda4e..7d616d4 100644
--- a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h
+++ b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h
@@ -22,7 +22,7 @@
   ~SystemMenuInsertionDelegateWin() override {}
 
   // Overridden from views::MenuInsertionDelegateWin:
-  int GetInsertionIndex(HMENU native_menu) override;
+  size_t GetInsertionIndex(HMENU native_menu) override;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_SYSTEM_MENU_INSERTION_DELEGATE_WIN_H_
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
index 66192da..6450ec0c 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
@@ -243,7 +243,7 @@
   AutocompleteInput input(
       u"foo", metrics::OmniboxEventProto::BLANK,
       ChromeAutocompleteSchemeClassifier(browser()->profile()));
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   edit_model()->autocomplete_controller()->Start(input);
 
   EXPECT_FALSE(edit_model()->result().empty());
@@ -599,7 +599,7 @@
   AutocompleteInput input(
       u"foo", metrics::OmniboxEventProto::BLANK,
       ChromeAutocompleteSchemeClassifier(browser()->profile()));
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   edit_model()->autocomplete_controller()->Start(input);
 
   // Create a match to populate the autocomplete.
diff --git a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog.cc b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog.cc
index c786883..8f76aa3 100644
--- a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog.cc
+++ b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog.cc
@@ -121,7 +121,9 @@
           .AddBodyText(body_text, kBodyText)
           .AddOkButton(
               base::BindOnce(&DisabledDialogModelDelegate::OnDialogAccepted,
-                             base::Unretained(model_delegate_ptr)))
+                             base::Unretained(model_delegate_ptr)),
+              l10n_util::GetStringUTF16(
+                  IDS_TAILORED_SECURITY_DISABLED_DIALOG_ACCEPT_BUTTON))
           .AddCancelButton(
               base::BindOnce(&DisabledDialogModelDelegate::OnDialogRejected,
                              base::Unretained(model_delegate_ptr),
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc b/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
index 3a10cce..e04c4d4a 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
@@ -70,8 +70,14 @@
 
 // Regression test for https://crbug.com/1042010, it should be possible to focus
 // the bubble with the "rotate pane focus" (F6) hotkey.
+// TODO(crbug.com/1343849): Flaky on Mac.
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_CanFocusBubbleWithRotatePaneFocusHotkey DISABLED_CanFocusBubbleWithRotatePaneFocusHotkey
+#else
+#define MAYBE_CanFocusBubbleWithRotatePaneFocusHotkey CanFocusBubbleWithRotatePaneFocusHotkey
+#endif
 IN_PROC_BROWSER_TEST_F(SessionCrashedBubbleViewTest,
-                       CanFocusBubbleWithRotatePaneFocusHotkey) {
+                       MAYBE_CanFocusBubbleWithRotatePaneFocusHotkey) {
   ShowUi("SessionCrashedBubble");
   views::FocusManager* focus_manager =
       crash_bubble_->GetWidget()->GetFocusManager();
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
index 1e81028..a97b8648 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
@@ -506,7 +506,7 @@
   return combobox;
 }
 
-bool SidePanelCoordinator::OnComboboxChangeTriggered(int index) {
+bool SidePanelCoordinator::OnComboboxChangeTriggered(size_t index) {
   SidePanelEntry::Id entry_id = combobox_model_->GetIdAt(index);
   Show(entry_id, SidePanelUtil::SidePanelOpenTrigger::kComboboxSelected);
   return true;
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
index 00537940..6b9f033 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
@@ -111,7 +111,7 @@
   // and before any selected id and combobox model change takes place. This
   // allows us to make the entry displayed in the combobox follow the same
   // delays as the side panel content when there are delays for loading content.
-  bool OnComboboxChangeTriggered(int index);
+  bool OnComboboxChangeTriggered(size_t index);
 
   // SidePanelRegistryObserver:
   void OnEntryRegistered(SidePanelEntry* entry) override;
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
index 604594a..dffdbe91 100644
--- a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
+++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
@@ -21,14 +21,30 @@
 #include "ui/views/layout/flex_layout_types.h"
 #include "ui/views/layout/flex_layout_view.h"
 
+namespace {
+class SideSearchWebView : public views::WebView {
+ public:
+  using WebView::WebView;
+
+  ~SideSearchWebView() override {
+    if (!web_contents())
+      return;
+    auto* side_contents_helper =
+        SideSearchSideContentsHelper::FromWebContents(web_contents());
+    if (!side_contents_helper)
+      return;
+    auto* helper = SideSearchTabContentsHelper::FromWebContents(
+        side_contents_helper->GetTabWebContents());
+    if (helper)
+      helper->ClearSidePanelContents();
+  }
+};
+}  // namespace
+
 UnifiedSideSearchController::UnifiedSideSearchController(
     content::WebContents* web_contents)
     : content::WebContentsUserData<UnifiedSideSearchController>(*web_contents) {
   Observe(web_contents);
-
-  // Update the state of the side panel to catch cases where we switch to a tab
-  // where the panel should be hidden (or vise versa).
-  UpdateSidePanel();
 }
 
 UnifiedSideSearchController::~UnifiedSideSearchController() {
@@ -88,7 +104,7 @@
   auto* browser_view = GetBrowserView();
   DCHECK(browser_view);
   auto side_search_view =
-      std::make_unique<views::WebView>(browser_view->GetProfile());
+      std::make_unique<SideSearchWebView>(browser_view->GetProfile());
   side_search_view->SetProperty(
       views::kFlexBehaviorKey,
       views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
@@ -143,7 +159,6 @@
         helper->MaybeRecordDurationSidePanelAvailableToFirstOpen();
     }
   }
-  UpdateSidePanel();
 }
 
 void UnifiedSideSearchController::CloseSidePanel(
@@ -152,10 +167,6 @@
   if (browser_view) {
     browser_view->side_panel_coordinator()->Close();
   }
-  UpdateSidePanel();
-
-  // Clear the side contents for the currently active tab.
-  ClearSideContentsCache();
 }
 
 BrowserView* UnifiedSideSearchController::GetBrowserView() const {
@@ -163,24 +174,6 @@
   return browser ? BrowserView::GetBrowserViewForBrowser(browser) : nullptr;
 }
 
-void UnifiedSideSearchController::ClearSideContentsCache() {
-  auto* browser_view = GetBrowserView();
-  if (!browser_view)
-    return;
-  DCHECK(!browser_view->side_panel_coordinator()->IsSidePanelShowing());
-  auto* registry = SidePanelRegistry::Get(web_contents());
-  if (!registry)
-    return;
-  auto* current_entry =
-      registry->GetEntryForId(SidePanelEntry::Id::kSideSearch);
-  if (current_entry)
-    current_entry->ClearCachedView();
-
-  auto* helper = SideSearchTabContentsHelper::FromWebContents(web_contents());
-  if (helper)
-    helper->ClearSidePanelContents();
-}
-
 void UnifiedSideSearchController::UpdateSidePanel() {
   auto* tab_contents_helper =
       SideSearchTabContentsHelper::FromWebContents(web_contents());
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.h b/chrome/browser/ui/views/side_search/unified_side_search_controller.h
index 2f28016..91e7310 100644
--- a/chrome/browser/ui/views/side_search/unified_side_search_controller.h
+++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.h
@@ -74,10 +74,6 @@
   // Creates a string representing the side search side panel's hosted content.
   std::u16string GetSideSearchName() const;
 
-  // Clears the side contents for the currently active tab in this browser
-  // window and the view in the side search registry.
-  void ClearSideContentsCache();
-
   // Updates side panel's availability from SideSearchTabContentsHelper.
   void UpdateSidePanel();
 
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller_interactive_uitest.cc b/chrome/browser/ui/views/side_search/unified_side_search_controller_interactive_uitest.cc
index 0eb2cc5..b4633d5 100644
--- a/chrome/browser/ui/views/side_search/unified_side_search_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/side_search/unified_side_search_controller_interactive_uitest.cc
@@ -447,3 +447,32 @@
   ActivateTabAt(browser(), 3);
   EXPECT_EQ(nullptr, coordinator->GetCurrentSidePanelEntryForTesting());
 }
+
+#if BUILDFLAG(IS_MAC)
+// TODO(crbug.com/1340387): Test is flaky on Mac.
+#define MAYBE_CloseSidePanelShouldClearCache \
+  DISABLED_CloseSidePanelShouldClearCache
+#else
+#define MAYBE_CloseSidePanelShouldClearCache CloseSidePanelShouldClearCache
+#endif
+IN_PROC_BROWSER_TEST_F(SideSearchV2Test, MAYBE_CloseSidePanelShouldClearCache) {
+  auto* browser_view = BrowserViewFor(browser());
+  NavigateActiveTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            browser_view->side_panel_coordinator()
+                ->GetCurrentSidePanelEntryForTesting()
+                ->id());
+
+  // When side panel is open,  side panel web contents is present.
+  auto* tab_contents_helper = SideSearchTabContentsHelper::FromWebContents(
+      browser()->tab_strip_model()->GetActiveWebContents());
+  EXPECT_NE(nullptr, tab_contents_helper->side_panel_contents_for_testing());
+
+  browser_view->side_panel_coordinator()->Close();
+
+  // When side panel is closed, side panel web contents is destroyed.
+  EXPECT_EQ(nullptr, tab_contents_helper->side_panel_contents_for_testing());
+}
diff --git a/chrome/browser/ui/webui/browser_command/DEPS b/chrome/browser/ui/webui/browser_command/DEPS
new file mode 100644
index 0000000..40885822
--- /dev/null
+++ b/chrome/browser/ui/webui/browser_command/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  # Browser command relies on the tutorial ID defined here.
+  "+chrome/browser/ui/views/user_education/browser_user_education_service.h",
+]
diff --git a/chrome/browser/ui/webui/browser_command/browser_command_handler.cc b/chrome/browser/ui/webui/browser_command/browser_command_handler.cc
index 542a05d6..145b236 100644
--- a/chrome/browser/ui/webui/browser_command/browser_command_handler.cc
+++ b/chrome/browser/ui/webui/browser_command/browser_command_handler.cc
@@ -11,13 +11,20 @@
 #include "chrome/browser/new_tab_page/promos/promo_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/user_education/user_education_service.h"
+#include "chrome/browser/ui/user_education/user_education_service_factory.h"
+#include "chrome/browser/ui/views/user_education/browser_user_education_service.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
 #include "components/safe_browsing/core/common/safe_browsing_policy_handler.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/user_education/common/tutorial_service.h"
+#include "ui/base/interaction/element_identifier.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 
@@ -75,8 +82,11 @@
       can_execute = !chrome::enterprise_util::IsBrowserManaged(profile_) &&
                     !profile_->IsChild();
       break;
-    default:
-      NOTREACHED() << "Unspecified behavior for command " << command_id;
+    case Command::kStartTabGroupTutorial:
+      can_execute = !!GetTutorialService();
+      break;
+    case Command::kOpenPasswordManager:
+      can_execute = true;
       break;
   }
   std::move(callback).Run(can_execute);
@@ -131,12 +141,46 @@
       base::RecordAction(
           base::UserMetricsAction("NewTabPage_Promos_PrivacyGuide"));
       break;
+    case Command::kStartTabGroupTutorial:
+      StartTabGroupTutorial();
+      break;
+    case Command::kOpenPasswordManager:
+      NavigateToURL(
+          GURL(chrome::GetSettingsUrl(chrome::kPasswordManagerSubPage)),
+          disposition);
+      break;
     default:
       NOTREACHED() << "Unspecified behavior for command " << id;
       break;
   }
 }
 
+user_education::TutorialService* BrowserCommandHandler::GetTutorialService() {
+  auto* service = UserEducationServiceFactory::GetForProfile(profile_);
+  return service ? &service->tutorial_service() : nullptr;
+}
+
+ui::ElementContext BrowserCommandHandler::GetUiElementContext() {
+  return chrome::FindBrowserWithProfile(profile_)
+      ->window()
+      ->GetElementContext();
+}
+
+void BrowserCommandHandler::StartTabGroupTutorial() {
+  user_education::TutorialService* tutorial_service = GetTutorialService();
+  if (!tutorial_service) {
+    // Should never happen since we return false in CanExecuteCommand(), but
+    // avoid a browser crash anyway.
+    return;
+  }
+
+  const ui::ElementContext context = GetUiElementContext();
+  if (!context)
+    return;
+
+  tutorial_service->StartTutorial(kTabGroupTutorialId, context);
+}
+
 void BrowserCommandHandler::OpenFeedbackForm() {
   chrome::ShowFeedbackPage(feedback_settings_.url, profile_,
                            feedback_settings_.source,
diff --git a/chrome/browser/ui/webui/browser_command/browser_command_handler.h b/chrome/browser/ui/webui/browser_command/browser_command_handler.h
index a4336233..21f7011a 100644
--- a/chrome/browser/ui/webui/browser_command/browser_command_handler.h
+++ b/chrome/browser/ui/webui/browser_command/browser_command_handler.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
+#include "ui/base/interaction/element_tracker.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/webui/resources/js/browser_command/browser_command.mojom.h"
 #include "url/gurl.h"
@@ -19,6 +20,10 @@
 class CommandUpdater;
 class Profile;
 
+namespace user_education {
+class TutorialService;
+}
+
 // Struct containing the information needed to customize/configure the feedback
 // form. Used to populate arguments passed to chrome::ShowFeedbackPage().
 struct FeedbackCommandSettings {
@@ -70,6 +75,9 @@
   virtual void NavigateToURL(const GURL& url,
                              WindowOpenDisposition disposition);
   virtual void OpenFeedbackForm();
+  virtual user_education::TutorialService* GetTutorialService();
+  virtual ui::ElementContext GetUiElementContext();
+  void StartTabGroupTutorial();
 
   FeedbackCommandSettings feedback_settings_;
   raw_ptr<Profile> profile_;
diff --git a/chrome/browser/ui/webui/browser_command/browser_command_handler_unittest.cc b/chrome/browser/ui/webui/browser_command/browser_command_handler_unittest.cc
index 32fe97f..4660a3b 100644
--- a/chrome/browser/ui/webui/browser_command/browser_command_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browser_command/browser_command_handler_unittest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/command_updater_impl.h"
 #include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/views/user_education/browser_user_education_service.h"
 #include "chrome/browser/ui/webui/browser_command/browser_command_handler.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/webui_url_constants.h"
@@ -19,9 +20,13 @@
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/user_education/common/help_bubble_factory_registry.h"
+#include "components/user_education/common/tutorial_registry.h"
+#include "components/user_education/common/tutorial_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/interaction/element_tracker.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/webui/resources/js/browser_command/browser_command.mojom.h"
 
@@ -38,8 +43,12 @@
     Command::kOpenSafeBrowsingEnhancedProtectionSettings,
     Command::kOpenFeedbackForm,
     Command::kOpenPrivacyGuide,
+    Command::kStartTabGroupTutorial,
+    Command::kOpenPasswordManager,
 };
 
+const ui::ElementContext kTestContext1(1);
+
 class TestCommandHandler : public BrowserCommandHandler {
  public:
   explicit TestCommandHandler(Profile* profile)
@@ -55,9 +64,15 @@
 
   void OpenFeedbackForm() override {
     // The functionality of opening the feedback form is removed, as it cannot
-    // be executed in a unittes.
+    // be executed in a unittest.
   }
 
+  user_education::TutorialService* GetTutorialService() override {
+    return tutorial_service_;
+  }
+
+  ui::ElementContext GetUiElementContext() override { return kTestContext1; }
+
   CommandUpdater* GetCommandUpdater() override {
     if (command_updater_)
       return command_updater_.get();
@@ -70,9 +85,50 @@
     EnableSupportedCommands();
   }
 
+  void SetTutorialService(user_education::TutorialService* service) {
+    tutorial_service_ = service;
+  }
+
+  user_education::TutorialService* tutorial_service_;
   std::unique_ptr<CommandUpdater> command_updater_;
 };
 
+class TestTutorialService : public user_education::TutorialService {
+ public:
+  TestTutorialService(
+      user_education::TutorialRegistry* tutorial_registry,
+      user_education::HelpBubbleFactoryRegistry* help_bubble_factory_registry)
+      : user_education::TutorialService(tutorial_registry,
+                                        help_bubble_factory_registry) {}
+  ~TestTutorialService() override = default;
+  std::u16string GetBodyIconAltText(bool is_last_step) const override {
+    return std::u16string();
+  }
+
+  bool StartTutorial(
+      user_education::TutorialIdentifier id,
+      ui::ElementContext context,
+      base::OnceClosure completed_callback = base::DoNothing(),
+      base::OnceClosure aborted_callback = base::DoNothing()) override {
+    return true;
+  }
+};
+
+class MockTutorialService : public TestTutorialService {
+ public:
+  MockTutorialService(
+      user_education::TutorialRegistry* tutorial_registry,
+      user_education::HelpBubbleFactoryRegistry* help_bubble_factory_registry)
+      : TestTutorialService(tutorial_registry, help_bubble_factory_registry) {}
+  ~MockTutorialService() override = default;
+
+  MOCK_METHOD4(StartTutorial,
+               bool(user_education::TutorialIdentifier,
+                    ui::ElementContext,
+                    base::OnceClosure,
+                    base::OnceClosure));
+};
+
 class MockCommandHandler : public TestCommandHandler {
  public:
   explicit MockCommandHandler(Profile* profile) : TestCommandHandler(profile) {}
@@ -353,3 +409,38 @@
                     DispositionFromClick(*info)));
   EXPECT_TRUE(ExecuteCommand(Command::kOpenPrivacyGuide, std::move(info)));
 }
+
+TEST_F(BrowserCommandHandlerTest, StartTabGroupTutorialCommand) {
+  // Command cannot be executed if the tutorial service doesn't exist.
+  command_handler_->SetTutorialService(nullptr);
+  EXPECT_FALSE(CanExecuteCommand(Command::kStartTabGroupTutorial));
+
+  // Create mock service so the command can be executed.
+  auto bubble_factory_registry =
+      std::make_unique<user_education::HelpBubbleFactoryRegistry>();
+  user_education::TutorialRegistry registry;
+  MockTutorialService service(&registry, bubble_factory_registry.get());
+  command_handler_->SetTutorialService(&service);
+  EXPECT_TRUE(CanExecuteCommand(Command::kStartTabGroupTutorial));
+
+  // The StartTabGroupTutorial command should start the tab group tutorial.
+  ClickInfoPtr info = ClickInfo::New();
+  EXPECT_CALL(service, StartTutorial(kTabGroupTutorialId, kTestContext1,
+                                     testing::_, testing::_));
+  EXPECT_TRUE(ExecuteCommand(Command::kStartTabGroupTutorial, std::move(info)));
+}
+
+TEST_F(BrowserCommandHandlerTest, OpenPasswordManagerCommand) {
+  // By default, opening the password manager is allowed.
+  EXPECT_TRUE(CanExecuteCommand(Command::kOpenPasswordManager));
+  ClickInfoPtr info = ClickInfo::New();
+  info->middle_button = true;
+  info->meta_key = true;
+  // The OpenPassswordManager command opens a new settings window with the
+  // password manager and the correct disposition.
+  EXPECT_CALL(*command_handler_,
+              NavigateToURL(
+                  GURL(chrome::GetSettingsUrl(chrome::kPasswordManagerSubPage)),
+                  DispositionFromClick(*info)));
+  EXPECT_TRUE(ExecuteCommand(Command::kOpenPasswordManager, std::move(info)));
+}
diff --git a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs_chromeos.cc
index c3d61dc..ed616d9 100644
--- a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs_chromeos.cc
+++ b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs_chromeos.cc
@@ -59,7 +59,7 @@
   }
 #if !defined(OFFICIAL_BUILD)
   map.AddUntrustedWebUIConfig(
-      std::make_unique<ash::UntrustedSampleSystemWebAppUIConfig>());
+      std::make_unique<ash::SampleSystemWebAppUntrustedUIConfig>());
   map.AddUntrustedWebUIConfig(
       std::make_unique<ash::DemoModeAppUntrustedUIConfig>(base::BindRepeating(
           [] { return ash::DemoSession::Get()->DemoAppComponentPath(); })));
diff --git a/chrome/browser/ui/webui/chromeos/OWNERS b/chrome/browser/ui/webui/chromeos/OWNERS
index c13c199..8816a6e 100644
--- a/chrome/browser/ui/webui/chromeos/OWNERS
+++ b/chrome/browser/ui/webui/chromeos/OWNERS
@@ -1,10 +1,5 @@
 file://ash/webui/PLATFORM_OWNERS
 
-achuith@chromium.org
-hidehiko@chromium.org
-khorimoto@chromium.org
-xiyuan@chromium.org
-
 per-file *bluetooth*=file://ui/webui/resources/cr_components/chromeos/bluetooth/OWNERS
 per-file *net*=file://ui/webui/resources/cr_components/chromeos/network/OWNERS
 per-file drive_internals_ui.*=file://ui/file_manager/OWNERS
diff --git a/chrome/browser/ui/webui/devtools_ui_data_source.cc b/chrome/browser/ui/webui/devtools_ui_data_source.cc
index 113d3832..a79bc9f 100644
--- a/chrome/browser/ui/webui/devtools_ui_data_source.cc
+++ b/chrome/browser/ui/webui/devtools_ui_data_source.cc
@@ -48,8 +48,8 @@
 
 // DevToolsDataSource ---------------------------------------------------------
 
-std::string GetMimeTypeForPath(const std::string& path) {
-  std::string filename = PathWithoutParams(path);
+std::string GetMimeTypeForUrl(const GURL& url) {
+  std::string filename = url.ExtractFileName();
   if (base::EndsWith(filename, ".html", base::CompareCase::INSENSITIVE_ASCII)) {
     return "text/html";
   } else if (base::EndsWith(filename, ".css",
@@ -207,8 +207,8 @@
   std::move(callback).Run(CreateNotFoundResponse());
 }
 
-std::string DevToolsDataSource::GetMimeType(const std::string& path) {
-  return GetMimeTypeForPath(path);
+std::string DevToolsDataSource::GetMimeType(const GURL& url) {
+  return GetMimeTypeForUrl(url);
 }
 
 bool DevToolsDataSource::ShouldAddContentSecurityPolicy() {
diff --git a/chrome/browser/ui/webui/devtools_ui_data_source.h b/chrome/browser/ui/webui/devtools_ui_data_source.h
index c10406db..992cd5d 100644
--- a/chrome/browser/ui/webui/devtools_ui_data_source.h
+++ b/chrome/browser/ui/webui/devtools_ui_data_source.h
@@ -52,7 +52,7 @@
   struct PendingRequest;
 
   // content::URLDataSource overrides.
-  std::string GetMimeType(const std::string& path) override;
+  std::string GetMimeType(const GURL& url) override;
   bool ShouldAddContentSecurityPolicy() override;
   bool ShouldDenyXFrameOptions() override;
   bool ShouldServeMimeTypeAsContentTypeHeader() override;
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc
index 604f7e1..92eec98 100644
--- a/chrome/browser/ui/webui/favicon_source.cc
+++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -199,7 +199,7 @@
   }
 }
 
-std::string FaviconSource::GetMimeType(const std::string&) {
+std::string FaviconSource::GetMimeType(const GURL&) {
   // We need to explicitly return a mime type, otherwise if the user tries to
   // drag the image they get no extension.
   return "image/png";
diff --git a/chrome/browser/ui/webui/favicon_source.h b/chrome/browser/ui/webui/favicon_source.h
index 3518ba6..9bb5b51 100644
--- a/chrome/browser/ui/webui/favicon_source.h
+++ b/chrome/browser/ui/webui/favicon_source.h
@@ -52,7 +52,7 @@
       const GURL& url,
       const content::WebContents::Getter& wc_getter,
       content::URLDataSource::GotDataCallback callback) override;
-  std::string GetMimeType(const std::string&) override;
+  std::string GetMimeType(const GURL&) override;
   bool AllowCaching() override;
   bool ShouldReplaceExistingSource() override;
   bool ShouldServiceRequest(const GURL& url,
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc
index 9b9c63a..29f044a 100644
--- a/chrome/browser/ui/webui/fileicon_source.cc
+++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -123,7 +123,7 @@
   FetchFileIcon(file_path, scale_factor, icon_size, std::move(callback));
 }
 
-std::string FileIconSource::GetMimeType(const std::string&) {
+std::string FileIconSource::GetMimeType(const GURL&) {
   // Rely on image decoder inferring the correct type.
   return std::string();
 }
diff --git a/chrome/browser/ui/webui/fileicon_source.h b/chrome/browser/ui/webui/fileicon_source.h
index 3bc04812..56843cf 100644
--- a/chrome/browser/ui/webui/fileicon_source.h
+++ b/chrome/browser/ui/webui/fileicon_source.h
@@ -33,7 +33,7 @@
       const GURL& url,
       const content::WebContents::Getter& wc_getter,
       content::URLDataSource::GotDataCallback callback) override;
-  std::string GetMimeType(const std::string&) override;
+  std::string GetMimeType(const GURL&) override;
   bool AllowCaching() override;
 
  protected:
diff --git a/chrome/browser/ui/webui/gcm_internals_ui.cc b/chrome/browser/ui/webui/gcm_internals_ui.cc
index cd9e56f..de9cca6 100644
--- a/chrome/browser/ui/webui/gcm_internals_ui.cc
+++ b/chrome/browser/ui/webui/gcm_internals_ui.cc
@@ -71,9 +71,8 @@
     Profile* profile,
     gcm::GCMProfileService* profile_service,
     const gcm::GCMClient::GCMStatistics* stats) {
-  base::DictionaryValue results;
-  gcm_driver::SetGCMInternalsInfo(stats, profile_service, profile->GetPrefs(),
-                                  &results);
+  base::Value results = gcm_driver::SetGCMInternalsInfo(stats, profile_service,
+                                                        profile->GetPrefs());
   FireWebUIListener(gcm_driver::kSetGcmInternalsInfo, results);
 }
 
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 9e6fe44..fce8b09 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -103,7 +103,7 @@
   ~InterstitialHTMLSource() override = default;
 
   // content::URLDataSource:
-  std::string GetMimeType(const std::string& mime_type) override;
+  std::string GetMimeType(const GURL& url) override;
   std::string GetSource() override;
   std::string GetContentSecurityPolicy(
       const network::mojom::CSPDirectiveName directive) override;
@@ -442,7 +442,7 @@
 
 // InterstitialHTMLSource
 
-std::string InterstitialHTMLSource::GetMimeType(const std::string& mime_type) {
+std::string InterstitialHTMLSource::GetMimeType(const GURL&) {
   return "text/html";
 }
 
diff --git a/chrome/browser/ui/webui/policy/policy_ui.cc b/chrome/browser/ui/webui/policy/policy_ui.cc
index 6b26cb6..aa5796e 100644
--- a/chrome/browser/ui/webui/policy/policy_ui.cc
+++ b/chrome/browser/ui/webui/policy/policy_ui.cc
@@ -84,11 +84,19 @@
   source->AddResourcePath("policy.css", IDR_POLICY_CSS);
   source->AddResourcePath("policy_base.js", IDR_POLICY_BASE_JS);
   source->AddResourcePath("policy.js", IDR_POLICY_JS);
+  source->AddResourcePath("policy_conflict.html.js",
+                          IDR_POLICY_POLICY_CONFLICT_HTML_JS);
   source->AddResourcePath("policy_conflict.js", IDR_POLICY_POLICY_CONFLICT_JS);
+  source->AddResourcePath("policy_row.html.js", IDR_POLICY_POLICY_ROW_HTML_JS);
   source->AddResourcePath("policy_row.js", IDR_POLICY_POLICY_ROW_JS);
+  source->AddResourcePath("policy_precedence_row.html.js",
+                          IDR_POLICY_POLICY_PRECEDENCE_ROW_HTML_JS);
   source->AddResourcePath("policy_precedence_row.js",
                           IDR_POLICY_POLICY_PRECEDENCE_ROW_JS);
+  source->AddResourcePath("policy_table.html.js",
+                          IDR_POLICY_POLICY_TABLE_HTML_JS);
   source->AddResourcePath("policy_table.js", IDR_POLICY_POLICY_TABLE_JS);
+  source->AddResourcePath("status_box.html.js", IDR_POLICY_STATUS_BOX_HTML_JS);
   source->AddResourcePath("status_box.js", IDR_POLICY_STATUS_BOX_JS);
   source->SetDefaultResource(IDR_POLICY_HTML);
 
diff --git a/chrome/browser/ui/webui/prefs_internals_source.cc b/chrome/browser/ui/webui/prefs_internals_source.cc
index 2b3d41b3..7ce302b2 100644
--- a/chrome/browser/ui/webui/prefs_internals_source.cc
+++ b/chrome/browser/ui/webui/prefs_internals_source.cc
@@ -23,7 +23,7 @@
   return chrome::kChromeUIPrefsInternalsHost;
 }
 
-std::string PrefsInternalsSource::GetMimeType(const std::string& path) {
+std::string PrefsInternalsSource::GetMimeType(const GURL& url) {
   return "text/plain";
 }
 
diff --git a/chrome/browser/ui/webui/prefs_internals_source.h b/chrome/browser/ui/webui/prefs_internals_source.h
index 5062b6c9..1a80093 100644
--- a/chrome/browser/ui/webui/prefs_internals_source.h
+++ b/chrome/browser/ui/webui/prefs_internals_source.h
@@ -22,7 +22,7 @@
 
   // content::URLDataSource:
   std::string GetSource() override;
-  std::string GetMimeType(const std::string& path) override;
+  std::string GetMimeType(const GURL& url) override;
   void StartDataRequest(
       const GURL& url,
       const content::WebContents::Getter& wc_getter,
diff --git a/chrome/browser/ui/webui/sanitized_image_source.cc b/chrome/browser/ui/webui/sanitized_image_source.cc
index 7cdb4be..90bcea8 100644
--- a/chrome/browser/ui/webui/sanitized_image_source.cc
+++ b/chrome/browser/ui/webui/sanitized_image_source.cc
@@ -212,7 +212,7 @@
       network::SimpleURLLoader::kMaxBoundedStringDownloadSize);
 }
 
-std::string SanitizedImageSource::GetMimeType(const std::string& path) {
+std::string SanitizedImageSource::GetMimeType(const GURL& url) {
   return "image/png";
 }
 
diff --git a/chrome/browser/ui/webui/sanitized_image_source.h b/chrome/browser/ui/webui/sanitized_image_source.h
index ad5a4838..a3c3724 100644
--- a/chrome/browser/ui/webui/sanitized_image_source.h
+++ b/chrome/browser/ui/webui/sanitized_image_source.h
@@ -64,7 +64,7 @@
       const GURL& url,
       const content::WebContents::Getter& wc_getter,
       content::URLDataSource::GotDataCallback callback) override;
-  std::string GetMimeType(const std::string& path) override;
+  std::string GetMimeType(const GURL& url) override;
   bool ShouldReplaceExistingSource() override;
 
   void set_identity_manager_for_test(
diff --git a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
index ec74788..35b6841 100644
--- a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
@@ -12,6 +12,8 @@
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"  // kSettingsAppId
+#include "components/services/app_service/public/cpp/app_launch_util.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/display/display.h"
@@ -112,10 +114,16 @@
     activated_from_keyboard = args[0].GetBool();
   int flags = activated_from_keyboard ? ui::EF_NONE : ui::EF_LEFT_MOUSE_BUTTON;
 
-  app_service_proxy_->Launch(
-      arc::kSettingsAppId, flags,
-      apps::mojom::LaunchSource::kFromParentalControls,
-      apps::MakeWindowInfo(GetDisplayIdForCurrentProfile()));
+  if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+    app_service_proxy_->Launch(
+        arc::kSettingsAppId, flags, apps::LaunchSource::kFromParentalControls,
+        std::make_unique<apps::WindowInfo>(GetDisplayIdForCurrentProfile()));
+  } else {
+    app_service_proxy_->Launch(
+        arc::kSettingsAppId, flags,
+        apps::mojom::LaunchSource::kFromParentalControls,
+        apps::MakeWindowInfo(GetDisplayIdForCurrentProfile()));
+  }
 }
 
 int64_t AndroidAppsHandler::GetDisplayIdForCurrentProfile() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index ce3abc55..1517811 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -133,8 +133,14 @@
   if (arc_app_list_prefs && arc_app_list_prefs->GetApp(app_id)) {
     DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
         profile_));
-    apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
-        app_id, ui::EF_NONE, apps::mojom::LaunchSource::kFromParentalControls);
+    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+      apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
+          app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls);
+    } else {
+      apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch(
+          app_id, ui::EF_NONE,
+          apps::mojom::LaunchSource::kFromParentalControls);
+    }
     return;
   }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
index 3299cff..bce5d294 100644
--- a/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc
@@ -15,9 +15,11 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.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/features.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
@@ -70,9 +72,15 @@
       chromeos::ChildUserService::kFamilyLinkHelperAppPackageName, profile_);
   if (registry.GetAppType(app_id) != apps::AppType::kUnknown) {
     // Launch FLH app since it is available.
-    proxy->Launch(app_id, ui::EF_NONE,
-                  apps::mojom::LaunchSource::kFromParentalControls,
-                  apps::MakeWindowInfo(display::kDefaultDisplayId));
+    if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
+      proxy->Launch(
+          app_id, ui::EF_NONE, apps::LaunchSource::kFromParentalControls,
+          std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
+    } else {
+      proxy->Launch(app_id, ui::EF_NONE,
+                    apps::mojom::LaunchSource::kFromParentalControls,
+                    apps::MakeWindowInfo(display::kDefaultDisplayId));
+    }
     return;
   }
 
diff --git a/chrome/browser/ui/webui/test_data_source.cc b/chrome/browser/ui/webui/test_data_source.cc
index 4b636f51..f301c85 100644
--- a/chrome/browser/ui/webui/test_data_source.cc
+++ b/chrome/browser/ui/webui/test_data_source.cc
@@ -64,19 +64,19 @@
                      std::move(callback)));
 }
 
-std::string TestDataSource::GetMimeType(const std::string& path) {
-  std::string clean_path = GetURLForPath(path).path();
-  if (base::EndsWith(clean_path, ".html",
+std::string TestDataSource::GetMimeType(const GURL& url) {
+  if (base::EndsWith(url.path_piece(), ".html",
                      base::CompareCase::INSENSITIVE_ASCII) ||
-      base::StartsWith(GetURLForPath(path).query(), kModuleQuery,
+      base::StartsWith(url.query_piece(), kModuleQuery,
                        base::CompareCase::INSENSITIVE_ASCII)) {
     // Direct request for HTML, or autogenerated HTML response for module query.
     return "text/html";
   }
   // The test data source currently only serves HTML and JS.
-  CHECK(base::EndsWith(clean_path, ".js", base::CompareCase::INSENSITIVE_ASCII))
+  CHECK(base::EndsWith(url.path_piece(), ".js",
+                       base::CompareCase::INSENSITIVE_ASCII))
       << "Tried to read file with unexpected type from test data source: "
-      << path;
+      << url.path_piece();
   return "application/javascript";
 }
 
diff --git a/chrome/browser/ui/webui/test_data_source.h b/chrome/browser/ui/webui/test_data_source.h
index cbc2af8..b0091f1 100644
--- a/chrome/browser/ui/webui/test_data_source.h
+++ b/chrome/browser/ui/webui/test_data_source.h
@@ -28,7 +28,7 @@
       const content::WebContents::Getter& wc_getter,
       content::URLDataSource::GotDataCallback callback) override;
 
-  std::string GetMimeType(const std::string& path) override;
+  std::string GetMimeType(const GURL& url) override;
 
   bool ShouldServeMimeTypeAsContentTypeHeader() override;
 
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index c9ff57de..f402c2f 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -169,7 +169,7 @@
     // user can also enter these into the omnibox, so we need to fail
     // gracefully.
     std::move(callback).Run(nullptr);
-  } else if ((GetMimeType(path) == "image/png") &&
+  } else if ((GetMimeType(url) == "image/png") &&
              ((scale > max_scale) || (frame != -1))) {
     // This will extract and scale frame 0 of animated images.
     // TODO(reveman): Support scaling of animated images and avoid scaling and
@@ -181,9 +181,9 @@
   }
 }
 
-std::string ThemeSource::GetMimeType(const std::string& path) {
+std::string ThemeSource::GetMimeType(const GURL& url) {
   std::string parsed_path;
-  webui::ParsePathAndScale(GetThemeUrl(path), &parsed_path, nullptr);
+  webui::ParsePathAndScale(url, &parsed_path, nullptr);
   return IsNewTabCssPath(parsed_path) ? "text/css" : "image/png";
 }
 
diff --git a/chrome/browser/ui/webui/theme_source.h b/chrome/browser/ui/webui/theme_source.h
index f434744..585077f 100644
--- a/chrome/browser/ui/webui/theme_source.h
+++ b/chrome/browser/ui/webui/theme_source.h
@@ -30,7 +30,7 @@
       const GURL& url,
       const content::WebContents::Getter& wc_getter,
       content::URLDataSource::GotDataCallback callback) override;
-  std::string GetMimeType(const std::string& path) override;
+  std::string GetMimeType(const GURL& url) override;
   bool AllowCaching() override;
   bool ShouldServiceRequest(const GURL& url,
                             content::BrowserContext* browser_context,
diff --git a/chrome/browser/ui/webui/theme_source_unittest.cc b/chrome/browser/ui/webui/theme_source_unittest.cc
index 19079766..254b5cae 100644
--- a/chrome/browser/ui/webui/theme_source_unittest.cc
+++ b/chrome/browser/ui/webui/theme_source_unittest.cc
@@ -74,10 +74,14 @@
 };
 
 TEST_F(WebUISourcesTest, ThemeSourceMimeTypes) {
-  EXPECT_EQ(theme_source()->GetMimeType("css/new_tab_theme.css"), "text/css");
-  EXPECT_EQ(theme_source()->GetMimeType("css/new_tab_theme.css?foo"),
-                                        "text/css");
-  EXPECT_EQ(theme_source()->GetMimeType("WRONGURL"), "image/png");
+  EXPECT_EQ(
+      theme_source()->GetMimeType(GURL("chrome://theme/css/new_tab_theme.css")),
+      "text/css");
+  EXPECT_EQ(theme_source()->GetMimeType(
+                GURL("chrome://theme/css/new_tab_theme.css?foo")),
+            "text/css");
+  EXPECT_EQ(theme_source()->GetMimeType(GURL("chrome://theme/WRONGURL")),
+            "image/png");
 }
 
 TEST_F(WebUISourcesTest, ThemeSourceImages) {
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_ui.cc b/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
index 3d2b4d0..44f99ae 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
+++ b/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
@@ -91,13 +91,12 @@
 void WhatsNewUI::CreateBrowserCommandHandler(
     mojo::PendingReceiver<browser_command::mojom::CommandHandler>
         pending_handler) {
-  // No supported commands for M104 only. New command to be added for M106.
-  std::vector<browser_command::mojom::Command> supported_commands = {};
+  std::vector<browser_command::mojom::Command> supported_commands = {
+      browser_command::mojom::Command::kStartTabGroupTutorial,
+      browser_command::mojom::Command::kOpenPasswordManager,
+  };
   command_handler_ = std::make_unique<BrowserCommandHandler>(
       std::move(pending_handler), profile_, supported_commands);
-  command_handler_->ConfigureFeedbackCommand(
-      {GURL(chrome::kChromeUIWhatsNewURL), chrome::kFeedbackSourceWhatsNew,
-       "whats-new-page"});
 }
 
 void WhatsNewUI::TryShowHatsSurveyWithTimeout() {
diff --git a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
index f3ad83e2..2d2db4e 100644
--- a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
+#include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -144,9 +145,8 @@
   const int32_t event_flags =
       apps::GetEventFlags(WindowOpenDisposition::NEW_WINDOW,
                           /*prefer_container=*/true);
-  proxy->Launch(app_id, event_flags, apps::mojom::LaunchSource::kUnknown,
-                apps::MakeWindowInfo(display::kDefaultDisplayId));
-  proxy->FlushMojoCallsForTesting();
+  proxy->Launch(app_id, event_flags, apps::LaunchSource::kUnknown,
+                std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId));
 
   proxy->AppRegistryCache().ForOneApp(
       app_id, [&original_key](const apps::AppUpdate& update) {
diff --git a/chrome/browser/web_applications/manifest_update_manager.cc b/chrome/browser/web_applications/manifest_update_manager.cc
index 160a02e8..424fb2ee 100644
--- a/chrome/browser/web_applications/manifest_update_manager.cc
+++ b/chrome/browser/web_applications/manifest_update_manager.cc
@@ -177,12 +177,6 @@
   // will hit it).
   if (result != ManifestUpdateResult::kNoAppInScope) {
     base::UmaHistogramEnumeration("Webapp.Update.ManifestUpdateResult", result);
-    if (app_id.has_value() &&
-        registrar_->HasExternalAppWithInstallSource(
-            app_id.value(), ExternalInstallSource::kExternalDefault)) {
-      base::UmaHistogramEnumeration(
-          "Webapp.Update.ManifestUpdateResult.DefaultApp", result);
-    }
   }
   if (result_callback_for_testing_)
     std::move(result_callback_for_testing_).Run(url, result);
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index ef00185..8849456 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1658317990-d11c01a0b2a0c77ac07ae6113b98ac29dd4d6310.profdata
+chrome-linux-main-1658338845-3dacf651afcf94500d2b59f5848c1a029dbd163c.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 31214320..9618145 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1658317990-b69841676eb352268bea14dd795ca6e3e4bceb9e.profdata
+chrome-mac-main-1658338845-e1333abbc25e46d76855c5d2e9215f699cea4c09.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 8980baf..0adeb955 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1658329194-e127a6da7d5ae8a3a2b2f7d30eed060c6ad86f6d.profdata
+chrome-win32-main-1658350137-de0a25488f79c4e358661263a872c6e606184db1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index daf7efddb..dbebb0c 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1658329194-db0d1b417a6f8df7d8399c87bf98fa771bd14a73.profdata
+chrome-win64-main-1658350137-8f636782cbfa279b6fb12674ead87668014b7e00.profdata
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index a2c0e75d..b9ca2a9 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -262,6 +262,10 @@
     "channel": "stable",
     "extension_types": ["extension"]
   },
+  "downloads.ui": {
+    "channel": "stable",
+    "extension_types": ["extension"]
+  },
   "enterprise.deviceAttributes": [{
     "channel": "stable",
     "extension_types": ["extension", "platform_app"],
diff --git a/chrome/common/extensions/api/downloads.idl b/chrome/common/extensions/api/downloads.idl
index d8b40ea..675cc7b 100644
--- a/chrome/common/extensions/api/downloads.idl
+++ b/chrome/common/extensions/api/downloads.idl
@@ -413,6 +413,12 @@
     [legalValues=(16,32)] long? size;
   };
 
+  // Encapsulates a change in the download UI.
+  [inline_doc] dictionary UiOptions {
+    // Enable or disable the download UI.
+    boolean enabled;
+  };
+
   callback DownloadCallback = void(long downloadId);
   callback SearchCallback = void(DownloadItem[] results);
   callback EraseCallback = void(long[] erasedIds);
@@ -534,6 +540,18 @@
     // $(ref:runtime.lastError). Requires the <code>"downloads.shelf"</code>
     // permission in addition to the <code>"downloads"</code> permission.
     static void setShelfEnabled(boolean enabled);
+
+    // Change the download UI of every window associated with the current
+    // browser profile. As long as at least one extension has set
+    // $(ref:UiOptions.enabled) to false, the download UI will be hidden.
+    // Setting $(ref:UiOptions.enabled) to true while at least one other
+    // extension has disabled it will return an error through
+    // $(ref:runtime.lastError). Requires the <code>"downloads.ui"</code>
+    // permission in addition to the <code>"downloads"</code> permission.
+    // |options|: Encapsulate a change to the download UI.
+    // |callback|: Called when the UI update is completed.
+    [supportsPromises] static void setUiOptions(UiOptions options,
+                                                optional NullCallback callback);
   };
 
   interface Events {
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index e254f9c..6ddb4ed5 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -41,6 +41,7 @@
     {APIPermissionID::kDownloads, "downloads"},
     {APIPermissionID::kDownloadsOpen, "downloads.open"},
     {APIPermissionID::kDownloadsShelf, "downloads.shelf"},
+    {APIPermissionID::kDownloadsUi, "downloads.ui"},
     {APIPermissionID::kIdentity, "identity"},
     {APIPermissionID::kIdentityEmail, "identity.email"},
     {APIPermissionID::kExperimental, "experimental",
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 6fd4653..5cb7afa 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -752,6 +752,7 @@
   skip.insert(APIPermissionID::kDiagnostics);
   skip.insert(APIPermissionID::kDns);
   skip.insert(APIPermissionID::kDownloadsShelf);
+  skip.insert(APIPermissionID::kDownloadsUi);
   skip.insert(APIPermissionID::kFontSettings);
   skip.insert(APIPermissionID::kFullscreen);
   skip.insert(APIPermissionID::kGcm);
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index cef74ec..f068771 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -739,7 +739,8 @@
 #endif
 }
 
-void ChromeContentRendererClient::WebViewCreated(blink::WebView* web_view) {
+void ChromeContentRendererClient::WebViewCreated(blink::WebView* web_view,
+                                                 bool was_created_by_renderer) {
   new prerender::NoStatePrefetchClient(web_view);
 }
 
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index ca2bd2b..4ba204c3 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -90,7 +90,8 @@
   void RenderThreadStarted() override;
   void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override;
   void RenderFrameCreated(content::RenderFrame* render_frame) override;
-  void WebViewCreated(blink::WebView* web_view) override;
+  void WebViewCreated(blink::WebView* web_view,
+                      bool was_created_by_renderer) override;
   SkBitmap* GetSadPluginBitmap() override;
   SkBitmap* GetSadWebViewBitmap() override;
   bool IsPluginHandledExternally(content::RenderFrame* render_frame,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d4cb1dc0..cada26f1 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1975,7 +1975,6 @@
       "../browser/portal/portal_browsertest.cc",
       "../browser/portal/portal_recently_audible_browsertest.cc",
       "../browser/predictors/loading_predictor_browsertest.cc",
-      "../browser/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc",
       "../browser/prefetch/prefetch_browsertest.cc",
       "../browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc",
       "../browser/prefetch/prefetch_proxy/prefetch_proxy_test_utils.cc",
@@ -1984,11 +1983,12 @@
       "../browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h",
       "../browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc",
       "../browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc",
-      "../browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc",
       "../browser/prefs/pref_functional_browsertest.cc",
       "../browser/prefs/pref_service_browsertest.cc",
       "../browser/prefs/tracked/pref_hash_browsertest.cc",
       "../browser/preloading/latency_ablation_browsertest.cc",
+      "../browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc",
+      "../browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc",
       "../browser/privacy_sandbox/privacy_sandbox_settings_browsertest.cc",
       "../browser/profile_resetter/profile_resetter_browsertest.cc",
       "../browser/profiles/host_zoom_map_browsertest.cc",
@@ -3053,8 +3053,8 @@
         "../browser/notifications/notification_permission_context_apitest.cc",
         "../browser/policy/extension_force_install_mixin.cc",
         "../browser/policy/extension_force_install_mixin.h",
-        "../browser/prefetch/no_state_prefetch/prerender_test_utils.cc",
-        "../browser/prefetch/no_state_prefetch/prerender_test_utils.h",
+        "../browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.cc",
+        "../browser/preloading/prefetch/no_state_prefetch/prerender_test_utils.h",
         "../browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc",
         "../browser/safe_browsing/settings_reset_prompt/default_settings_fetcher_browsertest.cc",
         "../browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.cc",
@@ -5289,7 +5289,6 @@
     "../browser/predictors/prefetch_manager_unittest.cc",
     "../browser/predictors/resource_prefetch_predictor_tables_unittest.cc",
     "../browser/predictors/resource_prefetch_predictor_unittest.cc",
-    "../browser/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc",
     "../browser/prefetch/prefetch_prefs_unittest.cc",
     "../browser/prefetch/prefetch_proxy/prefetch_container_unittest.cc",
     "../browser/prefetch/prefetch_proxy/prefetch_proxy_canary_checker_unittest.cc",
@@ -5309,6 +5308,7 @@
     "../browser/prefs/profile_pref_store_manager_unittest.cc",
     "../browser/prefs/proxy_policy_unittest.cc",
     "../browser/prefs/session_startup_pref_unittest.cc",
+    "../browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unittest.cc",
     "../browser/privacy/privacy_metrics_service_unittest.cc",
     "../browser/privacy_sandbox/privacy_sandbox_service_unittest.cc",
     "../browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc",
@@ -9660,6 +9660,10 @@
       configs += [ "//build/config/linux/atk" ]
     }
 
+    if (is_linux) {
+      deps += [ "//ui/linux:linux_ui_impl" ]
+    }
+
     if (is_linux || is_chromeos_lacros) {
       deps += [ "//ui/base/ime/linux" ]
     }
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index adfa4e24..57fd6cb9 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -138,6 +138,7 @@
 #include "components/account_manager_core/chromeos/account_manager.h"
 #include "components/account_manager_core/chromeos/account_manager_facade_factory.h"  // nogncheck
 #include "components/account_manager_core/chromeos/fake_account_manager_ui.h"  // nogncheck
+#include "content/public/test/network_connection_change_simulator.h"
 #include "ui/aura/test/ui_controls_factory_aura.h"
 #include "ui/base/test/ui_controls.h"
 #endif
@@ -729,6 +730,11 @@
 }
 
 void InProcessBrowserTest::PreRunTestOnMainThread() {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  content::NetworkConnectionChangeSimulator network_change_simulator;
+  network_change_simulator.InitializeChromeosConnectionType();
+#endif
+
   AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting();
 
   // Take the ChromeBrowserMainParts' RunLoop to run ourself, when we
diff --git a/chrome/test/data/extensions/api_test/downloads_split/manifest.json b/chrome/test/data/extensions/api_test/downloads_split/manifest.json
index aea946e55..3b76cab 100644
--- a/chrome/test/data/extensions/api_test/downloads_split/manifest.json
+++ b/chrome/test/data/extensions/api_test/downloads_split/manifest.json
@@ -10,6 +10,7 @@
     "downloads",
     "downloads.open",
     "downloads.shelf",
+    "downloads.ui",
     "http://*/*",
     "file://*"
   ]
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
index 2488739..e3164829 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -127,9 +127,13 @@
         getElementContent('#shareDiagnosticDataLabel'));
 
     // Screenshot elements.
-    assertTrue(!!getElement('#screenshotCheckbox'));
-    assertEquals('Screenshot', getElementContent('#screenshotCheckLabel'));
+    const screenshotCheckbox = getElement('#screenshotCheckbox');
+    assertTrue(!!screenshotCheckbox);
+    assertTrue(page.i18nExists('attachScreenshotCheckboxAriaLabel'));
+    assertEquals('Attach screenshot', screenshotCheckbox.ariaLabel);
+
     assertTrue(page.i18nExists('attachScreenshotLabel'));
+    assertEquals('Screenshot', getElementContent('#screenshotCheckLabel'));
     assertTrue(!!getElement('#screenshotImage'));
 
     // Add file attachment element.
@@ -201,6 +205,21 @@
     assertEquals('chrome://tab/', getElementContent('#pageUrlText'));
   });
 
+  // Test that the pageUrl section is hidden when the url is empty string.
+  test('pageUrlHidden', async () => {
+    await initializePage();
+    fakeFeedbackContext.pageUrl.url = '';
+    page.feedbackContext = fakeFeedbackContext;
+
+    // The pageUrl section should be hidden
+    const pageUrl = getElement('#pageUrl');
+    assertTrue(!!pageUrl);
+    assertFalse(isVisible(pageUrl));
+
+    // Change it back otherwise it will effect other tests.
+    fakeFeedbackContext.pageUrl.url = 'chrome://tab/';
+  });
+
   /**
    * Test that when when the send button is clicked, an on-continue is fired.
    * Case 1: Share pageUrl, do not share system logs.
@@ -559,4 +578,18 @@
 
     assertEquals(1, feedbackServiceProvider.getOpenMetricsDialogCallCount());
   });
+
+  /**
+   * Test that feedbackServiceProvider.openSystemInfoDialog is called
+   * when #sysInfoLink ("system and app info") link is clicked.
+   */
+  test('openSystemInfoDialog', async () => {
+    await initializePage();
+
+    assertEquals(0, feedbackServiceProvider.getOpenSystemInfoDialogCallCount());
+
+    getElement('#sysInfoLink').click();
+
+    assertEquals(1, feedbackServiceProvider.getOpenSystemInfoDialogCallCount());
+  });
 }
diff --git a/chrome/test/data/webui/extensions/site_permissions_by_site_test.ts b/chrome/test/data/webui/extensions/site_permissions_by_site_test.ts
index da4a934..99abaf5c 100644
--- a/chrome/test/data/webui/extensions/site_permissions_by_site_test.ts
+++ b/chrome/test/data/webui/extensions/site_permissions_by_site_test.ts
@@ -85,4 +85,27 @@
             'site-permissions-site-group');
     assertEquals(2, sitePermissionGroups.length);
   });
+
+  test('extension and user sites update when event is fired', async function() {
+    await delegate.whenCalled('getUserAndExtensionSitesByEtld');
+    flush();
+    delegate.resetResolver('getUserAndExtensionSitesByEtld');
+    delegate.siteGroups = [{
+      etldPlusOne: 'random.com',
+      sites: [{
+        siteList: chrome.developerPrivate.UserSiteSet.RESTRICTED,
+        site: 'http://www.random.com',
+      }],
+    }];
+
+    delegate.userSiteSettingsChangedTarget.callListeners(
+        {permittedSites: [], restrictedSites: ['http://www.random.com']});
+    await delegate.whenCalled('getUserAndExtensionSitesByEtld');
+    flush();
+
+    const sitePermissionGroups =
+        element.shadowRoot!.querySelectorAll<HTMLElement>(
+            'site-permissions-site-group');
+    assertEquals(1, sitePermissionGroups.length);
+  });
 });
diff --git a/chrome/test/data/webui/extensions/site_permissions_site_group_test.ts b/chrome/test/data/webui/extensions/site_permissions_site_group_test.ts
index 76ef1ab..575f8a2b 100644
--- a/chrome/test/data/webui/extensions/site_permissions_site_group_test.ts
+++ b/chrome/test/data/webui/extensions/site_permissions_site_group_test.ts
@@ -104,4 +104,72 @@
     assertFalse(isVisible(
         element.shadowRoot!.querySelector<HTMLElement>('cr-expand-button')));
   });
+
+  test(
+      'clicking the arrow for a single site shows dialog for that site',
+      async function() {
+        element.data = {
+          etldPlusOne: 'example.com',
+          sites: [{
+            siteList: chrome.developerPrivate.UserSiteSet.PERMITTED,
+            site: 'https://a.example.com',
+          }],
+        };
+        flush();
+
+        const editSiteButton = element.shadowRoot!.querySelector<HTMLElement>(
+            '#edit-one-site-button');
+        assertTrue(isVisible(editSiteButton));
+
+        editSiteButton!.click();
+        flush();
+
+        const dialog = element.shadowRoot!.querySelector(
+            'site-permissions-edit-permissions-dialog');
+        assertTrue(!!dialog);
+        assertTrue(dialog.$.dialog.open);
+        assertEquals('https://a.example.com', dialog.site);
+        assertEquals(
+            chrome.developerPrivate.UserSiteSet.PERMITTED,
+            dialog.originalSiteSet);
+      });
+
+  test(
+      'clicking the arrow for an expanded site shows dialog for that site',
+      async function() {
+        element.data = {
+          etldPlusOne: 'google.ca',
+          sites: [
+            {
+              siteList: chrome.developerPrivate.UserSiteSet.PERMITTED,
+              site: 'https://images.google.ca',
+            },
+            {
+              siteList: chrome.developerPrivate.UserSiteSet.RESTRICTED,
+              site: 'http://google.ca',
+            },
+          ],
+        };
+        flush();
+
+        element.shadowRoot!.querySelector<HTMLElement>(
+                               'cr-expand-button')!.click();
+        flush();
+
+        const editSiteButtons =
+            element.shadowRoot!.querySelectorAll<HTMLElement>('cr-icon-button');
+        assertEquals(2, editSiteButtons.length);
+
+        editSiteButtons[1]!.click();
+        flush();
+
+        const dialog = element.shadowRoot!.querySelector(
+            'site-permissions-edit-permissions-dialog');
+        assertTrue(!!dialog);
+        assertTrue(dialog.$.dialog.open);
+        assertEquals('http://google.ca', dialog.site);
+        assertEquals(
+            chrome.developerPrivate.UserSiteSet.RESTRICTED,
+            dialog.originalSiteSet);
+      });
 });
diff --git a/chrome/updater/app/server/win/com_classes.cc b/chrome/updater/app/server/win/com_classes.cc
index befa923..a4515a50 100644
--- a/chrome/updater/app/server/win/com_classes.cc
+++ b/chrome/updater/app/server/win/com_classes.cc
@@ -217,8 +217,8 @@
                           base::BindOnce(&IUpdaterRegisterAppCallback::Run,
                                          callback, response.status_code),
                           base::BindOnce([](HRESULT hr) {
-                            DVLOG(2) << "UpdaterImpl::RegisterApp "
-                                     << "callback returned " << std::hex << hr;
+                            VLOG(2) << "UpdaterImpl::RegisterApp "
+                                    << "callback returned " << std::hex << hr;
                           }));
                     },
                     task_runner, callback));
@@ -283,8 +283,8 @@
         base::BindOnce(&IUpdaterObserver::OnStateChange, observer_,
                        Microsoft::WRL::Make<UpdateStateImpl>(update_state)),
         base::BindOnce([](HRESULT hr) {
-          DVLOG(4) << "IUpdaterObserver::OnStateChange returned " << std::hex
-                   << hr;
+          VLOG(4) << "IUpdaterObserver::OnStateChange returned " << std::hex
+                  << hr;
         }));
   }
 
@@ -347,8 +347,8 @@
                               Microsoft::WRL::Make<CompleteStatusImpl>(
                                   static_cast<int>(result), L"")),
                           base::BindOnce([](HRESULT hr) {
-                            DVLOG(2) << "UpdaterImpl::Update "
-                                     << "callback returned " << std::hex << hr;
+                            VLOG(2) << "UpdaterImpl::Update "
+                                    << "callback returned " << std::hex << hr;
                           }));
                     },
                     task_runner, observer));
@@ -392,8 +392,8 @@
                               Microsoft::WRL::Make<CompleteStatusImpl>(
                                   static_cast<int>(result), L"")),
                           base::BindOnce([](HRESULT hr) {
-                            DVLOG(2) << "UpdaterImpl::UpdateAll "
-                                     << "callback returned " << std::hex << hr;
+                            VLOG(2) << "UpdaterImpl::UpdateAll "
+                                    << "callback returned " << std::hex << hr;
                           }));
                     },
                     task_runner, observer));
@@ -600,8 +600,8 @@
                               Microsoft::WRL::Make<CompleteStatusImpl>(
                                   static_cast<int>(result), L"")),
                           base::BindOnce([](HRESULT hr) {
-                            DVLOG(2) << "UpdaterImpl::RunInstaller "
-                                     << "callback returned " << std::hex << hr;
+                            VLOG(2) << "UpdaterImpl::RunInstaller "
+                                    << "callback returned " << std::hex << hr;
                           }));
                     },
                     task_runner, observer));
@@ -640,8 +640,8 @@
                       base::BindOnce(&IUpdaterInternalCallback::Run, callback,
                                      0),
                       base::BindOnce([](HRESULT hr) {
-                        DVLOG(2) << "UpdaterInternalImpl::Run "
-                                 << "callback returned " << std::hex << hr;
+                        VLOG(2) << "UpdaterInternalImpl::Run "
+                                << "callback returned " << std::hex << hr;
                       }));
                 },
                 task_runner, callback));
@@ -677,7 +677,7 @@
                       base::BindOnce(&IUpdaterInternalCallback::Run, callback,
                                      0),
                       base::BindOnce([](HRESULT hr) {
-                        DVLOG(2)
+                        VLOG(2)
                             << "UpdaterInternalImpl::InitializeUpdateService "
                             << "callback returned " << std::hex << hr;
                       }));
diff --git a/chrome/updater/installer_mac.cc b/chrome/updater/installer_mac.cc
index 5f3741d7..6faa624 100644
--- a/chrome/updater/installer_mac.cc
+++ b/chrome/updater/installer_mac.cc
@@ -20,7 +20,7 @@
     const std::string& arguments,
     const absl::optional<base::FilePath>& installer_data_file,
     InstallProgressCallback /*progress_callback*/) {
-  DVLOG(1) << "Running application install from DMG at " << app_installer;
+  VLOG(1) << "Running application install from DMG at " << app_installer;
   // InstallFromArchive() returns the exit code of the script. 0 is success and
   // anything else should be an error.
   const int exit_code = InstallFromArchive(
diff --git a/chrome/updater/prefs_win.cc b/chrome/updater/prefs_win.cc
index 5f793f3c..1873530 100644
--- a/chrome/updater/prefs_win.cc
+++ b/chrome/updater/prefs_win.cc
@@ -40,10 +40,10 @@
     base::TimeDelta timeout) {
   auto lock = std::make_unique<ScopedPrefsLockImpl>();
 
-  DVLOG(2) << "Trying to acquire the lock.";
+  VLOG(2) << "Trying to acquire the lock.";
   if (!lock->Initialize(scope, timeout))
     return nullptr;
-  DVLOG(2) << "Lock acquired.";
+  VLOG(2) << "Lock acquired.";
 
   return std::make_unique<ScopedPrefsLock>(std::move(lock));
 }
@@ -63,7 +63,7 @@
 ScopedPrefsLockImpl::~ScopedPrefsLockImpl() {
   if (mutex_.IsValid()) {
     ::ReleaseMutex(mutex_.Get());
-    DVLOG(2) << "Lock released.";
+    VLOG(2) << "Lock released.";
   }
 }
 
diff --git a/chrome/updater/update_service_impl.cc b/chrome/updater/update_service_impl.cc
index 840a3844..1e53144 100644
--- a/chrome/updater/update_service_impl.cc
+++ b/chrome/updater/update_service_impl.cc
@@ -280,7 +280,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   persisted_data_->SetLastStarted(base::Time::NowFromSystemTime());
-  DVLOG(1) << "last_started updated.";
+  VLOG(1) << "last_started updated.";
 
   // The installer should make an updater registration, but in case it halts
   // before it does, synthesize a registration if necessary here.
@@ -355,7 +355,7 @@
                 if (result == Result::kSuccess) {
                   persisted_data->SetLastChecked(
                       base::Time::NowFromSystemTime());
-                  DVLOG(1) << "last_checked updated.";
+                  VLOG(1) << "last_checked updated.";
                 }
                 std::move(callback).Run(result);
               },
@@ -490,7 +490,7 @@
                 base::BindRepeating(
                     [](StateChangeCallback state_update,
                        const std::string& app_id, int progress) {
-                      DVLOG(4) << "Install progress: " << progress;
+                      VLOG(4) << "Install progress: " << progress;
                       UpdateState state;
                       state.app_id = app_id;
                       state.state = UpdateState::State::kInstalling;
diff --git a/chrome/updater/update_service_internal_impl_qualifying.cc b/chrome/updater/update_service_internal_impl_qualifying.cc
index 0ef6474..0747616 100644
--- a/chrome/updater/update_service_internal_impl_qualifying.cc
+++ b/chrome/updater/update_service_internal_impl_qualifying.cc
@@ -73,7 +73,7 @@
                                     const RegistrationResponse& response) {
     // Create a `CheckForUpdatesTask` with the local prefs' config and perform
     // an `Update` task for `kQualificationAppId`.
-    DVLOG(2) << "RegistrationResponse: " << response.status_code;
+    VLOG(2) << "RegistrationResponse: " << response.status_code;
     base::MakeRefCounted<CheckForUpdatesTask>(
         config_,
         base::BindOnce(&UpdateServiceImpl::Update,
diff --git a/chrome/updater/win/installer_api.cc b/chrome/updater/win/installer_api.cc
index b44d168..551dddac 100644
--- a/chrome/updater/win/installer_api.cc
+++ b/chrome/updater/win/installer_api.cc
@@ -365,7 +365,7 @@
     bool wait_result = process.WaitForExitWithTimeout(
         base::Seconds(kWaitForInstallerProgressSec), &exit_code);
     auto progress = GetInstallerProgress(app_info.scope, app_info.app_id);
-    DVLOG(3) << "installer progress: " << progress;
+    VLOG(3) << "installer progress: " << progress;
     progress_callback.Run(progress);
     if (wait_result) {
       VLOG(1) << "Installer exit code " << exit_code;
diff --git a/chrome/updater/win/update_service_internal_proxy.cc b/chrome/updater/win/update_service_internal_proxy.cc
index 9917c07..cdc5c352a 100644
--- a/chrome/updater/win/update_service_internal_proxy.cc
+++ b/chrome/updater/win/update_service_internal_proxy.cc
@@ -135,8 +135,8 @@
   HRESULT hr = ::CoCreateInstance(GetInternalClass(), nullptr,
                                   CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&server));
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to instantiate the updater internal server. "
-             << std::hex << hr;
+    VLOG(2) << "Failed to instantiate the updater internal server. " << std::hex
+            << hr;
     std::move(callback).Run();
     return;
   }
@@ -144,8 +144,8 @@
   Microsoft::WRL::ComPtr<IUpdaterInternal> updater_internal;
   hr = server.As(&updater_internal);
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to query the updater_internal interface. " << std::hex
-             << hr;
+    VLOG(2) << "Failed to query the updater_internal interface. " << std::hex
+            << hr;
     std::move(callback).Run();
     return;
   }
@@ -162,7 +162,7 @@
       updater_internal, std::move(callback));
   hr = updater_internal->Run(rpc_callback.Get());
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdaterInternal::Run" << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdaterInternal::Run" << std::hex << hr;
 
     // Since the RPC call returned an error, it can't be determined what the
     // state of the update server is. The RPC callback may or may not have run.
@@ -194,8 +194,8 @@
   HRESULT hr = ::CoCreateInstance(GetInternalClass(), nullptr,
                                   CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&server));
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to instantiate the updater internal server. "
-             << std::hex << hr;
+    VLOG(2) << "Failed to instantiate the updater internal server. " << std::hex
+            << hr;
     std::move(callback).Run();
     return;
   }
@@ -203,8 +203,8 @@
   Microsoft::WRL::ComPtr<IUpdaterInternal> updater_internal;
   hr = server.As(&updater_internal);
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to query the updater_internal interface. " << std::hex
-             << hr;
+    VLOG(2) << "Failed to query the updater_internal interface. " << std::hex
+            << hr;
     std::move(callback).Run();
     return;
   }
@@ -213,8 +213,8 @@
       updater_internal, std::move(callback));
   hr = updater_internal->InitializeUpdateService(rpc_callback.Get());
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdaterInternal::InitializeUpdateService"
-             << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdaterInternal::InitializeUpdateService"
+            << std::hex << hr;
     rpc_callback->Disconnect().Run();
     return;
   }
diff --git a/chrome/updater/win/update_service_proxy.cc b/chrome/updater/win/update_service_proxy.cc
index 53da0ba..a9f1525 100644
--- a/chrome/updater/win/update_service_proxy.cc
+++ b/chrome/updater/win/update_service_proxy.cc
@@ -55,8 +55,8 @@
       scope == UpdaterScope::kSystem ? __uuidof(UpdaterSystemClass)
                                      : __uuidof(UpdaterUserClass),
       nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&server));
-  DVLOG_IF(2, FAILED(hr)) << "Failed to instantiate the update server: "
-                          << std::hex << hr;
+  VLOG_IF(2, FAILED(hr)) << "Failed to instantiate the update server: "
+                         << std::hex << hr;
   return hr;
 }
 
@@ -68,8 +68,8 @@
   if (FAILED(hr))
     return hr;
   hr = server.As(&updater);
-  DVLOG_IF(2, FAILED(hr)) << "Failed to query the updater interface: "
-                          << std::hex << hr;
+  VLOG_IF(2, FAILED(hr)) << "Failed to query the updater interface: "
+                         << std::hex << hr;
   return hr;
 }
 
@@ -96,7 +96,7 @@
     DCHECK(update_state);
 
     if (!state_update_callback_) {
-      DVLOG(2) << "Skipping posting the update state callback.";
+      VLOG(2) << "Skipping posting the update state callback.";
       return S_OK;
     }
 
@@ -116,7 +116,7 @@
   // so that the owner of this object can take back the callback ownership.
   UpdateService::Callback Disconnect() {
     DCHECK_EQ(base::PlatformThreadRef(), com_thread_ref_);
-    DVLOG(2) << __func__;
+    VLOG(2) << __func__;
     updater_ = nullptr;
     state_update_callback_.Reset();
     return std::move(callback_);
@@ -200,7 +200,7 @@
         update_service_state.extra_code1 = extra_code1;
     }
 
-    DVLOG(4) << update_service_state;
+    VLOG(4) << update_service_state;
     return update_service_state;
   }
 
@@ -212,7 +212,7 @@
     base::win::ScopedBstr message;
     CHECK(SUCCEEDED(complete_status->get_statusCode(&code)));
 
-    DVLOG(2) << "ICompleteStatus::OnComplete(" << code << ")";
+    VLOG(2) << "ICompleteStatus::OnComplete(" << code << ")";
     return static_cast<UpdateService::Result>(code);
   }
 
@@ -250,7 +250,7 @@
   // the STA thread directly by the COM RPC runtime.
   IFACEMETHODIMP Run(LONG status_code) override {
     DCHECK_EQ(base::PlatformThreadRef(), com_thread_ref_);
-    DVLOG(2) << __func__;
+    VLOG(2) << __func__;
     status_code_ = status_code;
     return S_OK;
   }
@@ -260,7 +260,7 @@
   // so that the owner of this object can take back the callback ownership.
   UpdateService::RegisterAppCallback Disconnect() {
     DCHECK_EQ(base::PlatformThreadRef(), com_thread_ref_);
-    DVLOG(2) << __func__;
+    VLOG(2) << __func__;
     updater_ = nullptr;
     return std::move(callback_);
   }
@@ -303,7 +303,7 @@
   // the task runner.
   IFACEMETHODIMP Run(LONG status_code) override {
     DCHECK_EQ(base::PlatformThreadRef(), com_thread_ref_);
-    DVLOG(2) << __func__;
+    VLOG(2) << __func__;
     status_code_ = status_code;
     return S_OK;
   }
@@ -313,7 +313,7 @@
   // so that the owner of this object can take back the callback ownership.
   base::OnceCallback<void(LONG)> Disconnect() {
     DCHECK_EQ(base::PlatformThreadRef(), com_thread_ref_);
-    DVLOG(2) << __func__;
+    VLOG(2) << __func__;
     updater_ = nullptr;
     return std::move(callback_);
   }
@@ -514,7 +514,7 @@
   }
   base::win::ScopedBstr version;
   if (HRESULT hr = updater->GetVersion(version.Receive()); FAILED(hr)) {
-    DVLOG(2) << "IUpdater::GetVersion failed: " << std::hex << hr;
+    VLOG(2) << "IUpdater::GetVersion failed: " << std::hex << hr;
     std::move(callback).Run(base::Version());
     return;
   }
@@ -576,7 +576,7 @@
           version.c_str(), existence_checker_path.c_str(),
           callback_wrapper.Get());
       FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdater::RegisterApp" << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdater::RegisterApp" << std::hex << hr;
     callback_wrapper->Disconnect().Run(RegistrationResponse(hr));
     return;
   }
@@ -612,7 +612,7 @@
                      std::move(callback)));
   if (HRESULT hr = updater->RunPeriodicTasks(callback_wrapper.Get());
       FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdater::RunPeriodicTasks" << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdater::RunPeriodicTasks" << std::hex << hr;
     callback_wrapper->Disconnect().Run(hr);
     return;
   }
@@ -643,7 +643,7 @@
   auto observer = Microsoft::WRL::Make<UpdaterObserver>(updater, state_update,
                                                         std::move(callback));
   if (HRESULT hr = updater->UpdateAll(observer.Get()); FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdater::UpdateAll" << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdater::UpdateAll" << std::hex << hr;
 
     // Since the RPC call returned an error, it can't be determined what the
     // state of the update server is. The observer may or may not post any
@@ -683,7 +683,7 @@
           UpdateService::PolicySameVersionUpdate::kAllowed,
       observer.Get());
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdater::UpdateAll: " << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdater::UpdateAll: " << std::hex << hr;
     observer->Disconnect().Run(Result::kServiceFailed);
     return;
   }
@@ -747,7 +747,7 @@
                                 base::UTF8ToWide(install_data_index).c_str(),
                                 static_cast<int>(priority), observer.Get());
   if (FAILED(hr)) {
-    DVLOG(2) << "Failed to call IUpdater::Install: " << std::hex << hr;
+    VLOG(2) << "Failed to call IUpdater::Install: " << std::hex << hr;
     observer->Disconnect().Run(Result::kServiceFailed);
     return;
   }
diff --git a/chrome/updater/win/win_util.cc b/chrome/updater/win/win_util.cc
index 4d05de5..eca8aac 100644
--- a/chrome/updater/win/win_util.cc
+++ b/chrome/updater/win/win_util.cc
@@ -495,7 +495,7 @@
   DCHECK_EQ(bytes_returned, sizeof(*session_id_ptr));
   DWORD session_id = *session_id_ptr;
   ::WTSFreeMemory(session_id_ptr);
-  DVLOG(1) << "::WTSQuerySessionInformation session id: " << session_id;
+  VLOG(1) << "::WTSQuerySessionInformation session id: " << session_id;
 
   HANDLE token_handle_raw = nullptr;
   if (!::WTSQueryUserToken(session_id, &token_handle_raw)) {
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn
index bcd7439e..ba5c91e 100644
--- a/chrome/utility/BUILD.gn
+++ b/chrome/utility/BUILD.gn
@@ -185,6 +185,8 @@
       "//chromeos/ash/components/assistant:buildflags",
       "//chromeos/ash/components/local_search_service",
       "//chromeos/ash/components/local_search_service/public/mojom",
+      "//chromeos/ash/components/trash_service",
+      "//chromeos/ash/components/trash_service/public/mojom",
       "//chromeos/services/tts",
       "//chromeos/services/tts/public/mojom",
     ]
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index 2451385..7db84be7 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -31,6 +31,8 @@
   "+chromeos/ash/components/assistant/buildflags.h",
   "+chromeos/ash/components/local_search_service/local_search_service.h",
   "+chromeos/ash/components/local_search_service/public/mojom",
+  "+chromeos/ash/components/trash_service/trash_service_impl.h",
+  "+chromeos/ash/components/trash_service/public/mojom",
   "+chromeos/ash/services/assistant",
   "+chromeos/ash/services/assistant/audio_decoder",
   "+chromeos/components/quick_answers/public",
diff --git a/chrome/utility/services.cc b/chrome/utility/services.cc
index 8c2ad3e..6bbade9e 100644
--- a/chrome/utility/services.cc
+++ b/chrome/utility/services.cc
@@ -120,6 +120,8 @@
 #include "chromeos/ash/components/assistant/buildflags.h"  // nogncheck
 #include "chromeos/ash/components/local_search_service/local_search_service.h"
 #include "chromeos/ash/components/local_search_service/public/mojom/local_search_service.mojom.h"
+#include "chromeos/ash/components/trash_service/public/mojom/trash_service.mojom.h"
+#include "chromeos/ash/components/trash_service/trash_service_impl.h"
 #include "chromeos/services/tts/public/mojom/tts_service.mojom.h"
 #include "chromeos/services/tts/tts_service.h"
 
@@ -347,6 +349,13 @@
       std::move(receiver), content::UtilityThread::Get()->GetIOTaskRunner());
 }
 
+auto RunTrashService(
+    mojo::PendingReceiver<chromeos::trash_service::mojom::TrashService>
+        receiver) {
+  return std::make_unique<chromeos::trash_service::TrashServiceImpl>(
+      std::move(receiver));
+}
+
 auto RunTtsService(
     mojo::PendingReceiver<chromeos::tts::mojom::TtsService> receiver) {
   return std::make_unique<chromeos::tts::TtsService>(std::move(receiver));
@@ -480,6 +489,7 @@
   services.Add(RunImeService);
   services.Add(RunRecordingService);
   services.Add(RunSharing);
+  services.Add(RunTrashService);
   services.Add(RunTtsService);
   services.Add(RunLocalSearchService);
   services.Add(RunQuickPairService);
diff --git a/chromecast/media/api/cma_backend_factory.h b/chromecast/media/api/cma_backend_factory.h
index 6ab51689..654d336 100644
--- a/chromecast/media/api/cma_backend_factory.h
+++ b/chromecast/media/api/cma_backend_factory.h
@@ -7,6 +7,9 @@
 
 #include <memory>
 
+#include "base/memory/scoped_refptr.h"
+#include "base/task/sequenced_task_runner.h"
+
 namespace service_manager {
 class Connector;
 }  // namespace service_manager
@@ -31,6 +34,9 @@
   // |media_task_runner_|.
   virtual std::unique_ptr<CmaBackend> CreateBackend(
       const MediaPipelineDeviceParams& params) = 0;
+
+  // Returns |media_task_runner_|.
+  virtual scoped_refptr<base::SequencedTaskRunner> GetMediaTaskRunner() = 0;
 };
 
 }  // namespace media
diff --git a/chromecast/media/audio/mixer_service/receiver/cma_backend_shim.cc b/chromecast/media/audio/mixer_service/receiver/cma_backend_shim.cc
index 03aa3d8..efc21a5 100644
--- a/chromecast/media/audio/mixer_service/receiver/cma_backend_shim.cc
+++ b/chromecast/media/audio/mixer_service/receiver/cma_backend_shim.cc
@@ -75,7 +75,7 @@
       delegate_task_runner_(std::move(delegate_task_runner)),
       params_(params),
       backend_manager_(backend_manager),
-      media_task_runner_(backend_manager_->task_runner()),
+      media_task_runner_(backend_manager_->GetMediaTaskRunner()),
       backend_task_runner_(backend_manager_->task_runner()),
       audio_decoder_(nullptr) {
   DETACH_FROM_SEQUENCE(media_sequence_checker_);
diff --git a/chromecast/media/cma/backend/cma_backend_factory_impl.cc b/chromecast/media/cma/backend/cma_backend_factory_impl.cc
index 60afd49..28e52ba 100644
--- a/chromecast/media/cma/backend/cma_backend_factory_impl.cc
+++ b/chromecast/media/cma/backend/cma_backend_factory_impl.cc
@@ -35,5 +35,10 @@
   return backend;
 }
 
+scoped_refptr<base::SequencedTaskRunner>
+CmaBackendFactoryImpl::GetMediaTaskRunner() {
+  return media_pipeline_backend_manager_->GetMediaTaskRunner();
+}
+
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/cma/backend/cma_backend_factory_impl.h b/chromecast/media/cma/backend/cma_backend_factory_impl.h
index bf5ddb9..631c333 100644
--- a/chromecast/media/cma/backend/cma_backend_factory_impl.h
+++ b/chromecast/media/cma/backend/cma_backend_factory_impl.h
@@ -32,6 +32,8 @@
   std::unique_ptr<CmaBackend> CreateBackend(
       const MediaPipelineDeviceParams& params) override;
 
+  scoped_refptr<base::SequencedTaskRunner> GetMediaTaskRunner() override;
+
  protected:
   MediaPipelineBackendManager* media_pipeline_backend_manager() {
     return media_pipeline_backend_manager_;
diff --git a/chromecast/media/cma/test/mock_cma_backend_factory.h b/chromecast/media/cma/test/mock_cma_backend_factory.h
index a0fc97a..a70d8ee4 100644
--- a/chromecast/media/cma/test/mock_cma_backend_factory.h
+++ b/chromecast/media/cma/test/mock_cma_backend_factory.h
@@ -22,6 +22,7 @@
 
   MOCK_METHOD1(CreateBackend,
                std::unique_ptr<CmaBackend>(const MediaPipelineDeviceParams&));
+  MOCK_METHOD0(GetMediaTaskRunner, scoped_refptr<base::SequencedTaskRunner>());
 };
 
 }  // namespace media
diff --git a/chromecast/media/common/media_pipeline_backend_manager.cc b/chromecast/media/common/media_pipeline_backend_manager.cc
index 924280d..c87af011 100644
--- a/chromecast/media/common/media_pipeline_backend_manager.cc
+++ b/chromecast/media/common/media_pipeline_backend_manager.cc
@@ -84,6 +84,11 @@
                                                        media_resource_tracker_);
 }
 
+scoped_refptr<base::SequencedTaskRunner>
+MediaPipelineBackendManager::GetMediaTaskRunner() {
+  return media_task_runner_;
+}
+
 void MediaPipelineBackendManager::BackendDestroyed(
     MediaPipelineBackendWrapper* backend_wrapper) {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
diff --git a/chromecast/media/common/media_pipeline_backend_manager.h b/chromecast/media/common/media_pipeline_backend_manager.h
index 6bd7cac..3fca7d47 100644
--- a/chromecast/media/common/media_pipeline_backend_manager.h
+++ b/chromecast/media/common/media_pipeline_backend_manager.h
@@ -98,6 +98,7 @@
   // media::CmaBackendFactory implementation:
   std::unique_ptr<CmaBackend> CreateBackend(
       const MediaPipelineDeviceParams& params) override;
+  scoped_refptr<base::SequencedTaskRunner> GetMediaTaskRunner() override;
 
   // Inform that a backend previously created is destroyed.
   // Must be called on the same thread as |media_task_runner_|.
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index fc5a0e5b..b8b512f 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -3446,6 +3446,9 @@
       <message name="IDS_FEEDBACK_TOOL_SCREENSHOT_LABEL" desc="Label for the screenshot field">
         Screenshot
       </message>
+      <message name="IDS_FEEDBACK_TOOL_ATTACH_SCREENSHOT_CHECKBOX_ARIA_LABEL" desc="Aria Label for the checkbox to select the screenshot">
+        Attach screenshot
+      </message>
       <message name="IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL" desc="Label for checkbox indicating whether the user agrees to be contacted back.">
         We may email you for more information or updates
       </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ATTACH_SCREENSHOT_CHECKBOX_ARIA_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ATTACH_SCREENSHOT_CHECKBOX_ARIA_LABEL.png.sha1
new file mode 100644
index 0000000..8d10715
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ATTACH_SCREENSHOT_CHECKBOX_ARIA_LABEL.png.sha1
@@ -0,0 +1 @@
+0c201199491044e181497c105f4121afc7add151
\ No newline at end of file
diff --git a/chromeos/components/quick_answers/quick_answers_model.h b/chromeos/components/quick_answers/quick_answers_model.h
index 8e41f00..aa68730c 100644
--- a/chromeos/components/quick_answers/quick_answers_model.h
+++ b/chromeos/components/quick_answers/quick_answers_model.h
@@ -178,8 +178,8 @@
   // Device language code.
   std::string device_language;
 
-  // Source language for translation query, should only be used for translation
-  // intents.
+  // Source language for definition or translation query, should only be used
+  // for definition or translation intents.
   std::string source_language;
 };
 
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.cc b/chromeos/components/quick_answers/understanding/intent_generator.cc
index d5acb8d..f113f0d 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator.cc
@@ -201,7 +201,8 @@
 }
 
 void IntentGenerator::CheckSpellingCallback(const QuickAnswersRequest& request,
-                                            bool correctness) {
+                                            bool correctness,
+                                            const std::string& language) {
   // Generate dictionary intent if the selected word passed spell check.
   // The dictionaries treat digits as valid words, while we will not be able to
   // grab any useful information from the Search server for words like that.
@@ -210,7 +211,8 @@
   if (correctness && !HasDigits(request.selected_text)) {
     std::move(complete_callback_)
         .Run(IntentInfo(request.selected_text, IntentType::kDictionary,
-                        QuickAnswersState::Get()->application_locale()));
+                        QuickAnswersState::Get()->application_locale(),
+                        language));
 
     // Record intent source type for dictionary intent.
     RecordDictionaryIntentSource(DictionaryIntentSource::kHunspell);
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.h b/chromeos/components/quick_answers/understanding/intent_generator.h
index e7df5d1..e507b42 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.h
+++ b/chromeos/components/quick_answers/understanding/intent_generator.h
@@ -54,7 +54,8 @@
 
   void MaybeLoadTextClassifier(const QuickAnswersRequest& request);
   void CheckSpellingCallback(const QuickAnswersRequest& request,
-                             bool correctness);
+                             bool correctness,
+                             const std::string& language);
 
   void LoadModelCallback(
       const QuickAnswersRequest& request,
diff --git a/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc b/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
index 1a33e09..581090b 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator_unittest.cc
@@ -48,13 +48,17 @@
   // SpellChecker:
   void CheckSpelling(const std::string& word,
                      CheckSpellingCallback callback) override {
-    std::move(callback).Run(dictionary_.find(word) != dictionary_.end());
+    std::move(callback).Run(dictionary_.find(word) != dictionary_.end(),
+                            dictionary_[word]);
   }
 
-  void AddWordToDictionary(std::string word) { dictionary_.insert(word); }
+  void AddWordToDictionary(const std::string& word,
+                           const std::string& language = "en") {
+    dictionary_.insert({word, language});
+  }
 
  private:
-  std::set<std::string> dictionary_;
+  std::map<std::string, std::string> dictionary_;
 };
 
 }  // namespace
@@ -571,6 +575,31 @@
   EXPECT_EQ(kWord, intent_info_.intent_text);
 }
 
+TEST_F(IntentGeneratorTest, ShouldTriggerForNonEnglishWordInDictionary) {
+  const std::string kWord = "palabra";
+  const std::string kLanguage = "es";
+
+  // No Annotation provided.
+  std::vector<TextAnnotationPtr> annotations;
+  UseFakeServiceConnection(annotations);
+
+  // Add word to the dictionary.
+  spell_checker()->AddWordToDictionary(kWord, kLanguage);
+
+  // Word selected.
+  std::unique_ptr<QuickAnswersRequest> quick_answers_request =
+      std::make_unique<QuickAnswersRequest>();
+  quick_answers_request->selected_text = kWord;
+
+  intent_generator_->GenerateIntent(*quick_answers_request);
+  task_environment_.RunUntilIdle();
+
+  // Should generate dictionary intent.
+  EXPECT_EQ(IntentType::kDictionary, intent_info_.intent_type);
+  EXPECT_EQ(kWord, intent_info_.intent_text);
+  EXPECT_EQ(kLanguage, intent_info_.source_language);
+}
+
 TEST_F(IntentGeneratorTest,
        ShouldNotTriggerForSingleWordInDictionaryWithDigits) {
   const std::string kWord = "1st";
diff --git a/chromeos/components/quick_answers/utils/quick_answers_utils.cc b/chromeos/components/quick_answers/utils/quick_answers_utils.cc
index 63b448e5d..3247c43 100644
--- a/chromeos/components/quick_answers/utils/quick_answers_utils.cc
+++ b/chromeos/components/quick_answers/utils/quick_answers_utils.cc
@@ -16,11 +16,34 @@
 namespace {
 
 constexpr char kUnitConversionQueryRewriteTemplate[] = "Convert:%s";
-constexpr char kDictionaryQueryRewriteTemplate[] = "Define %s";
+constexpr char kDictionaryQueryRewriteTemplate[] = "%s %s";
 constexpr char kTranslationQueryRewriteTemplate[] = "Translate:%s";
 
+constexpr char kDictionaryQueryKeyword[] = "Define";
+constexpr char kDictionaryQueryKeywordES[] = "Definir";
+constexpr char kDictionaryQueryKeywordIT[] = "Definire";
+constexpr char kDictionaryQueryKeywordFR[] = "Définir";
+constexpr char kDictionaryQueryKeywordPT[] = "Definir";
+constexpr char kDictionaryQueryKeywordDE[] = "Definieren";
+
 }  // namespace
 
+// Get the best dictionary query keyword based on the language.
+const char* GetDictionaryQueryKeyword(const std::string& language) {
+  if (language == "es")
+    return kDictionaryQueryKeywordES;
+  if (language == "it")
+    return kDictionaryQueryKeywordIT;
+  if (language == "fr")
+    return kDictionaryQueryKeywordFR;
+  if (language == "pt")
+    return kDictionaryQueryKeywordPT;
+  if (language == "de")
+    return kDictionaryQueryKeywordDE;
+
+  return kDictionaryQueryKeyword;
+}
+
 const PreprocessedOutput PreprocessRequest(const IntentInfo& intent_info) {
   PreprocessedOutput processed_output;
   processed_output.intent_info = intent_info;
@@ -33,7 +56,9 @@
       break;
     case IntentType::kDictionary:
       processed_output.query = base::StringPrintf(
-          kDictionaryQueryRewriteTemplate, intent_info.intent_text.c_str());
+          kDictionaryQueryRewriteTemplate,
+          GetDictionaryQueryKeyword(intent_info.source_language),
+          intent_info.intent_text.c_str());
       break;
     case IntentType::kTranslation:
       processed_output.query = base::StringPrintf(
diff --git a/chromeos/components/quick_answers/utils/spell_check_language.cc b/chromeos/components/quick_answers/utils/spell_check_language.cc
index 935f268..8df7b5f1 100644
--- a/chromeos/components/quick_answers/utils/spell_check_language.cc
+++ b/chromeos/components/quick_answers/utils/spell_check_language.cc
@@ -120,9 +120,9 @@
 
 SpellCheckLanguage::~SpellCheckLanguage() = default;
 
-void SpellCheckLanguage::Initialize(const std::string& locale) {
-  locale_ = locale;
-  dictionary_file_path_ = GetDictionaryFilePath(locale);
+void SpellCheckLanguage::Initialize(const std::string& language) {
+  language_ = language;
+  dictionary_file_path_ = GetDictionaryFilePath(language);
 
   base::PostTaskAndReplyWithResult(
       task_runner_.get(), FROM_HERE,
@@ -207,7 +207,7 @@
   }
 
   ++num_retries_;
-  Initialize(locale_);
+  Initialize(language_);
 }
 
 void SpellCheckLanguage::OnPathExistsComplete(bool path_exists) {
diff --git a/chromeos/components/quick_answers/utils/spell_check_language.h b/chromeos/components/quick_answers/utils/spell_check_language.h
index a9d9e83..21db5f2f 100644
--- a/chromeos/components/quick_answers/utils/spell_check_language.h
+++ b/chromeos/components/quick_answers/utils/spell_check_language.h
@@ -36,7 +36,7 @@
 
   ~SpellCheckLanguage() override;
 
-  void Initialize(const std::string& locale);
+  void Initialize(const std::string& language);
 
   // Check spelling of the given word, run |callback| with true if the word is
   // spelled correctly. Virtual for testing.
@@ -47,6 +47,8 @@
     return weak_factory_.GetWeakPtr();
   }
 
+  const std::string& language() const { return language_; }
+
  private:
   void InitializeSpellCheckService();
 
@@ -65,7 +67,7 @@
   // Task runner where the file operations takes place.
   scoped_refptr<base::SequencedTaskRunner> const task_runner_;
 
-  std::string locale_;
+  std::string language_;
 
   // Whether the spell check dictionary has been successfully initialized.
   bool dictionary_initialized_ = false;
diff --git a/chromeos/components/quick_answers/utils/spell_checker.cc b/chromeos/components/quick_answers/utils/spell_checker.cc
index 29d5a90..d3f40567 100644
--- a/chromeos/components/quick_answers/utils/spell_checker.cc
+++ b/chromeos/components/quick_answers/utils/spell_checker.cc
@@ -29,7 +29,7 @@
                                  CheckSpellingCallback callback) {
   auto iterator = spellcheck_languages_.begin();
   if (iterator == spellcheck_languages_.end()) {
-    std::move(callback).Run(false);
+    std::move(callback).Run(false, std::string());
     return;
   }
 
@@ -108,19 +108,19 @@
                                   int languages_list_version,
                                   bool is_correct) {
   if (is_correct) {
-    std::move(callback).Run(true);
+    std::move(callback).Run(true, iterator->get()->language());
     return;
   }
 
   // The languages list has been updated, return false for the current call.
   if (languages_list_version != languages_list_version_) {
-    std::move(callback).Run(true);
+    std::move(callback).Run(false, std::string());
     return;
   }
 
   iterator++;
   if (iterator == spellcheck_languages_.end()) {
-    std::move(callback).Run(false);
+    std::move(callback).Run(false, std::string());
     return;
   }
 
diff --git a/chromeos/components/quick_answers/utils/spell_checker.h b/chromeos/components/quick_answers/utils/spell_checker.h
index cead569a..906a8cc2 100644
--- a/chromeos/components/quick_answers/utils/spell_checker.h
+++ b/chromeos/components/quick_answers/utils/spell_checker.h
@@ -23,7 +23,8 @@
 // Utility class for spell check.
 class SpellChecker : public QuickAnswersStateObserver {
  public:
-  using CheckSpellingCallback = base::OnceCallback<void(bool)>;
+  using CheckSpellingCallback =
+      base::OnceCallback<void(bool, const std::string&)>;
   using SpellCheckLanguageIterator =
       std::vector<std::unique_ptr<SpellCheckLanguage>>::iterator;
 
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index 457b97e3a..538b3b7 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -57,6 +57,7 @@
     "message_center.mojom",
     "metrics_reporting.mojom",
     "native_theme.mojom",
+    "network_change.mojom",
     "network_settings_service.mojom",
     "networking_attributes.mojom",
     "networking_private.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index ac790cf..dc2cf32 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -53,6 +53,7 @@
 import "chromeos/crosapi/mojom/message_center.mojom";
 import "chromeos/crosapi/mojom/metrics_reporting.mojom";
 import "chromeos/crosapi/mojom/native_theme.mojom";
+import "chromeos/crosapi/mojom/network_change.mojom";
 import "chromeos/crosapi/mojom/networking_attributes.mojom";
 import "chromeos/crosapi/mojom/networking_private.mojom";
 import "chromeos/crosapi/mojom/power.mojom";
@@ -118,8 +119,8 @@
 // please note the milestone when you added it, to help us reason about
 // compatibility between the client applications and older ash-chrome binaries.
 //
-// Next version: 88
-// Next method id: 92
+// Next version: 89
+// Next method id: 93
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
 interface Crosapi {
@@ -381,6 +382,10 @@
   [MinVersion=8]
   BindMetricsReporting@13(pending_receiver<MetricsReporting> receiver);
 
+  // Binds the NetworkChange interface for getting network change notification.
+  [MinVersion=88]
+  BindNetworkChange@92(pending_receiver<NetworkChange> receiver);
+
   // Binds the networking attributes service which is used by enterprise
   // extension APIs to query details about the network.
   [MinVersion=39]
diff --git a/chromeos/crosapi/mojom/network_change.mojom b/chromeos/crosapi/mojom/network_change.mojom
new file mode 100644
index 0000000..69ce6daf
--- /dev/null
+++ b/chromeos/crosapi/mojom/network_change.mojom
@@ -0,0 +1,88 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module crosapi.mojom;
+
+// This needs to match the definition of net::ConnectionType.
+[Stable, Extensible]
+enum ConnectionType {
+  [Default] CONNECTION_UNKNOWN = 0,  // A connection exists, but its type is
+                                     // unknown. Also used as a default value.
+  CONNECTION_ETHERNET = 1,
+  CONNECTION_WIFI = 2,
+  CONNECTION_2G = 3,
+  CONNECTION_3G = 4,
+  CONNECTION_4G = 5,
+  CONNECTION_NONE = 6,     // No connection.
+  CONNECTION_BLUETOOTH = 7,
+  CONNECTION_5G = 8,
+  CONNECTION_LAST = CONNECTION_5G
+};
+
+// This needs to match the definition of net::ConnectionSubtype.
+[Stable, Extensible]
+enum ConnectionSubtype {
+  [Default] SUBTYPE_UNKNOWN = 0,
+  SUBTYPE_NONE,
+  SUBTYPE_OTHER,
+  SUBTYPE_GSM,
+  SUBTYPE_IDEN,
+  SUBTYPE_CDMA,
+  SUBTYPE_1XRTT,
+  SUBTYPE_GPRS,
+  SUBTYPE_EDGE,
+  SUBTYPE_UMTS,
+  SUBTYPE_EVDO_REV_0,
+  SUBTYPE_EVDO_REV_A,
+  SUBTYPE_HSPA,
+  SUBTYPE_EVDO_REV_B,
+  SUBTYPE_HSDPA,
+  SUBTYPE_HSUPA,
+  SUBTYPE_EHRPD,
+  SUBTYPE_HSPAP,
+  SUBTYPE_LTE,
+  SUBTYPE_LTE_ADVANCED,
+  SUBTYPE_BLUETOOTH_1_2,
+  SUBTYPE_BLUETOOTH_2_1,
+  SUBTYPE_BLUETOOTH_3_0,
+  SUBTYPE_BLUETOOTH_4_0,
+  SUBTYPE_ETHERNET,
+  SUBTYPE_FAST_ETHERNET,
+  SUBTYPE_GIGABIT_ETHERNET,
+  SUBTYPE_10_GIGABIT_ETHERNET,
+  SUBTYPE_WIFI_B,
+  SUBTYPE_WIFI_G,
+  SUBTYPE_WIFI_N,
+  SUBTYPE_WIFI_AC,
+  SUBTYPE_WIFI_AD,
+  SUBTYPE_LAST = SUBTYPE_WIFI_AD
+};
+
+// Implemented in Ash-chrome.
+// Next version: 1
+// Next method id: 1
+[Stable, Uuid="f1762d7c-f5cf-4580-8fad-e181dab68e4e"]
+interface  NetworkChange {
+    // Adds NetworkChangeObserver to NetworkChangeManagerClient in Ash.
+    AddObserver@0(pending_remote<NetworkChangeObserver> observer);
+};
+
+// Implemented in Lacros-chrome.
+// Next version: 1
+// Next method id: 1
+[Stable, Uuid="f95d3481-103e-4507-8e83-9bb6b7515c07"]
+interface NetworkChangeObserver {
+    // Notifies observer of network change.
+    OnNetworkChanged@0(
+        bool dns_changed,
+        bool ip_address_changed,
+        bool connection_type_changed,
+        // `new_connection_type` is ignored when `connection_type_changed` is
+        // set to false.
+        ConnectionType new_connection_type,
+        bool connection_subtype_changed,
+        // `new_connection_subtype` is ignored when `connectionsub_type_changed`
+        // is set to false.
+        ConnectionSubtype new_connection_subtype);
+};
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc
index 01ccf46..6767e84 100644
--- a/chromeos/lacros/lacros_service.cc
+++ b/chromeos/lacros/lacros_service.cc
@@ -59,6 +59,7 @@
 #include "chromeos/crosapi/mojom/login_state.mojom.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "chromeos/crosapi/mojom/metrics_reporting.mojom.h"
+#include "chromeos/crosapi/mojom/network_change.mojom.h"
 #include "chromeos/crosapi/mojom/network_settings_service.mojom.h"
 #include "chromeos/crosapi/mojom/networking_attributes.mojom.h"
 #include "chromeos/crosapi/mojom/networking_private.mojom.h"
@@ -370,6 +371,9 @@
       crosapi::mojom::NativeThemeService,
       &crosapi::mojom::Crosapi::BindNativeThemeService,
       Crosapi::MethodMinVersions::kBindNativeThemeServiceMinVersion>();
+  ConstructRemote<crosapi::mojom::NetworkChange,
+                  &crosapi::mojom::Crosapi::BindNetworkChange,
+                  Crosapi::MethodMinVersions::kBindNetworkChangeMinVersion>();
   ConstructRemote<crosapi::mojom::Power, &crosapi::mojom::Crosapi::BindPower,
                   Crosapi::MethodMinVersions::kBindPowerMinVersion>();
   ConstructRemote<
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index e887ad9b..3fd462da 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-105-5140.0-1657535009-benchmark-105.0.5180.0-r1.orderfile.xz
+chromeos-chrome-orderfile-field-105-5161.0-1658138909-benchmark-105.0.5187.0-r1.orderfile.xz
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index b85b7f1..dfdecf6 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -476,7 +476,7 @@
 }
 
 Iban GetIban() {
-  Iban iban(base::GenerateGUID(), kEmptyOrigin);
+  Iban iban(base::GenerateGUID());
   iban.set_value(u"DE91 1000 0000 0123 4567 89");
   iban.set_nickname(u"Nickname for Iban");
   return iban;
diff --git a/components/autofill/core/browser/data_model/iban.cc b/components/autofill/core/browser/data_model/iban.cc
index 98bf36e2..dc3fc2f 100644
--- a/components/autofill/core/browser/data_model/iban.cc
+++ b/components/autofill/core/browser/data_model/iban.cc
@@ -13,10 +13,11 @@
 
 namespace autofill {
 
-Iban::Iban(const std::string& guid, const std::string& origin)
-    : AutofillDataModel(guid, origin), record_type_(LOCAL_IBAN) {}
+Iban::Iban(const std::string& guid)
+    : AutofillDataModel(guid, /*origin=*/std::string()),
+      record_type_(LOCAL_IBAN) {}
 
-Iban::Iban() : Iban(base::GenerateGUID(), std::string()) {}
+Iban::Iban() : Iban(base::GenerateGUID()) {}
 
 Iban::Iban(const Iban& iban) : Iban() {
   operator=(iban);
@@ -27,16 +28,14 @@
 void Iban::operator=(const Iban& iban) {
   set_use_count(iban.use_count());
   set_use_date(iban.use_date());
-  set_modification_date(iban.modification_date());
 
-  // Just overwrite use_count, use_date and modification_date fields
-  // as those fields will not be compared for == operator.
+  // Just overwrite use_count and use_date fields as those fields will
+  // not be compared for == operator.
   if (this == &iban) {
     return;
   }
 
   set_guid(iban.guid());
-  set_origin(iban.origin());
 
   server_id_ = iban.server_id_;
   record_type_ = iban.record_type_;
@@ -106,8 +105,8 @@
 }
 
 bool Iban::operator==(const Iban& iban) const {
-  return guid() == iban.guid() && origin() == iban.origin() &&
-         record_type() == iban.record_type() && Compare(iban) == 0;
+  return guid() == iban.guid() && record_type() == iban.record_type() &&
+         Compare(iban) == 0;
 }
 
 bool Iban::operator!=(const Iban& iban) const {
diff --git a/components/autofill/core/browser/data_model/iban.h b/components/autofill/core/browser/data_model/iban.h
index f720b83..b0b2cd1 100644
--- a/components/autofill/core/browser/data_model/iban.h
+++ b/components/autofill/core/browser/data_model/iban.h
@@ -27,7 +27,7 @@
     SERVER_IBAN,
   };
 
-  Iban(const std::string& guid, const std::string& origin);
+  explicit Iban(const std::string& guid);
 
   // For use in STL containers.
   Iban();
diff --git a/components/autofill/core/browser/data_model/iban_unittest.cc b/components/autofill/core/browser/data_model/iban_unittest.cc
index fba1e07..ad2d763 100644
--- a/components/autofill/core/browser/data_model/iban_unittest.cc
+++ b/components/autofill/core/browser/data_model/iban_unittest.cc
@@ -18,13 +18,11 @@
   std::string guid = base::GenerateGUID();
   Iban iban_0;
   iban_0.set_guid(guid);
-  iban_0.set_origin("https://www.example.com");
   iban_0.set_nickname(u"Nickname 0");
   iban_0.set_value(u"DE91 1000 0000 0123 4567 89");
   Iban iban_1;
   guid = base::GenerateGUID();
   iban_1.set_guid(guid);
-  iban_1.set_origin("https://www.google.com");
   iban_1.set_nickname(u"Nickname 1");
   iban_1.set_value(u"IE64 IRCE 9205 0112 3456 78");
   iban_1 = iban_0;
@@ -47,7 +45,7 @@
 // and newlines with whitespace, replace multiple spaces into a single one
 // and trim leading/trailing whitespace.
 TEST(IbanTest, SetNickname) {
-  Iban iban(base::GenerateGUID(), "https://www.example.com/");
+  Iban iban(base::GenerateGUID());
 
   // Normal input nickname.
   iban.set_nickname(u"My doctor's IBAN");
@@ -75,7 +73,7 @@
 }
 
 TEST(IbanTest, SetValue) {
-  Iban iban(base::GenerateGUID(), "https://www.example.com/");
+  Iban iban(base::GenerateGUID());
 
   // Input value.
   iban.set_value(u"DE91 1000 0000 0123 4567 89");
@@ -83,7 +81,7 @@
 }
 
 TEST(IbanTest, SetRawData) {
-  Iban iban(base::GenerateGUID(), "https://www.example.com/");
+  Iban iban(base::GenerateGUID());
 
   // Verify RawInfo can be correctly set and read.
   iban.SetRawInfoWithVerificationStatus(
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index cdd8f03..ed3400a 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -432,21 +432,23 @@
   DCHECK(pending_profiles_query_ || pending_server_profiles_query_ ||
          pending_creditcards_query_ || pending_server_creditcards_query_ ||
          pending_server_creditcard_cloud_token_data_query_ ||
-         pending_customer_data_query_ || pending_upi_ids_query_ ||
-         pending_offer_data_query_);
+         pending_ibans_query_ || pending_customer_data_query_ ||
+         pending_upi_ids_query_ || pending_offer_data_query_);
 
   if (!result) {
     // Error from the web database.
-    if (h == pending_creditcards_query_)
-      pending_creditcards_query_ = 0;
-    else if (h == pending_profiles_query_)
+    if (h == pending_profiles_query_)
       pending_profiles_query_ = 0;
-    else if (h == pending_server_creditcards_query_)
-      pending_server_creditcards_query_ = 0;
     else if (h == pending_server_profiles_query_)
       pending_server_profiles_query_ = 0;
+    else if (h == pending_creditcards_query_)
+      pending_creditcards_query_ = 0;
+    else if (h == pending_server_creditcards_query_)
+      pending_server_creditcards_query_ = 0;
     else if (h == pending_server_creditcard_cloud_token_data_query_)
       pending_server_creditcard_cloud_token_data_query_ = 0;
+    else if (h == pending_ibans_query_)
+      pending_ibans_query_ = 0;
     else if (h == pending_customer_data_query_)
       pending_customer_data_query_ = 0;
     else if (h == pending_upi_ids_query_)
@@ -487,6 +489,12 @@
             h, result.get(), &pending_server_creditcard_cloud_token_data_query_,
             &server_credit_card_cloud_token_data_);
         break;
+      case AUTOFILL_IBANS_RESULT:
+        DCHECK_EQ(h, pending_ibans_query_)
+            << "received ibans from invalid request.";
+        ReceiveLoadedDbValues(h, result.get(), &pending_ibans_query_,
+                              &local_ibans_);
+        break;
       case AUTOFILL_CUSTOMERDATA_RESULT:
         DCHECK_EQ(h, pending_customer_data_query_)
             << "received customer data from invalid request.";
@@ -766,6 +774,48 @@
   return iter != profiles.end() ? *iter : nullptr;
 }
 
+void PersonalDataManager::AddIban(const Iban& iban) {
+  if (is_off_the_record_ || FindByGUID(local_ibans_, iban.guid()) ||
+      !database_helper_->GetLocalDatabase() ||
+      FindByContents(local_ibans_, iban)) {
+    return;
+  }
+
+  // Add the new iban to the web database.
+  database_helper_->GetLocalDatabase()->AddIban(iban);
+
+  // Refresh our local cache and send notifications to observers.
+  Refresh();
+}
+
+void PersonalDataManager::UpdateIban(const Iban& iban) {
+  DCHECK_EQ(Iban::LOCAL_IBAN, iban.record_type());
+  if (is_off_the_record_) {
+    return;
+  }
+  Iban* existing_iban = GetIbanByGUID(iban.guid());
+  if (!existing_iban) {
+    return;
+  }
+
+  // Do not overwrite iban if it's existed already.
+  if (existing_iban->Compare(iban) == 0) {
+    return;
+  }
+
+  // Update the cached version.
+  *existing_iban = iban;
+  if (!database_helper_->GetLocalDatabase()) {
+    return;
+  }
+
+  // Make the update.
+  database_helper_->GetLocalDatabase()->UpdateIban(iban);
+
+  // Refresh our local cache and send notifications to observers.
+  Refresh();
+}
+
 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
   if (!IsAutofillCreditCardEnabled())
     return;
@@ -1007,16 +1057,25 @@
   if (!database_helper_->GetLocalDatabase())
     return;
 
-  bool is_credit_card = FindByGUID(local_credit_cards_, guid);
-  if (is_credit_card) {
+  if (FindByGUID(local_credit_cards_, guid)) {
     database_helper_->GetLocalDatabase()->RemoveCreditCard(guid);
     // Refresh our local cache and send notifications to observers.
     Refresh();
+  } else if (FindByGUID(local_ibans_, guid)) {
+    database_helper_->GetLocalDatabase()->RemoveIban(guid);
+    // Refresh our local cache and send notifications to observers.
+    Refresh();
   } else {
     RemoveAutofillProfileByGUIDAndBlankCreditCardReference(guid);
   }
 }
 
+Iban* PersonalDataManager::GetIbanByGUID(const std::string& guid) {
+  const std::vector<Iban*>& ibans = GetIbans();
+  auto iter = FindElementByGUID(ibans, guid);
+  return iter != ibans.end() ? *iter : nullptr;
+}
+
 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
   const std::vector<CreditCard*>& credit_cards = GetCreditCards();
   auto iter = FindElementByGUID(credit_cards, guid);
@@ -1107,7 +1166,6 @@
 
 std::vector<CreditCard*> PersonalDataManager::GetCreditCards() const {
   std::vector<CreditCard*> result;
-
   result.reserve(local_credit_cards_.size() + server_credit_cards_.size());
   for (const auto& card : local_credit_cards_)
     result.push_back(card.get());
@@ -1119,6 +1177,15 @@
   return result;
 }
 
+std::vector<Iban*> PersonalDataManager::GetIbans() const {
+  std::vector<Iban*> result;
+  result.reserve(local_ibans_.size());
+  for (const auto& iban : local_ibans_) {
+    result.push_back(iban.get());
+  }
+  return result;
+}
+
 PaymentsCustomerData* PersonalDataManager::GetPaymentsCustomerData() const {
   return payments_customer_data_ ? payments_customer_data_.get() : nullptr;
 }
@@ -1199,6 +1266,7 @@
   LoadProfiles();
   LoadCreditCards();
   LoadCreditCardCloudTokenData();
+  LoadIbans();
   LoadPaymentsCustomerData();
   LoadUpiIds();
   LoadAutofillOffers();
@@ -1715,9 +1783,22 @@
       database_helper_->GetServerDatabase()->GetCreditCardCloudTokenData(this);
 }
 
-void PersonalDataManager::LoadUpiIds() {
-  if (!database_helper_->GetLocalDatabase())
+void PersonalDataManager::LoadIbans() {
+  if (!database_helper_->GetLocalDatabase()) {
+    NOTREACHED();
     return;
+  }
+
+  CancelPendingLocalQuery(&pending_ibans_query_);
+
+  pending_ibans_query_ = database_helper_->GetLocalDatabase()->GetIbans(this);
+}
+
+void PersonalDataManager::LoadUpiIds() {
+  if (!database_helper_->GetLocalDatabase()) {
+    NOTREACHED();
+    return;
+  }
 
   CancelPendingLocalQuery(&pending_upi_ids_query_);
 
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index c11ab0e..60a5f93 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -25,6 +25,7 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
+#include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/geo/alternative_state_name_map_updater.h"
 #include "components/autofill/core/browser/payments/account_info_getter.h"
@@ -200,6 +201,13 @@
       const std::string& guid,
       const std::vector<AutofillProfile*>& profiles);
 
+  // Adds |iban| to the web database as a local Iban.
+  virtual void AddIban(const Iban& iban);
+
+  // Updates |iban| which already exists in the web database. This
+  // can only be used on local ibans.
+  virtual void UpdateIban(const Iban& iban);
+
   // Adds |credit_card| to the web database as a local card.
   virtual void AddCreditCard(const CreditCard& credit_card);
 
@@ -245,6 +253,10 @@
   // the real database.
   void AddOfferDataForTest(std::unique_ptr<AutofillOfferData> offer_data);
 
+  // Returns the iban with the specified |guid|, or nullptr if there is no iban
+  // with the specified |guid|.
+  virtual Iban* GetIbanByGUID(const std::string& guid);
+
   // Returns the credit card with the specified |guid|, or nullptr if there is
   // no credit card with the specified |guid|.
   virtual CreditCard* GetCreditCardByGUID(const std::string& guid);
@@ -280,6 +292,9 @@
   // Returns all credit cards, server and local.
   virtual std::vector<CreditCard*> GetCreditCards() const;
 
+  // Returns local Ibans.
+  virtual std::vector<Iban*> GetIbans() const;
+
   // Returns the Payments customer data. Returns nullptr if no data is present.
   virtual PaymentsCustomerData* GetPaymentsCustomerData() const;
 
@@ -330,12 +345,12 @@
   const std::vector<CreditCard*> GetCreditCardsToSuggest(
       bool include_server_cards) const;
 
-  // Re-loads profiles and credit cards from the WebDatabase asynchronously.
-  // In the general case, this is a no-op and will re-create the same
-  // in-memory model as existed prior to the call.  If any change occurred to
-  // profiles in the WebDatabase directly, as is the case if the browser sync
-  // engine processed a change from the cloud, we will learn of these as a
-  // result of this call.
+  // Re-loads profiles, credit cards, and IBANs from the WebDatabase
+  // asynchronously. In the general case, this is a no-op and will re-create
+  // the same in-memory model as existed prior to the call.  If any change
+  // occurred to profiles in the WebDatabase directly, as is the case if the
+  // browser sync engine processed a change from the cloud, we will learn of
+  // these as a result of this call.
   //
   // Also see SetProfile for more details.
   virtual void Refresh();
@@ -431,6 +446,9 @@
   // Returns the value of the AutofillCreditCardEnabled pref.
   virtual bool IsAutofillCreditCardEnabled() const;
 
+  // TODO(crbug.com/1340310): Add IsAutofillIbanEnabled after adding
+  // kAutofillIbanEnabled which is related to Enterprise prefs.
+
   // Returns the value of the AutofillWalletImportEnabled pref.
   virtual bool IsAutofillWalletImportEnabled() const;
 
@@ -600,6 +618,9 @@
   // Loads the saved credit card cloud token data from the web database.
   virtual void LoadCreditCardCloudTokenData();
 
+  // Loads the saved IBANs from the web database.
+  virtual void LoadIbans();
+
   // Loads the payments customer data from the web database.
   virtual void LoadPaymentsCustomerData();
 
@@ -662,6 +683,9 @@
   std::vector<std::unique_ptr<CreditCard>> local_credit_cards_;
   std::vector<std::unique_ptr<CreditCard>> server_credit_cards_;
 
+  // Cached versions of the local Ibans.
+  std::vector<std::unique_ptr<Iban>> local_ibans_;
+
   // Cached UPI IDs.
   std::vector<std::string> upi_ids_;
 
@@ -686,6 +710,7 @@
   WebDataServiceBase::Handle pending_server_creditcards_query_ = 0;
   WebDataServiceBase::Handle pending_server_creditcard_cloud_token_data_query_ =
       0;
+  WebDataServiceBase::Handle pending_ibans_query_ = 0;
   WebDataServiceBase::Handle pending_customer_data_query_ = 0;
   WebDataServiceBase::Handle pending_upi_ids_query_ = 0;
   WebDataServiceBase::Handle pending_offer_data_query_ = 0;
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index e4d5d2fb..4aa5439e 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -999,6 +999,63 @@
   ExpectSameElements(profiles, personal_data_->GetProfiles());
 }
 
+TEST_F(PersonalDataManagerTest, AddUpdateRemoveIbans) {
+  Iban iban0(base::GenerateGUID());
+  iban0.set_value(u"IE12 BOFI 9000 0112 3456 78");
+  iban0.set_nickname(u"Nickname 0");
+
+  Iban iban1(base::GenerateGUID());
+  iban1.set_value(u"DE91 1000 0000 0123 4567 89");
+  iban1.set_nickname(u"Nickname 1");
+
+  Iban iban2(base::GenerateGUID());
+  iban2.set_value(u"ES79 2100 0813 6101 2345 6789");
+  iban2.set_nickname(u"Nickname 2");
+
+  // Add two test ibans to the database.
+  personal_data_->AddIban(iban0);
+  personal_data_->AddIban(iban1);
+
+  WaitForOnPersonalDataChanged();
+
+  std::vector<Iban*> ibans;
+  ibans.push_back(&iban0);
+  ibans.push_back(&iban1);
+  ExpectSameElements(ibans, personal_data_->GetIbans());
+
+  // Update iban0, remove iban1, and add iban2.
+  iban0.set_nickname(u"Nickname new 0");
+  iban0.SetRawInfo(IBAN_VALUE, u"GB98 MIDL 0700 9312 3456 78");
+  personal_data_->UpdateIban(iban0);
+  RemoveByGUIDFromPersonalDataManager(iban1.guid());
+  personal_data_->AddIban(iban2);
+
+  WaitForOnPersonalDataChanged();
+
+  ibans.clear();
+  ibans.push_back(&iban0);
+  ibans.push_back(&iban2);
+  ExpectSameElements(ibans, personal_data_->GetIbans());
+
+  // Verify that a duplicate iban should not be added.
+  Iban iban0_dup = iban0;
+  personal_data_->AddIban(iban0_dup);
+  ibans.clear();
+  ibans.push_back(&iban0);
+  ibans.push_back(&iban2);
+  ExpectSameElements(ibans, personal_data_->GetIbans());
+
+  // Reset the PersonalDataManager. This tests that the personal data was saved
+  // to the web database, and that we can load the ibans from the web database.
+  ResetPersonalDataManager(USER_MODE_NORMAL);
+
+  // Verify that we've reloaded the ibans from the web database.
+  ibans.clear();
+  ibans.push_back(&iban0);
+  ibans.push_back(&iban2);
+  ExpectSameElements(ibans, personal_data_->GetIbans());
+}
+
 TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
   CreditCard credit_card0(base::GenerateGUID(), test::kEmptyOrigin);
   test::SetCreditCardInfo(&credit_card0, "John Dillinger",
diff --git a/components/autofill/core/browser/test_personal_data_manager.cc b/components/autofill/core/browser/test_personal_data_manager.cc
index 0eb5bb1..beeb6390 100644
--- a/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/components/autofill/core/browser/test_personal_data_manager.cc
@@ -214,8 +214,20 @@
   }
 }
 
+void TestPersonalDataManager::LoadIbans() {
+  pending_ibans_query_ = 128;
+  {
+    std::vector<std::unique_ptr<Iban>> ibans;
+    local_ibans_.swap(ibans);
+    std::unique_ptr<WDTypedResult> result =
+        std::make_unique<WDResult<std::vector<std::unique_ptr<Iban>>>>(
+            AUTOFILL_IBANS_RESULT, std::move(ibans));
+    OnWebDataServiceRequestDone(pending_ibans_query_, std::move(result));
+  }
+}
+
 void TestPersonalDataManager::LoadUpiIds() {
-  pending_upi_ids_query_ = 128;
+  pending_upi_ids_query_ = 129;
   {
     std::vector<std::string> upi_ids = {"vpa@indianbank"};
     std::unique_ptr<WDTypedResult> result =
diff --git a/components/autofill/core/browser/test_personal_data_manager.h b/components/autofill/core/browser/test_personal_data_manager.h
index c979525..fad85f3 100644
--- a/components/autofill/core/browser/test_personal_data_manager.h
+++ b/components/autofill/core/browser/test_personal_data_manager.h
@@ -59,6 +59,7 @@
   void LoadProfiles() override;
   void LoadCreditCards() override;
   void LoadCreditCardCloudTokenData() override;
+  void LoadIbans() override;
   void LoadUpiIds() override;
   bool IsAutofillEnabled() const override;
   bool IsAutofillProfileEnabled() const override;
diff --git a/components/autofill/core/browser/webdata/autofill_change.h b/components/autofill/core/browser/webdata/autofill_change.h
index 9da26e5d..06bf75b 100644
--- a/components/autofill/core/browser/webdata/autofill_change.h
+++ b/components/autofill/core/browser/webdata/autofill_change.h
@@ -16,6 +16,7 @@
 namespace autofill {
 
 class CreditCard;
+class Iban;
 
 // For classic Autofill form fields, the KeyType is AutofillKey.
 // Autofill++ types such as AutofillProfile and CreditCard simply use a string.
@@ -80,6 +81,7 @@
 
 typedef AutofillDataModelChange<AutofillProfile> AutofillProfileChange;
 typedef AutofillDataModelChange<CreditCard> CreditCardChange;
+typedef AutofillDataModelChange<Iban> IbanChange;
 
 class AutofillProfileDeepChange : public AutofillProfileChange {
  public:
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index 642a1118..703933a 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -33,6 +33,7 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
+#include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
@@ -213,6 +214,13 @@
 // kUseDate = "use_date"
 // kBillingAddressId = "billing_address_id"
 
+constexpr base::StringPiece kIbansTable = "ibans";
+// kGuid = "guid"
+// kUseCount = "use_count"
+// kUseDate = "use_date"
+// kValue = "value"
+// kNickname = "nickname"
+
 constexpr base::StringPiece kServerAddressesTable = "server_addresses";
 // kId = "id"
 constexpr base::StringPiece kRecipientName = "recipient_name";
@@ -577,6 +585,20 @@
   s->BindString16(index++, credit_card.nickname());
 }
 
+void BindIbanToStatement(const Iban& iban,
+                         sql::Statement* s,
+                         const AutofillTableEncryptor& encryptor) {
+  DCHECK(base::IsValidGUID(iban.guid()));
+  int index = 0;
+  s->BindString(index++, iban.guid());
+
+  s->BindInt64(index++, iban.use_count());
+  s->BindInt64(index++, iban.use_date().ToTimeT());
+
+  s->BindString16(index++, iban.value());
+  s->BindString16(index++, iban.nickname());
+}
+
 std::u16string UnencryptedCardFromColumn(
     sql::Statement& s,
     int column_index,
@@ -614,6 +636,22 @@
   return credit_card;
 }
 
+std::unique_ptr<Iban> IbanFromStatement(
+    sql::Statement& s,
+    const AutofillTableEncryptor& encryptor) {
+  auto iban = std::make_unique<Iban>();
+
+  int index = 0;
+  iban->set_guid(s.ColumnString(index++));
+  DCHECK(base::IsValidGUID(iban->guid()));
+  iban->set_use_count(s.ColumnInt64(index++));
+  iban->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
+
+  iban->SetRawInfo(IBAN_VALUE, s.ColumnString16(index++));
+  iban->set_nickname(s.ColumnString16(index++));
+  return iban;
+}
+
 bool AddAutofillProfileNames(const AutofillProfile& profile,
                              sql::Database* db) {
   if (base::FeatureList::IsEnabled(
@@ -1002,14 +1040,15 @@
 }
 
 bool AutofillTable::CreateTablesIfNecessary() {
-  return InitMainTable() && InitCreditCardsTable() && InitProfilesTable() &&
-         InitProfileAddressesTable() && InitProfileNamesTable() &&
-         InitProfileEmailsTable() && InitProfilePhonesTable() &&
-         InitProfileBirthdatesTable() && InitMaskedCreditCardsTable() &&
-         InitUnmaskedCreditCardsTable() && InitServerCardMetadataTable() &&
-         InitServerAddressesTable() && InitServerAddressMetadataTable() &&
-         InitAutofillSyncMetadataTable() && InitModelTypeStateTable() &&
-         InitPaymentsCustomerDataTable() && InitPaymentsUPIVPATable() &&
+  return InitMainTable() && InitCreditCardsTable() && InitIbansTable() &&
+         InitProfilesTable() && InitProfileAddressesTable() &&
+         InitProfileNamesTable() && InitProfileEmailsTable() &&
+         InitProfilePhonesTable() && InitProfileBirthdatesTable() &&
+         InitMaskedCreditCardsTable() && InitUnmaskedCreditCardsTable() &&
+         InitServerCardMetadataTable() && InitServerAddressesTable() &&
+         InitServerAddressMetadataTable() && InitAutofillSyncMetadataTable() &&
+         InitModelTypeStateTable() && InitPaymentsCustomerDataTable() &&
+         InitPaymentsUPIVPATable() &&
          InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() &&
          InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable();
 }
@@ -1084,6 +1123,9 @@
     case 104:
       *update_compatible_version = false;
       return MigrateToVersion104AddProductDescriptionColumn();
+    case 105:
+      *update_compatible_version = false;
+      return MigrateToVersion105AddAutofillIbanTable();
   }
   return true;
 }
@@ -1668,6 +1710,78 @@
   SetServerProfilesAndMetadata(profiles, /*update_metadata=*/true);
 }
 
+bool AutofillTable::AddIban(const Iban& iban) {
+  sql::Statement s;
+  InsertBuilder(db_, s, kIbansTable,
+                {kGuid, kUseCount, kUseDate, kValue, kNickname});
+  BindIbanToStatement(iban, &s, *autofill_table_encryptor_);
+  if (!s.Run())
+    return false;
+
+  DCHECK_GT(db_->GetLastChangeCount(), 0);
+  return true;
+}
+
+bool AutofillTable::UpdateIban(const Iban& iban) {
+  DCHECK(base::IsValidGUID(iban.guid()));
+
+  std::unique_ptr<Iban> old_iban = GetIban(iban.guid());
+  if (!old_iban) {
+    return false;
+  }
+
+  if (*old_iban == iban) {
+    return true;
+  }
+
+  sql::Statement s(db_->GetUniqueStatement(
+      "UPDATE ibans "
+      "SET guid=?, use_count=?, use_date=?, value=?, nickname=? "
+      "WHERE guid=?1"));
+  BindIbanToStatement(iban, &s, *autofill_table_encryptor_);
+
+  bool result = s.Run();
+  DCHECK_GT(db_->GetLastChangeCount(), 0);
+  return result;
+}
+
+bool AutofillTable::RemoveIban(const std::string& guid) {
+  DCHECK(base::IsValidGUID(guid));
+  return DeleteWhereColumnEq(db_, kIbansTable, kGuid, guid);
+}
+
+std::unique_ptr<Iban> AutofillTable::GetIban(const std::string& guid) {
+  DCHECK(base::IsValidGUID(guid));
+  sql::Statement s;
+  SelectBuilder(db_, s, kIbansTable,
+                {kGuid, kUseCount, kUseDate, kValue, kNickname},
+                "WHERE guid = ?");
+  s.BindString(0, guid);
+
+  if (!s.Step())
+    return nullptr;
+
+  return IbanFromStatement(s, *autofill_table_encryptor_);
+}
+
+bool AutofillTable::GetIbans(std::vector<std::unique_ptr<Iban>>* ibans) {
+  DCHECK(ibans);
+  ibans->clear();
+
+  sql::Statement s;
+  SelectBuilder(db_, s, kIbansTable, {kGuid}, "ORDER BY use_date DESC, guid");
+
+  while (s.Step()) {
+    std::string guid = s.ColumnString(0);
+    std::unique_ptr<Iban> iban = GetIban(guid);
+    if (!iban)
+      return false;
+    ibans->push_back(std::move(iban));
+  }
+
+  return s.Succeeded();
+}
+
 bool AutofillTable::AddCreditCard(const CreditCard& credit_card) {
   sql::Statement s;
   InsertBuilder(db_, s, kCreditCardsTable,
@@ -2955,6 +3069,18 @@
   return transaction.Commit();
 }
 
+bool AutofillTable::MigrateToVersion105AddAutofillIbanTable() {
+  sql::Transaction transaction(db_);
+  return transaction.Begin() &&
+         CreateTable(db_, kIbansTable,
+                     {{kGuid, "VARCHAR"},
+                      {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                      {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+                      {kValue, "VARCHAR"},
+                      {kNickname, "VARCHAR"}}) &&
+         transaction.Commit();
+}
+
 bool AutofillTable::AddFormFieldValuesTime(
     const std::vector<FormFieldData>& elements,
     std::vector<AutofillChange>* changes,
@@ -3187,6 +3313,15 @@
                                  {kNickname, "VARCHAR"}});
 }
 
+bool AutofillTable::InitIbansTable() {
+  return CreateTableIfNotExists(db_, kIbansTable,
+                                {{kGuid, "VARCHAR PRIMARY KEY"},
+                                 {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kValue, "VARCHAR"},
+                                 {kNickname, "VARCHAR"}});
+}
+
 bool AutofillTable::InitProfilesTable() {
   return CreateTableIfNotExists(
       db_, kAutofillProfilesTable,
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index e38f7496..7670ecb1 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -39,6 +39,7 @@
 class CreditCard;
 struct CreditCardCloudTokenData;
 struct FormFieldData;
+class Iban;
 struct PaymentsCustomerData;
 
 // This class manages the various Autofill tables within the SQLite database
@@ -323,6 +324,19 @@
 //                      database, but always returned as an empty string in
 //                      CreditCard. Added in version 71.
 //
+// ibans                This table contains International Bank Account
+//                      Number(IBAN) data added by the user. The columns are
+//                      standard entries in an Iban form.
+//
+//   guid               A guid string to uniquely identify the IBAN.
+//   use_count          The number of times this IBAN has been used to fill
+//                      a form.
+//   use_date           The date this IBAN was last used to fill a form,
+//                      in time_t.
+//   value              Actual value of the IBAN (the bank account number).
+//   nickname           A nickname for the IBAN, entered by the user.
+//
+//
 // server_addresses     This table contains Autofill address data synced from
 //                      the wallet server. It's basically the same as the
 //                      autofill_profiles table but locally immutable.
@@ -533,6 +547,22 @@
   // the given ones.
   void SetServerProfiles(const std::vector<AutofillProfile>& profiles);
 
+  // Records a single Iban in the iban table.
+  bool AddIban(const Iban& iban);
+
+  // Updates the database values for the specified Iban.
+  bool UpdateIban(const Iban& iban);
+
+  // Removes a row from the ibans table. |guid| is the identifier of the
+  // iban to remove.
+  bool RemoveIban(const std::string& guid);
+
+  // Retrieves an Iban with the given |guid|.
+  std::unique_ptr<Iban> GetIban(const std::string& guid);
+
+  // Retrieves the local Ibans in the database.
+  bool GetIbans(std::vector<std::unique_ptr<Iban>>* ibans);
+
   // Records a single credit card in the credit_cards table.
   bool AddCreditCard(const CreditCard& credit_card);
 
@@ -700,6 +730,7 @@
   bool MigrateToVersion101RemoveCreditCardArtImageTable();
   bool MigrateToVersion102AddAutofillBirthdatesTable();
   bool MigrateToVersion104AddProductDescriptionColumn();
+  bool MigrateToVersion105AddAutofillIbanTable();
 
   // Max data length saved in the table, AKA the maximum length allowed for
   // form data.
@@ -793,6 +824,7 @@
 
   bool InitMainTable();
   bool InitCreditCardsTable();
+  bool InitIbansTable();
   bool InitProfilesTable();
   bool InitProfileAddressesTable();
   bool InitProfileNamesTable();
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 703cf5b..011dc4d 100644
--- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -1544,6 +1544,71 @@
   EXPECT_FALSE(db_profile);
 }
 
+TEST_F(AutofillTableTest, Iban) {
+  // Add a valid Iban.
+  Iban iban;
+  std::string guid = base::GenerateGUID();
+  iban.set_guid(guid);
+  iban.SetRawInfo(IBAN_VALUE, u"IE12 BOFI 9000 0112 3456 78");
+  iban.set_nickname(u"My doctor's IBAN");
+
+  EXPECT_TRUE(table_->AddIban(iban));
+
+  // Get the inserted Iban.
+  std::unique_ptr<Iban> db_iban = table_->GetIban(iban.guid());
+  ASSERT_TRUE(db_iban);
+  EXPECT_EQ(guid, db_iban->guid());
+  sql::Statement s_work(db_->GetSQLConnection()->GetUniqueStatement(
+      "SELECT guid, use_count, use_date, "
+      "value, nickname FROM ibans WHERE guid = ?"));
+  s_work.BindString(0, iban.guid());
+  ASSERT_TRUE(s_work.is_valid());
+  ASSERT_TRUE(s_work.Step());
+  EXPECT_FALSE(s_work.Step());
+
+  // Add another valid Iban.
+  Iban another_iban;
+  std::string another_guid = base::GenerateGUID();
+  another_iban.set_guid(another_guid);
+  another_iban.SetRawInfo(IBAN_VALUE, u"DE91 1000 0000 0123 4567 89");
+  another_iban.set_nickname(u"My brother's IBAN");
+
+  EXPECT_TRUE(table_->AddIban(another_iban));
+
+  db_iban = table_->GetIban(another_iban.guid());
+  ASSERT_TRUE(db_iban);
+
+  EXPECT_EQ(another_guid, db_iban->guid());
+  sql::Statement s_target(db_->GetSQLConnection()->GetUniqueStatement(
+      "SELECT guid, use_count, use_date, "
+      "value, nickname FROM ibans WHERE guid = ?"));
+  s_target.BindString(0, another_iban.guid());
+  ASSERT_TRUE(s_target.is_valid());
+  ASSERT_TRUE(s_target.Step());
+  EXPECT_FALSE(s_target.Step());
+
+  // Update the another_iban.
+  another_iban.set_origin("Interactive Autofill dialog");
+  another_iban.SetRawInfo(IBAN_VALUE, u"GB98 MIDL 0700 9312 3456 78");
+  another_iban.set_nickname(u"My teacher's IBAN");
+  EXPECT_TRUE(table_->UpdateIban(another_iban));
+  db_iban = table_->GetIban(another_iban.guid());
+  ASSERT_TRUE(db_iban);
+  EXPECT_EQ(another_guid, db_iban->guid());
+  sql::Statement s_target_updated(db_->GetSQLConnection()->GetUniqueStatement(
+      "SELECT guid, use_count, use_date, "
+      "value, nickname FROM ibans WHERE guid = ?"));
+  s_target_updated.BindString(0, another_iban.guid());
+  ASSERT_TRUE(s_target_updated.is_valid());
+  ASSERT_TRUE(s_target_updated.Step());
+  EXPECT_FALSE(s_target_updated.Step());
+
+  // Remove the 'Target' iban.
+  EXPECT_TRUE(table_->RemoveIban(another_iban.guid()));
+  db_iban = table_->GetIban(another_iban.guid());
+  EXPECT_FALSE(db_iban);
+}
+
 TEST_F(AutofillTableTest, CreditCard) {
   // Add a 'Work' credit card.
   CreditCard work_creditcard;
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index 141895fe..3df86af 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -16,6 +16,7 @@
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
+#include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/webdata/autofill_change.h"
@@ -513,6 +514,73 @@
   return WebDatabase::COMMIT_NEEDED;
 }
 
+std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetIbans(
+    WebDatabase* db) {
+  DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  std::vector<std::unique_ptr<Iban>> ibans;
+  AutofillTable::FromWebDatabase(db)->GetIbans(&ibans);
+
+  return std::make_unique<WDResult<std::vector<std::unique_ptr<Iban>>>>(
+      AUTOFILL_IBANS_RESULT, std::move(ibans));
+}
+
+WebDatabase::State AutofillWebDataBackendImpl::AddIban(const Iban& iban,
+                                                       WebDatabase* db) {
+  DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  if (!AutofillTable::FromWebDatabase(db)->AddIban(iban)) {
+    NOTREACHED();
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.IbanChanged(IbanChange(IbanChange::ADD, iban.guid(), &iban));
+  }
+  return WebDatabase::COMMIT_NEEDED;
+}
+
+WebDatabase::State AutofillWebDataBackendImpl::UpdateIban(const Iban& iban,
+                                                          WebDatabase* db) {
+  DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  // It is currently valid to try to update a missing iban. We simply drop
+  // the write and the caller will detect this on the next refresh.
+  std::unique_ptr<Iban> original_iban =
+      AutofillTable::FromWebDatabase(db)->GetIban(iban.guid());
+  if (!original_iban)
+    return WebDatabase::COMMIT_NOT_NEEDED;
+
+  if (!AutofillTable::FromWebDatabase(db)->UpdateIban(iban)) {
+    NOTREACHED();
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.IbanChanged(IbanChange(IbanChange::UPDATE, iban.guid(), &iban));
+  }
+  return WebDatabase::COMMIT_NEEDED;
+}
+
+WebDatabase::State AutofillWebDataBackendImpl::RemoveIban(
+    const std::string& guid,
+    WebDatabase* db) {
+  DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  std::unique_ptr<Iban> iban =
+      AutofillTable::FromWebDatabase(db)->GetIban(guid);
+  if (!iban) {
+    NOTREACHED();
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  if (!AutofillTable::FromWebDatabase(db)->RemoveIban(guid)) {
+    NOTREACHED();
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.IbanChanged(IbanChange(IbanChange::REMOVE, guid, iban.get()));
+  }
+  return WebDatabase::COMMIT_NEEDED;
+}
+
 WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
     const AutofillProfile& profile,
     WebDatabase* db) {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 8e4f8448..ba1cdc9 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -31,6 +31,7 @@
 class AutofillProfile;
 class AutofillWebDataServiceObserverOnDBSequence;
 class CreditCard;
+class Iban;
 
 // Backend implementation for the AutofillWebDataService. This class runs on the
 // DB sequence, as it handles reads and writes to the WebDatabase, and functions
@@ -177,6 +178,18 @@
   std::unique_ptr<WDTypedResult> GetCreditCards(WebDatabase* db);
   std::unique_ptr<WDTypedResult> GetServerCreditCards(WebDatabase* db);
 
+  // Returns a vector of local Ibans from the web database.
+  std::unique_ptr<WDTypedResult> GetIbans(WebDatabase* db);
+
+  // Adds an Iban to the web database. Valid only for local ibans.
+  WebDatabase::State AddIban(const Iban& iban, WebDatabase* db);
+
+  // Updates an Iban in the web database. Valid only for local ibans.
+  WebDatabase::State UpdateIban(const Iban& iban, WebDatabase* db);
+
+  // Removes an Iban from the web database. Valid only for local ibans.
+  WebDatabase::State RemoveIban(const std::string& guid, WebDatabase* db);
+
   // Server credit cards can be masked (only last 4 digits stored) or unmasked
   // (all data stored). These toggle between the two states.
   WebDatabase::State UnmaskServerCreditCard(const CreditCard& card,
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 1621156..39fc709 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -13,6 +13,7 @@
 #include "components/autofill/core/browser/data_model/autofill_offer_data.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_model/iban.h"
 #include "components/autofill/core/browser/geo/autofill_country.h"
 #include "components/autofill/core/browser/webdata/autofill_change.h"
 #include "components/autofill/core/browser/webdata/autofill_entry.h"
@@ -213,6 +214,32 @@
                      autofill_backend_, credit_card));
 }
 
+void AutofillWebDataService::AddIban(const Iban& iban) {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+                        base::BindOnce(&AutofillWebDataBackendImpl::AddIban,
+                                       autofill_backend_, iban));
+}
+
+WebDataServiceBase::Handle AutofillWebDataService::GetIbans(
+    WebDataServiceConsumer* consumer) {
+  return wdbs_->ScheduleDBTaskWithResult(
+      FROM_HERE,
+      base::BindOnce(&AutofillWebDataBackendImpl::GetIbans, autofill_backend_),
+      consumer);
+}
+
+void AutofillWebDataService::UpdateIban(const Iban& iban) {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+                        base::BindOnce(&AutofillWebDataBackendImpl::UpdateIban,
+                                       autofill_backend_, iban));
+}
+
+void AutofillWebDataService::RemoveIban(const std::string& guid) {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+                        base::BindOnce(&AutofillWebDataBackendImpl::RemoveIban,
+                                       autofill_backend_, guid));
+}
+
 WebDataServiceBase::Handle AutofillWebDataService::GetCreditCards(
     WebDataServiceConsumer* consumer) {
   return wdbs_->ScheduleDBTaskWithResult(
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h
index cb92fee..83c8c10 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -35,6 +35,7 @@
 class AutofillWebDataServiceObserverOnDBSequence;
 class AutofillWebDataServiceObserverOnUISequence;
 class CreditCard;
+class Iban;
 
 // API for Autofill web data.
 class AutofillWebDataService : public WebDataServiceBase {
@@ -114,6 +115,22 @@
       base::RepeatingCallback<void(const AutofillProfileDeepChange&)>
           change_cb);
 
+  // Schedules a task to add Iban to the web database.
+  void AddIban(const Iban& iban);
+
+  // Initiates the request for local Ibans. The method
+  // OnWebDataServiceRequestDone of |consumer| gets called when the request is
+  // finished, with the Iban included in the argument |result|. The consumer
+  // owns the Iban.
+  WebDataServiceBase::Handle GetIbans(WebDataServiceConsumer* consumer);
+
+  // Schedules a task to update iban in the web database.
+  void UpdateIban(const Iban& iban);
+
+  // Schedules a task to remove an iban from the web database.
+  // |guid| is the identifier of the iban to remove.
+  void RemoveIban(const std::string& guid);
+
   // Schedules a task to add credit card to the web database.
   void AddCreditCard(const CreditCard& credit_card);
 
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h b/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
index 60820bb..dcba766 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service_observer.h
@@ -23,6 +23,10 @@
   // the WebDatabase.
   virtual void CreditCardChanged(const CreditCardChange& change) {}
 
+  // Called on DB sequence when an Iban has been added/removed/updated in
+  // the WebDatabase.
+  virtual void IbanChanged(const IbanChange& change) {}
+
  protected:
   virtual ~AutofillWebDataServiceObserverOnDBSequence() {}
 };
diff --git a/components/autofill_assistant/android/BUILD.gn b/components/autofill_assistant/android/BUILD.gn
index dccfe9b..83e5695 100644
--- a/components/autofill_assistant/android/BUILD.gn
+++ b/components/autofill_assistant/android/BUILD.gn
@@ -105,7 +105,6 @@
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormSelectionChoice.java",
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormSelectionInput.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantColor.java",
-    "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDimension.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantGenericUiCoordinator.java",
@@ -287,7 +286,6 @@
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormInput.java",
     "java/src/org/chromium/components/autofill_assistant/form/AssistantFormModel.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantColor.java",
-    "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDimension.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java",
     "java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantGenericUiDelegate.java",
diff --git a/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml b/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
index e57bae9..6c939df2 100644
--- a/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
+++ b/components/autofill_assistant/android/internal/java/res/layout/autofill_assistant_info_box.xml
@@ -2,22 +2,9 @@
 <!-- Copyright 2019 The Chromium Authors. All rights reserved.
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
-<LinearLayout
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  xmlns:tools="http://schemas.android.com/tools"
-  android:layout_height="wrap_content"
-  android:orientation="vertical"
-  android:layout_gravity="center"
-  tools:ignore="UseCompoundDrawables" >
-  <ImageView
-    android:id="@+id/info_box_image"
-    android:layout_marginTop="16dp"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    tools:ignore="ContentDescription" />
-  <TextView
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/info_box_explanation"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -27,6 +14,3 @@
     android:paddingBottom="@dimen/autofill_assistant_info_box_spacing"
     android:drawablePadding="@dimen/autofill_assistant_bottombar_vertical_spacing"
     android:textAppearance="@style/TextAppearance.TextLarge.Primary"/>
-
-
-</LinearLayout>
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java
deleted file mode 100644
index 79a3625..0000000
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDeviceConfig.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill_assistant.generic_ui;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.DisplayMetrics;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * Contains methods to provide information about device configuration. It is used to select device
- * configuration specific resources.
- */
-@JNINamespace("autofill_assistant")
-public abstract class AssistantDeviceConfig {
-    @CalledByNative
-    public static boolean isDarkModeEnabled(Context context) {
-        return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                == Configuration.UI_MODE_NIGHT_YES;
-    }
-
-    @CalledByNative
-    public static String getDevicePixelDensity(Context context) {
-        int densityDpi = context.getResources().getDisplayMetrics().densityDpi;
-        if (densityDpi <= DisplayMetrics.DENSITY_LOW) {
-            return "ldpi";
-        } else if (densityDpi <= DisplayMetrics.DENSITY_MEDIUM) {
-            return "mdpi";
-        } else if (densityDpi <= DisplayMetrics.DENSITY_HIGH) {
-            return "hdpi";
-        } else if (densityDpi <= DisplayMetrics.DENSITY_XHIGH) {
-            return "xhdpi";
-        } else {
-            return "xxhdpi";
-        }
-    }
-}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
index 775713f..307d0988 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/generic_ui/AssistantDrawable.java
@@ -49,12 +49,6 @@
         return new AssistantBitmapDrawable(imageFetcher, url, widthInPixels, heightInPixels);
     }
 
-    @CalledByNative
-    public static AssistantDrawable createFromUrlWithIntrinsicDimensions(
-            ImageFetcher imageFetcher, String url) {
-        return new AssistantBitmapDrawable(imageFetcher, url);
-    }
-
     /** Returns whether {@code resourceId} is a valid resource identifier. */
     @CalledByNative
     public static boolean isValidDrawableResource(Context context, String resourceId) {
@@ -122,22 +116,12 @@
         private final String mUrl;
         private final int mWidthInPixels;
         private final int mHeightInPixels;
-        private final boolean mUseInstrinicDimensions;
 
         AssistantBitmapDrawable(ImageFetcher imageFetcher, String url, int width, int height) {
             mImageFetcher = imageFetcher;
             mUrl = url;
             mWidthInPixels = width;
             mHeightInPixels = height;
-            mUseInstrinicDimensions = false;
-        }
-
-        AssistantBitmapDrawable(ImageFetcher imageFetcher, String url) {
-            mImageFetcher = imageFetcher;
-            mUrl = url;
-            mWidthInPixels = 0;
-            mHeightInPixels = 0;
-            mUseInstrinicDimensions = true;
         }
 
         @Override
@@ -147,11 +131,9 @@
                     mUrl, ImageFetcher.ASSISTANT_DETAILS_UMA_CLIENT_NAME);
             mImageFetcher.fetchImage(params, result -> {
                 if (result != null) {
-                    if (!mUseInstrinicDimensions) {
-                        result = Bitmap.createScaledBitmap(
-                                result, mWidthInPixels, mHeightInPixels, true);
-                    }
-                    callback.onResult(new BitmapDrawable(context.getResources(), result));
+                    callback.onResult(new BitmapDrawable(context.getResources(),
+                            Bitmap.createScaledBitmap(
+                                    result, mWidthInPixels, mHeightInPixels, true)));
                 } else {
                     callback.onResult(null);
                 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
index 610b9a8e..0e6ad399 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBox.java
@@ -4,43 +4,35 @@
 
 package org.chromium.components.autofill_assistant.infobox;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.components.autofill_assistant.generic_ui.AssistantDrawable;
 
-/** Java side equivalent of autofill_assistant::InfoBoxProto. */
+/**
+ * Java side equivalent of autofill_assistant::InfoBoxProto.
+ */
 @JNINamespace("autofill_assistant")
 public class AssistantInfoBox {
-    @Nullable
-    private final AssistantDrawable mDrawable;
+    private final String mImagePath;
     private final String mExplanation;
-    private final boolean mUseIntrinsicDimensions;
 
-    public AssistantInfoBox(@Nullable AssistantDrawable drawable, String explanation,
-            boolean useIntrinsicDimensions) {
-        this.mDrawable = drawable;
+    public AssistantInfoBox(String imagePath, String explanation) {
+        this.mImagePath = imagePath;
         this.mExplanation = explanation;
-        this.mUseIntrinsicDimensions = useIntrinsicDimensions;
     }
 
-    public AssistantDrawable getDrawable() {
-        return mDrawable;
+    public String getImagePath() {
+        return mImagePath;
     }
 
     public String getExplanation() {
         return mExplanation;
     }
 
-    public boolean getUseIntrinsicDimensions() {
-        return mUseIntrinsicDimensions;
-    }
-
-    /** Create infobox with the given values. */
+    /**
+     * Create infobox with the given values.
+     */
     @CalledByNative
-    private static AssistantInfoBox create(@Nullable AssistantDrawable drawable, String explanation,
-            boolean useIntrinsicDimensions) {
-        return new AssistantInfoBox(drawable, explanation, useIntrinsicDimensions);
+    private static AssistantInfoBox create(String imagePath, String explanation) {
+        return new AssistantInfoBox(imagePath, explanation);
     }
 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
index ef5858b4..aec64ba 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
@@ -62,6 +62,6 @@
 
     private boolean isEmpty(AssistantInfoBox infoBox) {
         return infoBox == null
-                || (infoBox.getDrawable() == null && infoBox.getExplanation().isEmpty());
+                || (infoBox.getImagePath().isEmpty() && infoBox.getExplanation().isEmpty());
     }
 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
index c571c1c..f855189c 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/infobox/AssistantInfoBoxViewBinder.java
@@ -5,9 +5,9 @@
 package org.chromium.components.autofill_assistant.infobox;
 
 import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.view.View;
-import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.chromium.components.autofill_assistant.AssistantTextUtils;
@@ -24,13 +24,13 @@
 class AssistantInfoBoxViewBinder
         implements PropertyModelChangeProcessor.ViewBinder<AssistantInfoBoxModel,
                 AssistantInfoBoxViewBinder.ViewHolder, PropertyKey> {
-    /** A wrapper class that holds the different views of the info box. */
+    /**
+     * A wrapper class that holds the different views of the info box.
+     */
     static class ViewHolder {
-        final ImageView mImageView;
         final TextView mExplanationView;
 
         public ViewHolder(Context context, View infoBoxView) {
-            mImageView = infoBoxView.findViewById(R.id.info_box_image);
             mExplanationView = infoBoxView.findViewById(R.id.info_box_explanation);
         }
     }
@@ -43,7 +43,10 @@
         mContext = context;
         mImageFetcher = imageFetcher;
     }
-    /** Explicitly clean up. */
+
+    /**
+     * Explicitly clean up.
+     */
     public void destroy() {
         mImageFetcher.destroy();
         mImageFetcher = null;
@@ -69,39 +72,18 @@
         AssistantTextUtils.applyVisualAppearanceTags(
                 viewHolder.mExplanationView, explanation, null);
         viewHolder.mExplanationView.announceForAccessibility(viewHolder.mExplanationView.getText());
-        if (infoBox.getDrawable() == null) {
-            hideLegacyImage(viewHolder);
-            hideImageView(viewHolder);
+        if (infoBox.getImagePath().isEmpty()) {
+            viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
         } else {
-            infoBox.getDrawable().getDrawable(mContext, image -> {
+            ImageFetcher.Params params = ImageFetcher.Params.create(
+                    infoBox.getImagePath(), ImageFetcher.ASSISTANT_INFO_BOX_UMA_CLIENT_NAME);
+            mImageFetcher.fetchImage(params, image -> {
                 if (image != null) {
-                    if (infoBox.getUseIntrinsicDimensions()) {
-                        showLegacyImage(viewHolder, image);
-                    } else {
-                        showImageView(viewHolder, image);
-                    }
+                    Drawable d = new BitmapDrawable(mContext.getResources(), image);
+                    viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(
+                            null, d, null, null);
                 }
             });
         }
     }
-
-    private void hideLegacyImage(ViewHolder viewHolder) {
-        viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
-    }
-
-    private void showLegacyImage(ViewHolder viewHolder, Drawable image) {
-        hideImageView(viewHolder);
-        viewHolder.mExplanationView.setCompoundDrawablesWithIntrinsicBounds(
-                null, image, null, null);
-    }
-
-    private void hideImageView(ViewHolder viewHolder) {
-        viewHolder.mImageView.setVisibility(View.GONE);
-    }
-
-    private void showImageView(ViewHolder viewHolder, Drawable image) {
-        hideLegacyImage(viewHolder);
-        viewHolder.mImageView.setVisibility(View.VISIBLE);
-        viewHolder.mImageView.setImageDrawable(image);
-    }
 }
diff --git a/components/autofill_assistant/browser/android/ui_controller_android.cc b/components/autofill_assistant/browser/android/ui_controller_android.cc
index fb9a722..e7f1e362 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android.cc
+++ b/components/autofill_assistant/browser/android/ui_controller_android.cc
@@ -69,7 +69,6 @@
 namespace autofill_assistant {
 
 namespace {
-
 std::vector<float> ToFloatVector(const std::vector<RectF>& areas) {
   std::vector<float> flattened;
   for (const auto& rect : areas) {
@@ -1977,38 +1976,9 @@
   }
 
   const InfoBoxProto& proto = info_box->proto().info_box();
-  auto jcontext =
-      Java_AutofillAssistantUiController_getContext(env, java_object_);
-  absl::optional<DrawableProto> drawable_proto;
-  bool use_instrinsic_dimensions = false;
-  switch (proto.image_case()) {
-    case InfoBoxProto::ImageCase::kImagePath: {
-      if (!proto.image_path().empty()) {
-        drawable_proto.emplace();
-        auto* bitmap_proto = drawable_proto->mutable_bitmap();
-        bitmap_proto->set_url(proto.image_path());
-        bitmap_proto->set_use_instrinsic_dimensions(true);
-        use_instrinsic_dimensions = true;
-      }
-      break;
-    }
-    case InfoBoxProto::ImageCase::kDrawable: {
-      drawable_proto = proto.drawable();
-      break;
-    }
-    case InfoBoxProto::ImageCase::IMAGE_NOT_SET: {
-      break;
-    }
-  }
-  base::android::ScopedJavaLocalRef<jobject> jdrawable = nullptr;
-  if (drawable_proto.has_value()) {
-    jdrawable = ui_controller_android_utils::CreateJavaDrawable(
-        env, jcontext, *dependencies_, *drawable_proto,
-        execution_delegate_->GetUserModel());
-  }
   auto jinfo_box = Java_AssistantInfoBox_create(
-      env, jdrawable, ConvertUTF8ToJavaString(env, proto.explanation()),
-      use_instrinsic_dimensions);
+      env, ConvertUTF8ToJavaString(env, proto.image_path()),
+      ConvertUTF8ToJavaString(env, proto.explanation()));
   Java_AssistantInfoBoxModel_setInfoBox(env, jmodel, jinfo_box);
 }
 
diff --git a/components/autofill_assistant/browser/android/ui_controller_android_utils.cc b/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
index 88b4310e..ae134a5 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
+++ b/components/autofill_assistant/browser/android/ui_controller_android_utils.cc
@@ -16,7 +16,6 @@
 #include "components/autofill_assistant/android/jni_headers/AssistantChip_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantColor_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDateTime_jni.h"
-#include "components/autofill_assistant/android/jni_headers/AssistantDeviceConfig_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDialogButton_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDimension_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantDrawable_jni.h"
@@ -44,8 +43,6 @@
 using ::base::android::ConvertUTF8ToJavaString;
 using ::base::android::JavaRef;
 
-constexpr char kNightModePrefix[] = "night-";
-
 DrawableIcon MapDrawableIcon(DrawableProto::Icon icon) {
   switch (icon) {
     case DrawableProto::DRAWABLE_ICON_UNDEFINED:
@@ -100,81 +97,6 @@
   }
 }
 
-const std::pair<std::string, std::string> RemoveDarkQualifier(
-    std::string resource_qualifier,
-    std::string url) {
-  if (resource_qualifier.rfind(kNightModePrefix, 0) == 0) {
-    resource_qualifier =
-        resource_qualifier.substr(std::string(kNightModePrefix).length());
-  }
-  return {resource_qualifier, url};
-}
-
-std::map<std::string, std::string> FilterConfigBasedOnDayNightSetting(
-    bool is_dark_mode_enabled,
-    const ConfigBasedUrlProto& url_config) {
-  std::map<std::string, std::string> daynight_specific_config;
-  for (auto config_entry : url_config.url()) {
-    std::string resource_qualifier = config_entry.first;
-    std::string url = config_entry.second;
-    bool dark_mode_qualified =
-        resource_qualifier.rfind(kNightModePrefix, 0) == 0;
-    if (is_dark_mode_enabled == dark_mode_qualified) {
-      daynight_specific_config.insert(
-          RemoveDarkQualifier(resource_qualifier, url));
-    }
-  }
-  std::map<std::string, std::string> dpi_url_config;
-  if (daynight_specific_config.empty()) {
-    for (auto config_entry : url_config.url()) {
-      daynight_specific_config.insert(
-          RemoveDarkQualifier(config_entry.first, config_entry.second));
-    }
-  }
-  return daynight_specific_config;
-}
-
-const std::string GetBitmapImageUrlBasedOnDeviceConfig(
-    JNIEnv* env,
-    const JavaRef<jobject>& jcontext,
-    const ConfigBasedUrlProto& url_config) {
-  bool is_dark_mode_enabled =
-      Java_AssistantDeviceConfig_isDarkModeEnabled(env, jcontext);
-  std::map<std::string, std::string> daynight_specific_config =
-      FilterConfigBasedOnDayNightSetting(is_dark_mode_enabled, url_config);
-
-  // Return image for the device pixel density. If not available, fallback to
-  // mdpi. Caller has to specify mdpi image.
-  std::string device_density = ConvertJavaStringToUTF8(
-      Java_AssistantDeviceConfig_getDevicePixelDensity(env, jcontext));
-  auto pos_it = daynight_specific_config.find(device_density);
-  if (pos_it != daynight_specific_config.end()) {
-    return pos_it->second;
-  }
-  if (daynight_specific_config.find("mdpi") == daynight_specific_config.end()) {
-    return "";
-  }
-  return daynight_specific_config.find("mdpi")->second;
-}
-
-const std::string GetBitmapImageUrl(JNIEnv* env,
-                                    const JavaRef<jobject>& jcontext,
-                                    const BitmapDrawableProto& bitmap) {
-  switch (bitmap.image_url_case()) {
-    case BitmapDrawableProto::ImageUrlCase::kUrl: {
-      return bitmap.url();
-    }
-    case BitmapDrawableProto::ImageUrlCase::kConfigBasedUrl: {
-      return GetBitmapImageUrlBasedOnDeviceConfig(env, jcontext,
-                                                  bitmap.config_based_url());
-    }
-    case BitmapDrawableProto::ImageUrlCase::IMAGE_URL_NOT_SET: {
-      VLOG(1) << "Image url not set in bitmap image request.";
-      return "";
-    }
-  }
-}
-
 }  // namespace
 
 base::android::ScopedJavaLocalRef<jobject> GetJavaColor(
@@ -267,21 +189,14 @@
           env, base::android::ConvertUTF8ToJavaString(
                    env, proto.resource_identifier()));
     case DrawableProto::kBitmap: {
-      std::string url = GetBitmapImageUrl(env, jcontext, proto.bitmap());
-      if (proto.bitmap().use_instrinsic_dimensions()) {
-        return Java_AssistantDrawable_createFromUrlWithIntrinsicDimensions(
-            env, dependencies.CreateImageFetcher(),
-            base::android::ConvertUTF8ToJavaString(env, url));
-      } else {
-        int width_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
-            env, jcontext, proto.bitmap().width(), 0);
-        int height_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
-            env, jcontext, proto.bitmap().height(), 0);
-        return Java_AssistantDrawable_createFromUrl(
-            env, dependencies.CreateImageFetcher(),
-            base::android::ConvertUTF8ToJavaString(env, url), width_pixels,
-            height_pixels);
-      }
+      int width_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
+          env, jcontext, proto.bitmap().width(), 0);
+      int height_pixels = ui_controller_android_utils::GetPixelSizeOrDefault(
+          env, jcontext, proto.bitmap().height(), 0);
+      return Java_AssistantDrawable_createFromUrl(
+          env, dependencies.CreateImageFetcher(),
+          base::android::ConvertUTF8ToJavaString(env, proto.bitmap().url()),
+          width_pixels, height_pixels);
     }
     case DrawableProto::kShape: {
       switch (proto.shape().shape_case()) {
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index cab9551f..b9a67abc 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -3032,13 +3032,9 @@
 }
 
 message InfoBoxProto {
-  oneof image {
-    // Optional path to an image.
-    // This is deprecated and will be removed in M108.
-    string image_path = 1;
-    // Drawable shown in a separate ImageView above TextView.
-    DrawableProto drawable = 4;
-  }
+  // Optional path to an image. Ok tick used if not set.
+  optional string image_path = 1;
+
   // The explanation to show in the box. Not setting this field will clear an
   // existing info box.
   optional string explanation = 2;
diff --git a/components/autofill_assistant/browser/view_layout.proto b/components/autofill_assistant/browser/view_layout.proto
index 5c6138e9..78340a5e 100644
--- a/components/autofill_assistant/browser/view_layout.proto
+++ b/components/autofill_assistant/browser/view_layout.proto
@@ -67,18 +67,10 @@
   optional ColorProto stroke_color = 4;
 }
 
-message ConfigBasedUrlProto {
-  map<string, string> url = 1;
-}
-
 message BitmapDrawableProto {
-  oneof image_url {
-    string url = 1;
-    ConfigBasedUrlProto config_based_url = 4;
-  }
+  optional string url = 1;
   optional ClientDimensionProto width = 2;
   optional ClientDimensionProto height = 3;
-  optional bool use_instrinsic_dimensions = 5;
 }
 
 message FaviconDrawableProto {
diff --git a/components/download/resources/download_internals/BUILD.gn b/components/download/resources/download_internals/BUILD.gn
index d10c80a..6f8a40b 100644
--- a/components/download/resources/download_internals/BUILD.gn
+++ b/components/download/resources/download_internals/BUILD.gn
@@ -2,31 +2,44 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/preprocess_if_expr.gni")
+import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 
-# preprocess for <if expr>.
+ts_files = [
+  "download_internals_browser_proxy.ts",
+  "download_internals_visuals.ts",
+  "download_internals.ts",
+]
+
+preprocess_folder = "${target_gen_dir}/preprocessed"
+
 preprocess_if_expr("preprocess") {
-  in_folder = "./"
-  out_folder = "$target_gen_dir/preprocess"
-  out_manifest = "$target_gen_dir/manifest.json"
-  in_files = [ "download_internals.js" ]
+  in_folder = "."
+  out_folder = preprocess_folder
+  in_files = ts_files
+}
+
+ts_library("build_ts") {
+  root_dir = preprocess_folder
+  out_dir = "$target_gen_dir/tsc"
+  in_files = ts_files
+  deps = [ "//ui/webui/resources:library" ]
+  extra_deps = [ ":preprocess" ]
 }
 
 generate_grd("build_grd") {
   grd_prefix = "download_internals"
   out_grd = "$target_gen_dir/resources.grd"
   input_files = [
-    "download_internals_browser_proxy.js",
     "download_internals.css",
     "download_internals.html",
-    "download_internals_visuals.js",
   ]
   input_files_base_dir = rebase_path(".", "//")
-  deps = [ ":preprocess" ]
-  manifest_files = [ "$target_gen_dir/manifest.json" ]
+  deps = [ ":build_ts" ]
+  manifest_files =
+      filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
 }
 
 grit("resources") {
@@ -43,28 +56,3 @@
   ]
   output_dir = "$root_gen_dir/components"
 }
-
-js_type_check("closure_compile") {
-  deps = [
-    ":download_internals",
-    ":download_internals_browser_proxy",
-    ":download_internals_visuals",
-  ]
-}
-
-js_library("download_internals") {
-  deps = [
-    ":download_internals_browser_proxy",
-    "//third_party/jstemplate:jstemplate",
-    "//ui/webui/resources/js:cr.m",
-    "//ui/webui/resources/js:util.m",
-  ]
-}
-
-js_library("download_internals_browser_proxy") {
-  deps = [ "//ui/webui/resources/js:cr.m" ]
-}
-
-js_library("download_internals_visuals") {
-  deps = [ ":download_internals_browser_proxy" ]
-}
diff --git a/components/download/resources/download_internals/download_internals.js b/components/download/resources/download_internals/download_internals.ts
similarity index 68%
rename from components/download/resources/download_internals/download_internals.js
rename to components/download/resources/download_internals/download_internals.ts
index df1629e..6626fab 100644
--- a/components/download/resources/download_internals/download_internals.js
+++ b/components/download/resources/download_internals/download_internals.ts
@@ -11,23 +11,26 @@
 
 import {DownloadInternalsBrowserProxy, DownloadInternalsBrowserProxyImpl, ServiceEntry, ServiceEntryState, ServiceRequest, ServiceStatus} from './download_internals_browser_proxy.js';
 
-/** @type {!DownloadInternalsBrowserProxy} */
-const browserProxy = DownloadInternalsBrowserProxyImpl.getInstance();
+declare global {
+  class JsEvalContext {
+    constructor(data: any);
+  }
 
-/** @type {!Array<ServiceEntry>} */
-const ongoingServiceEntries = [];
+  function jstProcess(context: JsEvalContext, template: HTMLElement): void;
+}
 
-/** @type {!Array<ServiceEntry>} */
-const finishedServiceEntries = [];
+const browserProxy: DownloadInternalsBrowserProxy =
+    DownloadInternalsBrowserProxyImpl.getInstance();
 
-/** @type {!Array<ServiceRequest>} */
-const serviceRequests = [];
+const ongoingServiceEntries: ServiceEntry[] = [];
+const finishedServiceEntries: ServiceEntry[] = [];
+const serviceRequests: ServiceRequest[] = [];
 
 /**
- * @param {!Array<ServiceEntry>} list A list to remove the entry from.
- * @param {string} guid The guid to remove from the list.
+ * @param list A list to remove the entry from.
+ * @param guid The guid to remove from the list.
  */
-function removeGuidFromList(list, guid) {
+function removeGuidFromList(list: ServiceEntry[], guid: string) {
   const index = list.findIndex(entry => entry.guid == guid);
   if (index != -1) {
     list.splice(index, 1);
@@ -37,10 +40,9 @@
 /**
  * Replaces the ServiceEntry specified by guid in the list or, if it's not
  * found, adds a new entry.
- * @param {!Array<ServiceEntry>} list A list to update.
- * @param {!ServiceEntry} newEntry The new entry.
+ * @param list A list to update.
  */
-function addOrUpdateEntryByGuid(list, newEntry) {
+function addOrUpdateEntryByGuid(list: ServiceEntry[], newEntry: ServiceEntry) {
   const index = list.findIndex(entry => entry.guid == newEntry.guid);
   if (index != -1) {
     list[index] = newEntry;
@@ -58,9 +60,9 @@
 }
 
 /**
- * @param {!ServiceStatus} state The current status of the download service.
+ * @param state The current status of the download service.
  */
-function onServiceStatusChanged(state) {
+function onServiceStatusChanged(state: ServiceStatus) {
   $('service-state').textContent = state.serviceState;
   $('service-status-model').textContent = state.modelStatus;
   $('service-status-driver').textContent = state.driverStatus;
@@ -68,12 +70,11 @@
 }
 
 /**
- * @param {!Array<!ServiceEntry>} entries A list entries currently tracked by
- *     the download service.
+ * @param entries A list entries currently tracked by the download service.
  */
-function onServiceDownloadsAvailable(entries) {
+function onServiceDownloadsAvailable(entries: ServiceEntry[]) {
   for (let i = 0; i < entries.length; i++) {
-    const entry = entries[i];
+    const entry = entries[i]!;
     if (entry.state == ServiceEntryState.COMPLETE) {
       finishedServiceEntries.unshift(entry);
     } else {
@@ -85,10 +86,9 @@
 }
 
 /**
- * @param {!ServiceEntry} entry The new state for a particular download
- *     service entry.
+ * @param entry The new state for a particular download service entry.
  */
-function onServiceDownloadChanged(entry) {
+function onServiceDownloadChanged(entry: ServiceEntry) {
   if (entry.state == ServiceEntryState.COMPLETE) {
     removeGuidFromList(ongoingServiceEntries, entry.guid);
     addOrUpdateEntryByGuid(finishedServiceEntries, entry);
@@ -100,10 +100,9 @@
 }
 
 /**
- * @param {!ServiceEntry} entry The new state for a failed download service
- *     entry.
+ * @param entry The new state for a failed download service entry.
  */
-function onServiceDownloadFailed(entry) {
+function onServiceDownloadFailed(entry: ServiceEntry) {
   removeGuidFromList(ongoingServiceEntries, entry.guid);
   addOrUpdateEntryByGuid(finishedServiceEntries, entry);
 
@@ -111,10 +110,9 @@
 }
 
 /**
- * @param {!ServiceRequest} request The state for a newly issued download
- *     service request.
+ * @param request The state for a newly issued download service request.
  */
-function onServiceRequestMade(request) {
+function onServiceRequestMade(request: ServiceRequest) {
   serviceRequests.unshift(request);
   const input = new JsEvalContext({requests: serviceRequests});
   jstProcess(input, $('download-service-request-info'));
@@ -129,7 +127,7 @@
   addWebUIListener('service-request-made', onServiceRequestMade);
 
   $('start-download').onclick = function() {
-    browserProxy.startDownload($('download-url').value);
+    browserProxy.startDownload(($('download-url') as HTMLInputElement).value);
   };
 
   // Kick off requests for the current system state.
diff --git a/components/download/resources/download_internals/download_internals_browser_proxy.js b/components/download/resources/download_internals/download_internals_browser_proxy.js
deleted file mode 100644
index c35a58b..0000000
--- a/components/download/resources/download_internals/download_internals_browser_proxy.js
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
-
-/**
- * Contains the possible states a ServiceEntry can be in.
- * @enum {string}
- */
-export const ServiceEntryState = {
-  NEW: 'NEW',
-  AVAILABLE: 'AVAILABLE',
-  ACTIVE: 'ACTIVE',
-  PAUSED: 'PAUSED',
-  COMPLETE: 'COMPLETE',
-};
-
-/**
- * Contains the possible states a ServiceEntry's driver can be in.
- * @enum {string}
- */
-export const DriverEntryState = {
-  IN_PROGRESS: 'IN_PROGRESS',
-  COMPLETE: 'COMPLETE',
-  CANCELLED: 'CANCELLED',
-  INTERRUPTED: 'INTERRUPTED',
-};
-
-/**
- * Contains the possible results a ServiceEntry can have.
- * @enum {string}
- */
-export const ServiceEntryResult = {
-  SUCCEED: 'SUCCEED',
-  FAIL: 'FAIL',
-  ABORT: 'ABORT',
-  TIMEOUT: 'TIMEOUT',
-  UNKNOWN: 'UNKNOWN',
-  CANCEL: 'CANCEL',
-  OUT_OF_RETRIES: 'OUT_OF_RETRIES',
-  OUT_OF_RESUMPTIONS: 'OUT_OF_RESUMPTIONS',
-};
-
-/**
- * Contains the possible results of a ServiceRequest.
- * @enum {string}
- */
-export const ServiceRequestResult = {
-  ACCEPTED: 'ACCEPTED',
-  BACKOFF: 'BACKOFF',
-  UNEXPECTED_CLIENT: 'UNEXPECTED_CLIENT',
-  UNEXPECTED_GUID: 'UNEXPECTED_GUID',
-  CLIENT_CANCELLED: 'CLIENT_CANCELLED',
-  INTERNAL_ERROR: 'INTERNAL_ERROR',
-};
-
-/**
- * @typedef {{
- *   serviceState: string,
- *   modelStatus: string,
- *   driverStatus: string,
- *   fileMonitorStatus: string
- * }}
- */
-export let ServiceStatus;
-
-/**
- * @typedef {{
- *   client: string,
- *   guid: string,
- *   state: !ServiceEntryState,
- *   url: string,
- *   bytes_downloaded: number,
- *   time_downloaded: string,
- *   result: (!ServiceEntryResult|undefined),
- *   driver: {
- *     state: !DriverEntryState,
- *     paused: boolean,
- *     done: boolean
- *   }
- * }}
- */
-export let ServiceEntry;
-
-/**
- * @typedef {{
- *   client: string,
- *   guid: string,
- *   result: !ServiceRequestResult
- * }}
- */
-export let ServiceRequest;
-
-/** @interface */
-export class DownloadInternalsBrowserProxy {
-  /**
-   * Gets the current status of the Download Service.
-   * @return {!Promise<ServiceStatus>} A promise firing when the service
-   *     status is fetched.
-   */
-  getServiceStatus() {}
-
-  /**
-   * Gets the current list of downloads the Download Service is aware of.
-   * @return {!Promise<!Array<!ServiceEntry>>} A promise firing when the list
-   *     of downloads is fetched.
-   */
-  getServiceDownloads() {}
-
-  /**
-   * Starts a download with the Download Service.
-   * @param {string} url The download URL.
-   * @return {!Promise}
-   */
-  startDownload(url) {}
-}
-
-/**
- * @implements {DownloadInternalsBrowserProxy}
- */
-export class DownloadInternalsBrowserProxyImpl {
-  /** @override */
-  getServiceStatus() {
-    return sendWithPromise('getServiceStatus');
-  }
-
-  /** @override */
-  getServiceDownloads() {
-    return sendWithPromise('getServiceDownloads');
-  }
-
-  /** @override */
-  startDownload(url) {
-    return sendWithPromise('startDownload', url);
-  }
-}
-
-addSingletonGetter(DownloadInternalsBrowserProxyImpl);
diff --git a/components/download/resources/download_internals/download_internals_browser_proxy.ts b/components/download/resources/download_internals/download_internals_browser_proxy.ts
new file mode 100644
index 0000000..c2fcdd5
--- /dev/null
+++ b/components/download/resources/download_internals/download_internals_browser_proxy.ts
@@ -0,0 +1,123 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+
+/**
+ * Contains the possible states a ServiceEntry can be in.
+ */
+export enum ServiceEntryState {
+  NEW = 'NEW',
+  AVAILABLE = 'AVAILABLE',
+  ACTIVE = 'ACTIVE',
+  PAUSED = 'PAUSED',
+  COMPLETE = 'COMPLETE',
+}
+
+/**
+ * Contains the possible states a ServiceEntry's driver can be in.
+ */
+export enum DriverEntryState {
+  IN_PROGRESS = 'IN_PROGRESS',
+  COMPLETE = 'COMPLETE',
+  CANCELLED = 'CANCELLED',
+  INTERRUPTED = 'INTERRUPTED',
+}
+
+/**
+ * Contains the possible results a ServiceEntry can have.
+ */
+export enum ServiceEntryResult {
+  SUCCEED = 'SUCCEED',
+  FAIL = 'FAIL',
+  ABORT = 'ABORT',
+  TIMEOUT = 'TIMEOUT',
+  UNKNOWN = 'UNKNOWN',
+  CANCEL = 'CANCEL',
+  OUT_OF_RETRIES = 'OUT_OF_RETRIES',
+  OUT_OF_RESUMPTIONS = 'OUT_OF_RESUMPTIONS',
+}
+
+/**
+ * Contains the possible results of a ServiceRequest.
+ */
+export enum ServiceRequestResult {
+  ACCEPTED = 'ACCEPTED',
+  BACKOFF = 'BACKOFF',
+  UNEXPECTED_CLIENT = 'UNEXPECTED_CLIENT',
+  UNEXPECTED_GUID = 'UNEXPECTED_GUID',
+  CLIENT_CANCELLED = 'CLIENT_CANCELLED',
+  INTERNAL_ERROR = 'INTERNAL_ERROR',
+}
+
+export type ServiceStatus = {
+  serviceState: string,
+  modelStatus: string,
+  driverStatus: string,
+  fileMonitorStatus: string,
+};
+
+export type ServiceEntry = {
+  client: string,
+  guid: string,
+  state: ServiceEntryState,
+  url: string,
+  bytes_downloaded: number,
+  time_downloaded: string,
+  result?: ServiceEntryResult, driver: {
+    state: DriverEntryState,
+    paused: boolean,
+    done: boolean,
+  },
+};
+
+export type ServiceRequest = {
+  client: string,
+  guid: string,
+  result: ServiceRequestResult,
+};
+
+export interface DownloadInternalsBrowserProxy {
+  /**
+   * Gets the current status of the Download Service.
+   * @return A promise firing when the service status is fetched.
+   */
+  getServiceStatus(): Promise<ServiceStatus>;
+
+  /**
+   * Gets the current list of downloads the Download Service is aware of.
+   * @return A promise firing when the list of downloads is fetched.
+   */
+  getServiceDownloads(): Promise<ServiceEntry[]>;
+
+  /**
+   * Starts a download with the Download Service.
+   */
+  startDownload(url: string): Promise<void>;
+}
+
+export class DownloadInternalsBrowserProxyImpl implements
+    DownloadInternalsBrowserProxy {
+  getServiceStatus() {
+    return sendWithPromise('getServiceStatus');
+  }
+
+  getServiceDownloads() {
+    return sendWithPromise('getServiceDownloads');
+  }
+
+  startDownload(url: string) {
+    return sendWithPromise('startDownload', url);
+  }
+
+  static getInstance(): DownloadInternalsBrowserProxy {
+    return instance || (instance = new DownloadInternalsBrowserProxyImpl());
+  }
+
+  static setInstance(obj: DownloadInternalsBrowserProxy) {
+    instance = obj;
+  }
+}
+
+let instance: DownloadInternalsBrowserProxy|null = null;
diff --git a/components/download/resources/download_internals/download_internals_visuals.js b/components/download/resources/download_internals/download_internals_visuals.ts
similarity index 69%
rename from components/download/resources/download_internals/download_internals_visuals.js
rename to components/download/resources/download_internals/download_internals_visuals.ts
index 51d3732..25e3bfa 100644
--- a/components/download/resources/download_internals/download_internals_visuals.js
+++ b/components/download/resources/download_internals/download_internals_visuals.ts
@@ -2,13 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {DriverEntryState, ServiceEntryResult, ServiceEntryState, ServiceRequestResult} from './download_internals_browser_proxy.js';
+import {DriverEntryState, ServiceEntry, ServiceEntryResult, ServiceEntryState, ServiceRequest, ServiceRequestResult} from './download_internals_browser_proxy.js';
 
-// Expose these on |window| because they need to be accessed by jstemplate code
-// in download_internals.html
-window.downloadInternalsVisuals = {};
-
-function getOngoingServiceEntryClass(entry) {
+function getOngoingServiceEntryClass(entry: ServiceEntry) {
   switch (entry.state) {
     case ServiceEntryState.NEW:
       return 'service-entry-new';
@@ -29,10 +25,8 @@
       return '';
   }
 }
-window.downloadInternalsVisuals.getOngoingServiceEntryClass =
-    getOngoingServiceEntryClass;
 
-function getFinishedServiceEntryClass(entry) {
+function getFinishedServiceEntryClass(entry: ServiceEntry) {
   switch (entry.result) {
     case ServiceEntryResult.SUCCEED:
       return 'service-entry-success';
@@ -40,10 +34,8 @@
       return 'service-entry-fail';
   }
 }
-window.downloadInternalsVisuals.getFinishedServiceEntryClass =
-    getFinishedServiceEntryClass;
 
-function getServiceRequestClass(request) {
+function getServiceRequestClass(request: ServiceRequest) {
   switch (request.result) {
     case ServiceRequestResult.ACCEPTED:
       return 'service-entry-success';
@@ -54,4 +46,13 @@
       return 'service-entry-fail';
   }
 }
-window.downloadInternalsVisuals.getServiceRequestClass = getServiceRequestClass;
+
+// Expose these on |window| because they need to be accessed by jstemplate code
+// in download_internals.html
+Object.assign(window, {
+  downloadInternalsVisuals: {
+    getServiceRequestClass,
+    getFinishedServiceEntryClass,
+    getOngoingServiceEntryClass,
+  },
+});
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index 8baf9a5..2668f5b 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -736,7 +736,7 @@
 
 // If the current platform has a directly accesible network diagnostics tool and
 // the URL is valid add a suggestion.
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
   if (IsOnlySuggestion(suggestions, SUGGEST_DIAGNOSE_TOOL)) {
     int diagose_message_id =
         error_code == error_page::DNS_PROBE_FINISHED_NXDOMAIN
@@ -753,7 +753,7 @@
   }
 #else
   DCHECK(!IsSuggested(suggestions, SUGGEST_DIAGNOSE_TOOL));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
 
   // Add list prefix header.
   error_strings.Set(
diff --git a/components/error_page_strings.grdp b/components/error_page_strings.grdp
index 70c4a90a7..960025aa 100644
--- a/components/error_page_strings.grdp
+++ b/components/error_page_strings.grdp
@@ -361,7 +361,7 @@
       If spelling is correct, <ph name="BEGIN_LINK">&lt;a href="javascript:diagnoseErrors()" id="diagnose-link"&gt;</ph>try running Windows Network Diagnostics<ph name="END_LINK">&lt;/a&gt;</ph>.
     </message>
   </if>
-  <if expr="chromeos_ash">
+  <if expr="chromeos_ash or chromeos_lacros">
     <message name="IDS_ERRORPAGES_SUGGESTION_DIAGNOSE" desc="Label for the link that invokes the connection diagnostic tool on the error page displayed in a list of suggestions. The suggestions list is prefixed with 'Try:'.">
       <ph name="BEGIN_LINK">&lt;a href="javascript:diagnoseErrors()" id="diagnose-link"&gt;</ph>Running Connectivity Diagnostics<ph name="END_LINK">&lt;/a&gt;</ph>
     </message>
diff --git a/components/fullscreen_control_strings.grdp b/components/fullscreen_control_strings.grdp
index 95f0561..82a8f59 100644
--- a/components/fullscreen_control_strings.grdp
+++ b/components/fullscreen_control_strings.grdp
@@ -18,4 +18,7 @@
   <message name="IDS_PRESS_TO_EXIT_MOUSELOCK_TWO_KEYS" desc="Text displayed in the bubble to tell users how to escape from mouselock mode (where the mouse cursor is hidden) by activating ChromeOS's Overview mode, in the case where two keys must be pressed together. Please surround the names of the keys (e.g. 'Overview') in pipe characters so it can be rendered as a key.">
     Press |<ph name="ACCELERATOR1">$1<ex>Search</ex></ph>| + |<ph name="ACCELERATOR2">$2<ex>Overview</ex></ph>| to show your cursor
   </message>
+  <message name="IDS_FULLSCREEN_PRESS_TO_SEE_DOWNLOADS" desc="Text displayed in the bubble to tell users that they need to go to normal mode to see Downloads. Please surround the name of the key (e.g. 'Esc') in pipe characters so it can be rendered as a key.">
+    Download started. To see it, press |<ph name="ACCELERATOR">$1<ex>Esc</ex></ph>|.
+  </message>
 </grit-part>
diff --git a/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_PRESS_TO_SEE_DOWNLOADS.png.sha1 b/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_PRESS_TO_SEE_DOWNLOADS.png.sha1
new file mode 100644
index 0000000..a91f449
--- /dev/null
+++ b/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_PRESS_TO_SEE_DOWNLOADS.png.sha1
@@ -0,0 +1 @@
+dafbed225d745b44ba1bf74f7e7c1b46b6178a03
\ No newline at end of file
diff --git a/components/gcm_driver/gcm_internals_helper.cc b/components/gcm_driver/gcm_internals_helper.cc
index 6b360d6..ffb8121 100644
--- a/components/gcm_driver/gcm_internals_helper.cc
+++ b/components/gcm_driver/gcm_internals_helper.cc
@@ -22,169 +22,173 @@
 
 namespace {
 
-void SetCheckinInfo(const std::vector<gcm::CheckinActivity>& checkins,
-                    std::vector<base::Value>* checkin_info) {
+base::Value::List CheckinInfoToList(
+    const std::vector<gcm::CheckinActivity>& checkins) {
+  base::Value::List checkin_info;
   for (const gcm::CheckinActivity& checkin : checkins) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(checkin.time.ToJsTime());
     row.Append(checkin.event);
     row.Append(checkin.details);
-    checkin_info->push_back(std::move(row));
+    checkin_info.Append(std::move(row));
   }
+  return checkin_info;
 }
 
-void SetConnectionInfo(const std::vector<gcm::ConnectionActivity>& connections,
-                       std::vector<base::Value>* connection_info) {
+base::Value::List ConnectionInfoToList(
+    const std::vector<gcm::ConnectionActivity>& connections) {
+  base::Value::List connection_info;
   for (const gcm::ConnectionActivity& connection : connections) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(connection.time.ToJsTime());
     row.Append(connection.event);
     row.Append(connection.details);
-    connection_info->push_back(std::move(row));
+    connection_info.Append(std::move(row));
   }
+  return connection_info;
 }
 
-void SetRegistrationInfo(
-    const std::vector<gcm::RegistrationActivity>& registrations,
-    std::vector<base::Value>* registration_info) {
+base::Value::List RegistrationInfoToList(
+    const std::vector<gcm::RegistrationActivity>& registrations) {
+  base::Value::List registration_info;
   for (const gcm::RegistrationActivity& registration : registrations) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(registration.time.ToJsTime());
     row.Append(registration.app_id);
     row.Append(registration.source);
     row.Append(registration.event);
     row.Append(registration.details);
-    registration_info->push_back(std::move(row));
+    registration_info.Append(std::move(row));
   }
+  return registration_info;
 }
 
-void SetReceivingInfo(const std::vector<gcm::ReceivingActivity>& receives,
-                      std::vector<base::Value>* receive_info) {
+base::Value::List ReceivingInfoToList(
+    const std::vector<gcm::ReceivingActivity>& receives) {
+  base::Value::List receive_info;
   for (const gcm::ReceivingActivity& receive : receives) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(receive.time.ToJsTime());
     row.Append(receive.app_id);
     row.Append(receive.from);
     row.Append(base::NumberToString(receive.message_byte_size));
     row.Append(receive.event);
     row.Append(receive.details);
-    receive_info->push_back(std::move(row));
+    receive_info.Append(std::move(row));
   }
+  return receive_info;
 }
 
-void SetSendingInfo(const std::vector<gcm::SendingActivity>& sends,
-                    std::vector<base::Value>* send_info) {
+base::Value::List SendingInfoToList(
+    const std::vector<gcm::SendingActivity>& sends) {
+  base::Value::List send_info;
   for (const gcm::SendingActivity& send : sends) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(send.time.ToJsTime());
     row.Append(send.app_id);
     row.Append(send.receiver_id);
     row.Append(send.message_id);
     row.Append(send.event);
     row.Append(send.details);
-    send_info->push_back(std::move(row));
+    send_info.Append(std::move(row));
   }
+  return send_info;
 }
 
-void SetDecryptionFailureInfo(
-    const std::vector<gcm::DecryptionFailureActivity>& failures,
-    std::vector<base::Value>* failure_info) {
+base::Value::List DecryptionFailureInfoToList(
+    const std::vector<gcm::DecryptionFailureActivity>& failures) {
+  base::Value::List failure_info;
   for (const gcm::DecryptionFailureActivity& failure : failures) {
-    base::Value row(base::Value::Type::LIST);
+    base::Value::List row;
     row.Append(failure.time.ToJsTime());
     row.Append(failure.app_id);
     row.Append(failure.details);
-    failure_info->push_back(std::move(row));
+    failure_info.Append(std::move(row));
   }
+  return failure_info;
 }
 
 }  // namespace
 
-void SetGCMInternalsInfo(const gcm::GCMClient::GCMStatistics* stats,
-                         gcm::GCMProfileService* profile_service,
-                         PrefService* prefs,
-                         base::DictionaryValue* results) {
-  base::Value device_info(base::Value::Type::DICTIONARY);
+base::Value SetGCMInternalsInfo(const gcm::GCMClient::GCMStatistics* stats,
+                                gcm::GCMProfileService* profile_service,
+                                PrefService* prefs) {
+  base::Value::Dict results;
 
-  device_info.SetBoolKey(kProfileServiceCreated, profile_service != nullptr);
-  device_info.SetBoolKey(kGcmEnabled, true);
   if (stats) {
-    results->SetBoolKey(kIsRecording, stats->is_recording);
-    device_info.SetBoolKey(kGcmClientCreated, stats->gcm_client_created);
-    device_info.SetStringKey(kGcmClientState, stats->gcm_client_state);
-    device_info.SetBoolKey(kConnectionClientCreated,
-                           stats->connection_client_created);
+    results.Set(kIsRecording, stats->is_recording);
 
-    base::Value registered_app_ids(base::Value::Type::LIST);
+    base::Value::Dict device_info;
+    device_info.Set(kProfileServiceCreated, profile_service != nullptr);
+    device_info.Set(kGcmEnabled, true);
+    device_info.Set(kGcmClientCreated, stats->gcm_client_created);
+    device_info.Set(kGcmClientState, stats->gcm_client_state);
+    device_info.Set(kConnectionClientCreated, stats->connection_client_created);
+
+    base::Value::List registered_app_ids;
     for (const std::string& app_id : stats->registered_app_ids)
       registered_app_ids.Append(app_id);
 
-    device_info.SetKey(kRegisteredAppIds, std::move(registered_app_ids));
+    device_info.Set(kRegisteredAppIds, std::move(registered_app_ids));
 
     if (stats->connection_client_created)
-      device_info.SetStringKey(kConnectionState, stats->connection_state);
+      device_info.Set(kConnectionState, stats->connection_state);
     if (!stats->last_checkin.is_null()) {
-      device_info.SetStringKey(
-          kLastCheckin, base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                            stats->last_checkin)));
+      device_info.Set(kLastCheckin,
+                      base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                          stats->last_checkin)));
     }
     if (!stats->next_checkin.is_null()) {
-      device_info.SetStringKey(
-          kNextCheckin, base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
-                            stats->next_checkin)));
+      device_info.Set(kNextCheckin,
+                      base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
+                          stats->next_checkin)));
     }
     if (stats->android_id > 0) {
-      device_info.SetStringKey(
-          kAndroidId, base::StringPrintf("0x%" PRIx64, stats->android_id));
+      device_info.Set(kAndroidId,
+                      base::StringPrintf("0x%" PRIx64, stats->android_id));
     }
     if (stats->android_secret > 0) {
-      device_info.SetStringKey(kAndroidSecret,
-                               base::NumberToString(stats->android_secret));
+      device_info.Set(kAndroidSecret,
+                      base::NumberToString(stats->android_secret));
     }
-    device_info.SetIntKey(kSendQueueSize, stats->send_queue_size);
-    device_info.SetIntKey(kResendQueueSize, stats->resend_queue_size);
-    results->SetKey(kDeviceInfo, std::move(device_info));
+    device_info.Set(kSendQueueSize, stats->send_queue_size);
+    device_info.Set(kResendQueueSize, stats->resend_queue_size);
+    results.Set(kDeviceInfo, std::move(device_info));
 
     if (stats->recorded_activities.checkin_activities.size() > 0) {
-      std::vector<base::Value> checkin_info;
-      SetCheckinInfo(stats->recorded_activities.checkin_activities,
-                     &checkin_info);
-      results->SetKey(kCheckinInfo, base::Value(std::move(checkin_info)));
+      results.Set(
+          kCheckinInfo,
+          CheckinInfoToList(stats->recorded_activities.checkin_activities));
     }
     if (stats->recorded_activities.connection_activities.size() > 0) {
-      std::vector<base::Value> connection_info;
-      SetConnectionInfo(stats->recorded_activities.connection_activities,
-                        &connection_info);
-      results->SetKey(kConnectionInfo, base::Value(std::move(connection_info)));
+      results.Set(kConnectionInfo,
+                  ConnectionInfoToList(
+                      stats->recorded_activities.connection_activities));
     }
     if (stats->recorded_activities.registration_activities.size() > 0) {
-      std::vector<base::Value> registration_info;
-      SetRegistrationInfo(stats->recorded_activities.registration_activities,
-                          &registration_info);
-      results->SetKey(kRegistrationInfo,
-                      base::Value(std::move(registration_info)));
+      results.Set(kRegistrationInfo,
+                  RegistrationInfoToList(
+                      stats->recorded_activities.registration_activities));
     }
     if (stats->recorded_activities.receiving_activities.size() > 0) {
-      std::vector<base::Value> receive_info;
-      SetReceivingInfo(stats->recorded_activities.receiving_activities,
-                       &receive_info);
-      results->SetKey(kReceiveInfo, base::Value(std::move(receive_info)));
+      results.Set(
+          kReceiveInfo,
+          ReceivingInfoToList(stats->recorded_activities.receiving_activities));
     }
     if (stats->recorded_activities.sending_activities.size() > 0) {
-      std::vector<base::Value> send_info;
-      SetSendingInfo(stats->recorded_activities.sending_activities, &send_info);
-      results->SetKey(kSendInfo, base::Value(std::move(send_info)));
+      results.Set(
+          kSendInfo,
+          SendingInfoToList(stats->recorded_activities.sending_activities));
     }
 
     if (stats->recorded_activities.decryption_failure_activities.size() > 0) {
-      std::vector<base::Value> failure_info;
-      SetDecryptionFailureInfo(
-          stats->recorded_activities.decryption_failure_activities,
-          &failure_info);
-      results->SetKey(kDecryptionFailureInfo,
-                      base::Value(std::move(failure_info)));
+      results.Set(
+          kDecryptionFailureInfo,
+          DecryptionFailureInfoToList(
+              stats->recorded_activities.decryption_failure_activities));
     }
   }
+  return base::Value(std::move(results));
 }
 
 }  // namespace gcm_driver
diff --git a/components/gcm_driver/gcm_internals_helper.h b/components/gcm_driver/gcm_internals_helper.h
index 1ea48b2..35626ba 100644
--- a/components/gcm_driver/gcm_internals_helper.h
+++ b/components/gcm_driver/gcm_internals_helper.h
@@ -5,25 +5,21 @@
 #ifndef COMPONENTS_GCM_DRIVER_GCM_INTERNALS_HELPER_H_
 #define COMPONENTS_GCM_DRIVER_GCM_INTERNALS_HELPER_H_
 
+#include "base/values.h"
 #include "components/gcm_driver/gcm_client.h"
 
 class PrefService;
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace gcm {
 class GCMProfileService;
 }
 
 namespace gcm_driver {
 
-// Sets the GCM infos for the gcm-internals WebUI in |results|.
-void SetGCMInternalsInfo(const gcm::GCMClient::GCMStatistics* stats,
-                         gcm::GCMProfileService* profile_service,
-                         PrefService* prefs,
-                         base::DictionaryValue* results);
+// Returns the GCM infos for the gcm-internals WebUI.
+base::Value SetGCMInternalsInfo(const gcm::GCMClient::GCMStatistics* stats,
+                                gcm::GCMProfileService* profile_service,
+                                PrefService* prefs);
 
 }  // namespace gcm_driver
 
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
index 8cdfc3e..408c9c71 100644
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -181,7 +181,7 @@
 
 GuestViewBase::~GuestViewBase() {}
 
-void GuestViewBase::Init(const base::DictionaryValue& create_params,
+void GuestViewBase::Init(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) {
   if (initialized_)
     return;
@@ -195,16 +195,14 @@
     return;
   }
 
-  std::unique_ptr<base::DictionaryValue> params(create_params.DeepCopy());
   CreateWebContents(create_params,
                     base::BindOnce(&GuestViewBase::CompleteInit,
                                    weak_ptr_factory_.GetWeakPtr(),
-                                   std::move(params), std::move(callback)));
+                                   create_params.Clone(), std::move(callback)));
 }
 
-void GuestViewBase::InitWithWebContents(
-    const base::DictionaryValue& create_params,
-    WebContents* guest_web_contents) {
+void GuestViewBase::InitWithWebContents(const base::Value::Dict& create_params,
+                                        WebContents* guest_web_contents) {
   DCHECK(guest_web_contents);
 
   // Create a ZoomController to allow the guest's contents to be zoomed.
@@ -231,8 +229,8 @@
   GetGuestViewManager()->AddGuest(guest_instance_id_, guest_web_contents);
 
   // Populate the view instance ID if we have it on creation.
-  view_instance_id_ = create_params.FindIntKey(kParameterInstanceId)
-                          .value_or(view_instance_id_);
+  view_instance_id_ =
+      create_params.FindInt(kParameterInstanceId).value_or(view_instance_id_);
 
   SetUpSizing(create_params);
 
@@ -400,7 +398,7 @@
 
   opener_lifetime_observer_.reset();
 
-  SetUpSizing(*attach_params());
+  SetUpSizing(attach_params());
 
   // The guest should have the same muting state as the owner.
   web_contents()->SetAudioMuted(owner_web_contents()->IsAudioMuted());
@@ -460,10 +458,10 @@
     delete web_contents();
 }
 
-void GuestViewBase::SetAttachParams(const base::DictionaryValue& params) {
-  attach_params_.reset(params.DeepCopy());
-  view_instance_id_ = attach_params_->FindIntKey(kParameterInstanceId)
-                          .value_or(view_instance_id_);
+void GuestViewBase::SetAttachParams(const base::Value::Dict& params) {
+  attach_params_ = params.Clone();
+  view_instance_id_ =
+      attach_params_.FindInt(kParameterInstanceId).value_or(view_instance_id_);
 }
 
 void GuestViewBase::SetOpener(GuestViewBase* guest) {
@@ -793,10 +791,9 @@
   }
 }
 
-void GuestViewBase::CompleteInit(
-    std::unique_ptr<base::DictionaryValue> create_params,
-    WebContentsCreatedCallback callback,
-    WebContents* guest_web_contents) {
+void GuestViewBase::CompleteInit(base::Value::Dict create_params,
+                                 WebContentsCreatedCallback callback,
+                                 WebContents* guest_web_contents) {
   if (!guest_web_contents) {
     // The derived class did not create a WebContents so this class serves no
     // purpose. Let's self-destruct.
@@ -804,7 +801,7 @@
     std::move(callback).Run(nullptr);
     return;
   }
-  InitWithWebContents(*create_params, guest_web_contents);
+  InitWithWebContents(create_params, guest_web_contents);
   std::move(callback).Run(guest_web_contents);
 }
 
@@ -817,24 +814,24 @@
           embedder_web_contents()));
 }
 
-void GuestViewBase::SetUpSizing(const base::DictionaryValue& params) {
+void GuestViewBase::SetUpSizing(const base::Value::Dict& params) {
   // Read the autosize parameters passed in from the embedder.
   absl::optional<bool> auto_size_enabled_opt =
-      params.FindBoolKey(kAttributeAutoSize);
+      params.FindBool(kAttributeAutoSize);
   bool auto_size_enabled = auto_size_enabled_opt.value_or(auto_size_enabled_);
 
   int max_height =
-      params.FindIntKey(kAttributeMaxHeight).value_or(max_auto_size_.height());
+      params.FindInt(kAttributeMaxHeight).value_or(max_auto_size_.height());
   int max_width =
-      params.FindIntKey(kAttributeMaxWidth).value_or(max_auto_size_.width());
+      params.FindInt(kAttributeMaxWidth).value_or(max_auto_size_.width());
 
   int min_height =
-      params.FindIntKey(kAttributeMinHeight).value_or(min_auto_size_.height());
+      params.FindInt(kAttributeMinHeight).value_or(min_auto_size_.height());
   int min_width =
-      params.FindIntKey(kAttributeMinWidth).value_or(min_auto_size_.width());
+      params.FindInt(kAttributeMinWidth).value_or(min_auto_size_.width());
 
-  double element_height = params.FindDoublePath(kElementHeight).value_or(0.0);
-  double element_width = params.FindDoublePath(kElementWidth).value_or(0.0);
+  double element_height = params.FindDouble(kElementHeight).value_or(0.0);
+  double element_width = params.FindDouble(kElementWidth).value_or(0.0);
 
   // Set the normal size to the element size so that the guestview will fit
   // the element initially if autosize is disabled.
@@ -843,7 +840,7 @@
   // If the element size was provided in logical units (versus physical), then
   // it will be converted to physical units.
   absl::optional<bool> element_size_is_logical_opt =
-      params.FindBoolKey(kElementSizeIsLogical);
+      params.FindBool(kElementSizeIsLogical);
   bool element_size_is_logical = element_size_is_logical_opt.value_or(false);
   if (element_size_is_logical) {
     // Convert the element size from logical pixels to physical pixels.
diff --git a/components/guest_view/browser/guest_view_base.h b/components/guest_view/browser/guest_view_base.h
index c6dc516..bdfecfa 100644
--- a/components/guest_view/browser/guest_view_base.h
+++ b/components/guest_view/browser/guest_view_base.h
@@ -116,10 +116,10 @@
   // newly created WebContents.
   using WebContentsCreatedCallback =
       base::OnceCallback<void(content::WebContents*)>;
-  void Init(const base::DictionaryValue& create_params,
+  void Init(const base::Value::Dict& create_params,
             WebContentsCreatedCallback callback);
 
-  void InitWithWebContents(const base::DictionaryValue& create_params,
+  void InitWithWebContents(const base::Value::Dict& create_params,
                            content::WebContents* guest_web_contents);
 
   // Used to toggle autosize mode for this GuestView, and set both the automatic
@@ -138,7 +138,7 @@
 
   // Returns the parameters associated with the element hosting this GuestView
   // passed in from JavaScript.
-  base::DictionaryValue* attach_params() const { return attach_params_.get(); }
+  const base::Value::Dict& attach_params() const { return attach_params_; }
 
   // Returns whether this guest has an associated embedder.
   bool attached() const {
@@ -187,7 +187,7 @@
   virtual bool ShouldDestroyOnDetach() const;
 
   // Saves the attach state of the custom element hosting this GuestView.
-  void SetAttachParams(const base::DictionaryValue& params);
+  void SetAttachParams(const base::Value::Dict& params);
 
   // Returns the RenderWidgetHost corresponding to the owner frame.
   virtual content::RenderWidgetHost* GetOwnerRenderWidgetHost();
@@ -241,7 +241,7 @@
   // Given a set of initialization parameters, a concrete subclass of
   // GuestViewBase can create a specialized WebContents that it returns back to
   // GuestViewBase.
-  virtual void CreateWebContents(const base::DictionaryValue& create_params,
+  virtual void CreateWebContents(const base::Value::Dict& create_params,
                                  WebContentsCreatedCallback callback) = 0;
 
   // This method is called after the guest has been attached to an embedder and
@@ -255,7 +255,7 @@
   //
   // This gives the derived class an opportunity to perform additional
   // initialization.
-  virtual void DidInitialize(const base::DictionaryValue& create_params) {}
+  virtual void DidInitialize(const base::Value::Dict& create_params) {}
 
   // This method is called when embedder WebContents's fullscreen is toggled.
   //
@@ -376,7 +376,7 @@
 
   void SendQueuedEvents();
 
-  void CompleteInit(std::unique_ptr<base::DictionaryValue> create_params,
+  void CompleteInit(base::Value::Dict create_params,
                     WebContentsCreatedCallback callback,
                     content::WebContents* guest_web_contents);
 
@@ -390,7 +390,7 @@
   // Get the zoom factor for the embedder's web contents.
   double GetEmbedderZoomFactor() const;
 
-  void SetUpSizing(const base::DictionaryValue& params);
+  void SetUpSizing(const base::Value::Dict& params);
 
   void StartTrackingEmbedderZoomLevel();
   void StopTrackingEmbedderZoomLevel();
@@ -454,7 +454,7 @@
   // are passed in from JavaScript. This will typically be the view instance ID,
   // and element-specific parameters. These parameters are passed along to new
   // guests that are created from this guest.
-  std::unique_ptr<base::DictionaryValue> attach_params_;
+  base::Value::Dict attach_params_;
 
   // This observer ensures that this guest self-destructs if the embedder goes
   // away. It also tracks when the embedder's fullscreen is toggled so the guest
diff --git a/components/guest_view/browser/guest_view_manager.cc b/components/guest_view/browser/guest_view_manager.cc
index 167aa21..c5d3a2a 100644
--- a/components/guest_view/browser/guest_view_manager.cc
+++ b/components/guest_view/browser/guest_view_manager.cc
@@ -129,7 +129,7 @@
 void GuestViewManager::AttachGuest(int embedder_process_id,
                                    int element_instance_id,
                                    int guest_instance_id,
-                                   const base::DictionaryValue& attach_params) {
+                                   const base::Value::Dict& attach_params) {
   auto* guest_view =
       GuestViewBase::From(embedder_process_id, guest_instance_id);
   if (!guest_view)
@@ -180,7 +180,7 @@
 
 void GuestViewManager::CreateGuest(const std::string& view_type,
                                    content::WebContents* owner_web_contents,
-                                   const base::DictionaryValue& create_params,
+                                   const base::Value::Dict& create_params,
                                    WebContentsCreatedCallback callback) {
   GuestViewBase* guest = CreateGuestInternal(owner_web_contents, view_type);
   if (!guest) {
@@ -204,7 +204,7 @@
   // https://crbug.com/832879.
   std::unique_ptr<content::WebContents> guest_web_contents =
       WebContents::Create(guest_create_params);
-  guest->InitWithWebContents(base::DictionaryValue(), guest_web_contents.get());
+  guest->InitWithWebContents(base::Value::Dict(), guest_web_contents.get());
   return guest_web_contents.release();
 }
 
diff --git a/components/guest_view/browser/guest_view_manager.h b/components/guest_view/browser/guest_view_manager.h
index 105ce7af..2f5931c 100644
--- a/components/guest_view/browser/guest_view_manager.h
+++ b/components/guest_view/browser/guest_view_manager.h
@@ -13,13 +13,10 @@
 #include "base/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/values.h"
 #include "content/public/browser/browser_plugin_guest_manager.h"
 #include "content/public/browser/web_contents.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace content {
 class BrowserContext;
 class SiteInstance;
@@ -72,7 +69,7 @@
   virtual void AttachGuest(int embedder_process_id,
                            int element_instance_id,
                            int guest_instance_id,
-                           const base::DictionaryValue& attach_params);
+                           const base::Value::Dict& attach_params);
 
   // Removes the association between |element_instance_id| and a guest instance
   // ID if one exists.
@@ -113,7 +110,7 @@
       base::OnceCallback<void(content::WebContents*)>;
   void CreateGuest(const std::string& view_type,
                    content::WebContents* owner_web_contents,
-                   const base::DictionaryValue& create_params,
+                   const base::Value::Dict& create_params,
                    WebContentsCreatedCallback callback);
 
   content::WebContents* CreateGuestWithWebContentsParams(
diff --git a/components/guest_view/browser/guest_view_message_handler.cc b/components/guest_view/browser/guest_view_message_handler.cc
index ff68f8a..cf2cf24 100644
--- a/components/guest_view/browser/guest_view_message_handler.cc
+++ b/components/guest_view/browser/guest_view_message_handler.cc
@@ -77,7 +77,7 @@
     int embedder_local_render_frame_id,
     int element_instance_id,
     int guest_instance_id,
-    base::Value params,
+    base::Value::Dict params,
     AttachToEmbedderFrameCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!GetBrowserContext()) {
@@ -113,8 +113,7 @@
   // This sets up the embedder and guest pairing information inside
   // the manager.
   manager->AttachGuest(render_process_id(), element_instance_id,
-                       guest_instance_id,
-                       base::Value::AsDictionaryValue(params));
+                       guest_instance_id, params);
 
   const bool changed_owner_web_contents =
       owner_web_contents !=
diff --git a/components/guest_view/browser/guest_view_message_handler.h b/components/guest_view/browser/guest_view_message_handler.h
index 6ff5fba..45ec183 100644
--- a/components/guest_view/browser/guest_view_message_handler.h
+++ b/components/guest_view/browser/guest_view_message_handler.h
@@ -10,6 +10,7 @@
 
 #include <string>
 
+#include "base/values.h"
 #include "components/guest_view/common/guest_view.mojom.h"
 
 namespace content {
@@ -51,7 +52,7 @@
   void AttachToEmbedderFrame(int embedder_local_render_frame_id,
                              int element_instance_id,
                              int guest_instance_id,
-                             base::Value params,
+                             base::Value::Dict params,
                              AttachToEmbedderFrameCallback callback) override;
   void ViewCreated(int view_instance_id, const std::string& view_type) override;
   void ViewGarbageCollected(int view_instance_id) override;
diff --git a/components/guest_view/browser/test_guest_view_manager.cc b/components/guest_view/browser/test_guest_view_manager.cc
index e81907e2..c117d51 100644
--- a/components/guest_view/browser/test_guest_view_manager.cc
+++ b/components/guest_view/browser/test_guest_view_manager.cc
@@ -128,11 +128,10 @@
     num_created_message_loop_runner_->Quit();
 }
 
-void TestGuestViewManager::AttachGuest(
-    int embedder_process_id,
-    int element_instance_id,
-    int guest_instance_id,
-    const base::DictionaryValue& attach_params) {
+void TestGuestViewManager::AttachGuest(int embedder_process_id,
+                                       int element_instance_id,
+                                       int guest_instance_id,
+                                       const base::Value::Dict& attach_params) {
   GuestViewManager::AttachGuest(embedder_process_id, element_instance_id,
                                 guest_instance_id, attach_params);
 
diff --git a/components/guest_view/browser/test_guest_view_manager.h b/components/guest_view/browser/test_guest_view_manager.h
index 46e8da6..5abf47e 100644
--- a/components/guest_view/browser/test_guest_view_manager.h
+++ b/components/guest_view/browser/test_guest_view_manager.h
@@ -94,7 +94,7 @@
   void AttachGuest(int embedder_process_id,
                    int element_instance_id,
                    int guest_instance_id,
-                   const base::DictionaryValue& attach_params) override;
+                   const base::Value::Dict& attach_params) override;
 
   void WaitForViewGarbageCollected();
 
diff --git a/components/guest_view/common/guest_view.mojom b/components/guest_view/common/guest_view.mojom
index cf98794c..8929e45 100644
--- a/components/guest_view/common/guest_view.mojom
+++ b/components/guest_view/common/guest_view.mojom
@@ -18,7 +18,7 @@
       int32 embedder_local_frame_routing_id,
       int32 element_instance_id,
       int32 guest_instance_id,
-      mojo_base.mojom.DeprecatedDictionaryValue params) => ();
+      mojo_base.mojom.DictionaryValue params) => ();
 
   // Sent by the renderer when a GuestView (identified by |view_instance_id|)
   // has been created in JavaScript.
diff --git a/components/guest_view/renderer/guest_view_request.cc b/components/guest_view/renderer/guest_view_request.cc
index ad6b412..8b58642 100644
--- a/components/guest_view/renderer/guest_view_request.cc
+++ b/components/guest_view/renderer/guest_view_request.cc
@@ -41,7 +41,7 @@
     guest_view::GuestViewContainer* container,
     int render_frame_routing_id,
     int guest_instance_id,
-    std::unique_ptr<base::DictionaryValue> params,
+    base::Value::Dict params,
     v8::Local<v8::Function> callback,
     v8::Isolate* isolate)
     : container_(container),
@@ -56,7 +56,7 @@
 void GuestViewAttachRequest::PerformRequest() {
   GetGuestViewHost()->AttachToEmbedderFrame(
       render_frame_routing_id_, container_->element_instance_id(),
-      guest_instance_id_, params_->Clone(),
+      guest_instance_id_, params_.Clone(),
       base::BindOnce(&GuestViewAttachRequest::OnAcknowledged,
                      weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/components/guest_view/renderer/guest_view_request.h b/components/guest_view/renderer/guest_view_request.h
index ec5456df..2efda74 100644
--- a/components/guest_view/renderer/guest_view_request.h
+++ b/components/guest_view/renderer/guest_view_request.h
@@ -28,7 +28,7 @@
   GuestViewAttachRequest(GuestViewContainer* container,
                          int render_frame_routing_id,
                          int guest_instance_id,
-                         std::unique_ptr<base::DictionaryValue> params,
+                         base::Value::Dict params,
                          v8::Local<v8::Function> callback,
                          v8::Isolate* isolate);
 
@@ -55,7 +55,7 @@
   v8::Isolate* const isolate_;
   const int render_frame_routing_id_;
   const int guest_instance_id_;
-  std::unique_ptr<base::DictionaryValue> params_;
+  base::Value::Dict params_;
 
   base::WeakPtrFactory<GuestViewAttachRequest> weak_ptr_factory_{this};
 };
diff --git a/components/history_clusters/core/query_clusters_state.cc b/components/history_clusters/core/query_clusters_state.cc
index e4dcd4f8..cc4a3ed 100644
--- a/components/history_clusters/core/query_clusters_state.cc
+++ b/components/history_clusters/core/query_clusters_state.cc
@@ -5,6 +5,7 @@
 #include "components/history_clusters/core/query_clusters_state.h"
 
 #include <set>
+#include <string>
 
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/metrics/histogram_functions.h"
@@ -138,6 +139,12 @@
     return;
   }
 
+  // This feels like it belongs in `PostProcessor`, but this operates on the
+  // main thread, because the data needs to live on the main thread. Doing it
+  // on the task runner requires making heap copies, which probably costs more
+  // than just doing this simple computation on the main thread.
+  UpdateUniqueRawLabels(clusters);
+
   std::move(callback).Run(query_, std::move(clusters),
                           !continuation_params.exhausted_all_visits,
                           is_continuation_);
@@ -148,4 +155,26 @@
   base::UmaHistogramTimes("History.Clusters.ServiceLatency", service_latency);
 }
 
+void QueryClustersState::UpdateUniqueRawLabels(
+    const std::vector<history::Cluster>& clusters) {
+  // Skip this computation when there's a search query.
+  if (!query_.empty())
+    return;
+
+  for (const auto& cluster : clusters) {
+    if (!cluster.raw_label)
+      return;
+
+    const auto& raw_label_value = cluster.raw_label.value();
+
+    // Subtle code below: If we've NEVER encountered the label before, this []
+    // operator initializes the count to 0, and then post-increments it to 1.
+    // If it already exists, the post-increment will up the count, but will
+    // return false.
+    if (raw_label_counts_[raw_label_value]++ == 0) {
+      unique_raw_labels_.push_back(raw_label_value);
+    }
+  }
+}
+
 }  // namespace history_clusters
diff --git a/components/history_clusters/core/query_clusters_state.h b/components/history_clusters/core/query_clusters_state.h
index 34dc9a9..7d5c5d6 100644
--- a/components/history_clusters/core/query_clusters_state.h
+++ b/components/history_clusters/core/query_clusters_state.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_QUERY_CLUSTERS_STATE_H_
 #define COMPONENTS_HISTORY_CLUSTERS_CORE_QUERY_CLUSTERS_STATE_H_
 
+#include <string>
 #include <vector>
 
 #include "base/callback_forward.h"
@@ -53,6 +54,17 @@
   // Used to request another batch of clusters of the same query.
   void LoadNextBatchOfClusters(ResultCallback callback);
 
+  // Use these together to iterate through the list of raw labels in the same
+  // order as the clusters are ordered. The counts can be fetched by inputting
+  // the labels into the map as keys - but note, this only counts the number
+  // of label instances seen SO FAR, not necessarily in all of History.
+  const std::vector<std::u16string>& unique_raw_labels() {
+    return unique_raw_labels_;
+  }
+  const std::map<std::u16string, size_t>& raw_label_counts() {
+    return raw_label_counts_;
+  }
+
  private:
   friend class QueryClustersStateTest;
 
@@ -75,6 +87,9 @@
                      QueryClustersContinuationParams continuation_params,
                      std::vector<history::Cluster> clusters);
 
+  // Updates the internal state of raw labels for this next batch of `clusters`.
+  void UpdateUniqueRawLabels(const std::vector<history::Cluster>& clusters);
+
   // A weak pointer to the service in case we outlive the service.
   // Never nullptr, except in unit tests.
   const base::WeakPtr<HistoryClustersService> service_;
@@ -82,6 +97,17 @@
   // The string query the user entered into the searchbox.
   const std::string query_;
 
+  // The de-duplicated list of raw labels we've seen so far, in the same order
+  // as the clusters themselves were provided. This is only computed if `query`
+  // is empty. For non-empty `query`, this will be an empty list.
+  std::vector<std::u16string> unique_raw_labels_;
+  // Counts the number of instances of each raw label we've seen. Note that
+  // the value will always be an integer 1 or above. This is also used for our
+  // internal uniqueness test. Note: this only counts the number of raw labels
+  // of this string seen SO FAR, so unless we iterate through ALL the clusters,
+  // this number may be smaller than the total number in History.
+  std::map<std::u16string, size_t> raw_label_counts_;
+
   // The continuation params used to track where the last query left off and
   // query for the "next page".
   QueryClustersContinuationParams continuation_params_;
diff --git a/components/history_clusters/core/query_clusters_state_unittest.cc b/components/history_clusters/core/query_clusters_state_unittest.cc
index 0e8d781..0941a51c 100644
--- a/components/history_clusters/core/query_clusters_state_unittest.cc
+++ b/components/history_clusters/core/query_clusters_state_unittest.cc
@@ -11,9 +11,12 @@
 #include "components/history/core/browser/history_types.h"
 #include "components/history_clusters/core/history_clusters_service_test_api.h"
 #include "components/history_clusters/core/history_clusters_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+using ::testing::ElementsAre;
+
 namespace history_clusters {
 
 namespace {
@@ -263,4 +266,39 @@
   }
 }
 
+TEST_F(QueryClustersStateTest, UniqueRawLabels) {
+  QueryClustersState state(nullptr, "");
+
+  auto cluster1 = history::Cluster(1, {}, {});
+  cluster1.raw_label = u"rawlabel1";
+  auto cluster2 = history::Cluster(2, {}, {});
+  cluster2.raw_label = u"rawlabel2";
+  auto cluster3 = history::Cluster(3, {}, {});
+  cluster3.raw_label = u"rawlabel3";
+
+  // Now make some clusters with repeated raw labels.
+  auto cluster4 = history::Cluster(4, {}, {});
+  cluster4.raw_label = u"rawlabel1";
+  auto cluster5 = history::Cluster(5, {}, {});
+  cluster5.raw_label = u"rawlabel2";
+
+  auto result = InjectRawClustersAndAwaitPostProcessing(
+      &state, {cluster1, cluster2, cluster4}, {});
+  ASSERT_EQ(result.cluster_batch.size(), 3U);
+  EXPECT_THAT(state.unique_raw_labels(),
+              ElementsAre(u"rawlabel1", u"rawlabel2"));
+  EXPECT_EQ(state.raw_label_counts().at(u"rawlabel1"), 2U);
+  EXPECT_EQ(state.raw_label_counts().at(u"rawlabel2"), 1U);
+
+  // Test updating an existing count, and adding new ones after that.
+  result =
+      InjectRawClustersAndAwaitPostProcessing(&state, {cluster5, cluster3}, {});
+  ASSERT_EQ(result.cluster_batch.size(), 2U);
+  EXPECT_THAT(state.unique_raw_labels(),
+              ElementsAre(u"rawlabel1", u"rawlabel2", u"rawlabel3"));
+  EXPECT_EQ(state.raw_label_counts().at(u"rawlabel1"), 2U);
+  EXPECT_EQ(state.raw_label_counts().at(u"rawlabel2"), 2U);
+  EXPECT_EQ(state.raw_label_counts().at(u"rawlabel3"), 1U);
+}
+
 }  // namespace history_clusters
diff --git a/components/lookalikes/core/lookalike_url_util.cc b/components/lookalikes/core/lookalike_url_util.cc
index cb31070..a7fbe3e7 100644
--- a/components/lookalikes/core/lookalike_url_util.cc
+++ b/components/lookalikes/core/lookalike_url_util.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool.h"
 #include "base/time/default_clock.h"
@@ -44,6 +45,19 @@
   registry->RegisterListPref(prefs::kLookalikeWarningAllowlistDomains);
 }
 
+std::string GetConsoleMessage(const GURL& lookalike_url,
+                              bool is_new_heuristic) {
+  const char* const kNewHeuristicMessage =
+      "Future Chrome versions will show a warning on this domain name.\n";
+  return base::StringPrintf(
+      "Chrome has determined that %s could be fake or fraudulent.\n\n"
+      "%s"
+      "If you believe this is shown in error please visit "
+      "https://g.co/chrome/lookalike-warnings",
+      lookalike_url.host().c_str(),
+      is_new_heuristic ? kNewHeuristicMessage : "");
+}
+
 }  // namespace lookalikes
 
 namespace {
@@ -118,6 +132,13 @@
     "account", "activate", "active",   "admin", "login",
     "online",  "password", "security", "signin"};
 
+ComboSquattingParams* GetComboSquattingParams() {
+  static ComboSquattingParams params{
+      kBrandNamesforCSQ, std::size(kBrandNamesforCSQ), kPopularKeywordsforCSQ,
+      std::size(kPopularKeywordsforCSQ)};
+  return &params;
+}
+
 bool SkeletonsMatch(const url_formatter::Skeletons& skeletons1,
                     const url_formatter::Skeletons& skeletons2) {
   DCHECK(!skeletons1.empty());
@@ -1192,28 +1213,42 @@
   return false;
 }
 
+void SetComboSquattingParamsForTesting(const ComboSquattingParams& params) {
+  *GetComboSquattingParams() = params;
+}
+
+void ResetComboSquattingParamsForTesting() {
+  ComboSquattingParams* params = GetComboSquattingParams();
+  *params = {kBrandNamesforCSQ, std::size(kBrandNamesforCSQ),
+             kPopularKeywordsforCSQ, std::size(kPopularKeywordsforCSQ)};
+}
+
 bool IsComboSquatting(const DomainInfo& navigated_domain,
                       std::string* matched_domain) {
   // TODO(crbug.com/1341023): We should check the domain in allowlist once we
   // start getting metrics in future iterations.
-
+  ComboSquattingParams* combo_squatting_params = GetComboSquattingParams();
   // Check if the domain has any brand name and any popular keyword.
-  for (auto* const brand : kBrandNamesforCSQ) {
-    if (navigated_domain.domain_and_registry.find(brand) != std::string::npos &&
-        navigated_domain.domain_and_registry.size() != strlen(brand)) {
-      for (auto* const keyword : kPopularKeywordsforCSQ) {
-        if (navigated_domain.domain_and_registry.find(keyword) !=
-                std::string::npos &&
-            std::string(brand).find(keyword) == std::string::npos &&
-            std::string(keyword).find(brand) == std::string::npos) {
-          // TODO(crbug.com/1341320): In future cls we will compute a better
-          // suggestion for each domain.
-          *matched_domain = std::string(brand) + ".com";
-          return true;
-        }
+  for (size_t i = 0; i < combo_squatting_params->num_brand_names; i++) {
+    auto* const brand = combo_squatting_params->brand_names[i];
+    if (!(navigated_domain.domain_without_registry.find(brand) !=
+              std::string::npos &&
+          navigated_domain.domain_without_registry.size() != strlen(brand))) {
+      continue;
+    }
+
+    for (size_t j = 0; j < combo_squatting_params->num_popular_keywords; j++) {
+      auto* const keyword = combo_squatting_params->popular_keywords[j];
+      if (navigated_domain.domain_without_registry.find(keyword) !=
+              std::string::npos &&
+          std::string(brand).find(keyword) == std::string::npos &&
+          std::string(keyword).find(brand) == std::string::npos) {
+        // TODO(crbug.com/1341320): In future cls we will compute a better
+        // suggestion for each domain.
+        *matched_domain = std::string(brand) + ".com";
+        return true;
       }
     }
   }
-  *matched_domain = navigated_domain.hostname;
   return false;
 }
diff --git a/components/lookalikes/core/lookalike_url_util.h b/components/lookalikes/core/lookalike_url_util.h
index 03067bec..facc8f2 100644
--- a/components/lookalikes/core/lookalike_url_util.h
+++ b/components/lookalikes/core/lookalike_url_util.h
@@ -23,6 +23,12 @@
 
 // Register applicable preferences with the provided registry.
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+// Returns the console message to be shown in devtools when a URL is flagged by
+// a lookalike heuristic. If is_new_heuristic is true, the message is for a new
+// heuristic that's not fully launched and it has an extra line about future
+// behavior of Chrome.
+std::string GetConsoleMessage(const GURL& lookalike_url, bool is_new_heuristic);
 }
 
 using LookalikeTargetAllowlistChecker =
@@ -115,6 +121,20 @@
   size_t num_edit_distance_skeletons;
 };
 
+struct ComboSquattingParams {
+  // List of brand names such as "google", "youtube".
+  // Should be usable in domain names (i.e. lower case, no punctuation except
+  // for - etc.)
+  const char* const* brand_names;
+  // Number of brand names in combo_squatting_brand_names.
+  size_t num_brand_names;
+
+  // List of popular keywords such as "login", "online".
+  const char* const* popular_keywords;
+  // Number of popular keywords in combo_squatting_keywords.
+  size_t num_popular_keywords;
+};
+
 struct DomainInfo {
   // The full ASCII hostname, used in detecting target embedding. For
   // "https://www.google.com/mail" this will be "www.google.com".
@@ -251,6 +271,12 @@
     const std::string& lookalike_etld_plus_one,
     version_info::Channel channel);
 
+// Set brand names and keywords for testing Combo Squatting heuristic.
+void SetComboSquattingParamsForTesting(const ComboSquattingParams& params);
+
+// Reset brand names and keywords after testing Combo Squatting heuristic.
+void ResetComboSquattingParamsForTesting();
+
 // Returns true if the navigated_domain is flagged as Combo Squatting.
 // matched_domain is the suggested domain that will be shown to the user
 // instead of the navigated_domain in the warning UI.
diff --git a/components/lookalikes/core/lookalike_url_util_unittest.cc b/components/lookalikes/core/lookalike_url_util_unittest.cc
index fc6db89e..e5415d8 100644
--- a/components/lookalikes/core/lookalike_url_util_unittest.cc
+++ b/components/lookalikes/core/lookalike_url_util_unittest.cc
@@ -14,6 +14,19 @@
 
 using version_info::Channel;
 
+namespace {
+// Tests lists for Combo Squatting. Some of these entries are intended to test
+// for various edge cases and aren't realistic for production.
+const char* const kBrandNames[] = {"google", "youtube", "sample", "example",
+                                   "vice"};
+const char* const kPopularKeywords[] = {"online", "login",   "account",
+                                        "ample",  "service", "test"};
+const ComboSquattingParams kComboSquattingParams{
+    kBrandNames, std::size(kBrandNames), kPopularKeywords,
+    std::size(kPopularKeywords)};
+
+}  // namespace
+
 std::string TargetEmbeddingTypeToString(TargetEmbeddingType type) {
   switch (type) {
     case TargetEmbeddingType::kNone:
@@ -588,63 +601,68 @@
       "example3.com", Channel::BETA));
 }
 
+class ComboSquattingTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    SetComboSquattingParamsForTesting(kComboSquattingParams);
+  }
+  void TearDown() override { ResetComboSquattingParamsForTesting(); }
+};
+
 // Test for Combo Squatting check of domains.
-TEST(CombosquattingTest, IsComboSquatting) {
+TEST_F(ComboSquattingTest, IsComboSquatting) {
   const struct TestCase {
     const char* domain;
     const char* expected_suggested_domain;
     bool expected_result;
   } kTestCases[] = {
-      // Not Combo Squatting (CSQ)
-      {"google.com", "google.com", false},
-      {"youtube.ca", "youtube.ca", false},
+      // Not Combo Squatting (CSQ).
+      {"google.com", "", false},
+      {"youtube.ca", "", false},
 
       // Not CSQ, contains subdomains.
-      {"login.google.com", "login.google.com", false},
+      {"login.google.com", "", false},
 
-      // Not CSQ, non registrable domains
+      // Not CSQ, non registrable domains.
       {"google-login.test", "", false},
 
-      // CSQ with "-"
+      // CSQ with "-".
       {"google-online.com", "google.com", true},
 
-      // CSQ with more than one keyword with "-"
+      // CSQ with more than one keyword (login, online) with "-".
       {"google-login-online.com", "google.com", true},
 
-      // CSQ with one keyword and one random word with "-"
-      {"one-youtube-online.com", "youtube.com", true},
+      // CSQ with one keyword (online) and one random word (one) with "-".
+      {"one-sample-online.com", "sample.com", true},
 
-      // Not CSQ, with a keyword as TLD.
-      // I think TLD should be a valid TLD which we don't have in the keywords
-      // now.
-      {"www.youtube.test", "", false},
+      // Not CSQ, with a keyword (test) as TLD.
+      {"www.example.test", "", false},
 
-      // CSQ with more than one brand with "-"
+      // CSQ with more than one brand (google, youtube) with "-".
       {"google-youtube-account.com", "google.com", true},
 
-      // CSQ without separator
-      {"loginyoutube.com", "youtube.com", true},
+      // CSQ without separator.
+      {"loginsample.com", "sample.com", true},
 
-      // CSQ but in allowlist
-      // TODO(crbug.com/1341023): We will use one of the allowlists here.
-      //{"googleusercontent.com", false},
+      // Not CSQ with a keyword (ample) inside brand name (sample).
+      {"sample.com", "", false},
 
-      // TODO(crbug.com/1341323): Should define a list of brand names and
-      // keywords for testing in future cls.
+      // Current version of the heuristic cannot flag this kind of CSQ
+      // with a keyword (ample) inside brand name (sample) and as an added
+      // keyword to the domain.
+      {"sample-ample.com", "", false},
 
-      // Not CSQ with a keyword inside brand name
-      // TODO(crbug.com/1341323): Should find one brand name with this
-      // condition.
+      // CSQ with more than one keyword (account, online) without separator.
+      {"accountexampleonline.com", "example.com", true},
 
-      // CSQ with a keyword inside brand name and as an added keyword to the
-      // domain
-      // TODO(crbug.com/1341323): Should find a domain with this condition.
-
-      // CSQ with more than one keyword without separator.
-      {"signinyoutubeonline.com", "youtube.com", true},
-
-      // CSQ with one keyword and one random word without "-"
+      // CSQ with one keyword (login) and one random word (one) without "-".
       {"oneyoutubelogin.com", "youtube.com", true},
+
+      // Not CSQ, google is a public TLD.
+      {"online.google", "", false},
+
+      // Not CSQ, brand name (vice) is part of keyword (service).
+      {"keyservice.com", "", false},
   };
   for (const TestCase& test_case : kTestCases) {
     auto navigated =
diff --git a/components/messages/android/java/src/org/chromium/components/messages/MessagesMetrics.java b/components/messages/android/java/src/org/chromium/components/messages/MessagesMetrics.java
index a14bb25..6611df8 100644
--- a/components/messages/android/java/src/org/chromium/components/messages/MessagesMetrics.java
+++ b/components/messages/android/java/src/org/chromium/components/messages/MessagesMetrics.java
@@ -129,6 +129,8 @@
                 return "AutoDarkWebContents";
             case MessageIdentifier.TAILORED_SECURITY_ENABLED:
                 return "TailoredSecurityEnabled";
+            case MessageIdentifier.TAILORED_SECURITY_DISABLED:
+                return "TailoredSecurityDisabled";
             case MessageIdentifier.VR_SERVICES_UPGRADE:
                 return "VrServicesUpgrade";
             case MessageIdentifier.AR_CORE_UPGRADE:
@@ -143,6 +145,8 @@
                 return "OfferNotification";
             case MessageIdentifier.EXTERNAL_NAVIGATION:
                 return "ExternalNavigation";
+            case MessageIdentifier.INVALID_MESSAGE:
+                return "InvalidMessage";
             default:
                 return "Unknown";
         }
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc
index 41c59e6e..45848d3 100644
--- a/components/omnibox/browser/autocomplete_classifier.cc
+++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -102,7 +102,7 @@
   // lower-down suggestions.
   input.set_prefer_keyword(prefer_keyword);
   input.set_allow_exact_keyword_match(allow_exact_keyword_match);
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   controller_->Start(input);
   DCHECK(controller_->done());
 
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index 707e5af..7ad7ce3f 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -444,23 +444,23 @@
   TRACE_EVENT1("omnibox", "AutocompleteController::Start", "text",
                base::UTF16ToUTF8(input.text()));
 
-  // Providers assume synchronous inputs (`want_asynchronous_matches() ==
-  // false`) have default focus type (`focus_type() == DEFAULT`). See
+  // Providers assume synchronous inputs (`omit_asynchronous_matches() ==
+  // true`) have default focus type (`focus_type() == DEFAULT`). See
   // crbug.com/1339425.
-  DCHECK(input.want_asynchronous_matches() ||
+  DCHECK(!input.omit_asynchronous_matches() ||
          input.focus_type() == OmniboxFocusType::DEFAULT);
 
-  // When input.want_asynchronous_matches() is false, the AutocompleteController
+  // When input.omit_asynchronous_matches() is true, the AutocompleteController
   // is being used for text classification, which should not notify observers.
   // TODO(manukh): This seems unnecessary; `AutocompleteClassifier` and
   //   `OmniboxController` use separate instances of `AutocompleteController`,
   //   the former doesn't add observers, the latter always uses
-  //   `want_asynchronous_matches()` set to true. Besides, if that weren't the
+  //   `omit_asynchrous_matches()` set to false. Besides, if that weren't the
   //   case, e.g. the classifier did add an observer, then
   //   `AutocompleteController` should respect that, not assume it's a mistake
   //   and silently ignore the observer. Audit all call paths of `::Start()` to
   //   remove this check.
-  if (input.want_asynchronous_matches()) {
+  if (!input.omit_asynchronous_matches()) {
     for (Observer& obs : observers_)
       obs.OnStart(this, input);
   }
@@ -474,7 +474,7 @@
 
   const std::u16string old_input_text(input_.text());
   const bool old_allow_exact_keyword_match = input_.allow_exact_keyword_match();
-  const bool old_want_asynchronous_matches = input_.want_asynchronous_matches();
+  const bool old_omit_asynchronous_matches = input_.omit_asynchronous_matches();
   const OmniboxFocusType old_focus_type = input_.focus_type();
   input_ = input;
 
@@ -490,7 +490,7 @@
   const bool minimal_changes =
       (input_.text() == old_input_text) &&
       (input_.allow_exact_keyword_match() == old_allow_exact_keyword_match) &&
-      (input_.want_asynchronous_matches() == old_want_asynchronous_matches) &&
+      (input_.omit_asynchronous_matches() == old_omit_asynchronous_matches) &&
       (input_.focus_type() == old_focus_type);
 
   expire_timer_.Stop();
@@ -522,7 +522,7 @@
         provider_end_time - provider_start_time, base::Milliseconds(1),
         base::Seconds(5), 20);
   }
-  if (input.want_asynchronous_matches() && (input.text().length() < 6)) {
+  if (!input.omit_asynchronous_matches() && (input.text().length() < 6)) {
     // `UmaHistogramTimes()` uses 1ms - 10s buckets, whereas this uses 1ms - 1s
     // buckets.
     // TODO(crbug.com/1340291|manukh): This isn't handled by `metrics_` yet. Do
@@ -533,7 +533,7 @@
         end_time - start_time, base::Milliseconds(1), base::Seconds(1), 50);
   }
   base::UmaHistogramBoolean("Omnibox.Start.WantAsyncMatches",
-                            input.want_asynchronous_matches());
+                            !input.omit_asynchronous_matches());
 
   // This will usually set |done_| to false, unless all providers are finished
   // after the synchronous pass we just completed.
@@ -1147,7 +1147,7 @@
     }
   }
   // If asynchronous matches have been disallowed, all providers should be done.
-  DCHECK(input_.want_asynchronous_matches() || all_providers_done);
+  DCHECK(!input_.omit_asynchronous_matches() || all_providers_done);
   done_ = all_providers_done;
 }
 
diff --git a/components/omnibox/browser/autocomplete_controller_metrics.cc b/components/omnibox/browser/autocomplete_controller_metrics.cc
index e6d5a96..5f69c8a 100644
--- a/components/omnibox/browser/autocomplete_controller_metrics.cc
+++ b/components/omnibox/browser/autocomplete_controller_metrics.cc
@@ -53,7 +53,7 @@
   // logging as soon as the final update occurs, while `OnStop()` handles the
   // case where the final update never occurs because of interruptions.
   // TODO(manukh): Consider adding this filter to the above metrics as well.
-  if (!controller_.input().want_asynchronous_matches())
+  if (controller_.input().omit_asynchronous_matches())
     return;
   // E.g., suggestion deletion can call `OnUpdateResult()` after the controller
   // is done and finalization metrics have been logged. They shouldn't be
diff --git a/components/omnibox/browser/autocomplete_controller_metrics.h b/components/omnibox/browser/autocomplete_controller_metrics.h
index 7b4eea9..edc3dd1 100644
--- a/components/omnibox/browser/autocomplete_controller_metrics.h
+++ b/components/omnibox/browser/autocomplete_controller_metrics.h
@@ -26,7 +26,7 @@
 //      `AutocompleteController::OnProviderUpdate()`).
 // 2) How long until the suggestions finalize.
 //    - Does not track sync requests (i.e.,
-//      `AutocompleteInput::set_want_asynchronous_matches()` set to false).
+//      `AutocompleteInput::omit_asynchronous_matches()` set to true).
 //    - Does track async requests that complete syncly.
 //    - Tracks suggestion additions, changes, and removals.
 // 3) How many suggestions change during updates.
diff --git a/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc b/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc
index bc20581..c8adbda 100644
--- a/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc
+++ b/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc
@@ -39,7 +39,7 @@
   // By default, the controller wants async matches. `SetInputSync()` will
   // explicitly set this behavior.
   void SetInputSync(bool sync) {
-    controller_.input_.set_want_asynchronous_matches(!sync);
+    controller_.input_.set_omit_asynchronous_matches(sync);
   }
 
   // Mimics `AutocompleteController::Start()`'s behavior. `sync_results_only`
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc
index c8940301..8cc250b 100644
--- a/components/omnibox/browser/autocomplete_input.cc
+++ b/components/omnibox/browser/autocomplete_input.cc
@@ -106,7 +106,7 @@
       prefer_keyword_(false),
       allow_exact_keyword_match_(true),
       keyword_mode_entry_method_(metrics::OmniboxEventProto::INVALID),
-      want_asynchronous_matches_(true),
+      omit_asynchronous_matches_(false),
       should_use_https_as_default_scheme_(false),
       added_default_scheme_to_typed_url_(false),
       https_port_for_testing_(0),
@@ -752,7 +752,7 @@
   prevent_inline_autocomplete_ = false;
   prefer_keyword_ = false;
   allow_exact_keyword_match_ = false;
-  want_asynchronous_matches_ = true;
+  omit_asynchronous_matches_ = false;
   focus_type_ = OmniboxFocusType::DEFAULT;
   terms_prefixed_by_http_or_https_.clear();
   query_tile_id_.reset();
diff --git a/components/omnibox/browser/autocomplete_input.h b/components/omnibox/browser/autocomplete_input.h
index 0fd7082..e53da83 100644
--- a/components/omnibox/browser/autocomplete_input.h
+++ b/components/omnibox/browser/autocomplete_input.h
@@ -235,14 +235,14 @@
     keyword_mode_entry_method_ = entry_method;
   }
 
-  // Returns whether providers should be allowed to make asynchronous requests
-  // when processing this input.
-  bool want_asynchronous_matches() const { return want_asynchronous_matches_; }
-  // If |want_asynchronous_matches| is false, the controller asks the
+  // Returns whether providers should avoid obtaining matches asynchronously
+  // when processing the input.
+  bool omit_asynchronous_matches() const { return omit_asynchronous_matches_; }
+  // If |omit_asynchronous_matches| is true, the controller asks the
   // providers to only return matches which are synchronously available,
   // which should mean that all providers will be done immediately.
-  void set_want_asynchronous_matches(bool want_asynchronous_matches) {
-    want_asynchronous_matches_ = want_asynchronous_matches;
+  void set_omit_asynchronous_matches(bool omit_asynchronous_matches) {
+    omit_asynchronous_matches_ = omit_asynchronous_matches;
   }
 
   // Returns the type of UI interaction that started this autocomplete query.
@@ -318,7 +318,7 @@
   bool prefer_keyword_;
   bool allow_exact_keyword_match_;
   metrics::OmniboxEventProto::KeywordModeEntryMethod keyword_mode_entry_method_;
-  bool want_asynchronous_matches_;
+  bool omit_asynchronous_matches_;
   OmniboxFocusType focus_type_ = OmniboxFocusType::DEFAULT;
   std::vector<std::u16string> terms_prefixed_by_http_or_https_;
   absl::optional<std::string> query_tile_id_;
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h
index aa3c56ca..f1956c8 100644
--- a/components/omnibox/browser/autocomplete_provider.h
+++ b/components/omnibox/browser/autocomplete_provider.h
@@ -286,6 +286,12 @@
   // return.
   size_t provider_max_matches() const { return provider_max_matches_; }
 
+  // Returns a suggested upper bound for how many matches this provider should
+  // return while in keyword mode.
+  size_t provider_max_matches_in_keyword_mode() const {
+    return provider_max_matches_in_keyword_mode_;
+  }
+
   // Returns the set of matches for the current query.
   const ACMatches& matches() const { return matches_; }
 
@@ -295,7 +301,7 @@
   // for any provider, then the `AutocompleteController::done_` must also be
   // false. This ensures the controller can determine when each provider
   // finishes processing async requests. Should be true after either `Stop()` or
-  // `Start()` with `AutocompleteInput.want_asynchronous_matches` set to false
+  // `Start()` with `AutocompleteInput.omit_asynchronous_matches_` set to true
   // are called.
   bool done() const { return done_; }
 
@@ -401,6 +407,7 @@
   std::vector<AutocompleteProviderListener*> listeners_;
 
   const size_t provider_max_matches_;
+  const size_t provider_max_matches_in_keyword_mode_{7};
 
   ACMatches matches_;
   // A map of suggestion group IDs to suggestion group information corresponding
diff --git a/components/omnibox/browser/autocomplete_provider_unittest.cc b/components/omnibox/browser/autocomplete_provider_unittest.cc
index 94aaa4eb..0a0cdcc 100644
--- a/components/omnibox/browser/autocomplete_provider_unittest.cc
+++ b/components/omnibox/browser/autocomplete_provider_unittest.cc
@@ -155,7 +155,7 @@
   AddResultsWithSearchTermsArgs(3, 1, AutocompleteMatchType::SEARCH_SUGGEST,
                                 TemplateURLRef::SearchTermsArgs(u"query"));
 
-  if (input.want_asynchronous_matches()) {
+  if (!input.omit_asynchronous_matches()) {
     done_ = false;
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&TestProvider::Run, this));
@@ -266,7 +266,7 @@
   matches_.clear();
   done_ = false;
 
-  if (input.want_asynchronous_matches()) {
+  if (!input.omit_asynchronous_matches()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&TestPrefetchProvider::RunPrefetch, this));
   } else {
@@ -1752,7 +1752,7 @@
   // closure of `run_loop` before `run_loop` is run. This prevents the provider
   // from being able to notify the controller of finishing the non-prefetch
   // request resulting in the controller to remain in an invalid state.
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   controller_->StartPrefetch(input);
 
   // Wait for the provider to finish asynchronously.
diff --git a/components/omnibox/browser/bookmark_provider.cc b/components/omnibox/browser/bookmark_provider.cc
index 4e8bbd7..a134b5d6 100644
--- a/components/omnibox/browser/bookmark_provider.cc
+++ b/components/omnibox/browser/bookmark_provider.cc
@@ -139,8 +139,15 @@
     }
   }
 
+  // In keyword mode, it's possible we only provide results from one or two
+  // autocomplete provider(s), so it's sometimes necessary to show more results
+  // than provider_max_matches_.
+  size_t max_matches = InKeywordMode(input)
+                           ? provider_max_matches_in_keyword_mode_
+                           : provider_max_matches_;
+
   // Sort and clip the resulting matches.
-  size_t num_matches = std::min(matches_.size(), provider_max_matches_);
+  size_t num_matches = std::min(matches_.size(), max_matches);
   std::partial_sort(matches_.begin(), matches_.begin() + num_matches,
                     matches_.end(), AutocompleteMatch::MoreRelevant);
   matches_.resize(num_matches);
diff --git a/components/omnibox/browser/bookmark_provider_unittest.cc b/components/omnibox/browser/bookmark_provider_unittest.cc
index 94f92e69..286a41b 100644
--- a/components/omnibox/browser/bookmark_provider_unittest.cc
+++ b/components/omnibox/browser/bookmark_provider_unittest.cc
@@ -84,6 +84,16 @@
     {"testing short bookmarks", "https://zzz.com"},
     // For testing bookmarks search in keyword mode.
     {"@bookmarks", "chrome://bookmarks"},
+    // For testing max matches.
+    {"zyx1", "http://randomsite.com/zyx1"},
+    {"zyx2", "http://randomsite.com/zyx2"},
+    {"zyx3", "http://randomsite.com/zyx3"},
+    {"zyx4", "http://randomsite.com/zyx4"},
+    {"zyx5", "http://randomsite.com/zyx5"},
+    {"zyx6", "http://randomsite.com/zyx6"},
+    {"zyx7", "http://randomsite.com/zyx7"},
+    {"zyx8", "http://randomsite.com/zyx8"},
+    {"zyx9", "http://randomsite.com/zyx9"},
 };
 
 // Structures and functions supporting the BookmarkProviderTest.Positions
@@ -813,3 +823,22 @@
   ASSERT_EQ(matches.size(), 1u);
   EXPECT_EQ(u"domain", matches[0].description);
 }
+
+TEST_F(BookmarkProviderTest, MaxMatches) {
+  // Keyword mode is off. We should only get provider_max_matches_ matches.
+  AutocompleteInput input(u"zyx", metrics::OmniboxEventProto::OTHER,
+                          TestSchemeClassifier());
+  provider_->Start(input, false);
+
+  ACMatches matches = provider_->matches();
+  EXPECT_EQ(matches.size(), provider_->provider_max_matches());
+
+  // Turn keyword mode on. we should be able to get more matches now.
+  input.set_keyword_mode_entry_method(
+      metrics::OmniboxEventProto_KeywordModeEntryMethod_TAB);
+  input.set_prefer_keyword(true);
+  provider_->Start(input, false);
+
+  matches = provider_->matches();
+  EXPECT_EQ(matches.size(), provider_->provider_max_matches_in_keyword_mode());
+}
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc
index 406fdf1..39c011f8 100644
--- a/components/omnibox/browser/clipboard_provider.cc
+++ b/components/omnibox/browser/clipboard_provider.cc
@@ -146,7 +146,7 @@
     return;
 
   // Image matched was kicked off asynchronously, so proceed when that ends.
-  if (input.want_asynchronous_matches() && CreateImageMatch(input))
+  if (!input.omit_asynchronous_matches() && CreateImageMatch(input))
     return;
 
   bool read_clipboard_content = false;
@@ -179,7 +179,7 @@
   // user. To avoid this, all the methods above will not check the contents and
   // will return false/absl::nullopt. Instead, check the existence of content
   // without accessing the actual content and create blank matches.
-  if (input.want_asynchronous_matches()) {
+  if (!input.omit_asynchronous_matches()) {
     // Image matched was kicked off asynchronously, so proceed when that ends.
     CheckClipboardContent(input);
   }
diff --git a/components/omnibox/browser/clipboard_provider_unittest.cc b/components/omnibox/browser/clipboard_provider_unittest.cc
index 34e8047..6334eaaf 100644
--- a/components/omnibox/browser/clipboard_provider_unittest.cc
+++ b/components/omnibox/browser/clipboard_provider_unittest.cc
@@ -297,11 +297,11 @@
 
   gfx::Image test_image = gfx::test::CreateImage(/*width=*/10, /*height=*/10);
   SetClipboardImage(test_image);
-  // When `input.want_asynchronous_matches` is set to false, the clipboard
+  // When `input.omit_asynchronous_matches` is set to true, the clipboard
   // provider should skip any asynchronous logic associated with creating an
   // image match.
   AutocompleteInput input = CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS);
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   provider_->Start(input, false);
   ASSERT_TRUE(provider_->done());
   ASSERT_TRUE(provider_->matches().empty());
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc
index a3bd4b5e..e1a25f84 100644
--- a/components/omnibox/browser/document_provider.cc
+++ b/components/omnibox/browser/document_provider.cc
@@ -623,7 +623,7 @@
   CopyCachedMatchesToMatches();
   DemoteMatchesBeyondMax();
 
-  if (!input.want_asynchronous_matches()) {
+  if (input.omit_asynchronous_matches()) {
     return;
   }
 
diff --git a/components/omnibox/browser/document_provider_unittest.cc b/components/omnibox/browser/document_provider_unittest.cc
index 42b288c5..9f21e4f5 100644
--- a/components/omnibox/browser/document_provider_unittest.cc
+++ b/components/omnibox/browser/document_provider_unittest.cc
@@ -1221,7 +1221,7 @@
 
   AutocompleteInput input(u"document", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
 
   // Expect sync matches to be scored.
   // Fill cache.
@@ -1265,7 +1265,7 @@
 
   AutocompleteInput invalid_input(u"12", metrics::OmniboxEventProto::OTHER,
                                   TestSchemeClassifier());
-  invalid_input.set_want_asynchronous_matches(true);
+  invalid_input.set_omit_asynchronous_matches(false);
 
   provider_->done_ = false;
   provider_->Start(invalid_input, false);
diff --git a/components/omnibox/browser/history_cluster_provider.cc b/components/omnibox/browser/history_cluster_provider.cc
index df5a22d..a7df8e0 100644
--- a/components/omnibox/browser/history_cluster_provider.cc
+++ b/components/omnibox/browser/history_cluster_provider.cc
@@ -33,7 +33,7 @@
                                    bool minimal_changes) {
   Stop(true, false);
 
-  if (!input.want_asynchronous_matches())
+  if (input.omit_asynchronous_matches())
     return;
 
   if (!IsJourneysEnabledInOmnibox(client_->GetHistoryClustersService(),
diff --git a/components/omnibox/browser/history_cluster_provider_unittest.cc b/components/omnibox/browser/history_cluster_provider_unittest.cc
index 1a7facf..6226320 100644
--- a/components/omnibox/browser/history_cluster_provider_unittest.cc
+++ b/components/omnibox/browser/history_cluster_provider_unittest.cc
@@ -119,10 +119,10 @@
 };
 
 TEST_F(HistoryClustersProviderTest, WantAsynchronousMatchesFalse) {
-  // When `input.want_asynchronous_matches_` is false, should not  attempt
+  // When `input.omit_asynchronous_matches_` is true, should not attempt
   // to provide suggestions.
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
 
   EXPECT_TRUE(provider_->done());
   provider_->Start(input, false);
@@ -134,7 +134,7 @@
   // before the history cluster provider begins.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   search_provider_->matches_ = {CreateMatch(u"keyword")};
   search_provider_->done_ = true;
@@ -159,7 +159,7 @@
   // history cluster provider begins.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   // `done()` should be true before starting.
   EXPECT_TRUE(provider_->done());
@@ -192,7 +192,7 @@
   // Test the sync case where the search provider finds no matches.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   provider_->Start(input, false);
   EXPECT_TRUE(provider_->done());
@@ -205,7 +205,7 @@
   // Test the async case where the search provider finds no matches.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   search_provider_->done_ = false;
   provider_->Start(input, false);
@@ -225,7 +225,7 @@
   // the server are produced asyncly.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   // Simulate receiving sync search matches.
   search_provider_->done_ = false;
@@ -254,7 +254,7 @@
   // the sync pass.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   // Simulate receiving sync search matches.
   search_provider_->done_ = false;
@@ -276,7 +276,7 @@
   // Test the case where none of the search matches match a keyword.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   search_provider_->matches_ = {CreateMatch(u"key"), CreateMatch(u"keyworddd"),
                                 CreateMatch(u"Tigran Petrosian")};
@@ -296,7 +296,7 @@
   // Test the case where multiple of the search matches match a keyword.
 
   AutocompleteInput input;
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   search_provider_->matches_ = {CreateMatch(u"keyword2"),
                                 CreateMatch(u"keyword"),
diff --git a/components/omnibox/browser/history_quick_provider.cc b/components/omnibox/browser/history_quick_provider.cc
index bd1fc08..7e522c0e 100644
--- a/components/omnibox/browser/history_quick_provider.cc
+++ b/components/omnibox/browser/history_quick_provider.cc
@@ -79,10 +79,17 @@
 HistoryQuickProvider::~HistoryQuickProvider() = default;
 
 void HistoryQuickProvider::DoAutocomplete() {
+  // In keyword mode, it's possible we only provide results from one or two
+  // autocomplete provider(s), so it's sometimes necessary to show more results
+  // than provider_max_matches_.
+  size_t max_matches = InKeywordMode(autocomplete_input_)
+                           ? provider_max_matches_in_keyword_mode_
+                           : provider_max_matches_;
+
   // Get the matching URLs from the DB.
   ScoredHistoryMatches matches = in_memory_url_index_->HistoryItemsForTerms(
       autocomplete_input_.text(), autocomplete_input_.cursor_position(),
-      provider_max_matches_);
+      max_matches);
   if (matches.empty())
     return;
 
diff --git a/components/omnibox/browser/history_quick_provider_unittest.cc b/components/omnibox/browser/history_quick_provider_unittest.cc
index a18331ac..1aaaefb6 100644
--- a/components/omnibox/browser/history_quick_provider_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_unittest.cc
@@ -297,6 +297,14 @@
        "'pre suf' should score higher than 'presuf'", 3, 3, 2},
       {"https://suffix.com/prefixsuffix3",
        "'pre suf' should score higher than 'presuf'", 3, 3, 3},
+      {"http://somedomain.com/a", "a", 1, 1, 1},
+      {"http://somedomain.com/b", "b", 1, 1, 1},
+      {"http://somedomain.com/c", "c", 1, 1, 1},
+      {"http://somedomain.com/d", "d", 1, 1, 1},
+      {"http://somedomain.com/e", "e", 1, 1, 1},
+      {"http://somedomain.com/f", "f", 1, 1, 1},
+      {"http://somedomain.com/g", "g", 1, 1, 1},
+      {"http://somedomain.com/h", "h", 1, 1, 1},
   };
 }
 
@@ -979,6 +987,25 @@
   EXPECT_TRUE(match.contents.empty());
 }
 
+TEST_F(HistoryQuickProviderTest, MaxMatches) {
+  // Keyword mode is off. We should only get provider_max_matches_ matches.
+  AutocompleteInput input(u"somedomain.com", metrics::OmniboxEventProto::OTHER,
+                          TestSchemeClassifier());
+  provider().Start(input, false);
+
+  ACMatches matches = provider().matches();
+  EXPECT_EQ(matches.size(), provider().provider_max_matches());
+
+  // Turn keyword mode on. we should be able to get more matches now.
+  input.set_keyword_mode_entry_method(
+      metrics::OmniboxEventProto_KeywordModeEntryMethod_TAB);
+  input.set_prefer_keyword(true);
+  provider().Start(input, false);
+
+  matches = provider().matches();
+  EXPECT_EQ(matches.size(), provider().provider_max_matches_in_keyword_mode());
+}
+
 // HQPOrderingTest -------------------------------------------------------------
 
 class HQPOrderingTest : public HistoryQuickProviderTest {
diff --git a/components/omnibox/browser/history_url_provider.cc b/components/omnibox/browser/history_url_provider.cc
index a1db537..fcc0554 100644
--- a/components/omnibox/browser/history_url_provider.cc
+++ b/components/omnibox/browser/history_url_provider.cc
@@ -527,7 +527,7 @@
 
   // Pass 2: Ask the history service to call us back on the history thread,
   // where we can read the full on-disk DB.
-  if (search_url_database_ && autocomplete_input.want_asynchronous_matches()) {
+  if (search_url_database_ && !autocomplete_input.omit_asynchronous_matches()) {
     done_ = false;
     params_ = params.release();  // This object will be destroyed in
                                  // QueryComplete() once we're done with it.
@@ -621,22 +621,29 @@
   params->matches.clear();
   history::URLRows url_matches;
 
+  // In keyword mode, it's possible we only provide results from one or two
+  // autocomplete provider(s), so it's sometimes necessary to show more results
+  // than provider_max_matches_.
+  size_t max_matches = InKeywordMode(params->input)
+                           ? provider_max_matches_in_keyword_mode_
+                           : provider_max_matches_;
+
   if (search_url_database_) {
     const URLPrefixes& prefixes = URLPrefix::GetURLPrefixes();
     for (auto i(prefixes.begin()); i != prefixes.end(); ++i) {
       if (params->cancel_flag.IsSet())
         return;  // Canceled in the middle of a query, give up.
 
-      // We only need provider_max_matches_ results in the end, but before we
-      // get there we need to promote lower-quality matches that are prefixes of
-      // higher- quality matches, and remove lower-quality redirects.  So we ask
-      // for more results than we need, of every prefix type, in hopes this will
+      // We only need `max_matches` results in the end, but before we get there
+      // we need to promote lower-quality matches that are prefixes of higher-
+      // quality matches, and remove lower-quality redirects.  So we ask for
+      // more results than we need, of every prefix type, in hopes this will
       // give us far more than enough to work with.  CullRedirects() will then
-      // reduce the list to the best provider_max_matches_ results.
+      // reduce the list to the best `max_matches` results.
       std::string prefixed_input =
           base::UTF16ToUTF8(i->prefix + params->input.text());
-      db->AutocompleteForPrefix(prefixed_input, provider_max_matches_ * 2,
-                                !backend, &url_matches);
+      db->AutocompleteForPrefix(prefixed_input, max_matches * 2, !backend,
+                                &url_matches);
       for (history::URLRows::const_iterator j(url_matches.begin());
            j != url_matches.end(); ++j) {
         const GURL& row_url = j->url();
@@ -735,11 +742,11 @@
   }
 
   const size_t max_results =
-      provider_max_matches_ + (params->exact_suggestion_is_in_history ? 1 : 0);
+      max_matches + (params->exact_suggestion_is_in_history ? 1 : 0);
   if (backend) {
     // Remove redirects and trim list to size.  We want to provide up to
-    // provider_max_matches_ results plus the What You Typed result, if it was
-    // added to params->matches above.
+    // `max_matches` results plus the What You Typed result, if it was
+    // added to `params->matches` above.
     CullRedirects(backend, &params->matches, max_results);
   } else if (params->matches.size() > max_results) {
     // Simply trim the list to size.
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc
index b4fc5c7..d0aa22b 100644
--- a/components/omnibox/browser/history_url_provider_unittest.cc
+++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -1475,3 +1475,27 @@
   EXPECT_EQ(GURL("http://www.google.com/"), matches_[0].destination_url);
   EXPECT_TRUE(matches_[0].from_keyword);
 }
+
+TEST_F(HistoryURLProviderTest, MaxMatches) {
+  // Keyword mode is off. We should only get provider_max_matches_ matches.
+  AutocompleteInput input(u"star", metrics::OmniboxEventProto::OTHER,
+                          TestSchemeClassifier());
+  autocomplete_->Start(input, false);
+  if (!autocomplete_->done())
+    base::RunLoop().Run();
+
+  matches_ = autocomplete_->matches();
+  EXPECT_EQ(matches_.size(), autocomplete_->provider_max_matches());
+
+  // Turn keyword mode on. we should be able to get more matches now.
+  input.set_keyword_mode_entry_method(
+      metrics::OmniboxEventProto_KeywordModeEntryMethod_TAB);
+  input.set_prefer_keyword(true);
+  autocomplete_->Start(input, false);
+  if (!autocomplete_->done())
+    base::RunLoop().Run();
+
+  matches_ = autocomplete_->matches();
+  EXPECT_EQ(matches_.size(),
+            autocomplete_->provider_max_matches_in_keyword_mode());
+}
diff --git a/components/omnibox/browser/most_visited_sites_provider.cc b/components/omnibox/browser/most_visited_sites_provider.cc
index 3d20255..b2f96f7 100644
--- a/components/omnibox/browser/most_visited_sites_provider.cc
+++ b/components/omnibox/browser/most_visited_sites_provider.cc
@@ -145,7 +145,7 @@
   // If TopSites has not yet been loaded, then `OnMostVisitedUrlsAvailable` will
   // be called asynchronously, so we need to first check that async calls are
   // allowed for the given input.
-  if (!top_sites->loaded() && !input.want_asynchronous_matches()) {
+  if (!top_sites->loaded() && input.omit_asynchronous_matches()) {
     return;
   }
 
diff --git a/components/omnibox/browser/most_visited_sites_provider_unittest.cc b/components/omnibox/browser/most_visited_sites_provider_unittest.cc
index 76d5d8e..20836a3 100644
--- a/components/omnibox/browser/most_visited_sites_provider_unittest.cc
+++ b/components/omnibox/browser/most_visited_sites_provider_unittest.cc
@@ -380,7 +380,7 @@
   ASSERT_FALSE(top_sites_->loaded());
   auto input = BuildAutocompleteInputForWebOnFocus();
   input.set_focus_type(OmniboxFocusType::DEFAULT);
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
   controller_->Start(input);
   EXPECT_TRUE(provider_->done());
   EXPECT_EQ(0u, NumMostVisitedMatches());
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 0ef8573..03c930d3 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -699,7 +699,7 @@
     input.set_prefer_keyword(input_.prefer_keyword());
     input.set_keyword_mode_entry_method(input_.keyword_mode_entry_method());
     input.set_allow_exact_keyword_match(input_.allow_exact_keyword_match());
-    input.set_want_asynchronous_matches(input_.want_asynchronous_matches());
+    input.set_omit_asynchronous_matches(input_.omit_asynchronous_matches());
     input.set_focus_type(input_.focus_type());
     input_ = input;
     AutocompleteMatch url_match(VerbatimMatchForInput(
diff --git a/components/omnibox/browser/on_device_head_provider.cc b/components/omnibox/browser/on_device_head_provider.cc
index 7546947..7d5db77 100644
--- a/components/omnibox/browser/on_device_head_provider.cc
+++ b/components/omnibox/browser/on_device_head_provider.cc
@@ -112,7 +112,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_);
 
   // Only accept asynchronous request.
-  if (!input.want_asynchronous_matches() ||
+  if (input.omit_asynchronous_matches() ||
       input.type() == metrics::OmniboxInputType::EMPTY)
     return false;
 
diff --git a/components/omnibox/browser/on_device_head_provider_unittest.cc b/components/omnibox/browser/on_device_head_provider_unittest.cc
index 6a108bc..bcde71b 100644
--- a/components/omnibox/browser/on_device_head_provider_unittest.cc
+++ b/components/omnibox/browser/on_device_head_provider_unittest.cc
@@ -82,7 +82,7 @@
 TEST_F(OnDeviceHeadProviderTest, ModelInstanceNotCreated) {
   AutocompleteInput input(u"M", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
   ResetModelInstance();
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(false));
@@ -101,7 +101,7 @@
 TEST_F(OnDeviceHeadProviderTest, RejectSynchronousRequest) {
   AutocompleteInput input(u"M", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
 
   ASSERT_FALSE(IsOnDeviceHeadProviderAllowed(input));
 }
@@ -109,7 +109,7 @@
 TEST_F(OnDeviceHeadProviderTest, TestIfIncognitoIsAllowed) {
   AutocompleteInput input(u"M", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(true));
   EXPECT_CALL(*client_.get(), SearchSuggestEnabled())
@@ -124,7 +124,7 @@
 TEST_F(OnDeviceHeadProviderTest, RejectOnFocusRequest) {
   AutocompleteInput input(u"M", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
   input.set_focus_type(OmniboxFocusType::ON_FOCUS);
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(false));
@@ -136,7 +136,7 @@
 TEST_F(OnDeviceHeadProviderTest, NoMatches) {
   AutocompleteInput input(u"b", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(false));
   EXPECT_CALL(*client_.get(), SearchSuggestEnabled())
@@ -154,7 +154,7 @@
 TEST_F(OnDeviceHeadProviderTest, HasMatches) {
   AutocompleteInput input(u"M", metrics::OmniboxEventProto::OTHER,
                           TestSchemeClassifier());
-  input.set_want_asynchronous_matches(true);
+  input.set_omit_asynchronous_matches(false);
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(false));
   EXPECT_CALL(*client_.get(), SearchSuggestEnabled())
@@ -175,10 +175,10 @@
 TEST_F(OnDeviceHeadProviderTest, CancelInProgressRequest) {
   AutocompleteInput input1(u"g", metrics::OmniboxEventProto::OTHER,
                            TestSchemeClassifier());
-  input1.set_want_asynchronous_matches(true);
+  input1.set_omit_asynchronous_matches(false);
   AutocompleteInput input2(u"m", metrics::OmniboxEventProto::OTHER,
                            TestSchemeClassifier());
-  input2.set_want_asynchronous_matches(true);
+  input2.set_omit_asynchronous_matches(false);
 
   EXPECT_CALL(*client_.get(), IsOffTheRecord()).WillRepeatedly(Return(false));
   EXPECT_CALL(*client_.get(), SearchSuggestEnabled())
diff --git a/components/omnibox/browser/query_tile_provider.cc b/components/omnibox/browser/query_tile_provider.cc
index 30d03cf..87a622d 100644
--- a/components/omnibox/browser/query_tile_provider.cc
+++ b/components/omnibox/browser/query_tile_provider.cc
@@ -59,7 +59,7 @@
 
 void QueryTileProvider::Start(const AutocompleteInput& input,
                               bool minimal_changes) {
-  done_ = !input.want_asynchronous_matches();
+  done_ = input.omit_asynchronous_matches();
   matches_.clear();
   if (!AllowQueryTileSuggestions(input)) {
     done_ = true;
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index 034b57c..b1906680 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -754,12 +754,11 @@
   // For the minimal_changes case, if we finished the previous query and still
   // have its results, or are allowed to keep running it, just do that, rather
   // than starting a new query.
-  if (minimal_changes &&
-      (!default_results_.suggest_results.empty() ||
-       !default_results_.navigation_results.empty() ||
-       !keyword_results_.suggest_results.empty() ||
-       !keyword_results_.navigation_results.empty() ||
-       (!done_ && input_.want_asynchronous_matches())))
+  if (minimal_changes && (!default_results_.suggest_results.empty() ||
+                          !default_results_.navigation_results.empty() ||
+                          !keyword_results_.suggest_results.empty() ||
+                          !keyword_results_.navigation_results.empty() ||
+                          (!done_ && !input_.omit_asynchronous_matches())))
     return;
 
   // We can't keep running any previous query, so halt it.
@@ -774,7 +773,7 @@
     UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_);
 
   // We can't start a new query if we're only allowed synchronous results.
-  if (!input_.want_asynchronous_matches())
+  if (input_.omit_asynchronous_matches())
     return;
 
   // Kick off a timer that will start the URL fetch if it completes before
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index cd46b47..8aa45c9 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -13,7 +13,6 @@
 #include "base/callback.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/escape.h"
 #include "base/time/time.h"
@@ -43,6 +42,7 @@
 #include "url/gurl.h"
 
 using metrics::OmniboxEventProto;
+using metrics::OmniboxInputType;
 
 namespace {
 
@@ -50,37 +50,52 @@
 // suggestions on focus, and if not, why not.
 // These values are written to logs.  New enum values can be added, but existing
 // enums must never be renumbered or deleted and reused.
-enum class ZeroSuggestEligibility {
-  ELIGIBLE = 0,
-  // URL_INELIGIBLE would be ELIGIBLE except some property of the current URL
+enum class Eligibility {
+  kEligible = 0,
+  // kURLIneligible would be kEligible except some property of the current URL
   // itself prevents ZeroSuggest from triggering.
-  URL_INELIGIBLE = 1,
-  GENERALLY_INELIGIBLE = 2,
-  ELIGIBLE_MAX_VALUE
+  kURLIneligible = 1,
+  kGenerallyIneligible = 2,
+
+  kMaxValue = kGenerallyIneligible,
 };
 
-// Keeps track of how many Suggest requests are sent, how many requests were
-// invalidated, e.g., due to user starting to type, how many responses were
-// received, how many of those responses end up updating the results.
-// These values are written to logs.  New enum values can be added, but existing
+// The provider event types recorded as a result of prefetch and non-prefetch
+// requests for zero-prefix suggestions. Each event must be logged at most once
+// from when the provider is started until it is stopped.
+// These values are written to logs. New enum values can be added, but existing
 // enums must never be renumbered or deleted and reused.
-enum ZeroSuggestRequestsHistogramValue {
-  ZERO_SUGGEST_REQUEST_SENT = 1,
-  ZERO_SUGGEST_REQUEST_INVALIDATED = 2,
-  ZERO_SUGGEST_RESPONSE_RECEIVED = 3,
-  // ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE = 4, no longer used.
-  // ZERO_SUGGEST_CACHED_RESPONSE_IS_OUT_OF_DATE = 5,  no longer used.
-  ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS = 6,
-  ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE
+enum class Event {
+  // Cached response was synchronously converted to displayed matches.
+  KCachedResponseConvertedToMatches = 0,
+  // Remote request was sent.
+  kRequestSent = 1,
+  // Remote request was invalidated.
+  kRequestInvalidated = 2,
+  // Remote response was received asynchronously.
+  kRemoteResponseReceived = 3,
+  // Remote response was cached.
+  kRemoteResponseCached = 4,
+  // Remote response ended up being converted to displayed matches. This may
+  // happen due to an empty displayed result set or an empty remote result set.
+  kRemoteResponseConvertedToMatches = 5,
+
+  kMaxValue = kRemoteResponseConvertedToMatches,
 };
 
-void LogOmniboxZeroSuggestRequest(
-    ZeroSuggestRequestsHistogramValue request_value,
-    bool is_prefetch) {
+void LogEvent(Event event,
+              ZeroSuggestProvider::ResultType result_type,
+              bool is_prefetch) {
+  DCHECK_NE(ZeroSuggestProvider::ResultType::NONE, result_type);
+  const std::string result_type_string =
+      result_type == ZeroSuggestProvider::ResultType::REMOTE_NO_URL
+          ? ".NoURL"
+          : ".URLBased";
+  const std::string request_type_string =
+      is_prefetch ? ".Prefetch" : ".NonPrefetch";
   base::UmaHistogramEnumeration(
-      is_prefetch ? "Omnibox.ZeroSuggestRequests.Prefetch"
-                  : "Omnibox.ZeroSuggestRequests.NonPrefetch",
-      request_value, ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE);
+      "Omnibox.ZeroSuggestProvider" + result_type_string + request_type_string,
+      event);
 }
 
 // Relevance value to use if it was not set explicitly by the server.
@@ -152,9 +167,8 @@
   Stop(true, false);
 
   if (!AllowZeroSuggestSuggestions(input)) {
-    UMA_HISTOGRAM_ENUMERATION(kOmniboxZeroSuggestEligibleHistogramName,
-                              ZeroSuggestEligibility::GENERALLY_INELIGIBLE,
-                              ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE);
+    base::UmaHistogramEnumeration(kOmniboxZeroSuggestEligibleHistogramName,
+                                  Eligibility::kGenerallyIneligible);
     return;
   }
 
@@ -181,15 +195,21 @@
     done_ = false;
 
     // Prefetching is only meant to update the stored response with a fresh
-    // response. It is unnecessary to update the results when prefetching;
-    // as they will get cleared on the next call to `Start()`.
+    // response. It is unnecessary to convert it to the displayed matches when
+    // prefetching; as they will get cleared on the next call to `Start()`.
     auto response_data = ReadStoredResponse();
     if (response_data) {
-      ConvertResponseToAutocompleteMatches(std::move(response_data));
+      if (ConvertResponseToAutocompleteMatches(std::move(response_data))) {
+        LogEvent(Event::KCachedResponseConvertedToMatches, result_type_running_,
+                 is_prefetch);
+      }
     }
   }
 
-  if (!input.want_asynchronous_matches()) {
+  if (input.omit_asynchronous_matches()) {
+    // Asynchronous provider logic should only be omitted during non-prefetch
+    // ZPS requests.
+    DCHECK(!is_prefetch);
     Stop(true, false);
     return;
   }
@@ -205,8 +225,8 @@
               base::BindOnce(&ZeroSuggestProvider::OnURLLoadComplete,
                              weak_ptr_factory_.GetWeakPtr(), is_prefetch));
 
-  LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT,
-                               /*is_prefetch=*/!prefetch_done_);
+  LogEvent(Event::kRequestSent, result_type_running_,
+           /*is_prefetch=*/!prefetch_done_);
 }
 
 void ZeroSuggestProvider::Stop(bool clear_cached_results,
@@ -214,8 +234,8 @@
   AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity);
 
   if (loader_) {
-    LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED,
-                                 /*is_prefetch=*/!prefetch_done_);
+    LogEvent(Event::kRequestInvalidated, result_type_running_,
+             /*is_prefetch=*/!prefetch_done_);
   }
   loader_.reset();
   prefetch_done_ = true;
@@ -311,19 +331,21 @@
       (source->ResponseInfo() && source->ResponseInfo()->headers &&
        source->ResponseInfo()->headers->response_code() == 200);
   if (response_received) {
-    LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_RECEIVED, is_prefetch);
+    LogEvent(Event::kRemoteResponseReceived, result_type_running_, is_prefetch);
     response_data = StoreRemoteResponse(SearchSuggestionParser::ExtractJsonData(
-        source, std::move(response_body)));
+                                            source, std::move(response_body)),
+                                        is_prefetch);
   }
 
   // Prefetching is only meant to update the stored response with a fresh
-  // response. It is unnecessary to update the results with prefetched response;
-  // as they will get cleared on the next call to `Start()`.
-  const bool results_updated = response_data && !is_prefetch;
-  if (results_updated) {
-    LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS,
-                                 is_prefetch);
-    ConvertResponseToAutocompleteMatches(std::move(response_data));
+  // response. It is unnecessary to convert the prefetched response to the
+  // displayed matches; as they will get cleared on the next call to `Start()`.
+  const bool matches_updated = response_data && !is_prefetch;
+  if (matches_updated) {
+    if (ConvertResponseToAutocompleteMatches(std::move(response_data))) {
+      LogEvent(Event::kRemoteResponseConvertedToMatches, result_type_running_,
+               is_prefetch);
+    }
   }
 
   loader_.reset();
@@ -333,11 +355,12 @@
 
   // Do not notify the provider listener for prefetch requests.
   if (!is_prefetch)
-    NotifyListeners(results_updated);
+    NotifyListeners(matches_updated);
 }
 
 std::unique_ptr<base::Value> ZeroSuggestProvider::StoreRemoteResponse(
-    const std::string& response_json) {
+    const std::string& response_json,
+    bool is_prefetch) {
   if (response_json.empty()) {
     return nullptr;
   }
@@ -348,28 +371,30 @@
     return nullptr;
   }
 
+  SearchSuggestionParser::Results results;
+  if (!ParseSuggestResults(*response_data, kDefaultZeroSuggestRelevance,
+                           /*is_keyword_result=*/false, &results)) {
+    return nullptr;
+  }
+
   // Store the valid response only if running the REMOTE_NO_URL variant.
   if (result_type_running_ == REMOTE_NO_URL) {
     client()->GetPrefs()->SetString(omnibox::kZeroSuggestCachedResults,
                                     response_json);
+    LogEvent(Event::kRemoteResponseCached, result_type_running_, is_prefetch);
   }
 
-  // For display stability reasons, use the remote response to update the
-  // displayed results, if they are empty or if an empty result set is received;
-  // in which case, the display may be showing results that should not be shown.
-  const bool non_empty_matches = !matches().empty();
-  if (non_empty_matches) {
-    SearchSuggestionParser::Results results;
-    ParseSuggestResults(*response_data, kDefaultZeroSuggestRelevance, false,
-                        &results);
-    const bool non_empty_response =
-        !results.suggest_results.empty() || !results.navigation_results.empty();
-    if (non_empty_response) {
-      return nullptr;
-    }
+  // For display stability reasons, update the displayed results with the remote
+  // response only if they are empty or if an empty result set is received. In
+  // the latter case, the displayed results may no longer be valid to be shown.
+  const bool empty_matches = matches().empty();
+  const bool empty_results =
+      results.suggest_results.empty() && results.navigation_results.empty();
+  if (empty_matches || empty_results) {
+    return response_data;
   }
 
-  return response_data;
+  return nullptr;
 }
 
 std::unique_ptr<base::Value> ZeroSuggestProvider::ReadStoredResponse() {
@@ -415,16 +440,15 @@
   return match;
 }
 
-void ZeroSuggestProvider::ConvertResponseToAutocompleteMatches(
-    std::unique_ptr<base::Value> response) {
-  DCHECK(response);
-
-  matches_.clear();
-  suggestion_groups_map_.clear();
-  experiment_stats_v2s_.clear();
+bool ZeroSuggestProvider::ConvertResponseToAutocompleteMatches(
+    std::unique_ptr<base::Value> response_data) {
+  DCHECK(response_data);
 
   SearchSuggestionParser::Results results;
-  ParseSuggestResults(*response, kDefaultZeroSuggestRelevance, false, &results);
+  if (!ParseSuggestResults(*response_data, kDefaultZeroSuggestRelevance,
+                           /*is_keyword_result=*/false, &results)) {
+    return false;
+  }
 
   TemplateURLService* template_url_service = client()->GetTemplateURLService();
   DCHECK(template_url_service);
@@ -433,8 +457,13 @@
   // Fail if we can't set the clickthrough URL for query suggestions.
   if (default_provider == nullptr ||
       !default_provider->SupportsReplacement(
-          template_url_service->search_terms_data()))
-    return;
+          template_url_service->search_terms_data())) {
+    return false;
+  }
+
+  matches_.clear();
+  suggestion_groups_map_.clear();
+  experiment_stats_v2s_.clear();
 
   MatchMap map;
 
@@ -448,15 +477,17 @@
   const int num_query_results = map.size();
   const int num_nav_results = results.navigation_results.size();
   const int num_results = num_query_results + num_nav_results;
-  UMA_HISTOGRAM_COUNTS_1M("ZeroSuggest.QueryResults", num_query_results);
-  UMA_HISTOGRAM_COUNTS_1M("ZeroSuggest.URLResults", num_nav_results);
-  UMA_HISTOGRAM_COUNTS_1M("ZeroSuggest.AllResults", num_results);
+  base::UmaHistogramCounts1M("ZeroSuggest.QueryResults", num_query_results);
+  base::UmaHistogramCounts1M("ZeroSuggest.URLResults", num_nav_results);
+  base::UmaHistogramCounts1M("ZeroSuggest.AllResults", num_results);
 
-  if (num_results == 0)
-    return;
+  if (num_results == 0) {
+    return true;
+  }
 
-  for (MatchMap::const_iterator it(map.begin()); it != map.end(); ++it)
+  for (MatchMap::const_iterator it(map.begin()); it != map.end(); ++it) {
     matches_.push_back(it->second);
+  }
 
   const SearchSuggestionParser::NavigationResults& nav_results(
       results.navigation_results);
@@ -473,6 +504,8 @@
   for (const auto& experiment_stats_v2 : results.experiment_stats_v2s) {
     experiment_stats_v2s_.push_back(experiment_stats_v2);
   }
+
+  return true;
 }
 
 bool ZeroSuggestProvider::AllowZeroSuggestSuggestions(
@@ -487,15 +520,15 @@
   if (client()->IsOffTheRecord())
     return false;
 
-  if (input_type == metrics::OmniboxInputType::EMPTY) {
+  if (input_type == OmniboxInputType::EMPTY) {
     // Function that returns whether EMPTY input zero-suggest is allowed.
     auto IsEmptyZeroSuggestAllowed = [&]() {
-      if (page_class == metrics::OmniboxEventProto::CHROMEOS_APP_LIST ||
+      if (page_class == OmniboxEventProto::CHROMEOS_APP_LIST ||
           IsNTPPage(page_class)) {
         return true;
       }
 
-      if (page_class == metrics::OmniboxEventProto::OTHER) {
+      if (page_class == OmniboxEventProto::OTHER) {
         return input.focus_type() == OmniboxFocusType::DELETED_PERMANENT_TEXT &&
                base::FeatureList::IsEnabled(
                    omnibox::kClobberTriggersContextualWebZeroSuggest);
@@ -524,7 +557,7 @@
   // is running, these types of schemes aren't eligible to be sent to the
   // server to ask for suggestions (and thus in practice we won't display zero
   // suggest for them).
-  if (input_type != metrics::OmniboxInputType::EMPTY &&
+  if (input_type != OmniboxInputType::EMPTY &&
       !(page_url.is_valid() &&
         ((page_url.scheme() == url::kHttpScheme) ||
          (page_url.scheme() == url::kHttpsScheme) ||
@@ -551,7 +584,7 @@
       template_url_service->GetDefaultSearchProvider();
 
   GURL current_url = input.current_url();
-  metrics::OmniboxEventProto::PageClassification current_page_classification =
+  OmniboxEventProto::PageClassification current_page_classification =
       input.current_page_classification();
 
   const bool can_send_current_url = CanSendURL(
@@ -559,19 +592,17 @@
       template_url_service->search_terms_data(), client, false);
   // Collect metrics on eligibility.
   GURL arbitrary_insecure_url(kArbitraryInsecureUrlString);
-  ZeroSuggestEligibility eligibility = ZeroSuggestEligibility::ELIGIBLE;
+  Eligibility eligibility = Eligibility::kEligible;
   if (!can_send_current_url) {
     const bool can_send_ordinary_url =
         CanSendURL(arbitrary_insecure_url, suggest_url, default_provider,
                    current_page_classification,
                    template_url_service->search_terms_data(), client, false);
-    eligibility = can_send_ordinary_url
-                      ? ZeroSuggestEligibility::URL_INELIGIBLE
-                      : ZeroSuggestEligibility::GENERALLY_INELIGIBLE;
+    eligibility = can_send_ordinary_url ? Eligibility::kURLIneligible
+                                        : Eligibility::kGenerallyIneligible;
   }
-  UMA_HISTOGRAM_ENUMERATION(
-      kOmniboxZeroSuggestEligibleHistogramName, static_cast<int>(eligibility),
-      static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE));
+  base::UmaHistogramEnumeration(kOmniboxZeroSuggestEligibleHistogramName,
+                                eligibility);
 
   if (current_page_classification == OmniboxEventProto::CHROMEOS_APP_LIST ||
       current_page_classification ==
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h
index 4798570..a86d5b33 100644
--- a/components/omnibox/browser/zero_suggest_provider.h
+++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -60,7 +60,7 @@
   static ZeroSuggestProvider* Create(AutocompleteProviderClient* client,
                                      AutocompleteProviderListener* listener);
 
-  // Registers a preference used to cache zero suggest results.
+  // Registers a preference used to cache the zero suggest response.
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
   // AutocompleteProvider:
@@ -121,27 +121,38 @@
                          const network::SimpleURLLoader* source,
                          std::unique_ptr<std::string> response_body);
 
-  // Called when the remote response is received. Stores the remote response in
-  // the user prefs, if valid and applicable based on |result_type_running_|.
-  //
-  // Returns the successfully parsed response if it is eligible to update the
-  // displayed results or nullptr otherwise.
-  std::unique_ptr<base::Value> StoreRemoteResponse(
-      const std::string& response_json);
-
-  // Returns the response stored in the user prefs, if applicable based on
+  // Called when the remote response is received. Stores the response json in
+  // the user prefs, if successfully parsed and if applicable based on
   // |result_type_running_|.
-  // Returns the successfully parsed response or nullptr otherwise.
+  //
+  // Returns the successfully parsed response if it is eligible to be converted
+  // to |matches_| or nullptr otherwise.
+  std::unique_ptr<base::Value> StoreRemoteResponse(
+      const std::string& response_json,
+      bool is_prefetch);
+
+  // Called on Start().
+  //
+  // Returns the response stored in the user prefs, if applicable based on
+  // |result_type_running_| or nullptr otherwise.
   std::unique_ptr<base::Value> ReadStoredResponse();
 
   // Returns an AutocompleteMatch for a navigational suggestion |navigation|.
   AutocompleteMatch NavigationToMatch(
       const SearchSuggestionParser::NavigationResult& navigation);
 
-  // Converts the parsed response to a set of AutocompleteMatches and populates
-  // |matches_| and its associated metadata. Also records histograms for how
-  // many results were received.
-  void ConvertResponseToAutocompleteMatches(
+  // Called on Start() with the cached response (where |matches_| is empty), or
+  // when the remote response is received and is eligible to be converted to
+  // |matches_| (where |matches_| may not be empty).
+  //
+  // If the given response can be successfully parsed, converts it to a set of
+  // AutocompleteMatches and populates |matches_| as well as its associated
+  // metadata, if applicable. Also logs how many results were received.
+  //
+  // Returns whether the response was successfully converted to |matches_|.
+  // Note that this does not imply |matches_| were populated with the response.
+  // An empty result set in the response will clear |matches_| and return true.
+  bool ConvertResponseToAutocompleteMatches(
       std::unique_ptr<base::Value> response);
 
   // Whether zero suggest suggestions are allowed in the given context.
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc
index 5b8bb68..3465784 100644
--- a/components/omnibox/browser/zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -494,16 +494,25 @@
   EXPECT_TRUE(provider_->done());
 
   // Expect correct histograms to have been logged.
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                    3);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     1 /*ZERO_SUGGEST_REQUEST_SENT*/, 1);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     3 /*ZERO_SUGGEST_RESPONSE_RECEIVED*/, 1);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 4);
   histogram_tester.ExpectBucketCount(
-      "Omnibox.ZeroSuggestRequests.NonPrefetch",
-      6 /*ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS*/, 1);
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.Prefetch", 0);
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 1 /*REQUEST_SENT*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      3 /*REMOTE_RESPONSE_RECEIVED*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      4 /*REMOTE_RESPONSE_CACHED*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      5 /*REMOTE_RESPONSE_CONVERTED_TO_MATCHES*/, 1);
 
   // Expect the provider to have notified the provider listener.
   EXPECT_TRUE(provider_did_notify_);
@@ -520,7 +529,7 @@
       .WillRepeatedly(testing::Return(true));
 
   AutocompleteInput input = CreateNTPOnFocusInputForRemoteNoUrl();
-  input.set_want_asynchronous_matches(false);
+  input.set_omit_asynchronous_matches(true);
 
   GURL suggest_url = GetSuggestURL(
       metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS);
@@ -532,7 +541,7 @@
             provider_->GetResultTypeRunningForTesting());
 
   // There should be no pending network requests, given that asynchronous logic
-  // has been explicitly disabled (`want_asynchronous_matches_ == false`).
+  // has been explicitly disabled (`omit_asynchronous_matches_ == true`).
   ASSERT_FALSE(test_loader_factory()->IsPending(suggest_url.spec()));
   EXPECT_TRUE(provider_->done());
   EXPECT_TRUE(provider_->matches().empty());
@@ -584,16 +593,25 @@
   EXPECT_TRUE(provider_did_notify_);
 
   // Expect correct histograms to have been logged.
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                    2);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     1 /*ZERO_SUGGEST_REQUEST_SENT*/, 1);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     3 /*ZERO_SUGGEST_RESPONSE_RECEIVED*/, 1);
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 4);
   histogram_tester.ExpectBucketCount(
-      "Omnibox.ZeroSuggestRequests.NonPrefetch",
-      6 /*ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS*/, 0);
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 1 /*REQUEST_SENT*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      3 /*REMOTE_RESPONSE_RECEIVED*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      4 /*REMOTE_RESPONSE_CACHED*/, 1);
 
   // Expect the same results after the response has been handled.
   ASSERT_EQ(3U, provider_->matches().size());  // 3 results, no verbatim match
@@ -640,16 +658,28 @@
   EXPECT_TRUE(provider_->done());
 
   // Expect correct histograms to have been logged.
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                    3);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     1 /*ZERO_SUGGEST_REQUEST_SENT*/, 1);
-  histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                     3 /*ZERO_SUGGEST_RESPONSE_RECEIVED*/, 1);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0);
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 5);
   histogram_tester.ExpectBucketCount(
-      "Omnibox.ZeroSuggestRequests.NonPrefetch",
-      6 /*ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS*/, 1);
-  histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.Prefetch", 0);
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 1 /*REQUEST_SENT*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      3 /*REMOTE_RESPONSE_RECEIVED*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      4 /*REMOTE_RESPONSE_CACHED*/, 1);
+  histogram_tester.ExpectBucketCount(
+      "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+      5 /*REMOTE_RESPONSE_CONVERTED_TO_MATCHES*/, 1);
 
   // Expect the provider to have notified the provider listener.
   EXPECT_TRUE(provider_did_notify_);
@@ -700,17 +730,22 @@
     EXPECT_TRUE(provider_->done());
 
     // Expect correct histograms to have been logged.
-    histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.Prefetch",
-                                      2);
-    histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.Prefetch",
-                                       1 /*ZERO_SUGGEST_REQUEST_SENT*/, 1);
-    histogram_tester.ExpectBucketCount("Omnibox.ZeroSuggestRequests.Prefetch",
-                                       3 /*ZERO_SUGGEST_RESPONSE_RECEIVED*/, 1);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 3);
     histogram_tester.ExpectBucketCount(
-        "Omnibox.ZeroSuggestRequests.NonPrefetch",
-        6 /*ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS*/, 0);
-    histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                      0);
+        "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 1 /*REQUEST_SENT*/, 1);
+    histogram_tester.ExpectBucketCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.Prefetch",
+        3 /*REMOTE_RESPONSE_RECEIVED*/, 1);
+    histogram_tester.ExpectBucketCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.Prefetch",
+        4 /*REMOTE_RESPONSE_CACHED*/, 1);
 
     // Expect the provider not to have notified the provider listener.
     EXPECT_FALSE(provider_did_notify_);
@@ -751,19 +786,25 @@
     EXPECT_TRUE(provider_->done());
 
     // Expect correct histograms to have been logged.
-    histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.NonPrefetch",
-                                      2);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0);
+    histogram_tester.ExpectTotalCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 4);
     histogram_tester.ExpectBucketCount(
-        "Omnibox.ZeroSuggestRequests.NonPrefetch",
-        1 /*ZERO_SUGGEST_REQUEST_SENT*/, 1);
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+        0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1);
     histogram_tester.ExpectBucketCount(
-        "Omnibox.ZeroSuggestRequests.NonPrefetch",
-        3 /*ZERO_SUGGEST_RESPONSE_RECEIVED*/, 1);
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 1 /*REQUEST_SENT*/, 1);
     histogram_tester.ExpectBucketCount(
-        "Omnibox.ZeroSuggestRequests.NonPrefetch",
-        6 /*ZERO_SUGGEST_RESPONSE_UPDATED_RESULTS*/, 0);
-    histogram_tester.ExpectTotalCount("Omnibox.ZeroSuggestRequests.Prefetch",
-                                      0);
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+        3 /*REMOTE_RESPONSE_RECEIVED*/, 1);
+    histogram_tester.ExpectBucketCount(
+        "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch",
+        4 /*REMOTE_RESPONSE_CACHED*/, 1);
 
     // Expect the provider to have notified the provider listener.
     EXPECT_TRUE(provider_did_notify_);
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc b/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
index 58eaa6f..fe925473 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
+++ b/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
@@ -4,6 +4,7 @@
 
 #include "components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h"
 
+#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/checked_math.h"
 #include "base/time/default_tick_clock.h"
@@ -283,10 +284,17 @@
   if (result.ad_density_by_area) {
     max_page_ad_density_by_area_ = std::max(result.ad_density_by_area.value(),
                                             max_page_ad_density_by_area_);
+
+    VLOG(2) << "page-ad-density by area: " << result.ad_density_by_area.value()
+            << " (max: " << max_page_ad_density_by_area_ << ")";
   }
   if (result.ad_density_by_height) {
     max_page_ad_density_by_height_ = std::max(
         result.ad_density_by_height.value(), max_page_ad_density_by_height_);
+
+    VLOG(2) << "page-ad-density by height: "
+            << result.ad_density_by_height.value()
+            << " (max: " << max_page_ad_density_by_height_ << ")";
   }
 }
 
@@ -298,6 +306,18 @@
 
   AccumulateOutstandingViewportAdDensity();
   last_viewport_ad_density_by_area_ = result.ad_density_by_area.value();
+
+  if (VLOG_IS_ON(2)) {
+    UnivariateStats::DistributionMoments moments =
+        viewport_ad_density_by_area_stats_.CalculateStats();
+    VLOG(2) << "viewport-ad-density by area: "
+            << last_viewport_ad_density_by_area_
+            << " (mean: " << base::ClampRound(moments.mean)
+            << ", variance: " << base::ClampRound(moments.variance)
+            << ", skewness: " << base::ClampRound(moments.skewness)
+            << ", kurtosis: " << base::ClampRound(moments.excess_kurtosis)
+            << ")";
+  }
 }
 
 // Ad density measurement uses a modified Bentley's Algorithm, the high level
diff --git a/components/permissions/contexts/window_placement_permission_context.cc b/components/permissions/contexts/window_placement_permission_context.cc
index 34a7914..bc39e59 100644
--- a/components/permissions/contexts/window_placement_permission_context.cc
+++ b/components/permissions/contexts/window_placement_permission_context.cc
@@ -21,6 +21,17 @@
 
 WindowPlacementPermissionContext::~WindowPlacementPermissionContext() = default;
 
+#if BUILDFLAG(IS_ANDROID)
+ContentSetting WindowPlacementPermissionContext::GetPermissionStatusInternal(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& requesting_origin,
+    const GURL& embedding_origin) const {
+  // TODO(crbug.com/897300): Add window-placement support on Android.
+  NOTIMPLEMENTED_LOG_ONCE() << "window-placement permission is not supported";
+  return CONTENT_SETTING_BLOCK;
+}
+#endif  // IS_ANDROID
+
 bool WindowPlacementPermissionContext::IsRestrictedToSecureOrigins() const {
   return true;
 }
diff --git a/components/permissions/contexts/window_placement_permission_context.h b/components/permissions/contexts/window_placement_permission_context.h
index 7c13ae1..a662049 100644
--- a/components/permissions/contexts/window_placement_permission_context.h
+++ b/components/permissions/contexts/window_placement_permission_context.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_PERMISSIONS_CONTEXTS_WINDOW_PLACEMENT_PERMISSION_CONTEXT_H_
 #define COMPONENTS_PERMISSIONS_CONTEXTS_WINDOW_PLACEMENT_PERMISSION_CONTEXT_H_
 
+#include "build/build_config.h"
 #include "components/permissions/permission_context_base.h"
 
 namespace permissions {
@@ -22,6 +23,12 @@
 
  protected:
   // PermissionContextBase:
+#if BUILDFLAG(IS_ANDROID)
+  ContentSetting GetPermissionStatusInternal(
+      content::RenderFrameHost* render_frame_host,
+      const GURL& requesting_origin,
+      const GURL& embedding_origin) const override;
+#endif  // IS_ANDROID
   bool IsRestrictedToSecureOrigins() const override;
   void UserMadePermissionDecision(const PermissionRequestID& id,
                                   const GURL& requesting_origin,
diff --git a/components/permissions/permission_manager_unittest.cc b/components/permissions/permission_manager_unittest.cc
index b2df7827..a4e3f51 100644
--- a/components/permissions/permission_manager_unittest.cc
+++ b/components/permissions/permission_manager_unittest.cc
@@ -315,6 +315,11 @@
 #if BUILDFLAG(IS_ANDROID)
   CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
                         GetDefaultProtectedMediaIdentifierPermissionStatus());
+  CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT,
+                        PermissionStatus::DENIED);
+#else
+  CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT,
+                        PermissionStatus::ASK);
 #endif
 }
 
@@ -334,6 +339,14 @@
                 CONTENT_SETTING_ALLOW);
   CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER,
                         PermissionStatus::GRANTED);
+
+  SetPermission(ContentSettingsType::WINDOW_PLACEMENT, CONTENT_SETTING_ALLOW);
+  CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT,
+                        PermissionStatus::DENIED);
+#else
+  SetPermission(ContentSettingsType::WINDOW_PLACEMENT, CONTENT_SETTING_ALLOW);
+  CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT,
+                        PermissionStatus::GRANTED);
 #endif
 }
 
diff --git a/components/permissions/test/permission_test_util.cc b/components/permissions/test/permission_test_util.cc
index 8508c369..7fdbd81 100644
--- a/components/permissions/test/permission_test_util.cc
+++ b/components/permissions/test/permission_test_util.cc
@@ -5,6 +5,7 @@
 #include "components/permissions/test/permission_test_util.h"
 
 #include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/contexts/window_placement_permission_context.h"
 #include "components/permissions/permission_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
@@ -74,6 +75,8 @@
           browser_context, ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
           blink::mojom::PermissionsPolicyFeature::kEncryptedMedia);
 #endif
+  permission_contexts[ContentSettingsType::WINDOW_PLACEMENT] =
+      std::make_unique<WindowPlacementPermissionContext>(browser_context);
   return permission_contexts;
 }
 
diff --git a/components/policy/resources/webui/BUILD.gn b/components/policy/resources/webui/BUILD.gn
index 4259578..4f4c1e9 100644
--- a/components/policy/resources/webui/BUILD.gn
+++ b/components/policy/resources/webui/BUILD.gn
@@ -2,14 +2,16 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//tools/polymer/html_to_js.gni")
+import("//tools/polymer/html_to_wrapper.gni")
 
-html_to_js("web_components") {
-  js_files = [
-    "policy_conflict.js",
-    "policy_row.js",
-    "policy_precedence_row.js",
-    "policy_table.js",
-    "status_box.js",
+html_to_wrapper("html_wrapper_files") {
+  in_files = [
+    "policy_conflict.html",
+    "policy_row.html",
+    "policy_precedence_row.html",
+    "policy_table.html",
+    "status_box.html",
   ]
+  template = "native"
+  use_js = true
 }
diff --git a/components/policy/resources/webui/policy_conflict.js b/components/policy/resources/webui/policy_conflict.js
index b2bf14b..220745c8 100644
--- a/components/policy/resources/webui/policy_conflict.js
+++ b/components/policy/resources/webui/policy_conflict.js
@@ -6,7 +6,8 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+
+import {getTemplate} from './policy_conflict.html.js';
 
 /**
  * @typedef {{
@@ -20,7 +21,7 @@
 
 export class PolicyConflictElement extends CustomElement {
   static get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   connectedCallback() {
diff --git a/components/policy/resources/webui/policy_precedence_row.js b/components/policy/resources/webui/policy_precedence_row.js
index bed3445..bb965a9 100644
--- a/components/policy/resources/webui/policy_precedence_row.js
+++ b/components/policy/resources/webui/policy_precedence_row.js
@@ -5,11 +5,12 @@
 import './strings.m.js';
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+
+import {getTemplate} from './policy_precedence_row.html.js';
 
 export class PolicyPrecedenceRowElement extends CustomElement {
   static get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   connectedCallback() {
diff --git a/components/policy/resources/webui/policy_row.js b/components/policy/resources/webui/policy_row.js
index 57d9a7b..f37d6454 100644
--- a/components/policy/resources/webui/policy_row.js
+++ b/components/policy/resources/webui/policy_row.js
@@ -8,7 +8,8 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+
+import {getTemplate} from './policy_row.html.js';
 
 /**
  * @typedef {{
@@ -33,7 +34,7 @@
 
 export class PolicyRowElement extends CustomElement {
   static get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   connectedCallback() {
diff --git a/components/policy/resources/webui/policy_table.js b/components/policy/resources/webui/policy_table.js
index 4e3a956..bcecae83 100644
--- a/components/policy/resources/webui/policy_table.js
+++ b/components/policy/resources/webui/policy_table.js
@@ -8,7 +8,8 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+
+import {getTemplate} from './policy_table.html.js';
 
 /**
  * @typedef {{
@@ -23,7 +24,7 @@
 
 export class PolicyTableElement extends CustomElement {
   static get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   constructor() {
diff --git a/components/policy/resources/webui/status_box.js b/components/policy/resources/webui/status_box.js
index 1ca67f0..5aa264f 100644
--- a/components/policy/resources/webui/status_box.js
+++ b/components/policy/resources/webui/status_box.js
@@ -6,11 +6,12 @@
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
+
+import {getTemplate} from './status_box.html.js';
 
 export class StatusBoxElement extends CustomElement {
   static get template() {
-    return getTrustedHTML`{__html_template__}`;
+    return getTemplate();
   }
 
   /**
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn
index 62a60c7..de780a3 100644
--- a/components/resources/BUILD.gn
+++ b/components/resources/BUILD.gn
@@ -72,7 +72,7 @@
 
   deps = [
     "//components/local_state:build",
-    "//components/policy/resources/webui:web_components",
+    "//components/policy/resources/webui:html_wrapper_files",
   ]
   output_dir = "$root_gen_dir/components"
 }
diff --git a/components/resources/policy_resources.grdp b/components/resources/policy_resources.grdp
index dfcf018..1b50e212 100644
--- a/components/resources/policy_resources.grdp
+++ b/components/resources/policy_resources.grdp
@@ -4,9 +4,14 @@
   <include name="IDR_POLICY_HTML" file="../policy/resources/webui/policy.html" type="BINDATA" />
   <include name="IDR_POLICY_BASE_JS" file="../policy/resources/webui/policy_base.js" preprocess="true" type="BINDATA" />
   <include name="IDR_POLICY_JS" file="../policy/resources/webui/policy.js" type="BINDATA" />
-  <include name="IDR_POLICY_POLICY_CONFLICT_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_conflict.js" preprocess="true" use_base_dir="false" type="BINDATA" />
-  <include name="IDR_POLICY_POLICY_ROW_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_row.js" preprocess="true" use_base_dir="false" type="BINDATA" />
-  <include name="IDR_POLICY_POLICY_PRECEDENCE_ROW_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_precedence_row.js" preprocess="true" use_base_dir="false" type="BINDATA" />
-  <include name="IDR_POLICY_POLICY_TABLE_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_table.js" preprocess="true" use_base_dir="false" type="BINDATA" />
-  <include name="IDR_POLICY_STATUS_BOX_JS" file="${root_gen_dir}/components/policy/resources/webui/status_box.js" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_CONFLICT_HTML_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_conflict.html.js" preprocess="true" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_CONFLICT_JS" file="../policy/resources/webui/policy_conflict.js" preprocess="true" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_PRECEDENCE_ROW_HTML_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_precedence_row.html.js" preprocess="true" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_PRECEDENCE_ROW_JS" file="../policy/resources/webui/policy_precedence_row.js" preprocess="true" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_ROW_HTML_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_row.html.js" preprocess="true" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_ROW_JS" file="../policy/resources/webui/policy_row.js" preprocess="true" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_TABLE_HTML_JS" file="${root_gen_dir}/components/policy/resources/webui/policy_table.html.js" preprocess="true" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_POLICY_TABLE_JS" file="../policy/resources/webui/policy_table.js" preprocess="true" type="BINDATA" />
+  <include name="IDR_POLICY_STATUS_BOX_HTML_JS" file="${root_gen_dir}/components/policy/resources/webui/status_box.html.js" use_base_dir="false" type="BINDATA" />
+  <include name="IDR_POLICY_STATUS_BOX_JS" file="../policy/resources/webui/status_box.js" type="BINDATA" />
 </grit-part>
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json
index df0773c..42bbc4b1 100644
--- a/components/search_engines/prepopulated_engines.json
+++ b/components/search_engines/prepopulated_engines.json
@@ -28,7 +28,7 @@
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version. Otherwise, existing data may
     // continue to be used and updates made here will not always appear.
-    "kCurrentDataVersion": 131
+    "kCurrentDataVersion": 132
   },
 
   // The following engines are included in country lists and are added to the
@@ -139,7 +139,7 @@
       "name": "@MAIL.RU",
       "keyword": "mail.ru",
       "favicon_url": "https://go.imgsmail.ru/favicon.ico",
-      "search_url": "https://go.mail.ru/search?q={searchTerms}&{mailru:referralID}",
+      "search_url": "https://go.mail.ru/search?q={searchTerms}&{mailru:referralID}&fr=ch_omnibox",
       "alternate_urls": [
         "https://go.mail.ru/msearch?q={searchTerms}&{mailru:referralID}"
       ],
diff --git a/components/test/data/web_database/version_104.sql b/components/test/data/web_database/version_104.sql
new file mode 100644
index 0000000..3bd301b
--- /dev/null
+++ b/components/test/data/web_database/version_104.sql
@@ -0,0 +1,32 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO meta VALUES('mmap_status','-1');
+INSERT INTO meta VALUES('version','104');
+INSERT INTO meta VALUES('last_compatible_version','100');
+INSERT INTO meta VALUES('Builtin Keyword Version','127');
+CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR,alternate_urls VARCHAR,image_url VARCHAR,search_url_post_params VARCHAR,suggest_url_post_params VARCHAR,image_url_post_params VARCHAR,new_tab_url VARCHAR,last_visited INTEGER DEFAULT 0, created_from_play_api INTEGER DEFAULT 0, is_active INTEGER DEFAULT 0, starter_pack_id INTEGER DEFAULT 0);
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, date_created INTEGER DEFAULT 0, date_last_used INTEGER DEFAULT 0, count INTEGER DEFAULT 1, PRIMARY KEY (name, value));
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR, nickname VARCHAR);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, street_address VARCHAR, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, sorting_code VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', language_code VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, label VARCHAR, disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profile_addresses ( guid VARCHAR, street_address VARCHAR, street_name VARCHAR, dependent_street_name VARCHAR, house_number VARCHAR, subpremise VARCHAR, premise_name VARCHAR, street_address_status INTEGER DEFAULT 0, street_name_status INTEGER DEFAULT 0, dependent_street_name_status INTEGER DEFAULT 0, house_number_status INTEGER DEFAULT 0, subpremise_status INTEGER DEFAULT 0, premise_name_status INTEGER DEFAULT 0, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zip_code VARCHAR, sorting_code VARCHAR, country_code VARCHAR, dependent_locality_status INTEGER DEFAULT 0, city_status INTEGER DEFAULT 0, state_status INTEGER DEFAULT 0, zip_code_status INTEGER DEFAULT 0, sorting_code_status INTEGER DEFAULT 0, country_code_status INTEGER DEFAULT 0, apartment_number VARCHAR, floor VARCHAR, apartment_number_status INTEGER DEFAULT 0, floor_status INTEGER DEFAULT 0);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, full_name VARCHAR, honorific_prefix VARCHAR, first_last_name VARCHAR, conjunction_last_name VARCHAR, second_last_name VARCHAR, honorific_prefix_status INTEGER DEFAULT 0, first_name_status INTEGER DEFAULT 0, middle_name_status INTEGER DEFAULT 0, last_name_status INTEGER DEFAULT 0, first_last_name_status INTEGER DEFAULT 0, conjunction_last_name_status INTEGER DEFAULT 0, second_last_name_status INTEGER DEFAULT 0, full_name_status INTEGER DEFAULT 0, full_name_with_honorific_prefix VARCHAR, full_name_with_honorific_prefix_status INTEGER DEFAULT 0);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, number VARCHAR);
+CREATE TABLE masked_credit_cards (id VARCHAR,name_on_card VARCHAR,network VARCHAR,last_four VARCHAR,exp_month INTEGER DEFAULT 0,exp_year INTEGER DEFAULT 0, bank_name VARCHAR, nickname VARCHAR, card_issuer INTEGER DEFAULT 0, instrument_id INTEGER DEFAULT 0, virtual_card_enrollment_state INTEGER DEFAULT 0, card_art_url VARCHAR, product_description VARCHAR);
+CREATE TABLE unmasked_credit_cards (id VARCHAR,card_number_encrypted VARCHAR,unmask_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE server_card_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
+CREATE TABLE server_addresses (id VARCHAR,company_name VARCHAR,street_address VARCHAR,address_1 VARCHAR,address_2 VARCHAR,address_3 VARCHAR,address_4 VARCHAR,postal_code VARCHAR,sorting_code VARCHAR,country_code VARCHAR,language_code VARCHAR, recipient_name VARCHAR, phone_number VARCHAR);
+CREATE TABLE server_address_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, has_converted BOOL NOT NULL DEFAULT FALSE);
+CREATE TABLE autofill_sync_metadata (model_type INTEGER NOT NULL, storage_key VARCHAR NOT NULL, value BLOB, PRIMARY KEY (model_type, storage_key));
+CREATE TABLE autofill_model_type_state (model_type INTEGER NOT NULL PRIMARY KEY, value BLOB);
+CREATE TABLE payments_customer_data (customer_id VARCHAR);
+CREATE TABLE payments_upi_vpa (vpa VARCHAR);
+CREATE TABLE server_card_cloud_token_data ( id VARCHAR, suffix VARCHAR, exp_month INTEGER DEFAULT 0, exp_year INTEGER DEFAULT 0, card_art_url VARCHAR, instrument_token VARCHAR);
+CREATE TABLE offer_data ( offer_id UNSIGNED LONG, offer_reward_amount VARCHAR, expiry UNSIGNED LONG, offer_details_url VARCHAR, merchant_domain VARCHAR, promo_code VARCHAR, value_prop_text VARCHAR, see_details_text VARCHAR, usage_instructions_text VARCHAR);
+CREATE TABLE offer_eligible_instrument ( offer_id UNSIGNED LONG,instrument_id UNSIGNED LONG);
+CREATE TABLE offer_merchant_domain ( offer_id UNSIGNED LONG,merchant_domain VARCHAR);
+CREATE INDEX autofill_name ON autofill (name);
+CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
+COMMIT;
diff --git a/components/user_education/common/tutorial_service.h b/components/user_education/common/tutorial_service.h
index dc05364..5e8d84c 100644
--- a/components/user_education/common/tutorial_service.h
+++ b/components/user_education/common/tutorial_service.h
@@ -48,10 +48,11 @@
   void HideCurrentBubbleIfShowing();
 
   // Starts the tutorial by looking for the id in the Tutorial Registry.
-  bool StartTutorial(TutorialIdentifier id,
-                     ui::ElementContext context,
-                     CompletedCallback completed_callback = base::DoNothing(),
-                     AbortedCallback aborted_callback = base::DoNothing());
+  virtual bool StartTutorial(
+      TutorialIdentifier id,
+      ui::ElementContext context,
+      CompletedCallback completed_callback = base::DoNothing(),
+      AbortedCallback aborted_callback = base::DoNothing());
 
   void LogIPHLinkClicked(TutorialIdentifier id, bool iph_link_was_clicked);
 
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 838327ab..14c8ee0 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -241,8 +241,6 @@
     "quads/shared_quad_state.h",
     "quads/solid_color_draw_quad.cc",
     "quads/solid_color_draw_quad.h",
-    "quads/stream_video_draw_quad.cc",
-    "quads/stream_video_draw_quad.h",
     "quads/surface_draw_quad.cc",
     "quads/surface_draw_quad.h",
     "quads/texture_draw_quad.cc",
diff --git a/components/viz/common/DEPS b/components/viz/common/DEPS
index 398e9db0..adbe40b2 100644
--- a/components/viz/common/DEPS
+++ b/components/viz/common/DEPS
@@ -5,6 +5,7 @@
   # about how to communicate with viz.
   "-mojo/public/cpp/bindings",
   # Exception is struct_traits.h which is used for defining friends only.
+  "+cc/base",
   "+mojo/public/cpp/bindings/struct_traits.h",
   "+third_party/perfetto/protos/perfetto/trace/track_event",
   "+third_party/skia",
diff --git a/components/viz/common/quads/aggregated_render_pass.cc b/components/viz/common/quads/aggregated_render_pass.cc
index cc26bd14..961f1dd3 100644
--- a/components/viz/common/quads/aggregated_render_pass.cc
+++ b/components/viz/common/quads/aggregated_render_pass.cc
@@ -19,7 +19,6 @@
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -132,9 +131,6 @@
     case DrawQuad::Material::kTiledContent:
       CopyFromAndAppendTypedDrawQuad<TileDrawQuad>(quad);
       break;
-    case DrawQuad::Material::kStreamVideoContent:
-      CopyFromAndAppendTypedDrawQuad<StreamVideoDrawQuad>(quad);
-      break;
     case DrawQuad::Material::kSurfaceContent:
       CopyFromAndAppendTypedDrawQuad<SurfaceDrawQuad>(quad);
       break;
diff --git a/components/viz/common/quads/compositor_render_pass.cc b/components/viz/common/quads/compositor_render_pass.cc
index 594c308..510eda0 100644
--- a/components/viz/common/quads/compositor_render_pass.cc
+++ b/components/viz/common/quads/compositor_render_pass.cc
@@ -23,7 +23,6 @@
 #include "components/viz/common/quads/shared_element_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -161,9 +160,6 @@
     case DrawQuad::Material::kTiledContent:
       quad_list.AllocateAndCopyFrom(TileDrawQuad::MaterialCast(quad));
       break;
-    case DrawQuad::Material::kStreamVideoContent:
-      quad_list.AllocateAndCopyFrom(StreamVideoDrawQuad::MaterialCast(quad));
-      break;
     case DrawQuad::Material::kSurfaceContent:
       quad_list.AllocateAndCopyFrom(SurfaceDrawQuad::MaterialCast(quad));
       break;
diff --git a/components/viz/common/quads/draw_quad.h b/components/viz/common/quads/draw_quad.h
index 59734d3..cc45fc05 100644
--- a/components/viz/common/quads/draw_quad.h
+++ b/components/viz/common/quads/draw_quad.h
@@ -33,22 +33,24 @@
 // quad's transform maps the content space to the target space.
 class VIZ_COMMON_EXPORT DrawQuad {
  public:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
   enum class Material {
-    kInvalid,
-    kDebugBorder,
-    kPictureContent,
+    kInvalid = 0,
+    kDebugBorder = 1,
+    kPictureContent = 2,
     // This is the compositor, pre-aggregation, draw quad.
-    kCompositorRenderPass,
+    kCompositorRenderPass = 3,
     // This is the viz, post-aggregation, draw quad.
-    kAggregatedRenderPass,
-    kSolidColor,
-    kSharedElement,
-    kStreamVideoContent,
-    kSurfaceContent,
-    kTextureContent,
-    kTiledContent,
-    kYuvVideoContent,
-    kVideoHole,
+    kAggregatedRenderPass = 4,
+    kSolidColor = 5,
+    kSharedElement = 6,
+    // kStreamVideoContent = 7,  // Removed. Replaced with kTextureContent.
+    kSurfaceContent = 8,
+    kTextureContent = 9,
+    kTiledContent = 10,
+    kYuvVideoContent = 11,
+    kVideoHole = 12,
     kMaxValue = kVideoHole
   };
 
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index 030f24fd..d6d5ef4 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -24,7 +24,6 @@
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/shared_element_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -243,34 +242,6 @@
   EXPECT_EQ(force_anti_aliasing_off, copy_quad->force_anti_aliasing_off);
 }
 
-TEST(DrawQuadTest, CopyStreamVideoDrawQuad) {
-  gfx::Rect visible_rect(40, 50, 30, 20);
-  bool blending = true;
-  ResourceId resource_id(64);
-  gfx::Size resource_size_in_pixels = gfx::Size(40, 41);
-  gfx::PointF uv_top_left(0.25f, 0.3f);
-  gfx::PointF uv_bottom_right(0.75f, 0.7f);
-  CREATE_SHARED_STATE();
-
-  CREATE_QUAD_NEW(StreamVideoDrawQuad, visible_rect, blending, resource_id,
-                  resource_size_in_pixels, uv_top_left, uv_bottom_right);
-  EXPECT_EQ(DrawQuad::Material::kStreamVideoContent, copy_quad->material);
-  EXPECT_EQ(visible_rect, copy_quad->visible_rect);
-  EXPECT_EQ(blending, copy_quad->needs_blending);
-  EXPECT_EQ(resource_id, copy_quad->resource_id());
-  EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels());
-  EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
-  EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
-
-  CREATE_QUAD_ALL(StreamVideoDrawQuad, resource_id, resource_size_in_pixels,
-                  uv_top_left, uv_bottom_right);
-  EXPECT_EQ(DrawQuad::Material::kStreamVideoContent, copy_quad->material);
-  EXPECT_EQ(resource_id, copy_quad->resource_id());
-  EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels());
-  EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
-  EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
-}
-
 TEST(DrawQuadTest, CopySurfaceDrawQuad) {
   gfx::Rect visible_rect(40, 50, 30, 20);
   SurfaceId primary_surface_id(
@@ -333,6 +304,7 @@
   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
   EXPECT_EQ(secure_output_only, copy_quad->secure_output_only);
   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
+  EXPECT_FALSE(copy_quad->is_stream_video);
 
   CREATE_QUAD_ALL(TextureDrawQuad, resource_id, resource_size_in_pixels,
                   premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -349,6 +321,7 @@
   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
   EXPECT_EQ(secure_output_only, copy_quad->secure_output_only);
   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
+  EXPECT_FALSE(copy_quad->is_stream_video);
 }
 
 TEST(DrawQuadTest, CopyTileDrawQuad) {
@@ -574,23 +547,6 @@
   EXPECT_EQ(0, IterateAndCount(quad_new));
 }
 
-TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) {
-  gfx::Rect visible_rect(40, 50, 30, 20);
-  ResourceId resource_id(64);
-  gfx::Size resource_size_in_pixels = gfx::Size(40, 41);
-  gfx::PointF uv_top_left(0.25f, 0.3f);
-  gfx::PointF uv_bottom_right(0.75f, 0.7f);
-
-  CREATE_SHARED_STATE();
-  CREATE_QUAD_NEW(StreamVideoDrawQuad, visible_rect, needs_blending,
-                  resource_id, resource_size_in_pixels, uv_top_left,
-                  uv_bottom_right);
-  EXPECT_EQ(resource_id, quad_new->resource_id());
-  EXPECT_EQ(resource_size_in_pixels, quad_new->resource_size_in_pixels());
-  EXPECT_EQ(1, IterateAndCount(quad_new));
-  EXPECT_EQ(NextId(resource_id), quad_new->resource_id());
-}
-
 TEST_F(DrawQuadIteratorTest, SurfaceDrawQuad) {
   gfx::Rect visible_rect(40, 50, 30, 20);
   SurfaceId surface_id(kArbitraryFrameSinkId,
@@ -712,9 +668,6 @@
       case DrawQuad::Material::kTiledContent:
         largest = std::max(largest, sizeof(TileDrawQuad));
         break;
-      case DrawQuad::Material::kStreamVideoContent:
-        largest = std::max(largest, sizeof(StreamVideoDrawQuad));
-        break;
       case DrawQuad::Material::kYuvVideoContent:
         largest = std::max(largest, sizeof(YUVVideoDrawQuad));
         break;
@@ -763,9 +716,6 @@
       case DrawQuad::Material::kTiledContent:
         LOG(ERROR) << "TileDrawQuad " << sizeof(TileDrawQuad);
         break;
-      case DrawQuad::Material::kStreamVideoContent:
-        LOG(ERROR) << "StreamVideoDrawQuad " << sizeof(StreamVideoDrawQuad);
-        break;
       case DrawQuad::Material::kYuvVideoContent:
         LOG(ERROR) << "YUVVideoDrawQuad " << sizeof(YUVVideoDrawQuad);
         break;
diff --git a/components/viz/common/quads/largest_draw_quad.cc b/components/viz/common/quads/largest_draw_quad.cc
index 4b0a5a75..5ec9455a 100644
--- a/components/viz/common/quads/largest_draw_quad.cc
+++ b/components/viz/common/quads/largest_draw_quad.cc
@@ -13,7 +13,6 @@
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -40,7 +39,6 @@
             viz::PictureDrawQuad,
             viz::CompositorRenderPassDrawQuad,
             viz::SolidColorDrawQuad,
-            viz::StreamVideoDrawQuad,
             viz::SurfaceDrawQuad,
             viz::TextureDrawQuad,
             viz::TileDrawQuad,
@@ -65,7 +63,6 @@
              viz::PictureDrawQuad,
              viz::CompositorRenderPassDrawQuad,
              viz::SolidColorDrawQuad,
-             viz::StreamVideoDrawQuad,
              viz::SurfaceDrawQuad,
              viz::TextureDrawQuad,
              viz::TileDrawQuad,
diff --git a/components/viz/common/quads/quad_list.cc b/components/viz/common/quads/quad_list.cc
index 907beb7e..7c7ffcc 100644
--- a/components/viz/common/quads/quad_list.cc
+++ b/components/viz/common/quads/quad_list.cc
@@ -12,7 +12,6 @@
 #include "components/viz/common/quads/shared_element_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -75,11 +74,6 @@
       return InsertBeforeAndInvalidateAllPointers<TileDrawQuad>(at, count,
                                                                 copy);
     }
-    case DrawQuad::Material::kStreamVideoContent: {
-      const auto copy = *StreamVideoDrawQuad::MaterialCast(*at);
-      return InsertBeforeAndInvalidateAllPointers<StreamVideoDrawQuad>(
-          at, count, copy);
-    }
     case DrawQuad::Material::kSurfaceContent: {
       const auto copy = *SurfaceDrawQuad::MaterialCast(*at);
       return InsertBeforeAndInvalidateAllPointers<SurfaceDrawQuad>(at, count,
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index 2395e2c..0438074 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -21,7 +21,6 @@
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -1095,7 +1094,6 @@
   MAP_STRING_TO_MATERIAL(kCompositorRenderPass)
   MAP_STRING_TO_MATERIAL(kSharedElement)
   MAP_STRING_TO_MATERIAL(kSolidColor)
-  MAP_STRING_TO_MATERIAL(kStreamVideoContent)
   MAP_STRING_TO_MATERIAL(kSurfaceContent)
   MAP_STRING_TO_MATERIAL(kTextureContent)
   MAP_STRING_TO_MATERIAL(kTiledContent)
@@ -1249,17 +1247,6 @@
                    draw_quad->force_anti_aliasing_off);
 }
 
-void StreamVideoDrawQuadToDict(const StreamVideoDrawQuad* draw_quad,
-                               base::Value* dict) {
-  DCHECK(draw_quad);
-  DCHECK(dict);
-  dict->SetKey("uv_top_left", PointFToDict(draw_quad->uv_top_left));
-  dict->SetKey("uv_bottom_right", PointFToDict(draw_quad->uv_bottom_right));
-  DCHECK_EQ(1u, draw_quad->resources.count);
-  dict->SetKey("overlay_resource_size_in_pixels",
-               SizeToDict(draw_quad->overlay_resources.size_in_pixels));
-}
-
 #define MAP_VIDEO_TYPE_TO_STRING(NAME) \
   case gfx::ProtectedVideoType::NAME:  \
     return #NAME;
@@ -1321,6 +1308,12 @@
   if (draw_quad->damage_rect.has_value()) {
     dict->SetKey("damage_rect", RectToDict(draw_quad->damage_rect.value()));
   }
+  // Conditionally set is_stream_video to not break backwards-compatibility with
+  // unit test data.
+  // Note: is_video_frame is not being saved in dict.
+  if (draw_quad->is_stream_video) {
+    dict->SetBoolKey("is_stream_video", draw_quad->is_stream_video);
+  }
 }
 
 void TileDrawQuadToDict(const TileDrawQuad* draw_quad, base::Value* dict) {
@@ -1381,7 +1374,6 @@
     WRITE_DRAW_QUAD_TYPE_FIELDS(kCompositorRenderPass,
                                 CompositorRenderPassDrawQuad)
     WRITE_DRAW_QUAD_TYPE_FIELDS(kSolidColor, SolidColorDrawQuad)
-    WRITE_DRAW_QUAD_TYPE_FIELDS(kStreamVideoContent, StreamVideoDrawQuad)
     WRITE_DRAW_QUAD_TYPE_FIELDS(kSurfaceContent, SurfaceDrawQuad)
     WRITE_DRAW_QUAD_TYPE_FIELDS(kTextureContent, TextureDrawQuad)
     WRITE_DRAW_QUAD_TYPE_FIELDS(kTiledContent, TileDrawQuad)
@@ -1483,41 +1475,6 @@
   return true;
 }
 
-bool StreamVideoDrawQuadFromDict(const base::Value& dict,
-                                 const DrawQuadCommon& common,
-                                 StreamVideoDrawQuad* draw_quad) {
-  DCHECK(draw_quad);
-  if (!dict.is_dict())
-    return false;
-  if (common.resources.count != 1u)
-    return false;
-  const base::Value* uv_top_left = dict.FindDictKey("uv_top_left");
-  const base::Value* uv_bottom_right = dict.FindDictKey("uv_bottom_right");
-  const base::Value* overlay_resource_size_in_pixels =
-      dict.FindDictKey("overlay_resource_size_in_pixels");
-
-  if (!uv_top_left || !uv_bottom_right || !overlay_resource_size_in_pixels) {
-    return false;
-  }
-  gfx::PointF t_uv_top_left, t_uv_bottom_right;
-  gfx::Size t_overlay_resource_size_in_pixels;
-  if (!PointFFromDict(*uv_top_left, &t_uv_top_left) ||
-      !PointFFromDict(*uv_bottom_right, &t_uv_bottom_right) ||
-      !SizeFromDict(*overlay_resource_size_in_pixels,
-                    &t_overlay_resource_size_in_pixels)) {
-    return false;
-  }
-
-  const size_t kIndex = StreamVideoDrawQuad::kResourceIdIndex;
-  ResourceId resource_id = common.resources.ids[kIndex];
-
-  draw_quad->SetAll(common.shared_quad_state, common.rect, common.visible_rect,
-                    common.needs_blending, resource_id,
-                    t_overlay_resource_size_in_pixels, t_uv_top_left,
-                    t_uv_bottom_right);
-  return true;
-}
-
 bool SurfaceDrawQuadFromDict(const base::Value& dict,
                              const DrawQuadCommon& common,
                              SurfaceDrawQuad* draw_quad) {
@@ -1604,6 +1561,9 @@
       nearest_neighbor.value(), secure_output_only.value(),
       static_cast<gfx::ProtectedVideoType>(protected_video_type_index));
 
+  draw_quad->is_stream_video =
+      dict.FindBoolKey("is_stream_video").value_or(false);
+
   gfx::Rect t_damage_rect;
   if (damage_rect && RectFromDict(*damage_rect, &t_damage_rect)) {
     draw_quad->damage_rect = t_damage_rect;
@@ -1772,7 +1732,6 @@
     switch (common->material) {
       GET_QUAD_FROM_DICT(kCompositorRenderPass, CompositorRenderPassDrawQuad)
       GET_QUAD_FROM_DICT(kSolidColor, SolidColorDrawQuad)
-      GET_QUAD_FROM_DICT(kStreamVideoContent, StreamVideoDrawQuad)
       GET_QUAD_FROM_DICT(kSurfaceContent, SurfaceDrawQuad)
       GET_QUAD_FROM_DICT(kTextureContent, TextureDrawQuad)
       GET_QUAD_FROM_DICT(kTiledContent, TileDrawQuad)
@@ -2011,7 +1970,6 @@
     MAP_MATERIAL_TO_STRING(kCompositorRenderPass)
     MAP_MATERIAL_TO_STRING(kSharedElement)
     MAP_MATERIAL_TO_STRING(kSolidColor)
-    MAP_MATERIAL_TO_STRING(kStreamVideoContent)
     MAP_MATERIAL_TO_STRING(kSurfaceContent)
     MAP_MATERIAL_TO_STRING(kTextureContent)
     MAP_MATERIAL_TO_STRING(kTiledContent)
diff --git a/components/viz/common/quads/render_pass_io_unittest.cc b/components/viz/common/quads/render_pass_io_unittest.cc
index 6a0e2dcd..1f7e8b8a 100644
--- a/components/viz/common/quads/render_pass_io_unittest.cc
+++ b/components/viz/common/quads/render_pass_io_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/viz/common/quads/render_pass_io.h"
 
+#include <array>
 #include <memory>
 #include <string>
 
@@ -14,7 +15,6 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
@@ -191,9 +191,9 @@
 TEST(RenderPassIOTest, QuadList) {
   const size_t kSharedQuadStateCount = 5;
   size_t quad_count = 0;
-  const DrawQuad::Material kQuadMaterials[] = {
+  const std::array<DrawQuad::Material, 9> kQuadMaterials = {
       DrawQuad::Material::kSolidColor,
-      DrawQuad::Material::kStreamVideoContent,
+      DrawQuad::Material::kTextureContent,  // is_stream_video set to true.
       DrawQuad::Material::kVideoHole,
       DrawQuad::Material::kYuvVideoContent,
       DrawQuad::Material::kTextureContent,
@@ -225,13 +225,17 @@
       ++quad_count;
     }
     {
-      // 2. StreamVideoDrawQuad
-      StreamVideoDrawQuad* quad =
-          render_pass0->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
+      // 2. TextureDrawQuad with is_stream_video set to true.
+      TextureDrawQuad* quad =
+          render_pass0->CreateAndAppendDrawQuad<TextureDrawQuad>();
+      float opacity[] = {1, 1, 1, 1};
       quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index),
                    gfx::Rect(10, 10, 300, 400), gfx::Rect(10, 10, 200, 400),
-                   false, ResourceId(100), gfx::Size(600, 800),
-                   gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f));
+                   false, ResourceId(100), gfx::Size(600, 800), false,
+                   gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f),
+                   SkColors::kTransparent, opacity, false, false, false,
+                   gfx::ProtectedVideoType::kHardwareProtected);
+      quad->is_stream_video = true;
       ++sqs_index;
       ++quad_count;
     }
diff --git a/components/viz/common/quads/stream_video_draw_quad.cc b/components/viz/common/quads/stream_video_draw_quad.cc
deleted file mode 100644
index 5a854f4..0000000
--- a/components/viz/common/quads/stream_video_draw_quad.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/quads/stream_video_draw_quad.h"
-
-#include "base/check.h"
-#include "base/trace_event/traced_value.h"
-#include "base/values.h"
-#include "cc/base/math_util.h"
-
-namespace viz {
-
-StreamVideoDrawQuad::StreamVideoDrawQuad() = default;
-StreamVideoDrawQuad::~StreamVideoDrawQuad() = default;
-StreamVideoDrawQuad::StreamVideoDrawQuad(const StreamVideoDrawQuad& quad) =
-    default;
-
-void StreamVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
-                                 const gfx::Rect& rect,
-                                 const gfx::Rect& visible_rect,
-                                 bool needs_blending,
-                                 ResourceId resource_id,
-                                 gfx::Size resource_size_in_pixels,
-                                 const gfx::PointF& top_left,
-                                 const gfx::PointF& bottom_right) {
-  DrawQuad::SetAll(shared_quad_state, DrawQuad::Material::kStreamVideoContent,
-                   rect, visible_rect, needs_blending);
-  resources.ids[kResourceIdIndex] = resource_id;
-  overlay_resources.size_in_pixels = resource_size_in_pixels;
-  resources.count = 1;
-  uv_top_left = top_left;
-  uv_bottom_right = bottom_right;
-}
-
-void StreamVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
-                                 const gfx::Rect& rect,
-                                 const gfx::Rect& visible_rect,
-                                 bool needs_blending,
-                                 ResourceId resource_id,
-                                 gfx::Size resource_size_in_pixels,
-                                 const gfx::PointF& top_left,
-                                 const gfx::PointF& bottom_right) {
-  DrawQuad::SetAll(shared_quad_state, DrawQuad::Material::kStreamVideoContent,
-                   rect, visible_rect, needs_blending);
-  resources.ids[kResourceIdIndex] = resource_id;
-  overlay_resources.size_in_pixels = resource_size_in_pixels;
-  resources.count = 1;
-  uv_top_left = top_left;
-  uv_bottom_right = bottom_right;
-}
-
-const StreamVideoDrawQuad* StreamVideoDrawQuad::MaterialCast(
-    const DrawQuad* quad) {
-  DCHECK(quad->material == DrawQuad::Material::kStreamVideoContent);
-  return static_cast<const StreamVideoDrawQuad*>(quad);
-}
-
-void StreamVideoDrawQuad::ExtendValue(
-    base::trace_event::TracedValue* value) const {
-  value->SetInteger("resource_id",
-                    resources.ids[kResourceIdIndex].GetUnsafeValue());
-  cc::MathUtil::AddToTracedValue("uv_top_left", uv_top_left, value);
-  cc::MathUtil::AddToTracedValue("uv_bottom_right", uv_bottom_right, value);
-}
-
-StreamVideoDrawQuad::OverlayResources::OverlayResources() {}
-
-}  // namespace viz
diff --git a/components/viz/common/quads/stream_video_draw_quad.h b/components/viz/common/quads/stream_video_draw_quad.h
deleted file mode 100644
index a6c9bc3..0000000
--- a/components/viz/common/quads/stream_video_draw_quad.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_QUADS_STREAM_VIDEO_DRAW_QUAD_H_
-#define COMPONENTS_VIZ_COMMON_QUADS_STREAM_VIDEO_DRAW_QUAD_H_
-
-#include <stddef.h>
-
-#include "components/viz/common/quads/draw_quad.h"
-#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/viz_common_export.h"
-#include "gpu/ipc/common/vulkan_ycbcr_info.h"
-#include "ui/gfx/geometry/point_f.h"
-
-namespace viz {
-
-class VIZ_COMMON_EXPORT StreamVideoDrawQuad : public DrawQuad {
- public:
-  static const size_t kResourceIdIndex = 0;
-
-  StreamVideoDrawQuad();
-  ~StreamVideoDrawQuad() override;
-  StreamVideoDrawQuad(const StreamVideoDrawQuad& quad);
-
-  void SetNew(const SharedQuadState* shared_quad_state,
-              const gfx::Rect& rect,
-              const gfx::Rect& visible_rect,
-              bool needs_blending,
-              ResourceId resource_id,
-              gfx::Size resource_size_in_pixels,
-              const gfx::PointF& top_left,
-              const gfx::PointF& bottom_right);
-
-  void SetAll(const SharedQuadState* shared_quad_state,
-              const gfx::Rect& rect,
-              const gfx::Rect& visible_rect,
-              bool needs_blending,
-              ResourceId resource_id,
-              gfx::Size resource_size_in_pixels,
-              const gfx::PointF& top_left,
-              const gfx::PointF& bottom_right);
-
-  gfx::PointF uv_top_left;
-  gfx::PointF uv_bottom_right;
-
-  struct OverlayResources {
-    OverlayResources();
-    gfx::Size size_in_pixels;
-  };
-  OverlayResources overlay_resources;
-
-  static const StreamVideoDrawQuad* MaterialCast(const DrawQuad*);
-
-  ResourceId resource_id() const { return resources.ids[kResourceIdIndex]; }
-  const gfx::Size& resource_size_in_pixels() const {
-    return overlay_resources.size_in_pixels;
-  }
-
- private:
-  void ExtendValue(base::trace_event::TracedValue* value) const override;
-};
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_COMMON_QUADS_STREAM_VIDEO_DRAW_QUAD_H_
diff --git a/components/viz/common/quads/texture_draw_quad.cc b/components/viz/common/quads/texture_draw_quad.cc
index 66b6132..804a5b0c 100644
--- a/components/viz/common/quads/texture_draw_quad.cc
+++ b/components/viz/common/quads/texture_draw_quad.cc
@@ -20,6 +20,7 @@
       premultiplied_alpha(false),
       secure_output_only(false),
       is_video_frame(false),
+      is_stream_video(false),
       protected_video_type(gfx::ProtectedVideoType::kClear) {
   static_assert(static_cast<int>(gfx::ProtectedVideoType::kMaxValue) < 4,
                 "protected_video_type needs more bits in order to represent "
@@ -122,6 +123,7 @@
   value->SetBoolean("y_flipped", y_flipped);
   value->SetBoolean("nearest_neighbor", nearest_neighbor);
   value->SetBoolean("is_video_frame", is_video_frame);
+  value->SetBoolean("is_stream_video", is_stream_video);
   value->SetInteger("protected_video_type",
                     static_cast<int>(protected_video_type));
 }
diff --git a/components/viz/common/quads/texture_draw_quad.h b/components/viz/common/quads/texture_draw_quad.h
index a9aae8a..f1d876a 100644
--- a/components/viz/common/quads/texture_draw_quad.h
+++ b/components/viz/common/quads/texture_draw_quad.h
@@ -74,6 +74,11 @@
   // True if this quad contains a video frame from VideoResourceUpdater instead
   // of canvas or webgl content.
   bool is_video_frame : 1;
+
+  // True if this quad is a stream video texture. This mostly affects overlay
+  // creation (e.g. color space, protection type).
+  bool is_stream_video : 1;
+
   absl::optional<gfx::HDRMetadata> hdr_metadata;
 
   // kClear if the contents do not require any special protection. See enum of a
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc
index 4108adc0..21c7922 100644
--- a/components/viz/common/resources/resource_format_utils.cc
+++ b/components/viz/common/resources/resource_format_utils.cc
@@ -421,6 +421,10 @@
     // candidate.
     case RED_8:
 #endif
+#if BUILDFLAG(IS_MAC)
+    case BGRX_8888:
+    case RGBX_8888:
+#endif
     case R16_EXT:
     case RGBA_4444:
     case RGBA_8888:
@@ -436,13 +440,15 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     case RED_8:
 #endif
+#if !BUILDFLAG(IS_MAC)
+    case BGRX_8888:
+    case RGBX_8888:
+#endif
     case RGB_565:
     case LUMINANCE_F16:
     case BGR_565:
     case RG_88:
     case RG16_EXT:
-    case RGBX_8888:
-    case BGRX_8888:
     case YVU_420:
     case YUV_420_BIPLANAR:
     case P010:
diff --git a/components/viz/common/viz_utils.cc b/components/viz/common/viz_utils.cc
index 4de5eb1..6da7dc0 100644
--- a/components/viz/common/viz_utils.cc
+++ b/components/viz/common/viz_utils.cc
@@ -10,7 +10,9 @@
 #include "base/command_line.h"
 #include "base/system/sys_info.h"
 #include "build/build_config.h"
+#include "cc/base/math_util.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/rrect_f.h"
 
 #if BUILDFLAG(IS_ANDROID)
@@ -148,5 +150,17 @@
   return true;
 #endif  // BUILDFLAG(IS_POSIX)
 }
+gfx::RectF ClippedQuadRectangleF(const DrawQuad* quad) {
+  gfx::RectF quad_rect = cc::MathUtil::MapClippedRect(
+      quad->shared_quad_state->quad_to_target_transform,
+      gfx::RectF(quad->rect));
+  if (quad->shared_quad_state->clip_rect)
+    quad_rect.Intersect(gfx::RectF(*quad->shared_quad_state->clip_rect));
+  return quad_rect;
+}
+
+gfx::Rect ClippedQuadRectangle(const DrawQuad* quad) {
+  return gfx::ToEnclosingRect(ClippedQuadRectangleF(quad));
+}
 
 }  // namespace viz
diff --git a/components/viz/common/viz_utils.h b/components/viz/common/viz_utils.h
index 008f122..d07ab405 100644
--- a/components/viz/common/viz_utils.h
+++ b/components/viz/common/viz_utils.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_
 
 #include "base/timer/elapsed_timer.h"
+#include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/viz_common_export.h"
 
 #include "build/build_config.h"
@@ -48,6 +49,9 @@
                                      int* active_fd_count,
                                      int* rlim_cur);
 
+// Returns the smallest rectangle in target space that contains the quad.
+VIZ_COMMON_EXPORT gfx::Rect ClippedQuadRectangle(const DrawQuad* quad);
+VIZ_COMMON_EXPORT gfx::RectF ClippedQuadRectangleF(const DrawQuad* quad);
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_
diff --git a/components/viz/service/display/aggregated_frame.h b/components/viz/service/display/aggregated_frame.h
index b80f4ac..efb07b45 100644
--- a/components/viz/service/display/aggregated_frame.h
+++ b/components/viz/service/display/aggregated_frame.h
@@ -51,6 +51,11 @@
   // Indicates whether this frame may contain video.
   bool may_contain_video = false;
 
+  // Indicates whether this is a page fullscreen mode without Chrome tabs. When
+  // in the page fullscreen mode, the content surface has the same size as the
+  // root render pass |output_rect| (display size) on the root surface.
+  bool page_fullscreen_mode = false;
+
   // A list of surface damage rects in the current frame, used for overlays.
   SurfaceDamageRectList surface_damage_rect_list_;
 
diff --git a/components/viz/service/display/ca_layer_overlay.cc b/components/viz/service/display/ca_layer_overlay.cc
index b434668..1fb9c55 100644
--- a/components/viz/service/display/ca_layer_overlay.cc
+++ b/components/viz/service/display/ca_layer_overlay.cc
@@ -10,8 +10,8 @@
 #include "base/metrics/histogram_macros.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
+#include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
@@ -143,19 +143,6 @@
   return gfx::kCALayerSuccess;
 }
 
-gfx::CALayerResult FromStreamVideoQuad(
-    DisplayResourceProvider* resource_provider,
-    const StreamVideoDrawQuad* quad,
-    CALayerOverlay* ca_layer_overlay) {
-  ResourceId resource_id = quad->resource_id();
-  if (!resource_provider->IsOverlayCandidate(resource_id))
-    return gfx::kCALayerFailedStreamVideoNotCandidate;
-  ca_layer_overlay->contents_resource_id = resource_id;
-  ca_layer_overlay->contents_rect =
-      BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
-  return gfx::kCALayerSuccess;
-}
-
 gfx::CALayerResult FromSolidColorDrawQuad(const SolidColorDrawQuad* quad,
                                           CALayerOverlay* ca_layer_overlay,
                                           bool* skip) {
@@ -348,21 +335,21 @@
     *render_pass_draw_quad =
         quad->material == DrawQuad::Material::kAggregatedRenderPass;
     switch (quad->material) {
-      case DrawQuad::Material::kTextureContent:
-        return FromTextureQuad(resource_provider,
-                               TextureDrawQuad::MaterialCast(quad),
+      case DrawQuad::Material::kTextureContent: {
+        const TextureDrawQuad* texture_draw_quad =
+            TextureDrawQuad::MaterialCast(quad);
+        // Stream video counts as a yuv draw quad.
+        if (texture_draw_quad->is_stream_video)
+          yuv_draw_quad_count += 1;
+        return FromTextureQuad(resource_provider, texture_draw_quad,
                                ca_layer_overlay);
+      }
       case DrawQuad::Material::kTiledContent:
         return FromTileQuad(resource_provider, TileDrawQuad::MaterialCast(quad),
                             ca_layer_overlay);
       case DrawQuad::Material::kSolidColor:
         return FromSolidColorDrawQuad(SolidColorDrawQuad::MaterialCast(quad),
                                       ca_layer_overlay, skip);
-      case DrawQuad::Material::kStreamVideoContent:
-        yuv_draw_quad_count++;
-        return FromStreamVideoQuad(resource_provider,
-                                   StreamVideoDrawQuad::MaterialCast(quad),
-                                   ca_layer_overlay);
       case DrawQuad::Material::kDebugBorder:
         return gfx::kCALayerFailedDebugBoarder;
       case DrawQuad::Material::kPictureContent:
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index 0fea056..73f869b 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -17,9 +17,9 @@
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/viz_utils.h"
 #include "components/viz/service/display/display_resource_provider.h"
 #include "components/viz/service/display/overlay_processor_interface.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -28,6 +28,7 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/video_types.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gl_utils.h"
 
@@ -65,22 +66,11 @@
 };
 
 enum : size_t {
-  kStreamVideoResourceIndex = 0,
   kTextureResourceIndex = 0,
   kYPlaneResourceIndex = 0,
   kUVPlaneResourceIndex = 1,
 };
 
-// This returns the smallest rectangle in target space that contains the quad.
-gfx::RectF ClippedQuadRectangle(const DrawQuad* quad) {
-  gfx::RectF quad_rect = cc::MathUtil::MapClippedRect(
-      quad->shared_quad_state->quad_to_target_transform,
-      gfx::RectF(quad->rect));
-  if (quad->shared_quad_state->clip_rect)
-    quad_rect.Intersect(gfx::RectF(*quad->shared_quad_state->clip_rect));
-  return quad_rect;
-}
-
 gfx::RectF GetExpandedRectWithPixelMovingFilter(
     const AggregatedRenderPassDrawQuad* rpdq,
     float max_pixel_movement) {
@@ -127,7 +117,7 @@
   if (processed_yuv_overlay_count >= allowed_yuv_overlay_count)
     return DC_LAYER_FAILED_TOO_MANY_OVERLAYS;
 
-  auto quad_target_rect = gfx::ToEnclosingRect(ClippedQuadRectangle(quad));
+  auto quad_target_rect = ClippedQuadRectangle(quad);
   for (const auto& filter_target_rect : backdrop_filter_rects) {
     if (filter_target_rect.Intersects(quad_target_rect))
       return DC_LAYER_FAILED_BACKDROP_FILTERS;
@@ -171,38 +161,6 @@
   dc_layer->hdr_metadata = quad->hdr_metadata.value_or(gfx::HDRMetadata());
 }
 
-void FromStreamVideoQuad(const StreamVideoDrawQuad* quad,
-                         const gfx::Transform& transform_to_root_target,
-                         DCLayerOverlay* dc_layer) {
-  dc_layer->resources[kStreamVideoResourceIndex] = quad->resource_id();
-  dc_layer->quad_rect = quad->rect;
-  // Quad rect is in quad content space so both quad to target, and target to
-  // root transforms must be applied to it.
-  gfx::Transform quad_to_root_transform(
-      quad->shared_quad_state->quad_to_target_transform);
-  quad_to_root_transform.ConcatTransform(transform_to_root_target);
-  // Flatten transform to 2D since DirectComposition doesn't support 3D
-  // transforms.
-  quad_to_root_transform.FlattenTo2d();
-  dc_layer->transform = quad_to_root_transform;
-
-  dc_layer->clip_rect = quad->shared_quad_state->clip_rect;
-  if (dc_layer->clip_rect) {
-    // Clip rect is in quad target space, and must be transformed to root target
-    // space.
-    gfx::RectF clip_rect =
-        gfx::RectF(dc_layer->clip_rect.value_or(gfx::Rect()));
-    transform_to_root_target.TransformRect(&clip_rect);
-    dc_layer->clip_rect = gfx::ToEnclosingRect(clip_rect);
-  }
-
-  dc_layer->color_space = gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT709,
-                                          gfx::ColorSpace::TransferID::BT709);
-  // Set the protected_video_type to kHardwareProtected to signal that a DC
-  // layer is required for this quad
-  dc_layer->protected_video_type = gfx::ProtectedVideoType::kHardwareProtected;
-}
-
 DCLayerResult ValidateTextureQuad(
     const TextureDrawQuad* quad,
     const std::vector<gfx::Rect>& backdrop_filter_rects,
@@ -222,7 +180,7 @@
     return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
   }
 
-  auto quad_target_rect = gfx::ToEnclosingRect(ClippedQuadRectangle(quad));
+  auto quad_target_rect = ClippedQuadRectangle(quad);
   for (const auto& filter_target_rect : backdrop_filter_rects) {
     if (filter_target_rect.Intersects(quad_target_rect))
       return DC_LAYER_FAILED_BACKDROP_FILTERS;
@@ -256,11 +214,21 @@
   if (quad->shared_quad_state->clip_rect) {
     // Clip rect is in quad target space, and must be transformed to root target
     // space.
-    gfx::RectF clip_rect = gfx::RectF(*quad->shared_quad_state->clip_rect);
+    gfx::RectF clip_rect =
+        gfx::RectF(quad->shared_quad_state->clip_rect.value_or(gfx::Rect()));
     transform_to_root_target.TransformRect(&clip_rect);
     dc_layer->clip_rect = gfx::ToEnclosingRect(clip_rect);
   }
+
   dc_layer->color_space = gfx::ColorSpace::CreateSRGB();
+
+  // Both color space and protected_video_type are hard-coded for stream video.
+  if (quad->is_stream_video) {
+    dc_layer->color_space = gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT709,
+                                            gfx::ColorSpace::TransferID::BT709);
+    dc_layer->protected_video_type =
+        gfx::ProtectedVideoType::kHardwareProtected;
+  }
 }
 
 bool IsProtectedVideo(const QuadList::ConstIterator& it) {
@@ -270,7 +238,8 @@
                gfx::ProtectedVideoType::kHardwareProtected ||
            yuv_quad->protected_video_type ==
                gfx::ProtectedVideoType::kSoftwareProtected;
-  } else if (it->material == DrawQuad::Material::kStreamVideoContent) {
+  } else if (it->material == DrawQuad::Material::kTextureContent &&
+             TextureDrawQuad::MaterialCast(*it)->is_stream_video) {
     return true;
   } else {
     return false;
@@ -323,7 +292,7 @@
     }
 
     if (!has_pixel_moving_filter)
-      overlap_rect = ClippedQuadRectangle(quad);
+      overlap_rect = ClippedQuadRectangleF(quad);
 
     if (quad->material == DrawQuad::Material::kSolidColor) {
       SkColor4f color = SolidColorDrawQuad::MaterialCast(quad)->color;
@@ -393,14 +362,16 @@
       RecordVideoDCLayerResult(
           result, YUVVideoDrawQuad::MaterialCast(*it)->protected_video_type);
       break;
-    case DrawQuad::Material::kStreamVideoContent:
-      UMA_HISTOGRAM_ENUMERATION(
-          "GPU.DirectComposition.DCLayerResult.StreamVideo", result);
+    case DrawQuad::Material::kTextureContent: {
+      if (TextureDrawQuad::MaterialCast(*it)->is_stream_video) {
+        UMA_HISTOGRAM_ENUMERATION(
+            "GPU.DirectComposition.DCLayerResult.StreamVideo", result);
+      } else {
+        UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.DCLayerResult.Texture",
+                                  result);
+      }
       break;
-    case DrawQuad::Material::kTextureContent:
-      UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.DCLayerResult.Texture",
-                                result);
-      break;
+    }
     default:
       break;
   }
@@ -427,7 +398,6 @@
 QuadList::Iterator FindAnOverlayCandidate(QuadList& quad_list) {
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
     if (it->material == DrawQuad::Material::kYuvVideoContent ||
-        it->material == DrawQuad::Material::kStreamVideoContent ||
         it->material == DrawQuad::Material::kTextureContent)
       return it;
   }
@@ -439,8 +409,10 @@
   QuadList::Iterator it = quad_list.end();
   for (auto quad_it = quad_list.begin(); quad_it != quad_list.end();
        ++quad_it) {
-    if (quad_it->material == DrawQuad::Material::kStreamVideoContent)
+    if (quad_it->material == DrawQuad::Material::kTextureContent &&
+        TextureDrawQuad::MaterialCast(*quad_it)->is_stream_video) {
       return quad_list.end();
+    }
     if (it == quad_list.end() &&
         (quad_it->material == DrawQuad::Material::kYuvVideoContent ||
          quad_it->material == DrawQuad::Material::kTextureContent))
@@ -668,7 +640,7 @@
     auto candidate_it = std::next(quad_list->begin(), index);
     if (IsClearVideoQuad(candidate_it)) {
       gfx::Rect quad_rectangle_in_target_space =
-          gfx::ToEnclosingRect(ClippedQuadRectangle(*candidate_it));
+          ClippedQuadRectangle(*candidate_it);
       current_frame_overlay_candidate_rects.push_back(
           quad_rectangle_in_target_space);
     }
@@ -750,8 +722,7 @@
       auto render_pass_it =
           render_pass_backdrop_filters.find(rpdq->render_pass_id);
       if (render_pass_it != render_pass_backdrop_filters.end()) {
-        backdrop_filter_rects.push_back(
-            gfx::ToEnclosingRect(ClippedQuadRectangle(rpdq)));
+        backdrop_filter_rects.push_back(ClippedQuadRectangle(rpdq));
       }
       continue;
     }
@@ -774,29 +745,21 @@
             processed_yuv_overlay_count_++;
         }
         break;
-      case DrawQuad::Material::kStreamVideoContent: {
-        if (allow_promotion_hinting_) {
-          // If this quad has marked itself as wanting promotion hints then get
-          // the associated mailbox.
-          const StreamVideoDrawQuad* sv_quad =
-              StreamVideoDrawQuad::MaterialCast(*it);
-          ResourceId id = sv_quad->resource_id();
-          if (resource_provider->DoesResourceWantPromotionHint(id)) {
-            promotion_hint_mailbox = resource_provider->GetMailbox(id);
-          }
-        }
-        // Stream video quads contain Media Foundation dcomp surface which is
-        // always presented as overlay.
-        result = DC_LAYER_SUCCESS;
-      } break;
       case DrawQuad::Material::kTextureContent: {
-        result = ValidateTextureQuad(TextureDrawQuad::MaterialCast(*it),
-                                     backdrop_filter_rects, resource_provider);
+        const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it);
+
+        if (tex_quad->is_stream_video) {
+          // Stream video quads contain Media Foundation dcomp surface which is
+          // always presented as overlay.
+          result = DC_LAYER_SUCCESS;
+        } else {
+          result = ValidateTextureQuad(tex_quad, backdrop_filter_rects,
+                                       resource_provider);
+        }
 
         if (allow_promotion_hinting_) {
           // If this quad has marked itself as wanting promotion hints then get
           // the associated mailbox.
-          const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it);
           ResourceId id = tex_quad->resource_id();
           if (resource_provider->DoesResourceWantPromotionHint(id)) {
             promotion_hint_mailbox = resource_provider->GetMailbox(id);
@@ -893,8 +856,7 @@
       continue;
     }
 
-    gfx::Rect quad_rectangle_in_target_space =
-        gfx::ToEnclosingRect(ClippedQuadRectangle(*it));
+    gfx::Rect quad_rectangle_in_target_space = ClippedQuadRectangle(*it);
 
     // Quad is considered an "overlay" if it has no occluders.
     bool is_overlay = !IsOccluded(gfx::RectF(quad_rectangle_in_target_space),
@@ -1028,10 +990,6 @@
                   render_pass->transform_to_root_target, &dc_layer);
       processed_yuv_overlay_count_++;
       break;
-    case DrawQuad::Material::kStreamVideoContent:
-      FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(*it),
-                          render_pass->transform_to_root_target, &dc_layer);
-      break;
     case DrawQuad::Material::kTextureContent:
       FromTextureQuad(TextureDrawQuad::MaterialCast(*it),
                       render_pass->transform_to_root_target, &dc_layer);
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index b6b3bd8..2d93ab3 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -80,7 +80,6 @@
     DrawQuad::Material::kDebugBorder,
     // Exclude possible overlay candidates from quad splitting
     // See OverlayCandidate::FromDrawQuad
-    DrawQuad::Material::kStreamVideoContent,
     DrawQuad::Material::kTextureContent,
     DrawQuad::Material::kVideoHole,
     // See DCLayerOverlayProcessor::ProcessRenderPass
diff --git a/components/viz/service/display/overlay_ca_unittest.cc b/components/viz/service/display/overlay_ca_unittest.cc
index cf462fd..b893a67 100644
--- a/components/viz/service/display/overlay_ca_unittest.cc
+++ b/components/viz/service/display/overlay_ca_unittest.cc
@@ -22,7 +22,6 @@
 #include "components/viz/common/quads/compositor_render_pass.h"
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
diff --git a/components/viz/service/display/overlay_candidate.h b/components/viz/service/display/overlay_candidate.h
index 2a44296..805b36b 100644
--- a/components/viz/service/display/overlay_candidate.h
+++ b/components/viz/service/display/overlay_candidate.h
@@ -33,7 +33,6 @@
 namespace viz {
 class AggregatedRenderPassDrawQuad;
 class DisplayResourceProvider;
-class StreamVideoDrawQuad;
 
 class VIZ_SERVICE_EXPORT OverlayCandidate {
  public:
@@ -109,9 +108,9 @@
   gpu::Mailbox mailbox;
 
 #if BUILDFLAG(IS_ANDROID)
-  // For candidates from StreamVideoDrawQuads, this records whether the quad is
-  // marked as being backed by a SurfaceTexture or not.  If so, it's not really
-  // promotable to an overlay.
+  // For candidates from TextureDrawQuads with is_stream_video set to true, this
+  // records whether the quad is marked as being backed by a SurfaceTexture or
+  // not.  If so, it's not really promotable to an overlay.
   bool is_backed_by_surface_texture = false;
   // Crop within the buffer to be placed inside |display_rect| before
   // |clip_rect| was applied. Valid only for surface control.
diff --git a/components/viz/service/display/overlay_candidate_factory.cc b/components/viz/service/display/overlay_candidate_factory.cc
index 98a9c31..74158e3 100644
--- a/components/viz/service/display/overlay_candidate_factory.cc
+++ b/components/viz/service/display/overlay_candidate_factory.cc
@@ -10,7 +10,6 @@
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
@@ -121,9 +120,6 @@
     case DrawQuad::Material::kVideoHole:
       return FromVideoHoleQuad(VideoHoleDrawQuad::MaterialCast(quad),
                                candidate);
-    case DrawQuad::Material::kStreamVideoContent:
-      return FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad),
-                                 candidate);
     case DrawQuad::Material::kSolidColor:
       if (!is_delegated_context_)
         return CandidateStatus::kFailQuadNotSupported;
@@ -442,21 +438,15 @@
     // quads are not intended to become overlays.
     if (!quad->resource_size_in_pixels().IsEmpty())
       candidate.priority_hint = gfx::OverlayPriorityHint::kRegular;
-  }
-  return rtn;
-}
 
-OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromStreamVideoQuad(
-    const StreamVideoDrawQuad* quad,
-    OverlayCandidate& candidate) const {
-  auto rtn = FromDrawQuadResource(quad, quad->resource_id(), false, candidate);
-
-  if (rtn == CandidateStatus::kSuccess) {
-    candidate.resource_size_in_pixels = quad->resource_size_in_pixels();
-    candidate.uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
 #if BUILDFLAG(IS_ANDROID)
-    candidate.is_backed_by_surface_texture =
-        resource_provider_->IsBackedBySurfaceTexture(quad->resource_id());
+    if (quad->is_stream_video) {
+      // StreamVideoDrawQuad used to set the resource_size_in_pixels directly
+      // from the quad rather than from the resource.
+      candidate.resource_size_in_pixels = quad->resource_size_in_pixels();
+      candidate.is_backed_by_surface_texture =
+          resource_provider_->IsBackedBySurfaceTexture(quad->resource_id());
+    }
 #endif
   }
   return rtn;
diff --git a/components/viz/service/display/overlay_candidate_factory.h b/components/viz/service/display/overlay_candidate_factory.h
index 1d1f6d8..0956c3d 100644
--- a/components/viz/service/display/overlay_candidate_factory.h
+++ b/components/viz/service/display/overlay_candidate_factory.h
@@ -34,7 +34,6 @@
 class AggregatedRenderPassDrawQuad;
 class DisplayResourceProvider;
 class SolidColorDrawQuad;
-class StreamVideoDrawQuad;
 class TextureDrawQuad;
 class VideoHoleDrawQuad;
 
@@ -105,9 +104,6 @@
   CandidateStatus FromSolidColorQuad(const SolidColorDrawQuad* quad,
                                      OverlayCandidate& candidate) const;
 
-  CandidateStatus FromStreamVideoQuad(const StreamVideoDrawQuad* quad,
-                                      OverlayCandidate& candidate) const;
-
   CandidateStatus FromVideoHoleQuad(const VideoHoleDrawQuad* quad,
                                     OverlayCandidate& candidate) const;
 
diff --git a/components/viz/service/display/overlay_dc_unittest.cc b/components/viz/service/display/overlay_dc_unittest.cc
index 8fe0787..670994d 100644
--- a/components/viz/service/display/overlay_dc_unittest.cc
+++ b/components/viz/service/display/overlay_dc_unittest.cc
@@ -20,7 +20,6 @@
 #include "components/viz/common/quads/aggregated_render_pass.h"
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
diff --git a/components/viz/service/display/overlay_processor_android.cc b/components/viz/service/display/overlay_processor_android.cc
index ca7412c..11de2ab 100644
--- a/components/viz/service/display/overlay_processor_android.cc
+++ b/components/viz/service/display/overlay_processor_android.cc
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/synchronization/waitable_event.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
 #include "components/viz/service/display/overlay_processor_on_gpu.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
@@ -200,9 +200,12 @@
   ResourceIdSet promotion_hint_requestor_set;
 
   for (auto* quad : quad_list) {
-    if (quad->material != DrawQuad::Material::kStreamVideoContent)
+    if (quad->material != DrawQuad::Material::kTextureContent)
       continue;
-    ResourceId id = StreamVideoDrawQuad::MaterialCast(quad)->resource_id();
+    const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
+    if (!texture_quad->is_stream_video)
+      continue;
+    ResourceId id = texture_quad->resource_id();
     if (!resource_provider->DoesResourceWantPromotionHint(id))
       continue;
     promotion_hint_requestor_set.insert(id);
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index 38af7fa..45e8ff7 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -28,7 +28,6 @@
 #include "components/viz/common/quads/compositor_render_pass.h"
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
 #include "components/viz/common/resources/resource_id.h"
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 178e4c56..01f73cfc0 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -30,7 +30,6 @@
 #include "components/viz/common/quads/debug_border_draw_quad.h"
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
@@ -245,7 +244,6 @@
     case DrawQuad::Material::kTiledContent:
       return TileDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
     case DrawQuad::Material::kYuvVideoContent:
-    case DrawQuad::Material::kStreamVideoContent:
     case DrawQuad::Material::kTextureContent:
       // This is done to match the behaviour of GLRenderer and we can revisit it
       // later.
@@ -1105,10 +1103,6 @@
       DrawSolidColorQuad(SolidColorDrawQuad::MaterialCast(quad), rpdq_params,
                          params);
       break;
-    case DrawQuad::Material::kStreamVideoContent:
-      DrawStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad), rpdq_params,
-                          params);
-      break;
     case DrawQuad::Material::kTextureContent:
       DrawTextureQuad(TextureDrawQuad::MaterialCast(quad), rpdq_params, params);
       break;
@@ -1884,7 +1878,6 @@
 
   DCHECK_NE(new_quad->material, DrawQuad::Material::kCompositorRenderPass);
   if (new_quad->material != DrawQuad::Material::kAggregatedRenderPass &&
-      new_quad->material != DrawQuad::Material::kStreamVideoContent &&
       new_quad->material != DrawQuad::Material::kTextureContent &&
       new_quad->material != DrawQuad::Material::kTiledContent)
     return true;
@@ -2207,48 +2200,6 @@
   DrawColoredQuad(quad->color, rpdq_params, params);
 }
 
-void SkiaRenderer::DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
-                                       const DrawRPDQParams* rpdq_params,
-                                       DrawQuadParams* params) {
-  TRACE_EVENT0("viz", "SkiaRenderer::DrawStreamVideoQuad");
-  DCHECK(!MustFlushBatchedQuads(quad, rpdq_params, *params));
-
-  sk_sp<SkColorSpace> override_color_space;
-
-  // Force SRGB color space if we don't want real color space from media
-  // decoder.
-  if (!use_real_color_space_for_stream_video_)
-    override_color_space = SkColorSpace::MakeSRGB();
-
-  ScopedSkImageBuilder builder(this, quad->resource_id(),
-                               /*maybe_concurrent_reads=*/true,
-                               kUnpremul_SkAlphaType, kTopLeft_GrSurfaceOrigin,
-                               override_color_space);
-  const SkImage* image = builder.sk_image();
-  if (!image)
-    return;
-
-  gfx::RectF uv_rect = gfx::ScaleRect(
-      gfx::BoundingRect(quad->uv_top_left, quad->uv_bottom_right),
-      image->width(), image->height());
-  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
-      uv_rect, gfx::RectF(quad->rect), params->visible_rect);
-
-  // Use provided resource size if not empty, otherwise use the full image size
-  // as the content area
-  gfx::RectF valid_texel_bounds =
-      quad->resource_size_in_pixels().IsEmpty()
-          ? gfx::RectF(image->width(), image->height())
-          : gfx::RectF(gfx::SizeF(quad->resource_size_in_pixels()));
-
-  if (rpdq_params) {
-    SkPaint paint = params->paint(GetContentColorFilter());
-    DrawSingleImage(image, valid_texel_bounds, rpdq_params, &paint, params);
-  } else {
-    AddQuadToBatch(image, valid_texel_bounds, params);
-  }
-}
-
 void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad,
                                    const DrawRPDQParams* rpdq_params,
                                    DrawQuadParams* params) {
@@ -2256,12 +2207,15 @@
   const gfx::ColorSpace& src_color_space =
       resource_provider()->GetColorSpace(quad->resource_id());
   const bool needs_color_conversion_filter =
-      (quad->is_video_frame && src_color_space.IsHDR()) ||
-      src_color_space.IsToneMappedByDefault();
+      ((quad->is_video_frame && src_color_space.IsHDR()) ||
+       src_color_space.IsToneMappedByDefault()) &&
+      // Don't do color conversions for stream video.
+      !quad->is_stream_video;
 
   sk_sp<SkColorSpace> override_color_space;
-  if (needs_color_conversion_filter)
+  if (needs_color_conversion_filter) {
     override_color_space = CurrentRenderPassSkColorSpace();
+  }
 
     // TODO(b/221643955): Some Chrome OS tests rely on the old GLRenderer
     // behavior of skipping color space conversions if the quad's color space is
@@ -2272,6 +2226,12 @@
     override_color_space = CurrentRenderPassSkColorSpace();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+  // Force SRGB color space if we don't want real color space from media
+  // decoder.
+  if (!use_real_color_space_for_stream_video_ && quad->is_stream_video) {
+    override_color_space = SkColorSpace::MakeSRGB();
+  }
+
   ScopedSkImageBuilder builder(
       this, quad->resource_id(), /*maybe_concurrent_reads=*/true,
       quad->premultiplied_alpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index f941566..3a0074b 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -218,9 +218,6 @@
                           const DrawRPDQParams* rpdq_params,
                           DrawQuadParams* params);
 
-  void DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
-                           const DrawRPDQParams* rpdq_params,
-                           DrawQuadParams* params);
   void DrawTextureQuad(const TextureDrawQuad* quad,
                        const DrawRPDQParams* rpdq_params,
                        DrawQuadParams* params);
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index 7ee2ca6..96a044c 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -346,7 +346,6 @@
       break;
     case DrawQuad::Material::kInvalid:
     case DrawQuad::Material::kYuvVideoContent:
-    case DrawQuad::Material::kStreamVideoContent:
     case DrawQuad::Material::kSharedElement:
       DrawUnsupportedQuad(quad);
       NOTREACHED();
@@ -433,7 +432,7 @@
 }
 
 void SoftwareRenderer::DrawTextureQuad(const TextureDrawQuad* quad) {
-  if (!IsSoftwareResource(quad->resource_id())) {
+  if (!IsSoftwareResource(quad->resource_id()) || quad->is_stream_video) {
     DrawUnsupportedQuad(quad);
     return;
   }
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index ad880441..ceca380c 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -35,6 +35,7 @@
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
 #include "components/viz/common/surfaces/surface_range.h"
+#include "components/viz/common/viz_utils.h"
 #include "components/viz/service/debugger/viz_debugger.h"
 #include "components/viz/service/display/aggregated_frame.h"
 #include "components/viz/service/display/display_resource_provider.h"
@@ -288,6 +289,7 @@
   bool video_capture_enabled = false;
   bool may_contain_video = false;
   bool frame_sinks_changed = false;
+  bool page_fullscreen_mode = false;
   gfx::ContentColorUsage content_color_usage = gfx::ContentColorUsage::kSRGB;
 };
 
@@ -1604,6 +1606,19 @@
       if (!quad_damage_rect.IsEmpty()) {
         resolved_pass.aggregation().has_damage_from_contributing_content = true;
       }
+
+      // Only check for root render pass on the root surface.
+      if (parent_pass == nullptr && resolved_pass.is_root() &&
+          !result.page_fullscreen_mode) {
+        gfx::Rect surface_quad_on_target_space = ClippedQuadRectangle(quad);
+        // Often time the surface_quad_on_target_space is not exactly the same
+        // as the output_rect after the math operations, although they are meant
+        // to be the same. Set the delta tolerance to 8 pixels.
+        if (surface_quad_on_target_space.ApproximatelyEqual(
+                render_pass.output_rect, /*tolerance=*/8)) {
+          result.page_fullscreen_mode = true;
+        }
+      }
     } else if (quad->material == DrawQuad::Material::kCompositorRenderPass) {
       auto* render_pass_quad = CompositorRenderPassDrawQuad::MaterialCast(quad);
 
@@ -2023,6 +2038,7 @@
   frame.video_capture_enabled = prewalk_result.video_capture_enabled;
   frame.may_contain_video = prewalk_result.may_contain_video;
   frame.content_color_usage = prewalk_result.content_color_usage;
+  frame.page_fullscreen_mode = prewalk_result.page_fullscreen_mode;
 
   base::ElapsedTimer copy_timer;
   CopyUndrawnSurfaces(&prewalk_result);
diff --git a/components/viz/service/display_embedder/image_context_impl.h b/components/viz/service/display_embedder/image_context_impl.h
index 3d755e6..dd33929 100644
--- a/components/viz/service/display_embedder/image_context_impl.h
+++ b/components/viz/service/display_embedder/image_context_impl.h
@@ -113,14 +113,14 @@
 
   // Only one of the follow should be non-null at the same time.
   scoped_refptr<gpu::gles2::TexturePassthrough> texture_passthrough_;
-  std::unique_ptr<gpu::SharedImageRepresentationSkia> representation_;
-  std::unique_ptr<gpu::SharedImageRepresentationRaster> raster_representation_;
+  std::unique_ptr<gpu::SkiaImageRepresentation> representation_;
+  std::unique_ptr<gpu::RasterImageRepresentation> raster_representation_;
 
   // For scoped read accessing |representation|. It is only accessed on GPU
   // thread.
-  std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<gpu::SkiaImageRepresentation::ScopedReadAccess>
       representation_scoped_read_access_;
-  std::unique_ptr<gpu::SharedImageRepresentationRaster::ScopedReadAccess>
+  std::unique_ptr<gpu::RasterImageRepresentation::ScopedReadAccess>
       representation_raster_scoped_access_;
 
   // For holding SkPromiseImageTexture create from |fallback_texture| or legacy
diff --git a/components/viz/service/display_embedder/output_presenter.h b/components/viz/service/display_embedder/output_presenter.h
index 2b8cbaba..5db0804e 100644
--- a/components/viz/service/display_embedder/output_presenter.h
+++ b/components/viz/service/display_embedder/output_presenter.h
@@ -43,7 +43,7 @@
         const gpu::Mailbox& mailbox,
         SkiaOutputSurfaceDependency* deps);
 
-    gpu::SharedImageRepresentationSkia* skia_representation() {
+    gpu::SkiaImageRepresentation* skia_representation() {
       return skia_representation_.get();
     }
 
@@ -62,8 +62,8 @@
 
    private:
     base::ScopedClosureRunner shared_image_deleter_;
-    std::unique_ptr<gpu::SharedImageRepresentationSkia> skia_representation_;
-    std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+    std::unique_ptr<gpu::SkiaImageRepresentation> skia_representation_;
+    std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess>
         scoped_skia_write_access_;
 
     std::vector<GrBackendSemaphore> end_semaphores_;
@@ -115,8 +115,7 @@
   // Default.
   using OverlayPlaneCandidate = OverlayCandidate;
 #endif
-  using ScopedOverlayAccess =
-      gpu::SharedImageRepresentationOverlay::ScopedReadAccess;
+  using ScopedOverlayAccess = gpu::OverlayImageRepresentation::ScopedReadAccess;
   virtual void ScheduleOverlayPlane(
       const OverlayPlaneCandidate& overlay_plane_candidate,
       ScopedOverlayAccess* access,
diff --git a/components/viz/service/display_embedder/output_presenter_fuchsia.cc b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
index a451f62..b3d0429e 100644
--- a/components/viz/service/display_embedder/output_presenter_fuchsia.cc
+++ b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
@@ -63,9 +63,8 @@
  private:
   VulkanContextProvider* vulkan_context_provider_ = nullptr;
 
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay>
-      overlay_representation_;
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
+  std::unique_ptr<gpu::OverlayImageRepresentation> overlay_representation_;
+  std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
       scoped_overlay_read_access_;
 
   int present_count_ = 0;
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc
index 6a4de66..87e93c2 100644
--- a/components/viz/service/display_embedder/output_presenter_gl.cc
+++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -72,9 +72,8 @@
   }
 
  private:
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay>
-      overlay_representation_;
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
+  std::unique_ptr<gpu::OverlayImageRepresentation> overlay_representation_;
+  std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
       scoped_overlay_read_access_;
 
   int present_count_ = 0;
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
index 77259f0f..ded9a27 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -59,10 +59,9 @@
  public:
   OverlayData() = default;
 
-  OverlayData(
-      std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation,
-      std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
-          scoped_read_access)
+  OverlayData(std::unique_ptr<gpu::OverlayImageRepresentation> representation,
+              std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
+                  scoped_read_access)
       : representation_(std::move(representation)),
         scoped_read_access_(std::move(scoped_read_access)),
         ref_(1) {
@@ -111,7 +110,7 @@
 
   bool unique() const { return ref_ == 1; }
   const gpu::Mailbox& mailbox() const { return representation_->mailbox(); }
-  gpu::SharedImageRepresentationOverlay::ScopedReadAccess* scoped_read_access()
+  gpu::OverlayImageRepresentation::ScopedReadAccess* scoped_read_access()
       const {
     return scoped_read_access_.get();
   }
@@ -123,8 +122,8 @@
     ref_ = 0;
   }
 
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation_;
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
+  std::unique_ptr<gpu::OverlayImageRepresentation> representation_;
+  std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
       scoped_read_access_;
   int ref_ = 0;
 };
@@ -191,7 +190,7 @@
 
 SkiaOutputDeviceBufferQueue::~SkiaOutputDeviceBufferQueue() {
   // TODO(vasilyt): We should not need this when we stop using
-  // SharedImageBackingGLImage.
+  // GLImageBacking.
   if (context_state_->context_lost()) {
     for (auto& overlay : overlays_) {
       overlay.OnContextLost();
@@ -605,7 +604,7 @@
   // MacOS it needs context to be current.
 #if BUILDFLAG(IS_APPLE)
   // TODO(vasilyt): We shouldn't need this after we stop using
-  // SharedImageBackingGLImage as backing.
+  // GLImageBacking as backing.
   if (!context_state_->MakeCurrent(nullptr)) {
     for (auto& overlay : overlays_) {
       overlay.OnContextLost();
@@ -738,7 +737,7 @@
   if (!needs_background_image_)
     return;
 
-  gpu::SharedImageRepresentationOverlay::ScopedReadAccess* access = nullptr;
+  gpu::OverlayImageRepresentation::ScopedReadAccess* access = nullptr;
   OutputPresenter::OverlayPlaneCandidate candidate;
 #if defined(USE_OZONE)
   candidate.color_space = color_space_;
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
index 432b5d8..683f291f 100644
--- a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
@@ -139,10 +139,10 @@
 
 // Here starts SkiaOutputDeviceBufferQueue test related code
 
-class TestSharedImageBackingFactory : public gpu::SharedImageBackingFactory {
+class TestImageBackingFactory : public gpu::SharedImageBackingFactory {
  public:
-  TestSharedImageBackingFactory() = default;
-  ~TestSharedImageBackingFactory() override = default;
+  TestImageBackingFactory() = default;
+  ~TestImageBackingFactory() override = default;
 
   // gpu::SharedImageBackingFactory implementation.
   std::unique_ptr<gpu::SharedImageBacking> CreateSharedImage(
@@ -157,7 +157,7 @@
       bool is_thread_safe) override {
     size_t estimated_size =
         ResourceSizes::CheckedSizeInBytes<size_t>(size, format);
-    return std::make_unique<gpu::TestSharedImageBacking>(
+    return std::make_unique<gpu::TestImageBacking>(
         mailbox, format, size, color_space, surface_origin, alpha_type, usage,
         estimated_size);
   }
@@ -170,7 +170,7 @@
       SkAlphaType alpha_type,
       uint32_t usage,
       base::span<const uint8_t> pixel_data) override {
-    return std::make_unique<gpu::TestSharedImageBacking>(
+    return std::make_unique<gpu::TestImageBacking>(
         mailbox, format, size, color_space, surface_origin, alpha_type, usage,
         pixel_data.size());
   }
@@ -457,7 +457,7 @@
   std::unique_ptr<SkiaOutputSurfaceDependency> dependency_;
   scoped_refptr<MockGLSurfaceAsync> gl_surface_;
   std::unique_ptr<MemoryTrackerStub> memory_tracker_;
-  TestSharedImageBackingFactory test_backing_factory_;
+  TestImageBackingFactory test_backing_factory_;
   std::unique_ptr<gpu::SharedImageFactory> shared_image_factory_;
   std::unique_ptr<gpu::SharedImageRepresentationFactory>
       shared_image_representation_factory_;
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc
index d063577..0db0956 100644
--- a/components/viz/service/display_embedder/skia_output_device_gl.cc
+++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -70,7 +70,7 @@
       : texture_(std::move(texture)) {}
 
   explicit OverlayData(
-      std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation)
+      std::unique_ptr<gpu::OverlayImageRepresentation> representation)
       : representation_(std::move(representation)) {}
 
   ~OverlayData() = default;
@@ -95,9 +95,8 @@
   void EndOverlayAccess() { access_.reset(); }
 
  private:
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay> representation_;
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay::ScopedReadAccess>
-      access_;
+  std::unique_ptr<gpu::OverlayImageRepresentation> representation_;
+  std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess> access_;
   scoped_refptr<gpu::gles2::TexturePassthrough> texture_;
 };
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index eb47736..263909c 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -280,7 +280,7 @@
 
   // Even with Vulkan/Dawn compositing, the SharedImageFactory constructor
   // always initializes a GL-backed SharedImage factory to fall back on.
-  // Creating the SharedImageBackingFactoryGLTexture invokes GL API calls, so
+  // Creating the GLTextureImageBackingFactory invokes GL API calls, so
   // we need to ensure there is a current GL context.
   if (!context_state->MakeCurrent(nullptr, true /* need_gl */)) {
     LOG(ERROR) << "Failed to make current during initialization.";
@@ -719,7 +719,7 @@
   }
 }
 
-std::unique_ptr<gpu::SharedImageRepresentationSkia>
+std::unique_ptr<gpu::SkiaImageRepresentation>
 SkiaOutputSurfaceImplOnGpu::CreateSharedImageRepresentationSkia(
     ResourceFormat resource_format,
     const gfx::Size& size,
@@ -941,7 +941,7 @@
 
     SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry};
 
-    std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+    std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess>
         scoped_write = representation->BeginScopedWriteAccess(
             /*final_msaa_count=*/1, surface_props, &plane_data.begin_semaphores,
             &plane_data.end_semaphores,
@@ -983,7 +983,7 @@
 
     SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry};
 
-    std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+    std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess>
         scoped_write = representation->BeginScopedWriteAccess(
             /*final_msaa_count=*/1, surface_props, &plane_data.begin_semaphores,
             &plane_data.end_semaphores,
@@ -1339,7 +1339,7 @@
 
 ReleaseCallback
 SkiaOutputSurfaceImplOnGpu::CreateDestroyCopyOutputResourcesOnGpuThreadCallback(
-    std::unique_ptr<gpu::SharedImageRepresentationSkia> representation) {
+    std::unique_ptr<gpu::SkiaImageRepresentation> representation) {
   copy_output_images_.push_back(std::move(representation));
 
   auto closure_on_gpu_thread = base::BindOnce(
@@ -1399,8 +1399,8 @@
   DCHECK(scoped_output_device_paint_ || !from_framebuffer);
 
   SkSurface* surface;
-  std::unique_ptr<gpu::SharedImageRepresentationSkia> backing_representation;
-  std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<gpu::SkiaImageRepresentation> backing_representation;
+  std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess>
       scoped_access;
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 9077aed7..710b875e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -264,8 +264,8 @@
 
     SkISize size;
     gpu::Mailbox mailbox;
-    std::unique_ptr<gpu::SharedImageRepresentationSkia> representation;
-    std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+    std::unique_ptr<gpu::SkiaImageRepresentation> representation;
+    std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess>
         scoped_write;
 
     std::vector<GrBackendSemaphore> begin_semaphores;
@@ -330,7 +330,7 @@
                       std::unique_ptr<CopyOutputRequest> request);
 
   // Helper for `CopyOutputNV12()` & `CopyOutputRGBA()` methods:
-  std::unique_ptr<gpu::SharedImageRepresentationSkia>
+  std::unique_ptr<gpu::SkiaImageRepresentation>
   CreateSharedImageRepresentationSkia(ResourceFormat resource_format,
                                       const gfx::Size& size,
                                       const gfx::ColorSpace& color_space);
@@ -443,12 +443,12 @@
   // ImplOnGpu is already destroyed, however, there is no way of running the
   // release callback from the client, so this vector holds all pending images
   // so resources can still be cleaned up in the dtor.
-  std::vector<std::unique_ptr<gpu::SharedImageRepresentationSkia>>
+  std::vector<std::unique_ptr<gpu::SkiaImageRepresentation>>
       copy_output_images_;
 
   // Helper, creates a release callback for the passed in |representation|.
   ReleaseCallback CreateDestroyCopyOutputResourcesOnGpuThreadCallback(
-      std::unique_ptr<gpu::SharedImageRepresentationSkia> representation);
+      std::unique_ptr<gpu::SkiaImageRepresentation> representation);
 
 #if defined(USE_OZONE)
   // This should outlive gl_surface_ and vulkan_surface_.
diff --git a/components/viz/test/draw_quad_matchers.cc b/components/viz/test/draw_quad_matchers.cc
index 5fd17f94..20eefed0 100644
--- a/components/viz/test/draw_quad_matchers.cc
+++ b/components/viz/test/draw_quad_matchers.cc
@@ -26,8 +26,6 @@
       return "kSolidColor";
     case DrawQuad::Material::kSharedElement:
       return "kSharedElement";
-    case DrawQuad::Material::kStreamVideoContent:
-      return "kStreamVideoContent";
     case DrawQuad::Material::kSurfaceContent:
       return "kSurfaceContent";
     case DrawQuad::Material::kTextureContent:
diff --git a/components/webdata/common/BUILD.gn b/components/webdata/common/BUILD.gn
index 8c0fd674..cb407f8 100644
--- a/components/webdata/common/BUILD.gn
+++ b/components/webdata/common/BUILD.gn
@@ -42,6 +42,7 @@
     "//components/test/data/web_database/version_101.sql",
     "//components/test/data/web_database/version_102.sql",
     "//components/test/data/web_database/version_103.sql",
+    "//components/test/data/web_database/version_104.sql",
     "//components/test/data/web_database/version_82.sql",
     "//components/test/data/web_database/version_83.sql",
     "//components/test/data/web_database/version_84.sql",
diff --git a/components/webdata/common/web_data_results.h b/components/webdata/common/web_data_results.h
index ecc8ab4d..5f4bbe6 100644
--- a/components/webdata/common/web_data_results.h
+++ b/components/webdata/common/web_data_results.h
@@ -29,14 +29,14 @@
   AUTOFILL_VALUE_RESULT,         // WDResult<std::vector<AutofillEntry>>
   AUTOFILL_CLEANUP_RESULT,       // WDResult<size_t>
   AUTOFILL_CHANGES,              // WDResult<std::vector<AutofillChange>>
-  AUTOFILL_PROFILE_RESULT,       // WDResult<AutofillProfile>
   AUTOFILL_PROFILES_RESULT,      // WDResult<std::vector<
                                  //     std::unique_ptr<AutofillProfile>>>
   AUTOFILL_CLOUDTOKEN_RESULT,    // WDResult<std::vector<std::unique_ptr<
                                  //     CreditCardCloudTokenData>>>
-  AUTOFILL_CREDITCARD_RESULT,    // WDResult<CreditCard>
   AUTOFILL_CREDITCARDS_RESULT,   // WDResult<std::vector<
                                  //     std::unique_ptr<CreditCard>>>
+  AUTOFILL_IBANS_RESULT,         // WDResult<std::vector<
+                                 //     std::unique_ptr<Iban>>>
   AUTOFILL_CUSTOMERDATA_RESULT,  // WDResult<std::unique_ptr<
                                  //     PaymentsCustomerData>>
   AUTOFILL_OFFER_DATA,           // WDResult<std::vector<std::unique_ptr<
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index 70d5f832..5b50fa2 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -867,3 +867,39 @@
                                            "product_description"));
   }
 }
+
+// Tests addition of new table 'ibans'.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion104ToCurrent) {
+  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_104.sql")));
+
+  // Verify pre-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    // Check version.
+    EXPECT_EQ(104, VersionFromConnection(&connection));
+
+    sql::MetaTable meta_table;
+    ASSERT_TRUE(meta_table.Init(&connection, 104, 100));
+
+    // The ibans table should not exist.
+    EXPECT_FALSE(connection.DoesTableExist("ibans"));
+  }
+
+  DoMigration();
+
+  // Verify post-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    // Check version.
+    EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+    // The ibans table should exist.
+    EXPECT_TRUE(connection.DoesTableExist("ibans"));
+  }
+}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index bd6e266..1a6ad373 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -109,6 +109,7 @@
     "//components/web_package",
     "//content:content_resources",
     "//content:dev_ui_content_resources",
+    "//content/browser/aggregation_service/proto:aggregatable_report_proto",
     "//content/browser/attribution_reporting:attribution_reporting_proto",
     "//content/browser/attribution_reporting:mojo_bindings",
     "//content/browser/background_fetch:background_fetch_proto",
@@ -368,6 +369,8 @@
     "aggregation_service/aggregatable_report.h",
     "aggregation_service/aggregatable_report_assembler.cc",
     "aggregation_service/aggregatable_report_assembler.h",
+    "aggregation_service/aggregatable_report_scheduler.cc",
+    "aggregation_service/aggregatable_report_scheduler.h",
     "aggregation_service/aggregatable_report_sender.cc",
     "aggregation_service/aggregatable_report_sender.h",
     "aggregation_service/aggregation_service.cc",
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index f88870ad..2fe30320 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -63,45 +63,9 @@
 // is not a native text field (input or textarea).
 BrowserAccessibility* GetTextFieldInnerEditorElement(
     const BrowserAccessibility& text_field) {
-  if (!text_field.IsAtomicTextField() || !text_field.InternalChildCount())
-    return nullptr;
-
-  // Text fields wrap their static text and inline text boxes in generic
-  // containers, and some, like input type=search, wrap the wrapper as well.
-  // There are several incarnations of this structure.
-  // 1. An empty native text field:
-  // -- Generic container <-- there can be any number of these in a chain.
-  //    However, some empty text fields have the below structure, with empty
-  //    text boxes.
-  // 2. A single line, native text field with some text in it:
-  // -- Generic container <-- there can be any number of these in a chain.
-  // ---- Static text
-  // ------ Inline text box children (zero or more)
-  // ---- Line Break (optional,  a placeholder break element if the text data
-  //                    ends with '\n' or '\r')
-  // 3. A multiline text area with some text in it:
-  //    Similar to #2, but can repeat the static text, line break children
-  //    multiple times.
-
-  BrowserAccessibility* text_container = text_field.InternalDeepestFirstChild();
-
-  // Non-empty text fields expose a set of static text objects with one or more
-  // inline text boxes each. On some platforms, such as Android, we don't enable
-  // inline text boxes, and only the static text objects are exposed.
-  if (text_container->GetRole() == ax::mojom::Role::kInlineTextBox)
-    text_container = text_container->InternalGetParent();
-
-  // Get the parent of the static text or the line break, if any. A line break
-  // is possible when the field contains a line break as its first character.
-  if (text_container->GetRole() == ax::mojom::Role::kStaticText ||
-      text_container->GetRole() == ax::mojom::Role::kLineBreak) {
-    text_container = text_container->InternalGetParent();
-  }
-
-  DCHECK(text_container);
-  if (text_container->GetRole() == ax::mojom::Role::kGenericContainer)
-    return text_container;
-  return nullptr;
+  ui::AXNode* text_container =
+      text_field.node()->GetTextFieldInnerEditorElement();
+  return text_field.manager()->GetFromAXNode(text_container);
 }
 
 }  // namespace
@@ -116,7 +80,7 @@
 
   // If the input type is not plain or text it may be a complex field, such as
   // a datetime input. We don't try to enforce a special structure for those.
-  std::string input_type =
+  const std::string& input_type =
       GetStringAttribute(ax::mojom::StringAttribute::kInputType);
   if (!input_type.empty() && input_type != "text")
     return true;  // Not a plain text field, just consider it valid.
@@ -138,8 +102,7 @@
 }
 
 bool BrowserAccessibility::CanFireEvents() const {
-  // Allow events unless this object would be trimmed away.
-  return !IsChildOfLeaf();
+  return node()->CanFireEvents();
 }
 
 ui::AXPlatformNode* BrowserAccessibility::GetAXPlatformNode() const {
@@ -149,29 +112,33 @@
 }
 
 size_t BrowserAccessibility::PlatformChildCount() const {
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
   return IsLeaf() ? 0 : node()->GetUnignoredChildCountCrossingTreeBoundary();
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetParent() const {
-  ui::AXNode* parent = node()->GetUnignoredParent();
-  if (parent)
-    return manager()->GetFromAXNode(parent);
-  return manager()->GetParentNodeFromParentTree();
+  ui::AXNode* parent = node()->GetUnignoredParentCrossingTreeBoundary();
+  return manager()->GetFromAXNode(parent);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetFirstChild() const {
-  if (PlatformChildCount() == 0)
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
+  if (IsLeaf())
     return nullptr;
-
-  return PlatformGetChild(0);
+  ui::AXNode* first_child =
+      node()->GetFirstUnignoredChildCrossingTreeBoundary();
+  return manager()->GetFromAXNode(first_child);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetLastChild() const {
-  if (PlatformChildCount() == 0)
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
+  if (IsLeaf())
     return nullptr;
-
-  BrowserAccessibility* child_tree_root = PlatformGetRootOfChildTree();
-  return child_tree_root ? child_tree_root : InternalGetLastChild();
+  ui::AXNode* last_child = node()->GetLastUnignoredChildCrossingTreeBoundary();
+  return manager()->GetFromAXNode(last_child);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetNextSibling() const {
@@ -214,42 +181,35 @@
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
     size_t child_index) const {
-  if (PlatformChildCount() == 0)
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
+  if (IsLeaf())
     return nullptr;
-
-  BrowserAccessibility* child_tree_root = PlatformGetRootOfChildTree();
-  if (child_tree_root) {
-    // A node with a child tree has only one child.
-    return child_index ? nullptr : child_tree_root;
-  }
-  return InternalGetChild(child_index);
+  ui::AXNode* child =
+      node()->GetUnignoredChildAtIndexCrossingTreeBoundary(child_index);
+  return manager()->GetFromAXNode(child);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetLowestPlatformAncestor()
     const {
   ui::AXNode* lowest_platform_ancestor = node()->GetLowestPlatformAncestor();
-  if (!lowest_platform_ancestor)
-    return nullptr;
   return manager()->GetFromAXNode(lowest_platform_ancestor);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetTextFieldAncestor()
     const {
   ui::AXNode* text_field_ancestor = node()->GetTextFieldAncestor();
-  if (!text_field_ancestor)
-    return nullptr;
   return manager()->GetFromAXNode(text_field_ancestor);
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformGetSelectionContainer()
     const {
   ui::AXNode* selection_container_ancestor = node()->GetSelectionContainer();
-  if (!selection_container_ancestor)
-    return nullptr;
   return manager()->GetFromAXNode(selection_container_ancestor);
 }
 
 bool BrowserAccessibility::IsPreviousSiblingOnSameLine() const {
+  // TODO(nektar): Replace this method with `!AXPosition::AtStartOfLine()`.
   const BrowserAccessibility* previous_sibling = PlatformGetPreviousSibling();
   if (!previous_sibling)
     return false;
@@ -274,6 +234,7 @@
 }
 
 bool BrowserAccessibility::IsNextSiblingOnSameLine() const {
+  // TODO(nektar): Replace this method with `!AXPosition::AtEndOfLine()`.
   const BrowserAccessibility* next_sibling = PlatformGetNextSibling();
   if (!next_sibling)
     return false;
@@ -297,39 +258,40 @@
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const {
-  if (!PlatformChildCount())
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
+  if (IsLeaf())
     return nullptr;
-
   BrowserAccessibility* deepest_child = PlatformGetFirstChild();
-  while (deepest_child->PlatformChildCount())
+  while (!deepest_child->IsLeaf())
     deepest_child = deepest_child->PlatformGetFirstChild();
-
   return deepest_child;
 }
 
 BrowserAccessibility* BrowserAccessibility::PlatformDeepestLastChild() const {
-  if (!PlatformChildCount())
+  // We need to explicitly check for leafiness here instead of relying on
+  // `AXNode::IsLeaf()` because Android has a different notion of this concept.
+  if (IsLeaf())
     return nullptr;
-
   BrowserAccessibility* deepest_child = PlatformGetLastChild();
-  while (deepest_child->PlatformChildCount()) {
+  while (!deepest_child->IsLeaf())
     deepest_child = deepest_child->PlatformGetLastChild();
-  }
-
   return deepest_child;
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalDeepestFirstChild() const {
+  // By design, this method should be able to traverse platform leaves, hence we
+  // don't check for leafiness.
   ui::AXNode* deepest_child = node()->GetDeepestFirstUnignoredChild();
-  if (!deepest_child)
-    return nullptr;
   return manager()->GetFromAXNode(deepest_child);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalDeepestLastChild() const {
+  // By design, this method should be able to traverse platform leaves, hence we
+  // don't check for leafiness. We need to explicitly check for leafiness here
+  // instead of relying on `AXNode::IsLeaf()` because Android has a different
+  // notion of this concept.
   ui::AXNode* deepest_child = node()->GetDeepestLastUnignoredChild();
-  if (!deepest_child)
-    return nullptr;
   return manager()->GetFromAXNode(deepest_child);
 }
 
@@ -343,44 +305,38 @@
 
 BrowserAccessibility* BrowserAccessibility::InternalGetChild(
     size_t child_index) const {
+  // By design, this method should be able to traverse platform leaves, hence we
+  // don't check for leafiness.
   ui::AXNode* child_node = node_->GetUnignoredChildAtIndex(child_index);
-  if (!child_node)
-    return nullptr;
   return manager_->GetFromAXNode(child_node);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalGetParent() const {
   ui::AXNode* parent_node = node_->GetUnignoredParent();
-  if (!parent_node)
-    return nullptr;
   return manager_->GetFromAXNode(parent_node);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalGetFirstChild() const {
+  // By design, this method should be able to traverse platform leaves, hence we
+  // don't check for leafiness.
   ui::AXNode* child_node = node_->GetFirstUnignoredChild();
-  if (!child_node)
-    return nullptr;
   return manager_->GetFromAXNode(child_node);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalGetLastChild() const {
+  // By design, this method should be able to traverse platform leaves, hence we
+  // don't check for leafiness.
   ui::AXNode* child_node = node_->GetLastUnignoredChild();
-  if (!child_node)
-    return nullptr;
   return manager_->GetFromAXNode(child_node);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalGetNextSibling() const {
   ui::AXNode* sibling_node = node_->GetNextUnignoredSibling();
-  if (!sibling_node)
-    return nullptr;
   return manager_->GetFromAXNode(sibling_node);
 }
 
 BrowserAccessibility* BrowserAccessibility::InternalGetPreviousSibling() const {
   ui::AXNode* sibling_node = node_->GetPreviousUnignoredSibling();
-  if (!sibling_node)
-    return nullptr;
   return manager_->GetFromAXNode(sibling_node);
 }
 
@@ -399,13 +355,13 @@
   if (child_tree_root_)
     return index_ == 0 ? child_tree_root_ : nullptr;
 
+  // TODO(nektar): Consider using
+  // `AXNode::GetChildAtIndexCrossingTreeBoundary()`.
   ui::AXNode* child = parent_->node()->GetChildAtIndex(index_);
-  if (!child)
-    return nullptr;
-  return parent_->manager_->GetFromAXNode(child);
+  return parent_->manager()->GetFromAXNode(child);
 }
 
-int32_t BrowserAccessibility::GetId() const {
+ui::AXNodeID BrowserAccessibility::GetId() const {
   return node()->id();
 }
 
@@ -464,11 +420,13 @@
 
   const std::u16string& text_str = GetHypertext();
   if (effective_start_offset < 0 ||
-      effective_start_offset >= static_cast<int>(text_str.size()))
+      effective_start_offset >= static_cast<int>(text_str.size())) {
     return gfx::Rect();
+  }
   if (effective_end_offset < 0 ||
-      effective_end_offset > static_cast<int>(text_str.size()))
+      effective_end_offset > static_cast<int>(text_str.size())) {
     return gfx::Rect();
+  }
 
   if (coordinate_system == ui::AXCoordinateSystem::kFrame) {
     NOTIMPLEMENTED();
@@ -495,10 +453,12 @@
     int len,
     const ui::AXClippingBehavior clipping_behavior,
     ui::AXOffscreenResult* offscreen_result) const {
+  // TODO(nektar): Move to `AXNode` as soon as hypertext computation is fully
+  // migrated to that class.
   DCHECK_GE(start, 0);
   DCHECK_GE(len, 0);
 
-  // Native text fields such as textarea have a text container node inside them
+  // Atomic text fields such as textarea have a text container node inside them
   // that holds all the text and do not expose any IA2 hypertext. We need to get
   // to the flattened representation of the text in the field in order that
   // `start` and `len` would be applicable. Non-native text fields, including
@@ -612,6 +572,9 @@
 gfx::Rect BrowserAccessibility::GetRootFrameHypertextBoundsPastEndOfText(
     const ui::AXClippingBehavior clipping_behavior,
     ui::AXOffscreenResult* offscreen_result) const {
+  // TODO(nektar): Move to `AXNode` as soon as hypertext computation is fully
+  // migrated to that class.
+
   // Step 1: get approximate caret bounds. The thickness may not yet be correct.
   gfx::Rect bounds;
   if (InternalChildCount() > 0) {
@@ -678,6 +641,8 @@
     const ui::AXCoordinateSystem coordinate_system,
     const ui::AXClippingBehavior clipping_behavior,
     ui::AXOffscreenResult* offscreen_result) const {
+  // TODO(nektar): Move to `AXNode` as soon as hypertext computation is fully
+  // migrated to that class.
   if (GetRole() == ax::mojom::Role::kInlineTextBox) {
     return RelativeToAbsoluteBounds(
         GetInlineTextRect(start_offset, end_offset,
@@ -726,6 +691,7 @@
 gfx::RectF BrowserAccessibility::GetInlineTextRect(const int start_offset,
                                                    const int end_offset,
                                                    const int max_length) const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
   DCHECK(start_offset >= 0 && end_offset >= 0 && start_offset <= end_offset);
   int local_start_offset = start_offset, local_end_offset = end_offset;
   const std::vector<int32_t>& character_offsets =
@@ -782,6 +748,10 @@
 
 BrowserAccessibility* BrowserAccessibility::ApproximateHitTest(
     const gfx::Point& blink_screen_point) {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   // The best result found that's a child of this object.
   BrowserAccessibility* child_result = nullptr;
   // The best result that's an indirect descendant like grandchild, etc.
@@ -826,6 +796,7 @@
 }
 
 bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
   if (!ui::IsPlatformDocument(GetRole()))
     return false;
 
@@ -861,6 +832,7 @@
 }
 
 std::string BrowserAccessibility::GetLiveRegionText() const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
   if (IsIgnored())
     return "";
 
@@ -933,6 +905,10 @@
     const ui::AXCoordinateSystem coordinate_system,
     const ui::AXClippingBehavior clipping_behavior,
     ui::AXOffscreenResult* offscreen_result) const {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   const bool clip_bounds =
       clipping_behavior == ui::AXClippingBehavior::kClipped;
   bool offscreen = false;
@@ -1021,6 +997,7 @@
 }
 
 bool BrowserAccessibility::HasVisibleCaretOrSelection() const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
   ui::AXTree::Selection unignored_selection =
       manager()->ax_tree()->GetUnignoredSelection();
   ui::AXNodeID focus_id = unignored_selection.focus_object_id;
@@ -1181,7 +1158,9 @@
 }
 
 ax::mojom::Role BrowserAccessibility::GetRole() const {
-  return node_ ? node_->GetRole() : ax::mojom::Role::kUnknown;
+  // TODO(accessibility): Why is role checked after this object has been
+  // destructed causing a dangling pointer bug?
+  return node() ? node()->GetRole() : ax::mojom::Role::kUnknown;
 }
 
 bool BrowserAccessibility::HasBoolAttribute(
@@ -1363,6 +1342,8 @@
 
 const ui::AXTree::Selection BrowserAccessibility::GetUnignoredSelection()
     const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
+
   ui::AXTree::Selection selection =
       manager()->ax_tree()->GetUnignoredSelection();
 
@@ -1493,7 +1474,7 @@
   // children. The only exception to enforce leafiness is when the button has
   // a single text child and to prevent screen readers from double speak.
   if (GetRole() == ax::mojom::Role::kButton) {
-    uint32_t child_count = InternalChildCount();
+    size_t child_count = InternalChildCount();
     return !child_count ||
            (child_count == 1 && InternalGetFirstChild()->IsText());
   }
@@ -1503,6 +1484,8 @@
 }
 
 bool BrowserAccessibility::IsFocused() const {
+  // TODO(nektar): Create an `ax_focus` class to share focus state between Views
+  // and Web.
   return manager()->GetFocus() == this;
 }
 
@@ -1737,10 +1720,10 @@
 
 ui::AXPlatformNode* BrowserAccessibility::GetTableCaption() const {
   ui::AXNode* caption = node()->GetTableCaption();
-  if (caption)
+  if (caption) {
     return const_cast<BrowserAccessibility*>(this)->GetFromNodeID(
         caption->id());
-
+  }
   return nullptr;
 }
 
@@ -1806,6 +1789,8 @@
 
 bool BrowserAccessibility::AccessibilityPerformAction(
     const ui::AXActionData& data) {
+  // TODO(crbug.com/1049261): Move the ability to perform actions to
+  // `AXTreeManager`.
   switch (data.action) {
     case ax::mojom::Action::kDoDefault:
       manager_->DoDefaultAction(*this);
@@ -1925,6 +1910,10 @@
 
 std::u16string BrowserAccessibility::GetLocalizedStringForImageAnnotationStatus(
     ax::mojom::ImageAnnotationStatus status) const {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   ContentClient* content_client = content::GetContentClient();
 
   int message_id = 0;
@@ -1957,12 +1946,18 @@
 
 std::u16string
 BrowserAccessibility::GetLocalizedRoleDescriptionForUnlabeledImage() const {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   ContentClient* content_client = content::GetContentClient();
   return content_client->GetLocalizedString(
       IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION);
 }
 
 std::u16string BrowserAccessibility::GetLocalizedStringForLandmarkType() const {
+  // This method is Web specific and thus cannot be move to `AXNode`.
+
   ContentClient* content_client = content::GetContentClient();
 
   switch (GetRole()) {
@@ -1987,6 +1982,8 @@
 
 std::u16string BrowserAccessibility::GetLocalizedStringForRoleDescription()
     const {
+  // TODO(nektar): Move this method to `AXNode` if possible.
+
   // Localized role description strings live in ui/strings/ax_strings.grd
   ContentClient* content_client = content::GetContentClient();
 
@@ -2392,6 +2389,7 @@
 
 std::u16string BrowserAccessibility::GetStyleNameAttributeAsLocalizedString()
     const {
+  // This method is Web specific and thus cannot be moved to `AXNode`.
   const BrowserAccessibility* current_node = this;
   while (current_node) {
     if (current_node->GetRole() == ax::mojom::Role::kMark) {
@@ -2444,8 +2442,6 @@
 BrowserAccessibility*
 BrowserAccessibility::GetCollapsedMenuListPopUpButtonAncestor() const {
   ui::AXNode* popup_button = node()->GetCollapsedMenuListPopUpButtonAncestor();
-  if (!popup_button)
-    return nullptr;
   return manager()->GetFromAXNode(popup_button);
 }
 
@@ -2455,6 +2451,8 @@
 
 bool BrowserAccessibility::SetHypertextSelection(int start_offset,
                                                  int end_offset) {
+  // TODO(nektar): Move to `AXNode` as soon as hypertext computation is fully
+  // migrated to that class.
   manager()->SetSelection(AXRange(CreatePositionForSelectionAt(start_offset),
                                   CreatePositionForSelectionAt(end_offset)));
   return true;
@@ -2487,6 +2485,10 @@
 
 ui::TextAttributeMap BrowserAccessibility::GetSpellingAndGrammarAttributes()
     const {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   ui::TextAttributeMap spelling_attributes;
   if (IsText()) {
     const std::vector<int32_t>& marker_types =
@@ -2593,6 +2595,10 @@
 
 ui::TextAttributeMap BrowserAccessibility::ComputeTextAttributeMap(
     const ui::TextAttributeList& default_attributes) const {
+  // TODO(crbug.com/1049261): This is one of the few methods that won't be moved
+  // to `AXNode` in the foreseeable future because the functionality it provides
+  // is not immediately needed in Views.
+
   ui::TextAttributeMap attributes_map;
   if (IsLeaf()) {
     attributes_map[0] = default_attributes;
@@ -2673,6 +2679,7 @@
 }
 
 bool BrowserAccessibility::IsHierarchicalList() const {
+  // TODO(nektar): Move this method to `AXNode` in the immediate future.
   if (!ui::IsStaticList(GetRole()))
     return false;
   return HasListDescendant(this, this) || HasListAncestor(InternalGetParent());
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 3901b2b0..23f23bc 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -1916,6 +1916,10 @@
   return false;
 }
 
+bool BrowserAccessibilityAndroid::CanFireEvents() const {
+  return !IsChildOfLeaf();
+}
+
 void BrowserAccessibilityAndroid::OnDataChanged() {
   BrowserAccessibility::OnDataChanged();
 
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h
index c986b14..abaf611 100644
--- a/content/browser/accessibility/browser_accessibility_android.h
+++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -32,6 +32,7 @@
   int32_t unique_id() const { return GetUniqueId().Get(); }
 
   // BrowserAccessibility Overrides.
+  bool CanFireEvents() const override;
   void OnDataChanged() override;
   void OnLocationChanged() override;
   std::u16string GetLocalizedStringForImageAnnotationStatus(
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index fffd349..c7d8943 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/content_client.h"
 #include "ui/accessibility/ax_common.h"
+#include "ui/accessibility/ax_enum_localization_util.h"
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/accessibility/ax_role_properties.h"
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index a73acfbf..84a1e91 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -382,8 +382,14 @@
 
 BrowserAccessibility* BrowserAccessibilityManager::GetFromAXNode(
     const ui::AXNode* node) const {
+  // TODO(benjamin.beaudry): Consider moving `GetFromId` to
+  // `AXPlatformTreeManager`.
   if (!node)
     return nullptr;
+  if (AXTreeManager* manager = node->GetManager()) {
+    return static_cast<BrowserAccessibilityManager*>(manager)->GetFromID(
+        node->id());
+  }
   return GetFromID(node->id());
 }
 
diff --git a/content/browser/aggregation_service/aggregatable_report.cc b/content/browser/aggregation_service/aggregatable_report.cc
index b6cf287..32719cd1 100644
--- a/content/browser/aggregation_service/aggregatable_report.cc
+++ b/content/browser/aggregation_service/aggregatable_report.cc
@@ -18,10 +18,9 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/containers/span.h"
+#include "base/guid.h"
 #include "base/json/json_writer.h"
-#include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
-#include "base/strings/abseil_string_number_conversions.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -30,6 +29,7 @@
 #include "components/cbor/values.h"
 #include "components/cbor/writer.h"
 #include "content/browser/aggregation_service/aggregation_service_features.h"
+#include "content/browser/aggregation_service/proto/aggregatable_report.pb.h"
 #include "content/browser/aggregation_service/public_key.h"
 #include "content/common/aggregatable_report.mojom.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
@@ -255,6 +255,161 @@
   return payload;
 }
 
+absl::optional<AggregationServicePayloadContents>
+ConvertPayloadContentsFromProto(
+    const proto::AggregationServicePayloadContents& proto) {
+  if (proto.operation() !=
+      proto::AggregationServicePayloadContents_Operation_HISTOGRAM) {
+    return absl::nullopt;
+  }
+  AggregationServicePayloadContents::Operation operation(
+      AggregationServicePayloadContents::Operation::kHistogram);
+
+  std::vector<mojom::AggregatableReportHistogramContribution> contributions;
+  for (const proto::AggregatableReportHistogramContribution&
+           contribution_proto : proto.contributions()) {
+    contributions.emplace_back(
+        /*bucket=*/absl::MakeUint128(contribution_proto.bucket_high(),
+                                     contribution_proto.bucket_low()),
+        /*value=*/contribution_proto.value());
+  }
+
+  mojom::AggregationServiceMode aggregation_mode =
+      mojom::AggregationServiceMode::kTeeBased;
+  switch (proto.aggregation_mode()) {
+    case proto::AggregationServiceMode::TEE_BASED:
+      break;
+    case proto::AggregationServiceMode::EXPERIMENTAL_POPLAR:
+      aggregation_mode = mojom::AggregationServiceMode::kExperimentalPoplar;
+      break;
+    default:
+      return absl::nullopt;
+  }
+
+  return AggregationServicePayloadContents(operation, std::move(contributions),
+                                           aggregation_mode);
+}
+
+absl::optional<AggregatableReportSharedInfo> ConvertSharedInfoFromProto(
+    const proto::AggregatableReportSharedInfo& proto) {
+  base::Time scheduled_report_time = base::Time::FromDeltaSinceWindowsEpoch(
+      base::Microseconds(proto.scheduled_report_time()));
+  base::GUID report_id = base::GUID::ParseLowercase(proto.report_id());
+  url::Origin reporting_origin =
+      url::Origin::Create(GURL(proto.reporting_origin()));
+
+  AggregatableReportSharedInfo::DebugMode debug_mode =
+      AggregatableReportSharedInfo::DebugMode::kDisabled;
+  switch (proto.debug_mode()) {
+    case proto::AggregatableReportSharedInfo_DebugMode_DISABLED:
+      break;
+    case proto::AggregatableReportSharedInfo_DebugMode_ENABLED:
+      debug_mode = AggregatableReportSharedInfo::DebugMode::kEnabled;
+      break;
+    default:
+      return absl::nullopt;
+  }
+
+  std::string api_version = proto.api_version();
+  std::string api_identifier = proto.api_identifier();
+
+  return AggregatableReportSharedInfo(
+      scheduled_report_time, std::move(report_id), std::move(reporting_origin),
+      debug_mode,
+      // TODO(alexmt): Persist additional_fields when it becomes necessary.
+      /*additional_fields=*/base::Value::Dict(),
+      // TODO(crbug.com/1340296): Add mechanism to upgrade stored requests from
+      // older to newer versions.
+      std::move(api_version), std::move(api_identifier));
+}
+
+absl::optional<AggregatableReportRequest> ConvertReportRequestFromProto(
+    proto::AggregatableReportRequest request_proto) {
+  absl::optional<AggregationServicePayloadContents> payload_contents(
+      ConvertPayloadContentsFromProto(request_proto.payload_contents()));
+  if (!payload_contents.has_value()) {
+    return absl::nullopt;
+  }
+
+  absl::optional<AggregatableReportSharedInfo> shared_info(
+      ConvertSharedInfoFromProto(request_proto.shared_info()));
+  if (!shared_info.has_value()) {
+    return absl::nullopt;
+  }
+
+  return AggregatableReportRequest::Create(
+      std::move(payload_contents.value()), std::move(shared_info.value()),
+      std::move(*request_proto.mutable_reporting_path()));
+}
+
+void ConvertPayloadContentsToProto(
+    const AggregationServicePayloadContents& payload_contents,
+    proto::AggregationServicePayloadContents* out) {
+  switch (payload_contents.operation) {
+    case AggregationServicePayloadContents::Operation::kHistogram:
+      out->set_operation(
+          proto::AggregationServicePayloadContents_Operation_HISTOGRAM);
+  }
+
+  for (const mojom::AggregatableReportHistogramContribution& contribution :
+       payload_contents.contributions) {
+    proto::AggregatableReportHistogramContribution* contribution_proto =
+        out->add_contributions();
+    contribution_proto->set_bucket_high(
+        absl::Uint128High64(contribution.bucket));
+    contribution_proto->set_bucket_low(absl::Uint128Low64(contribution.bucket));
+    contribution_proto->set_value(contribution.value);
+  }
+
+  switch (payload_contents.aggregation_mode) {
+    case mojom::AggregationServiceMode::kTeeBased:
+      out->set_aggregation_mode(proto::AggregationServiceMode::TEE_BASED);
+      break;
+    case mojom::AggregationServiceMode::kExperimentalPoplar:
+      out->set_aggregation_mode(
+          proto::AggregationServiceMode::EXPERIMENTAL_POPLAR);
+      break;
+  }
+}
+
+void ConvertSharedInfoToProto(const AggregatableReportSharedInfo& shared_info,
+                              proto::AggregatableReportSharedInfo* out) {
+  out->set_scheduled_report_time(
+      shared_info.scheduled_report_time.ToDeltaSinceWindowsEpoch()
+          .InMicroseconds());
+  out->set_report_id(shared_info.report_id.AsLowercaseString());
+  out->set_reporting_origin(shared_info.reporting_origin.Serialize());
+
+  switch (shared_info.debug_mode) {
+    case AggregatableReportSharedInfo::DebugMode::kDisabled:
+      out->set_debug_mode(
+          proto::AggregatableReportSharedInfo_DebugMode_DISABLED);
+      break;
+    case AggregatableReportSharedInfo::DebugMode::kEnabled:
+      out->set_debug_mode(
+          proto::AggregatableReportSharedInfo_DebugMode_ENABLED);
+      break;
+  }
+
+  DCHECK(shared_info.additional_fields.empty());
+
+  out->set_api_version(shared_info.api_version);
+  out->set_api_identifier(shared_info.api_identifier);
+}
+
+proto::AggregatableReportRequest ConvertReportRequestToProto(
+    const AggregatableReportRequest& request) {
+  proto::AggregatableReportRequest request_proto;
+  ConvertPayloadContentsToProto(
+      request.payload_contents(),
+      /*out=*/request_proto.mutable_payload_contents());
+  ConvertSharedInfoToProto(request.shared_info(),
+                           /*out=*/request_proto.mutable_shared_info());
+  *request_proto.mutable_reporting_path() = request.reporting_path();
+
+  return request_proto;
+}
+
 }  // namespace
 
 AggregationServicePayloadContents::AggregationServicePayloadContents(
@@ -433,6 +588,31 @@
   return shared_info().reporting_origin.GetURL().Resolve(reporting_path_);
 }
 
+absl::optional<AggregatableReportRequest>
+AggregatableReportRequest::Deserialize(
+    base::span<const uint8_t> serialized_proto) {
+  proto::AggregatableReportRequest request_proto;
+  if (!request_proto.ParseFromArray(serialized_proto.data(),
+                                    serialized_proto.size())) {
+    return absl::nullopt;
+  }
+
+  return ConvertReportRequestFromProto(std::move(request_proto));
+}
+
+std::vector<uint8_t> AggregatableReportRequest::Serialize() {
+  proto::AggregatableReportRequest request_proto =
+      ConvertReportRequestToProto(*this);
+
+  size_t size = request_proto.ByteSizeLong();
+  std::vector<uint8_t> serialized_proto(size);
+  if (!request_proto.SerializeToArray(serialized_proto.data(), size)) {
+    return {};
+  }
+
+  return serialized_proto;
+}
+
 AggregatableReport::AggregationServicePayload::AggregationServicePayload(
     std::vector<uint8_t> payload,
     std::string key_id,
diff --git a/content/browser/aggregation_service/aggregatable_report.h b/content/browser/aggregation_service/aggregatable_report.h
index dfa78d8d..75bffd2f 100644
--- a/content/browser/aggregation_service/aggregatable_report.h
+++ b/content/browser/aggregation_service/aggregatable_report.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/guid.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
@@ -256,6 +257,7 @@
   // `IsNumberOfHistogramContributionsValid()` above). Also returns
   // `absl::nullopt` if any contribution has a negative value or if
   // `shared_info.report_id` is not valid.
+  // TODO(alexmt): Add validation for scheduled_report_time being non-null/inf.
   static absl::optional<AggregatableReportRequest> Create(
       AggregationServicePayloadContents payload_contents,
       AggregatableReportSharedInfo shared_info,
@@ -274,6 +276,11 @@
       AggregatableReportSharedInfo shared_info,
       std::string reporting_path = std::string());
 
+  // Deserializes a bytestring generated by `Serialize()`. Returns
+  // `absl::nullopt` in the case of a deserialization error.
+  static absl::optional<AggregatableReportRequest> Deserialize(
+      base::span<const uint8_t> serialized_proto);
+
   // Move-only.
   AggregatableReportRequest(AggregatableReportRequest&& other);
   AggregatableReportRequest& operator=(AggregatableReportRequest&& other);
@@ -292,6 +299,10 @@
   // if the reporting_path is empty.
   GURL GetReportingUrl() const;
 
+  // Serializes the report request to a binary protobuf encoding. Returns an
+  // empty vector in case of an error.
+  std::vector<uint8_t> Serialize();
+
  private:
   static absl::optional<AggregatableReportRequest> CreateInternal(
       std::vector<GURL> processing_urls,
diff --git a/content/browser/aggregation_service/aggregatable_report_scheduler.cc b/content/browser/aggregation_service/aggregatable_report_scheduler.cc
new file mode 100644
index 0000000..2ce5f2c
--- /dev/null
+++ b/content/browser/aggregation_service/aggregatable_report_scheduler.cc
@@ -0,0 +1,135 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/aggregation_service/aggregatable_report_scheduler.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/check.h"
+#include "base/containers/cxx20_erase.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/sequence_bound.h"
+#include "base/time/time.h"
+#include "content/browser/aggregation_service/aggregatable_report.h"
+#include "content/browser/aggregation_service/aggregation_service_storage.h"
+#include "content/browser/aggregation_service/aggregation_service_storage_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace content {
+
+AggregatableReportScheduler::AggregatableReportScheduler(
+    AggregationServiceStorageContext* storage_context,
+    base::RepeatingCallback<
+        void(std::vector<AggregationServiceStorage::RequestAndId>)>
+        on_scheduled_report_time_reached)
+    : storage_context_(*storage_context),
+      timer_delegate_(
+          *(new TimerDelegate(storage_context,
+                              std::move(on_scheduled_report_time_reached)))),
+      timer_(base::WrapUnique(&*timer_delegate_)) {
+  DCHECK(storage_context);
+}
+AggregatableReportScheduler::~AggregatableReportScheduler() = default;
+
+void AggregatableReportScheduler::ScheduleRequest(
+    AggregatableReportRequest request) {
+  base::Time report_time = request.shared_info().scheduled_report_time;
+  storage_context_->GetStorage()
+      .AsyncCall(&AggregationServiceStorage::StoreRequest)
+      .WithArgs(std::move(request));
+
+  // If the time is in the past, the timer will fire immediately.
+  timer_.MaybeSet(report_time);
+}
+
+void AggregatableReportScheduler::NotifyInProgressRequestSucceeded(
+    AggregationServiceStorage::RequestId request_id) {
+  storage_context_->GetStorage()
+      .AsyncCall(&AggregationServiceStorage::DeleteRequest)
+      .WithArgs(request_id)
+      .Then(base::BindOnce(&TimerDelegate::NotifyRequestCompleted,
+                           timer_delegate_->GetWeakPtr(), request_id));
+}
+
+void AggregatableReportScheduler::NotifyInProgressRequestFailed(
+    AggregationServiceStorage::RequestId request_id) {
+  // TODO(crbug.com/1340040): Implement retry handling. Ideally also handle
+  // different errors differently. Also, ensure this composes well with offline
+  // handling.
+  storage_context_->GetStorage()
+      .AsyncCall(&AggregationServiceStorage::DeleteRequest)
+      .WithArgs(request_id)
+      .Then(base::BindOnce(&TimerDelegate::NotifyRequestCompleted,
+                           timer_delegate_->GetWeakPtr(), request_id));
+}
+
+AggregatableReportScheduler::TimerDelegate::TimerDelegate(
+    AggregationServiceStorageContext* storage_context,
+    base::RepeatingCallback<
+        void(std::vector<AggregationServiceStorage::RequestAndId>)>
+        on_scheduled_report_time_reached)
+    : storage_context_(*storage_context),
+      on_scheduled_report_time_reached_(
+          std::move(on_scheduled_report_time_reached)) {
+  DCHECK(storage_context);
+}
+AggregatableReportScheduler::TimerDelegate::~TimerDelegate() = default;
+
+void AggregatableReportScheduler::TimerDelegate::GetNextReportTime(
+    base::OnceCallback<void(absl::optional<base::Time>)> callback,
+    base::Time now) {
+  storage_context_->GetStorage()
+      .AsyncCall(&AggregationServiceStorage::NextReportTimeAfter)
+      .WithArgs(now)
+      .Then(std::move(callback));
+}
+
+void AggregatableReportScheduler::TimerDelegate::OnReportingTimeReached(
+    base::Time now) {
+  storage_context_->GetStorage()
+      .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+      .WithArgs(now)
+      .Then(base::BindOnce(&AggregatableReportScheduler::TimerDelegate::
+                               OnRequestsReturnedFromStorage,
+                           weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AggregatableReportScheduler::TimerDelegate::AdjustOfflineReportTimes(
+    base::OnceCallback<void(absl::optional<base::Time>)> maybe_set_timer_cb) {
+  // TODO(crbug.com/1340042): Implement offline and startup handling
+  std::move(maybe_set_timer_cb).Run(absl::nullopt);
+}
+
+void AggregatableReportScheduler::TimerDelegate::NotifyRequestCompleted(
+    AggregationServiceStorage::RequestId request_id) {
+  in_progress_requests_.erase(request_id);
+}
+
+void AggregatableReportScheduler::TimerDelegate::OnRequestsReturnedFromStorage(
+    std::vector<AggregationServiceStorage::RequestAndId> requests_and_ids) {
+  // TODO(alexmt): Consider adding metrics of the number of in-progress requests
+  // erased to see if optimizations would be desirable.
+  base::EraseIf(
+      requests_and_ids,
+      [this](const AggregationServiceStorage::RequestAndId& request_and_id) {
+        return base::Contains(in_progress_requests_, request_and_id.id);
+      });
+  for (const AggregationServiceStorage::RequestAndId& request_and_id :
+       requests_and_ids) {
+    in_progress_requests_.insert(request_and_id.id);
+  }
+
+  if (!requests_and_ids.empty()) {
+    on_scheduled_report_time_reached_.Run(std::move(requests_and_ids));
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/aggregation_service/aggregatable_report_scheduler.h b/content/browser/aggregation_service/aggregatable_report_scheduler.h
new file mode 100644
index 0000000..5ebe9e3
--- /dev/null
+++ b/content/browser/aggregation_service/aggregatable_report_scheduler.h
@@ -0,0 +1,138 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_SCHEDULER_H_
+#define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_SCHEDULER_H_
+
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/raw_ref.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/aggregation_service/aggregation_service_storage.h"
+#include "content/browser/aggregation_service/report_scheduler_timer.h"
+#include "content/common/content_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base {
+class Time;
+}  // namespace base
+
+namespace content {
+
+class AggregatableReportRequest;
+class AggregationServiceStorageContext;
+
+// UI thread class that is responsible for interacting with the storage layer
+// for report requests, waiting for a report's reporting time to be reached and
+// then calling the appropriate callback.
+//
+// Note that report requests can have one of two states: "pending" or
+// "in-progress". This represents whether the request is currently being
+// processed (i.e. assembled and sent). To ensure that no report is 'lost',
+// all requests (that haven't been deleted) become pending once more on start
+// up. Note that all reports with future report times are pending (unless wall
+// clock time goes backward).
+class CONTENT_EXPORT AggregatableReportScheduler {
+ public:
+  AggregatableReportScheduler(
+      AggregationServiceStorageContext* storage_context,
+      base::RepeatingCallback<
+          void(std::vector<AggregationServiceStorage::RequestAndId>)>
+          on_scheduled_report_time_reached);
+
+  AggregatableReportScheduler(const AggregatableReportScheduler& other) =
+      delete;
+  AggregatableReportScheduler& operator=(
+      const AggregatableReportScheduler& other) = delete;
+  ~AggregatableReportScheduler();
+
+  // Schedules the `request` to be assembled and sent at
+  // `request.shared_info().scheduled_report_time`.
+  void ScheduleRequest(AggregatableReportRequest request);
+
+  // Notifies that the request to assemble and send the report with `request_id`
+  // was successfully completed. There must be an in-progress request stored
+  // with that `request_id`.
+  void NotifyInProgressRequestSucceeded(
+      AggregationServiceStorage::RequestId request_id);
+
+  // Notifies that the request to assemble and send the report with `request_id`
+  // completed unsuccessfully. There must be an in-progress request stored with
+  // that `request_id`.
+  void NotifyInProgressRequestFailed(
+      AggregationServiceStorage::RequestId request_id);
+
+  // TODO(crbug.com/1340042): Implement offline and startup handling
+
+ private:
+  class TimerDelegate : public ReportSchedulerTimer::Delegate {
+   public:
+    TimerDelegate(AggregationServiceStorageContext* storage_context,
+                  base::RepeatingCallback<void(
+                      std::vector<AggregationServiceStorage::RequestAndId>)>
+                      on_scheduled_report_time_reached);
+    ~TimerDelegate() override;
+
+    TimerDelegate(const TimerDelegate&) = delete;
+    TimerDelegate& operator=(const TimerDelegate&) = delete;
+    TimerDelegate(TimerDelegate&&) = delete;
+    TimerDelegate& operator=(TimerDelegate&&) = delete;
+
+    // Notifies that we no longer need to track `request_id` as in-progress.
+    void NotifyRequestCompleted(
+        AggregationServiceStorage::RequestId request_id);
+
+    base::WeakPtr<AggregatableReportScheduler::TimerDelegate> GetWeakPtr() {
+      return weak_ptr_factory_.GetWeakPtr();
+    }
+
+   private:
+    // ReportSchedulerTimer::Delegate:
+    void GetNextReportTime(base::OnceCallback<void(absl::optional<base::Time>)>,
+                           base::Time now) override;
+    void OnReportingTimeReached(base::Time now) override;
+    void AdjustOfflineReportTimes(
+        base::OnceCallback<void(absl::optional<base::Time>)>) override;
+
+    void OnRequestsReturnedFromStorage(
+        std::vector<AggregationServiceStorage::RequestAndId> requests_and_ids);
+
+    // Using a raw reference is safe because `storage_context_` is guaranteed to
+    // outlive `this`.
+    raw_ref<AggregationServiceStorageContext> storage_context_;
+
+    // Called when a report request's scheduled report time is reached. May
+    // return multiple requests if their report times were all reached before
+    // the timer fired. If multiple requests are returned, they will be ordered
+    // by the report time (which may differ from the initially scheduled report
+    // time).
+    base::RepeatingCallback<void(
+        std::vector<AggregationServiceStorage::RequestAndId>)>
+        on_scheduled_report_time_reached_;
+
+    // The set of IDs of all in-progress report requests.
+    // TODO(alexmt): Consider switching to a flat_set when we have metrics on
+    // the typical size.
+    std::set<AggregationServiceStorage::RequestId> in_progress_requests_;
+
+    base::WeakPtrFactory<AggregatableReportScheduler::TimerDelegate>
+        weak_ptr_factory_{this};
+  };
+
+  // Using a raw reference is safe because `storage_context_` is guaranteed to
+  // outlive `this`.
+  raw_ref<AggregationServiceStorageContext> storage_context_;
+
+  // Using a raw reference is safe because it's owned by `timer_`. Do not use
+  // once destruction has begun as `timer_` is destroyed before this reference.
+  raw_ref<TimerDelegate> timer_delegate_;
+
+  ReportSchedulerTimer timer_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_SCHEDULER_H_
diff --git a/content/browser/aggregation_service/aggregatable_report_scheduler_unittest.cc b/content/browser/aggregation_service/aggregatable_report_scheduler_unittest.cc
new file mode 100644
index 0000000..aea6e03d
--- /dev/null
+++ b/content/browser/aggregation_service/aggregatable_report_scheduler_unittest.cc
@@ -0,0 +1,401 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/aggregation_service/aggregatable_report_scheduler.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "base/threading/sequence_bound.h"
+#include "base/time/default_clock.h"
+#include "base/time/time.h"
+#include "content/browser/aggregation_service/aggregatable_report.h"
+#include "content/browser/aggregation_service/aggregation_service_storage.h"
+#include "content/browser/aggregation_service/aggregation_service_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace content {
+
+namespace {
+
+using testing::_;
+using testing::Invoke;
+
+// Will be used to verify the sequence of expected function calls.
+using Checkpoint = ::testing::MockFunction<void(int)>;
+
+const base::Time kExampleTime = base::Time::FromJavaTime(1652984901234);
+
+}  // namespace
+
+class AggregatableReportSchedulerTest : public testing::Test {
+ public:
+  AggregatableReportSchedulerTest()
+      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
+        storage_context_(base::DefaultClock::GetInstance()),
+        scheduler_(&storage_context_,
+                   /*on_scheduled_report_time_reached=*/mock_callback_.Get()) {}
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  TestAggregationServiceStorageContext storage_context_;
+  base::MockRepeatingCallback<void(
+      std::vector<AggregationServiceStorage::RequestAndId>)>
+      mock_callback_;
+  AggregatableReportScheduler scheduler_;
+};
+
+TEST_F(AggregatableReportSchedulerTest,
+       ScheduleRequest_RetrievedAtAppropriateTime) {
+  AggregatableReportRequest example_request =
+      aggregation_service::CreateExampleRequest();
+
+  AggregatableReportSharedInfo expected_shared_info =
+      example_request.shared_info().Clone();
+  expected_shared_info.scheduled_report_time = kExampleTime;
+
+  AggregatableReportRequest expected_request =
+      AggregatableReportRequest::Create(example_request.payload_contents(),
+                                        std::move(expected_shared_info))
+          .value();
+
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 0u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  Checkpoint checkpoint;
+  {
+    testing::InSequence seq;
+
+    EXPECT_CALL(mock_callback_, Run).Times(0);
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(mock_callback_, Run)
+        .WillOnce(
+            Invoke([&expected_request](
+                       std::vector<AggregationServiceStorage::RequestAndId>
+                           requests_and_ids) {
+              ASSERT_EQ(requests_and_ids.size(), 1u);
+              EXPECT_TRUE(aggregation_service::ReportRequestsEqual(
+                  requests_and_ids[0].request, expected_request));
+            }));
+  }
+
+  scheduler_.ScheduleRequest(
+      aggregation_service::CloneReportRequest(expected_request));
+
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 1u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  base::TimeDelta fast_forward_required = kExampleTime - base::Time::Now();
+  task_environment_.FastForwardBy(fast_forward_required -
+                                  base::Microseconds(1));
+
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 1u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  checkpoint.Call(1);
+
+  task_environment_.FastForwardBy(base::Microseconds(1));
+}
+
+TEST_F(AggregatableReportSchedulerTest,
+       InProgressRequestCompleted_DeletedFromStorage) {
+  AggregatableReportRequest example_request =
+      aggregation_service::CreateExampleRequest();
+
+  AggregatableReportSharedInfo expected_shared_info =
+      example_request.shared_info().Clone();
+  expected_shared_info.scheduled_report_time = kExampleTime;
+
+  scheduler_.ScheduleRequest(
+      AggregatableReportRequest::Create(example_request.payload_contents(),
+                                        std::move(expected_shared_info))
+          .value());
+
+  EXPECT_CALL(mock_callback_, Run);
+  base::TimeDelta fast_forward_required = kExampleTime - base::Time::Now();
+
+  task_environment_.FastForwardBy(fast_forward_required);
+
+  // The request is still stored even while it's in-progress.
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 1u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  // Request IDs are incremented from 1.
+  scheduler_.NotifyInProgressRequestSucceeded(
+      AggregationServiceStorage::RequestId(1));
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 0u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+}
+
+// TODO(crbug.com/1340040): Update when retry handling is added.
+TEST_F(AggregatableReportSchedulerTest,
+       InProgressRequestFailed_DeletedFromStorage) {
+  AggregatableReportRequest example_request =
+      aggregation_service::CreateExampleRequest();
+
+  AggregatableReportSharedInfo expected_shared_info =
+      example_request.shared_info().Clone();
+  expected_shared_info.scheduled_report_time = kExampleTime;
+
+  scheduler_.ScheduleRequest(
+      AggregatableReportRequest::Create(example_request.payload_contents(),
+                                        std::move(expected_shared_info))
+          .value());
+
+  EXPECT_CALL(mock_callback_, Run);
+  base::TimeDelta fast_forward_required = kExampleTime - base::Time::Now();
+
+  task_environment_.FastForwardBy(fast_forward_required);
+
+  // The request is still stored even while it's in-progress.
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 1u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  // Request IDs are incremented from 1.
+  scheduler_.NotifyInProgressRequestFailed(
+      AggregationServiceStorage::RequestId(1));
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 0u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+}
+
+TEST_F(AggregatableReportSchedulerTest,
+       MultipleRequests_RetrievedAtAppropriateTime) {
+  // Test both simultaneous and non-simultaneous reports.
+  std::vector<base::Time> scheduled_report_times = {
+      kExampleTime, kExampleTime, kExampleTime + base::Hours(1)};
+
+  AggregatableReportRequest example_request =
+      aggregation_service::CreateExampleRequest();
+
+  Checkpoint checkpoint;
+  {
+    testing::InSequence seq;
+
+    EXPECT_CALL(mock_callback_, Run).Times(0);
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(mock_callback_, Run)
+        .WillOnce(Invoke([](std::vector<AggregationServiceStorage::RequestAndId>
+                                requests_and_ids) {
+          ASSERT_EQ(requests_and_ids.size(), 2u);
+
+          // Ignore request ordering. Storage IDs should be incremented from 1
+          EXPECT_EQ(base::flat_set<AggregationServiceStorage::RequestId>(
+                        {requests_and_ids[0].id, requests_and_ids[1].id}),
+                    base::flat_set<AggregationServiceStorage::RequestId>(
+                        {AggregationServiceStorage::RequestId(1),
+                         AggregationServiceStorage::RequestId(2)}));
+        }));
+    EXPECT_CALL(checkpoint, Call(2));
+    EXPECT_CALL(mock_callback_, Run)
+        .WillOnce(Invoke([](std::vector<AggregationServiceStorage::RequestAndId>
+                                requests_and_ids) {
+          ASSERT_EQ(requests_and_ids.size(), 1u);
+          EXPECT_EQ(requests_and_ids[0].id,
+                    AggregationServiceStorage::RequestId(3));
+        }));
+  }
+
+  for (base::Time scheduled_report_time : scheduled_report_times) {
+    AggregatableReportSharedInfo expected_shared_info =
+        example_request.shared_info().Clone();
+    expected_shared_info.scheduled_report_time = scheduled_report_time;
+
+    scheduler_.ScheduleRequest(
+        AggregatableReportRequest::Create(example_request.payload_contents(),
+                                          std::move(expected_shared_info))
+            .value());
+  }
+
+  {
+    base::RunLoop run_loop;
+
+    storage_context_.GetStorage()
+        .AsyncCall(&AggregationServiceStorage::GetRequestsReportingOnOrBefore)
+        .WithArgs(base::Time::Max())
+        .Then(base::BindLambdaForTesting(
+            [&run_loop](std::vector<AggregationServiceStorage::RequestAndId>
+                            requests_and_ids) {
+              EXPECT_EQ(requests_and_ids.size(), 3u);
+              run_loop.Quit();
+            }));
+
+    run_loop.Run();
+  }
+
+  checkpoint.Call(1);
+
+  task_environment_.FastForwardBy(kExampleTime - base::Time::Now());
+
+  checkpoint.Call(2);
+
+  task_environment_.FastForwardBy(base::Hours(1));
+}
+
+TEST_F(AggregatableReportSchedulerTest,
+       MultipleRequestsReturned_OrderedByReportTime) {
+  // Order them to check reports are not returned by storage order.
+  std::vector<base::Time> scheduled_report_times = {
+      kExampleTime, kExampleTime + base::Hours(3),
+      kExampleTime + base::Hours(1), kExampleTime + base::Hours(2)};
+
+  AggregatableReportRequest example_request =
+      aggregation_service::CreateExampleRequest();
+
+  Checkpoint checkpoint;
+  {
+    testing::InSequence seq;
+    EXPECT_CALL(mock_callback_, Run).Times(0);
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(mock_callback_, Run)
+        .WillOnce(Invoke([](std::vector<AggregationServiceStorage::RequestAndId>
+                                requests_and_ids) {
+          ASSERT_EQ(requests_and_ids.size(), 2u);
+
+          // Ordered correctly. Storage IDs should be incremented from 1.
+          EXPECT_EQ(requests_and_ids[0].id,
+                    AggregationServiceStorage::RequestId(1));
+          EXPECT_EQ(requests_and_ids[1].id,
+                    AggregationServiceStorage::RequestId(3));
+        }));
+    EXPECT_CALL(checkpoint, Call(2));
+    EXPECT_CALL(mock_callback_, Run)
+        .WillOnce(Invoke([](std::vector<AggregationServiceStorage::RequestAndId>
+                                requests_and_ids) {
+          ASSERT_EQ(requests_and_ids.size(), 2u);
+
+          // Ordered correctly. Storage IDs should be incremented from 1.
+          EXPECT_EQ(requests_and_ids[0].id,
+                    AggregationServiceStorage::RequestId(4));
+          EXPECT_EQ(requests_and_ids[1].id,
+                    AggregationServiceStorage::RequestId(2));
+        }));
+  }
+
+  for (base::Time scheduled_report_time : scheduled_report_times) {
+    AggregatableReportSharedInfo expected_shared_info =
+        example_request.shared_info().Clone();
+    expected_shared_info.scheduled_report_time = scheduled_report_time;
+
+    scheduler_.ScheduleRequest(
+        AggregatableReportRequest::Create(example_request.payload_contents(),
+                                          std::move(expected_shared_info))
+            .value());
+  }
+
+  checkpoint.Call(1);
+
+  // Can't use `FastForwardBy()` as that will result in one call per report
+  // request.
+  task_environment_.AdvanceClock(kExampleTime + base::Hours(1) -
+                                 base::Time::Now());
+  task_environment_.RunUntilIdle();
+
+  checkpoint.Call(2);
+
+  // Can't use `FastForwardBy()` as that will result in one call per report
+  // request.
+  task_environment_.AdvanceClock(base::Hours(2));
+  task_environment_.RunUntilIdle();
+}
+
+}  // namespace content
diff --git a/content/browser/aggregation_service/aggregation_service_impl.cc b/content/browser/aggregation_service/aggregation_service_impl.cc
index 5ffb4c9..900206b 100644
--- a/content/browser/aggregation_service/aggregation_service_impl.cc
+++ b/content/browser/aggregation_service/aggregation_service_impl.cc
@@ -112,6 +112,7 @@
   storage_.AsyncCall(&AggregationServiceStorage::ClearPublicKeysFetchedBetween)
       .WithArgs(delete_begin, delete_end)
       .Then(std::move(done));
+  // TODO(crbug.com/1340053): Clear stored report requests as well.
 }
 
 void AggregationServiceImpl::SetPublicKeysForTesting(
diff --git a/content/browser/aggregation_service/aggregation_service_impl.h b/content/browser/aggregation_service/aggregation_service_impl.h
index a2e9a61..100eecd5 100644
--- a/content/browser/aggregation_service/aggregation_service_impl.h
+++ b/content/browser/aggregation_service/aggregation_service_impl.h
@@ -81,6 +81,8 @@
                          std::unique_ptr<AggregatableReportAssembler> assembler,
                          std::unique_ptr<AggregatableReportSender> sender);
 
+  // TODO(crbug.com/1340050): Hook scheduler up to service and sender.
+
   base::SequenceBound<AggregationServiceStorage> storage_;
   std::unique_ptr<AggregatableReportAssembler> assembler_;
   std::unique_ptr<AggregatableReportSender> sender_;
diff --git a/content/browser/aggregation_service/aggregation_service_storage.h b/content/browser/aggregation_service/aggregation_service_storage.h
index 9120028..88fc140 100644
--- a/content/browser/aggregation_service/aggregation_service_storage.h
+++ b/content/browser/aggregation_service/aggregation_service_storage.h
@@ -5,8 +5,14 @@
 #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_H_
 #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_H_
 
+#include <stdint.h>
+
 #include <vector>
 
+#include "base/types/strong_alias.h"
+#include "content/browser/aggregation_service/aggregatable_report.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
 class GURL;
 
 namespace base {
@@ -18,12 +24,22 @@
 struct PublicKey;
 struct PublicKeyset;
 
-// This class provides an interface for persisting helper server public keys
-// and performing queries on it.
+// This class provides an interface for persisting helper server public keys and
+// aggregatable report requests, as well as performing queries on those. The
+// public key and report request methods are in the same interface to allow a
+// single SequenceBound to own the (joint) implementation class.
 class AggregationServiceStorage {
  public:
+  using RequestId = base::StrongAlias<AggregatableReportRequest, int64_t>;
+  struct RequestAndId {
+    AggregatableReportRequest request;
+    RequestId id;
+  };
+
   virtual ~AggregationServiceStorage() = default;
 
+  // == Public key methods =====
+
   // Returns the public keys for `url` that are currently valid. The returned
   // value should not be stored for future operations as it may expire soon.
   virtual std::vector<PublicKey> GetPublicKeys(const GURL& url) = 0;
@@ -43,6 +59,31 @@
   // Clears the stored public keys that expire no later than `delete_end`
   // (inclusive).
   virtual void ClearPublicKeysExpiredBy(base::Time delete_end) = 0;
+
+  // == Aggregatable report request methods =====
+
+  // Persists the `request` with a report time of `*report_time_override`. If
+  // the optional has no value, the `request`'s scheduled report time is used.
+  virtual void StoreRequest(AggregatableReportRequest request) = 0;
+
+  // Deletes the report request with the given `request_id`, if any.
+  virtual void DeleteRequest(RequestId request_id) = 0;
+
+  // Returns the earliest report time for a stored pending request strictly
+  // after `strictly_after_time`. If there are no such requests stored, returns
+  // `absl::nullopt`.
+  virtual absl::optional<base::Time> NextReportTimeAfter(
+      base::Time strictly_after_time) = 0;
+
+  // Returns requests with report times on or before `not_after_time`. The
+  // returned reports are ordered by report time.
+  // TODO(crbug.com/1340046): Limit the number of in-progress reports kept in
+  // memory at the same time.
+  virtual std::vector<RequestAndId> GetRequestsReportingOnOrBefore(
+      base::Time not_after_time) = 0;
+
+  // TODO(crbug.com/1340042): Add a method to randomly delay all reports in the
+  // past (for startup and coming online).
 };
 
 }  // namespace content
diff --git a/content/browser/aggregation_service/aggregation_service_storage_context.h b/content/browser/aggregation_service/aggregation_service_storage_context.h
index 0faf11f..4cad3c8 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_context.h
+++ b/content/browser/aggregation_service/aggregation_service_storage_context.h
@@ -16,7 +16,7 @@
  public:
   virtual ~AggregationServiceStorageContext() = default;
 
-  // Returns the underlying storage for public keys.
+  // Returns the underlying storage for public keys and report requests.
   virtual const base::SequenceBound<AggregationServiceStorage>&
   GetStorage() = 0;
 };
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql.cc b/content/browser/aggregation_service/aggregation_service_storage_sql.cc
index 29b4b07..70c64e8 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_sql.cc
+++ b/content/browser/aggregation_service/aggregation_service_storage_sql.cc
@@ -18,17 +18,23 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/notreached.h"
+#include "base/sequence_checker.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
+#include "content/browser/aggregation_service/aggregatable_report.h"
+#include "content/browser/aggregation_service/aggregation_service_storage.h"
+#include "content/browser/aggregation_service/proto/aggregatable_report.pb.h"
 #include "content/browser/aggregation_service/public_key.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "sql/database.h"
 #include "sql/meta_table.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
+#include "third_party/abseil-cpp/absl/numeric/int128.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace content {
 
@@ -41,22 +47,70 @@
 //
 // Version 1 - https://crrev.com/c/3038364
 //             https://crrev.com/c/3462368
-constexpr int kCurrentVersionNumber = 1;
+// Version 2 - https://crrev.com/c/3733377 (adding report_requests table)
+constexpr int kCurrentVersionNumber = 2;
 
 // Earliest version which can use a `kCurrentVersionNumber` database
 // without failing.
-constexpr int kCompatibleVersionNumber = 1;
+constexpr int kCompatibleVersionNumber = 2;
 
 // Latest version of the database that cannot be upgraded to
 // `kCurrentVersionNumber` without razing the database.
 constexpr int kDeprecatedVersionNumber = 0;
 
+// All columns in this table except `report_time` are designed to be "const".
+// `request_id` uses AUTOINCREMENT to ensure that IDs aren't reused over the
+// lifetime of the DB.
+// `report_time` is when the request should be assembled and sent
+// `creation_time` is when the request was stored in the database and will be
+// used for data deletion.
+// `reporting_origin` should match the corresponding proto field, but is
+// maintained separately for data deletion.
+// `request_proto` is a serialized AggregatableReportRequest proto.
+static constexpr char kReportRequestsCreateTableSql[] =
+    // clang-format off
+    "CREATE TABLE IF NOT EXISTS report_requests("
+        "request_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+        "report_time INTEGER NOT NULL,"
+        "creation_time INTEGER NOT NULL,"
+        "reporting_origin TEXT NOT NULL,"
+        "request_proto BLOB NOT NULL)";
+// clang-format on
+
+// Used to optimize report request lookup by report_time.
+static constexpr char kReportTimeIndexSql[] =
+    "CREATE INDEX IF NOT EXISTS report_time_idx ON "
+    "report_requests(report_time)";
+
+// Will be used to optimize report request lookup by creation_time for data
+// clearing, see crbug.com/1340053.
+static constexpr char kCreationTimeIndexSql[] =
+    "CREATE INDEX IF NOT EXISTS creation_time_idx ON "
+    "report_requests(creation_time)";
+
 bool UpgradeAggregationServiceStorageSqlSchema(sql::Database& db,
                                                sql::MetaTable& meta_table) {
-  // Placeholder for database migration logic.
-  NOTREACHED();
+  if (meta_table.GetVersionNumber() != 1)
+    return false;  // Only one migration is supported.
 
-  return true;
+  // == Migrate from version 1 to 2 ==
+  // Simply create the new empty table.
+
+  sql::Transaction transaction(&db);
+  if (!transaction.Begin())
+    return false;
+
+  if (!db.Execute(kReportRequestsCreateTableSql))
+    return false;
+
+  if (!db.Execute(kReportTimeIndexSql))
+    return false;
+
+  if (!db.Execute(kCreationTimeIndexSql))
+    return false;
+
+  meta_table.SetVersionNumber(kCurrentVersionNumber);
+  return transaction.Commit();
 }
 
 void RecordInitializationStatus(
@@ -362,6 +416,118 @@
   transaction.Commit();
 }
 
+void AggregationServiceStorageSql::StoreRequest(
+    AggregatableReportRequest request) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // Force the creation of the database if it doesn't exist, as we need to
+  // persist the public keys.
+  if (!EnsureDatabaseOpen(DbCreationPolicy::kCreateIfAbsent))
+    return;
+
+  static constexpr char kStoreRequestSql[] =
+      "INSERT INTO report_requests("
+      "report_time,creation_time,reporting_origin,request_proto) "
+      "VALUES(?,?,?,?)";
+
+  sql::Statement store_request_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kStoreRequestSql));
+
+  const AggregatableReportSharedInfo& shared_info = request.shared_info();
+
+  store_request_statement.BindTime(0, shared_info.scheduled_report_time);
+  store_request_statement.BindTime(1, clock_.Now());
+  store_request_statement.BindString(2,
+                                     shared_info.reporting_origin.Serialize());
+
+  std::vector<uint8_t> serialized_request = request.Serialize();
+
+  // While an empty vector can be a valid proto serialization, report requests
+  // should always be non-empty.
+  DCHECK(!serialized_request.empty());
+  store_request_statement.BindBlob(3, serialized_request);
+
+  store_request_statement.Run();
+}
+
+void AggregationServiceStorageSql::DeleteRequest(
+    AggregationServiceStorage::RequestId request_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!EnsureDatabaseOpen(DbCreationPolicy::kFailIfAbsent))
+    return;
+
+  static constexpr char kDeleteRequestSql[] =
+      "DELETE FROM report_requests WHERE request_id=?";
+
+  sql::Statement delete_request_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kDeleteRequestSql));
+
+  delete_request_statement.BindInt64(0, request_id.value());
+
+  delete_request_statement.Run();
+}
+
+absl::optional<base::Time> AggregationServiceStorageSql::NextReportTimeAfter(
+    base::Time strictly_after_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!EnsureDatabaseOpen(DbCreationPolicy::kFailIfAbsent))
+    return absl::nullopt;
+
+  static constexpr char kGetRequestsSql[] =
+      "SELECT MIN(report_time) FROM report_requests WHERE report_time>?";
+
+  sql::Statement get_requests_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kGetRequestsSql));
+
+  get_requests_statement.BindTime(0, strictly_after_time);
+
+  if (get_requests_statement.Step() &&
+      get_requests_statement.GetColumnType(0) != sql::ColumnType::kNull) {
+    return get_requests_statement.ColumnTime(0);
+  }
+  return absl::nullopt;
+}
+
+std::vector<AggregationServiceStorage::RequestAndId>
+AggregationServiceStorageSql::GetRequestsReportingOnOrBefore(
+    base::Time not_after_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!EnsureDatabaseOpen(DbCreationPolicy::kFailIfAbsent))
+    return {};
+
+  static constexpr char kGetRequestsSql[] =
+      "SELECT request_id,report_time,request_proto FROM report_requests "
+      "WHERE report_time<=? ORDER BY report_time";
+
+  sql::Statement get_requests_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kGetRequestsSql));
+  get_requests_statement.BindTime(0, not_after_time);
+
+  // Partial results are not returned in case of any error.
+  // TODO(crbug.com/1340046): Limit the total number of results that can be
+  // returned in one query.
+  std::vector<AggregationServiceStorage::RequestAndId> result;
+  while (get_requests_statement.Step()) {
+    absl::optional<AggregatableReportRequest> parsed_request =
+        AggregatableReportRequest::Deserialize(
+            get_requests_statement.ColumnBlob(2));
+    if (!parsed_request)
+      return {};
+
+    result.push_back(AggregationServiceStorage::RequestAndId{
+        .request = std::move(parsed_request.value()),
+        .id = AggregationServiceStorage::RequestId(
+            get_requests_statement.ColumnInt64(0))});
+  }
+
+  if (!get_requests_statement.Succeeded())
+    return {};
+
+  return result;
+}
+
 void AggregationServiceStorageSql::HandleInitializationFailure(
     const InitStatus status) {
   RecordInitializationStatus(status);
@@ -439,22 +605,28 @@
     return true;
 
   if (current_version <= kDeprecatedVersionNumber ||
-      meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
-    // The database version is either deprecated or is too new to be used. For
-    // the second case, the DB will never work until Chrome is re-upgraded.
-    // Assume the user will continue using this Chrome version and raze the DB
-    // to get aggregation service storage working.
+      meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber ||
+      !UpgradeAggregationServiceStorageSqlSchema(db_, meta_table_)) {
+    // The database version is either deprecated, the version is too new to be
+    // used, or the attempt to upgrade failed. In the second case (version too
+    // new), the DB will never work until Chrome is re-upgraded. Assume the user
+    // will continue using this Chrome version and raze the DB to get
+    // aggregation service storage working.
     db_.Raze();
     meta_table_.Reset();
     return CreateSchema();
   }
 
-  return UpgradeAggregationServiceStorageSqlSchema(db_, meta_table_);
+  return true;  // Upgrade was successful.
 }
 
 bool AggregationServiceStorageSql::CreateSchema() {
   base::ElapsedThreadTimer timer;
 
+  sql::Transaction transaction(&db_);
+  if (!transaction.Begin())
+    return false;
+
   // All of the columns in this table are designed to be "const".
   // `url` is the helper server url.
   // `fetch_time` is when the key is fetched and inserted into database, and
@@ -505,6 +677,16 @@
   if (!db_.Execute(kKeysTableSql))
     return false;
 
+  // See constant definitions above for documentation.
+  if (!db_.Execute(kReportRequestsCreateTableSql))
+    return false;
+
+  if (!db_.Execute(kReportTimeIndexSql))
+    return false;
+
+  if (!db_.Execute(kCreationTimeIndexSql))
+    return false;
+
   if (!meta_table_.Init(&db_, kCurrentVersionNumber,
                         kCompatibleVersionNumber)) {
     return false;
@@ -514,7 +696,7 @@
       "PrivacySandbox.AggregationService.Storage.Sql.CreationTime",
       timer.Elapsed());
 
-  return true;
+  return transaction.Commit();
 }
 
 void AggregationServiceStorageSql::DatabaseErrorCallback(int extended_error,
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql.h b/content/browser/aggregation_service/aggregation_service_storage_sql.h
index 578fca5..9eb10e8 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_sql.h
+++ b/content/browser/aggregation_service/aggregation_service_storage_sql.h
@@ -5,7 +5,7 @@
 #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_SQL_H_
 #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_SQL_H_
 
-#include "stdint.h"
+#include <stdint.h>
 
 #include <vector>
 
@@ -22,6 +22,7 @@
 
 namespace base {
 class Clock;
+class Time;
 }  // namespace base
 
 namespace sql {
@@ -30,6 +31,7 @@
 
 namespace content {
 
+class AggregatableReportRequest;
 struct PublicKey;
 struct PublicKeyset;
 
@@ -58,6 +60,12 @@
   void ClearPublicKeysFetchedBetween(base::Time delete_begin,
                                      base::Time delete_end) override;
   void ClearPublicKeysExpiredBy(base::Time delete_end) override;
+  void StoreRequest(AggregatableReportRequest request) override;
+  void DeleteRequest(AggregationServiceStorage::RequestId request_id) override;
+  absl::optional<base::Time> NextReportTimeAfter(
+      base::Time strictly_after_time) override;
+  std::vector<AggregationServiceStorage::RequestAndId>
+  GetRequestsReportingOnOrBefore(base::Time not_after_time) override;
 
   void set_ignore_errors_for_testing(bool ignore_for_testing)
       VALID_CONTEXT_REQUIRED(sequence_checker_) {
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc b/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
index 511a0b1..7a65a47 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
+++ b/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
@@ -8,12 +8,14 @@
 #include <utility>
 #include <vector>
 
+#include "base/containers/flat_set.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
+#include "content/browser/aggregation_service/aggregatable_report.h"
 #include "content/browser/aggregation_service/aggregation_service_storage.h"
 #include "content/browser/aggregation_service/aggregation_service_test_utils.h"
 #include "content/browser/aggregation_service/public_key.h"
@@ -21,6 +23,7 @@
 #include "sql/meta_table.h"
 #include "sql/test/test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -136,16 +139,17 @@
     sql::Database raw_db;
     EXPECT_TRUE(raw_db.Open(db_path()));
 
-    // [urls], [keys], [meta].
-    EXPECT_EQ(sql::test::CountSQLTables(&raw_db), 3u);
+    // [urls], [keys], [report_requests], [meta], [sqlite_sequence] (for
+    // AUTOINCREMENT support).
+    EXPECT_EQ(sql::test::CountSQLTables(&raw_db), 5u);
 
-    // [urls_by_url_idx], [fetch_time_idx], [expiry_time_idx] and meta
-    // table index.
-    EXPECT_EQ(sql::test::CountSQLIndices(&raw_db), 4u);
+    // [urls_by_url_idx], [fetch_time_idx], [expiry_time_idx],
+    // [report_time_idx], [creation_time_idx] and meta table index.
+    EXPECT_EQ(sql::test::CountSQLIndices(&raw_db), 6u);
   }
 }
 
-TEST_F(AggregationServiceStorageSqlTest, DatabaseReopened_DataPersisted) {
+TEST_F(AggregationServiceStorageSqlTest, DatabaseReopened_KeysPersisted) {
   OpenDatabase();
 
   GURL url(kExampleUrl);
@@ -373,7 +377,7 @@
 }
 
 TEST_F(AggregationServiceStorageSqlInMemoryTest,
-       DatabaseInMemoryReopened_DataNotPersisted) {
+       DatabaseInMemoryReopened_PublicKeyDataNotPersisted) {
   OpenDatabase();
 
   GURL url(kExampleUrl);
@@ -387,4 +391,243 @@
   EXPECT_TRUE(storage_->GetPublicKeys(url).empty());
 }
 
+TEST_F(AggregationServiceStorageSqlTest, StoreRequest_ExpectedResult) {
+  OpenDatabase();
+
+  EXPECT_FALSE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_TRUE(
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).empty());
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+  ASSERT_TRUE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(base::Time::Min()).value(),
+            request.shared_info().scheduled_report_time);
+
+  std::vector<AggregationServiceStorage::RequestAndId> stored_requests_and_ids =
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max());
+
+  ASSERT_EQ(stored_requests_and_ids.size(), 1u);
+
+  // IDs autoincrement from 1.
+  EXPECT_EQ(stored_requests_and_ids[0].id,
+            AggregationServiceStorage::RequestId(1));
+  EXPECT_TRUE(aggregation_service::ReportRequestsEqual(
+      stored_requests_and_ids[0].request, request));
+}
+
+TEST_F(AggregationServiceStorageSqlTest, DeleteRequest_ExpectedResult) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+  EXPECT_EQ(storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).size(),
+            1u);
+
+  // IDs autoincrement from 1.
+  storage_->DeleteRequest(AggregationServiceStorage::RequestId(1));
+  EXPECT_TRUE(
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).empty());
+}
+
+TEST_F(AggregationServiceStorageSqlTest,
+       RepeatGetPendingRequests_RequestReturnedAgain) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+  ASSERT_TRUE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(base::Time::Min()).value(),
+            request.shared_info().scheduled_report_time);
+
+  std::vector<AggregationServiceStorage::RequestAndId> stored_requests =
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max());
+
+  ASSERT_EQ(stored_requests.size(), 1u);
+  EXPECT_TRUE(aggregation_service::ReportRequestsEqual(
+      stored_requests[0].request, request));
+
+  stored_requests = storage_->GetRequestsReportingOnOrBefore(base::Time::Max());
+
+  ASSERT_EQ(stored_requests.size(), 1u);
+  EXPECT_TRUE(aggregation_service::ReportRequestsEqual(
+      stored_requests[0].request, request));
+  ASSERT_TRUE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(base::Time::Min()).value(),
+            request.shared_info().scheduled_report_time);
+}
+
+TEST_F(AggregationServiceStorageSqlTest, DatabaseReopened_RequestsPersisted) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+
+  CloseDatabase();
+
+  OpenDatabase();
+
+  std::vector<AggregationServiceStorage::RequestAndId> stored_requests =
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max());
+
+  ASSERT_EQ(stored_requests.size(), 1u);
+  EXPECT_TRUE(aggregation_service::ReportRequestsEqual(
+      stored_requests[0].request, request));
+}
+
+TEST_F(AggregationServiceStorageSqlTest,
+       GetRequestsReportingOnOrBefore_ReturnValuesAlignWithReportTime) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+  base::Time report_time = request.shared_info().scheduled_report_time;
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+
+  const struct {
+    base::Time not_after_time;
+    size_t number_requests;
+  } kTestCases[] = {
+      {base::Time::Min(), 0}, {report_time - base::Seconds(1), 0},
+      {report_time, 1},       {report_time + base::Seconds(1), 1},
+      {base::Time::Max(), 1},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    EXPECT_EQ(storage_->GetRequestsReportingOnOrBefore(test_case.not_after_time)
+                  .size(),
+              test_case.number_requests)
+        << test_case.not_after_time;
+  }
+}
+
+TEST_F(AggregationServiceStorageSqlTest,
+       NextReportTimeAfter_ReturnValuesAlignWithReportTime) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+  base::Time report_time = request.shared_info().scheduled_report_time;
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+
+  const struct {
+    base::Time strictly_after_time;
+    absl::optional<base::Time> expected_return_value;
+  } kTestCases[] = {
+      {base::Time::Min(), report_time},
+      {report_time - base::Seconds(1), report_time},
+      {report_time, absl::nullopt},
+      {report_time + base::Seconds(1), absl::nullopt},
+      {base::Time::Max(), absl::nullopt},
+
+  };
+
+  for (const auto& test_case : kTestCases) {
+    EXPECT_EQ(storage_->NextReportTimeAfter(test_case.strictly_after_time),
+              test_case.expected_return_value)
+        << test_case.strictly_after_time;
+  }
+}
+
+TEST_F(AggregationServiceStorageSqlTest,
+       MultipleRequests_ReturnValuesAlignsWithReportTime) {
+  OpenDatabase();
+
+  const base::Time kExampleTime = base::Time::FromJavaTime(1652984901234);
+
+  std::vector<base::Time> scheduled_report_times = {
+      kExampleTime, kExampleTime, kExampleTime + base::Hours(1)};
+
+  for (base::Time scheduled_report_time : scheduled_report_times) {
+    AggregatableReportRequest example_request =
+        aggregation_service::CreateExampleRequest();
+    AggregatableReportSharedInfo shared_info =
+        example_request.shared_info().Clone();
+    shared_info.scheduled_report_time = scheduled_report_time;
+
+    absl::optional<AggregatableReportRequest> request =
+        AggregatableReportRequest::Create(example_request.payload_contents(),
+                                          std::move(shared_info));
+    ASSERT_TRUE(request.has_value());
+
+    storage_->StoreRequest(std::move(request.value()));
+  }
+  ASSERT_TRUE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(base::Time::Min()).value(),
+            kExampleTime);
+
+  EXPECT_TRUE(
+      storage_
+          ->GetRequestsReportingOnOrBefore(kExampleTime - base::Milliseconds(1))
+          .empty());
+
+  ASSERT_TRUE(
+      storage_->NextReportTimeAfter(kExampleTime - base::Milliseconds(1))
+          .has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(kExampleTime - base::Milliseconds(1))
+                .value(),
+            kExampleTime);
+
+  std::vector<AggregationServiceStorage::RequestAndId> example_time_reports =
+      storage_->GetRequestsReportingOnOrBefore(kExampleTime);
+  ASSERT_EQ(example_time_reports.size(), 2u);
+
+  EXPECT_EQ(base::flat_set<AggregationServiceStorage::RequestId>(
+                {example_time_reports[0].id, example_time_reports[1].id}),
+            // Request IDs autoincrement from 1.
+            base::flat_set<AggregationServiceStorage::RequestId>(
+                {AggregationServiceStorage::RequestId(1),
+                 AggregationServiceStorage::RequestId(2)}));
+
+  ASSERT_TRUE(storage_->NextReportTimeAfter(kExampleTime).has_value());
+  EXPECT_EQ(storage_->NextReportTimeAfter(kExampleTime).value(),
+            kExampleTime + base::Hours(1));
+
+  EXPECT_EQ(storage_
+                ->GetRequestsReportingOnOrBefore(kExampleTime + base::Hours(1) -
+                                                 base::Milliseconds(1))
+                .size(),
+            2u);
+
+  std::vector<AggregationServiceStorage::RequestAndId> all_reports =
+      storage_->GetRequestsReportingOnOrBefore(kExampleTime + base::Hours(1));
+  ASSERT_EQ(all_reports.size(), 3u);
+  EXPECT_EQ(all_reports[2].id, AggregationServiceStorage::RequestId(3));
+
+  EXPECT_FALSE(
+      storage_->NextReportTimeAfter(kExampleTime + base::Hours(1)).has_value());
+  EXPECT_EQ(storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).size(),
+            3u);
+}
+
+TEST_F(AggregationServiceStorageSqlInMemoryTest,
+       DatabaseInMemoryReopened_RequestsNotPersisted) {
+  OpenDatabase();
+
+  AggregatableReportRequest request =
+      aggregation_service::CreateExampleRequest();
+
+  storage_->StoreRequest(aggregation_service::CloneReportRequest(request));
+  EXPECT_EQ(storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).size(),
+            1u);
+
+  CloseDatabase();
+
+  OpenDatabase();
+
+  EXPECT_FALSE(storage_->NextReportTimeAfter(base::Time::Min()).has_value());
+  EXPECT_TRUE(
+      storage_->GetRequestsReportingOnOrBefore(base::Time::Max()).empty());
+}
+
 }  // namespace content
diff --git a/content/browser/aggregation_service/proto/BUILD.gn b/content/browser/aggregation_service/proto/BUILD.gn
new file mode 100644
index 0000000..c7c1e1e
--- /dev/null
+++ b/content/browser/aggregation_service/proto/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("aggregatable_report_proto") {
+  sources = [ "aggregatable_report.proto" ]
+}
diff --git a/content/browser/aggregation_service/proto/aggregatable_report.proto b/content/browser/aggregation_service/proto/aggregatable_report.proto
new file mode 100644
index 0000000..86f2352
--- /dev/null
+++ b/content/browser/aggregation_service/proto/aggregatable_report.proto
@@ -0,0 +1,60 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Protos for persisting AggregatableReportRequests.
+
+syntax = "proto3";
+
+package content.proto;
+
+option optimize_for = LITE_RUNTIME;
+
+// Proto equivalent of `content::mojom::AggregationServiceMode`
+enum AggregationServiceMode {
+  TEE_BASED = 0;
+  EXPERIMENTAL_POPLAR = 1;
+}
+
+// Proto equivalent of `content::mojom::AggregatableReportHistogramContribution`
+message AggregatableReportHistogramContribution {
+  uint64 bucket_high = 1;
+  uint64 bucket_low = 2;
+  int32 value = 3;
+}
+
+// Proto equivalent of `content::AggregationServicePayloadContents`
+message AggregationServicePayloadContents {
+  enum Operation {
+    HISTOGRAM = 0;
+  }
+
+  Operation operation = 1;
+  repeated AggregatableReportHistogramContribution contributions = 2;
+  AggregationServiceMode aggregation_mode = 3;
+}
+
+// Proto equivalent of `content::AggregatableReportSharedInfo`
+message AggregatableReportSharedInfo {
+  enum DebugMode {
+    DISABLED = 0;
+    ENABLED = 1;
+  }
+
+  // Stored as microseconds since the Windows epoch (1601-01-01 00:00:00 UTC).
+  int64 scheduled_report_time = 1;
+  string report_id = 2;
+  string reporting_origin = 3;
+  DebugMode debug_mode = 4;
+  // additional_fields is assumed to be empty (for now)
+  string api_version = 5;
+  string api_identifier = 6;
+}
+
+// Proto equivalent of `content::AggregatableReportRequest`
+message AggregatableReportRequest {
+  // processing_urls is inferred to be the default value(s).
+  AggregationServicePayloadContents payload_contents = 1;
+  AggregatableReportSharedInfo shared_info = 2;
+  string reporting_path = 3;
+}
diff --git a/content/browser/aggregation_service/report_scheduler_timer.cc b/content/browser/aggregation_service/report_scheduler_timer.cc
index a65d3f5..565907d 100644
--- a/content/browser/aggregation_service/report_scheduler_timer.cc
+++ b/content/browser/aggregation_service/report_scheduler_timer.cc
@@ -52,17 +52,23 @@
 }
 
 void ReportSchedulerTimer::Refresh() {
+  RefreshImpl(base::Time::Now());
+}
+
+void ReportSchedulerTimer::RefreshImpl(base::Time now) {
   if (IsOffline()) {
     return;
   }
 
   delegate_->GetNextReportTime(base::BindOnce(&ReportSchedulerTimer::MaybeSet,
-                                              weak_ptr_factory_.GetWeakPtr()));
+                                              weak_ptr_factory_.GetWeakPtr()),
+                               now);
 }
 
 void ReportSchedulerTimer::OnTimerFired() {
-  delegate_->OnReportingTimeReached();
-  Refresh();
+  base::Time now = base::Time::Now();
+  delegate_->OnReportingTimeReached(now);
+  RefreshImpl(now);
 }
 
 void ReportSchedulerTimer::OnConnectionChanged(
diff --git a/content/browser/aggregation_service/report_scheduler_timer.h b/content/browser/aggregation_service/report_scheduler_timer.h
index 92aa8ae..245d2fb 100644
--- a/content/browser/aggregation_service/report_scheduler_timer.h
+++ b/content/browser/aggregation_service/report_scheduler_timer.h
@@ -33,15 +33,17 @@
    public:
     virtual ~Delegate() = default;
 
-    // Should be overridden with a method that gets the next report time and
-    // returns it via the callback. If there is no next report time,
-    // `absl::nullopt` should be returned instead.
+    // Should be overridden with a method that gets the next report time that
+    // the timer should fire at and returns it via the callback. If there is no
+    // next report time, `absl::nullopt` should be returned instead.
     virtual void GetNextReportTime(
-        base::OnceCallback<void(absl::optional<base::Time>)>) = 0;
+        base::OnceCallback<void(absl::optional<base::Time>)>,
+        base::Time now) = 0;
 
-    // Called when the timer is fired. `Refresh()` is automatically called
-    // after.
-    virtual void OnReportingTimeReached() = 0;
+    // Called when the timer is fired, with the current time `now`. `Refresh()`
+    // is automatically called after. If this causes a `GetNextReportTime()`
+    // call, that will be passed the same `now`.
+    virtual void OnReportingTimeReached(base::Time now) = 0;
 
     // Called when the connection changes from offline to online. May also be
     // called on a connection change if there are no stored reports, see
@@ -71,6 +73,7 @@
 
  private:
   void OnTimerFired();
+  void RefreshImpl(base::Time now);
 
   // network::NetworkConnectionTracker::NetworkConnectionObserver:
   void OnConnectionChanged(network::mojom::ConnectionType) override;
diff --git a/content/browser/aggregation_service/report_scheduler_timer_unittest.cc b/content/browser/aggregation_service/report_scheduler_timer_unittest.cc
index 47cfacd8..10abb7b 100644
--- a/content/browser/aggregation_service/report_scheduler_timer_unittest.cc
+++ b/content/browser/aggregation_service/report_scheduler_timer_unittest.cc
@@ -35,9 +35,10 @@
  public:
   MOCK_METHOD(void,
               GetNextReportTime,
-              (base::OnceCallback<void(absl::optional<base::Time>)>),
+              (base::OnceCallback<void(absl::optional<base::Time>)>,
+               base::Time),
               (override));
-  MOCK_METHOD(void, OnReportingTimeReached, (), (override));
+  MOCK_METHOD(void, OnReportingTimeReached, (base::Time), (override));
 
   MOCK_METHOD(void,
               AdjustOfflineReportTimes,
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc
index ec054bf6..e2f9590d 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -97,13 +97,17 @@
   AttributionReportScheduler& operator=(AttributionReportScheduler&&) = delete;
 
  private:
+  // TODO(crbug.com/1345751): Ensure that no reports are missed by using the
+  // `now` parameter in the following two calls.
+
   // ReportSchedulerTimer::Delegate:
   void GetNextReportTime(
-      base::OnceCallback<void(absl::optional<base::Time>)> callback) override {
+      base::OnceCallback<void(absl::optional<base::Time>)> callback,
+      base::Time now) override {
     attribution_storage_.AsyncCall(&AttributionStorage::GetNextReportTime)
         .Then(std::move(callback));
   };
-  void OnReportingTimeReached() override { send_reports_.Run(); };
+  void OnReportingTimeReached(base::Time now) override { send_reports_.Run(); };
   void AdjustOfflineReportTimes(
       base::OnceCallback<void(absl::optional<base::Time>)> maybe_set_timer_cb)
       override {
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index a8c8c6b..a84921b 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -182,7 +182,7 @@
     return media_keys_listener_manager_.get();
   }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // Only expose this on ChromeOS since it's only needed there. On Android this
   // be null if this process started in reduced mode.
   net::NetworkChangeNotifier* network_change_notifier() const {
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc
index 3217399..201301b 100644
--- a/content/browser/cache_storage/cache_storage_manager.cc
+++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -409,7 +409,8 @@
           /*total_size_bytes=*/0,
           /*last_modified=*/base::Time()));
     }
-    GetAllStorageKeysUsageGetSizes(std::move(callback), std::move(usages));
+    GetAllStorageKeysUsageGetSizes(owner, std::move(callback),
+                                   std::move(usages));
     return;
   }
 
@@ -420,11 +421,13 @@
           base::WrapRefCounted(scheduler_task_runner_.get()), std::move(usages),
           profile_path_, owner,
           base::BindOnce(&CacheStorageManager::GetAllStorageKeysUsageGetSizes,
-                         base::WrapRefCounted(this), std::move(callback))));
+                         base::WrapRefCounted(this), owner,
+                         std::move(callback))));
 }
 
 // TODO(https://crbug.com/1304786):  Rename to or add GetAllBucketsUsageGetSizes
 void CacheStorageManager::GetAllStorageKeysUsageGetSizes(
+    storage::mojom::CacheStorageOwner owner,
     storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback,
     std::vector<storage::mojom::StorageUsageInfoPtr> usages) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -452,8 +455,7 @@
       continue;
     }
     CacheStorageHandle cache_storage =
-        OpenCacheStorage(blink::StorageKey(usage->origin),
-                         storage::mojom::CacheStorageOwner::kCacheAPI);
+        OpenCacheStorage(blink::StorageKey(usage->origin), owner);
     CacheStorage::From(cache_storage)
         ->Size(base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage));
   }
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h
index b8848f1..ed9e364 100644
--- a/content/browser/cache_storage/cache_storage_manager.h
+++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -144,6 +144,7 @@
       CacheStorageMap;
 
   void GetAllStorageKeysUsageGetSizes(
+      storage::mojom::CacheStorageOwner owner,
       storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback
           callback,
       std::vector<storage::mojom::StorageUsageInfoPtr> usage_info);
diff --git a/content/browser/fenced_frame/fenced_frame.cc b/content/browser/fenced_frame/fenced_frame.cc
index 3970abd..405aa00 100644
--- a/content/browser/fenced_frame/fenced_frame.cc
+++ b/content/browser/fenced_frame/fenced_frame.cc
@@ -112,6 +112,10 @@
     return;
   }
 
+  GURL validated_url = url;
+  owner_render_frame_host_->GetSiteInstance()->GetProcess()->FilterURL(
+      /*empty_allowed=*/false, &validated_url);
+
   FrameTreeNode* inner_root = frame_tree_->root();
 
   // Rerandomize the fenced frame's storage partitioning nonce, so that state
@@ -136,7 +140,8 @@
   url::Origin initiator_origin;
 
   inner_root->navigator().NavigateFromFrameProxy(
-      inner_root->current_frame_host(), url, /*initiator_frame_token=*/nullptr,
+      inner_root->current_frame_host(), validated_url,
+      /*initiator_frame_token=*/nullptr,
       content::ChildProcessHost::kInvalidUniqueID, initiator_origin,
       /*source_site_instance=*/nullptr, content::Referrer(),
       ui::PAGE_TRANSITION_AUTO_SUBFRAME,
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
index bbdd4dc..650a912 100644
--- a/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -253,10 +253,17 @@
   private_->UpdateGpuExtraInfo(gpu_extra_info);
 }
 
-void GpuDataManagerImpl::UpdateMojoMediaVideoCapabilities(
+void GpuDataManagerImpl::UpdateMojoMediaVideoDecoderCapabilities(
     const media::SupportedVideoDecoderConfigs& configs) {
   base::AutoLock auto_lock(lock_);
-  private_->UpdateMojoMediaVideoCapabilities(configs);
+  private_->UpdateMojoMediaVideoDecoderCapabilities(configs);
+}
+
+void GpuDataManagerImpl::UpdateMojoMediaVideoEncoderCapabilities(
+    const media::VideoEncodeAccelerator::SupportedProfiles&
+        supported_profiles) {
+  base::AutoLock auto_lock(lock_);
+  private_->UpdateMojoMediaVideoEncoderCapabilities(supported_profiles);
 }
 
 gpu::GpuFeatureInfo GpuDataManagerImpl::GetGpuFeatureInfo() const {
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h
index 0a019006..9f2b350 100644
--- a/content/browser/gpu/gpu_data_manager_impl.h
+++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -26,6 +26,8 @@
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_mode.h"
+#include "media/base/supported_video_decoder_config.h"
+#include "media/video/video_encode_accelerator.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/gpu/gpu.mojom.h"
 #include "ui/display/display_observer.h"
@@ -41,11 +43,6 @@
 struct GpuPreferences;
 }
 
-namespace media {
-struct SupportedVideoDecoderConfig;
-using SupportedVideoDecoderConfigs = std::vector<SupportedVideoDecoderConfig>;
-}  // namespace media
-
 namespace content {
 
 class GpuDataManagerImplPrivate;
@@ -137,8 +134,11 @@
                             const absl::optional<gpu::GpuFeatureInfo>&
                                 gpu_feature_info_for_hardware_gpu);
   void UpdateGpuExtraInfo(const gfx::GpuExtraInfo& gpu_extra_info);
-  void UpdateMojoMediaVideoCapabilities(
+  void UpdateMojoMediaVideoDecoderCapabilities(
       const media::SupportedVideoDecoderConfigs& configs);
+  void UpdateMojoMediaVideoEncoderCapabilities(
+      const media::VideoEncodeAccelerator::SupportedProfiles&
+          supported_profiles);
 
   gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
 
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 54e4a91..5100caa 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -31,6 +31,7 @@
 #include "base/path_service.h"
 #include "base/rand_util.h"
 #include "base/strings/string_util.h"
+#include "base/task/bind_post_task.h"
 #include "base/trace_event/trace_event.h"
 #include "base/version.h"
 #include "build/build_config.h"
@@ -66,8 +67,10 @@
 #include "gpu/ipc/host/gpu_memory_buffer_support.h"
 #include "gpu/ipc/host/shader_disk_cache.h"
 #include "gpu/vulkan/buildflags.h"
+#include "media/gpu/gpu_video_accelerator_util.h"
 #include "media/media_buildflags.h"
 #include "media/mojo/clients/mojo_video_decoder.h"
+#include "media/mojo/mojom/video_encode_accelerator.mojom.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/switches.h"
@@ -451,90 +454,6 @@
   LOG(FATAL) << "GPU process isn't usable. Goodbye.";
 }
 
-gpu::VideoCodecProfile ToGpuVideoCodecProfile(
-    media::VideoCodecProfile profile) {
-  switch (profile) {
-    case media::VIDEO_CODEC_PROFILE_UNKNOWN:
-      return gpu::VIDEO_CODEC_PROFILE_UNKNOWN;
-    case media::H264PROFILE_BASELINE:
-      return gpu::H264PROFILE_BASELINE;
-    case media::H264PROFILE_MAIN:
-      return gpu::H264PROFILE_MAIN;
-    case media::H264PROFILE_EXTENDED:
-      return gpu::H264PROFILE_EXTENDED;
-    case media::H264PROFILE_HIGH:
-      return gpu::H264PROFILE_HIGH;
-    case media::H264PROFILE_HIGH10PROFILE:
-      return gpu::H264PROFILE_HIGH10PROFILE;
-    case media::H264PROFILE_HIGH422PROFILE:
-      return gpu::H264PROFILE_HIGH422PROFILE;
-    case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
-      return gpu::H264PROFILE_HIGH444PREDICTIVEPROFILE;
-    case media::H264PROFILE_SCALABLEBASELINE:
-      return gpu::H264PROFILE_SCALABLEBASELINE;
-    case media::H264PROFILE_SCALABLEHIGH:
-      return gpu::H264PROFILE_SCALABLEHIGH;
-    case media::H264PROFILE_STEREOHIGH:
-      return gpu::H264PROFILE_STEREOHIGH;
-    case media::H264PROFILE_MULTIVIEWHIGH:
-      return gpu::H264PROFILE_MULTIVIEWHIGH;
-    case media::VP8PROFILE_ANY:
-      return gpu::VP8PROFILE_ANY;
-    case media::VP9PROFILE_PROFILE0:
-      return gpu::VP9PROFILE_PROFILE0;
-    case media::VP9PROFILE_PROFILE1:
-      return gpu::VP9PROFILE_PROFILE1;
-    case media::VP9PROFILE_PROFILE2:
-      return gpu::VP9PROFILE_PROFILE2;
-    case media::VP9PROFILE_PROFILE3:
-      return gpu::VP9PROFILE_PROFILE3;
-    case media::HEVCPROFILE_MAIN:
-      return gpu::HEVCPROFILE_MAIN;
-    case media::HEVCPROFILE_MAIN10:
-      return gpu::HEVCPROFILE_MAIN10;
-    case media::HEVCPROFILE_MAIN_STILL_PICTURE:
-      return gpu::HEVCPROFILE_MAIN_STILL_PICTURE;
-    case media::HEVCPROFILE_REXT:
-      return gpu::HEVCPROFILE_REXT;
-    case media::HEVCPROFILE_HIGH_THROUGHPUT:
-      return gpu::HEVCPROFILE_HIGH_THROUGHPUT;
-    case media::HEVCPROFILE_MULTIVIEW_MAIN:
-      return gpu::HEVCPROFILE_MULTIVIEW_MAIN;
-    case media::HEVCPROFILE_SCALABLE_MAIN:
-      return gpu::HEVCPROFILE_SCALABLE_MAIN;
-    case media::HEVCPROFILE_3D_MAIN:
-      return gpu::HEVCPROFILE_3D_MAIN;
-    case media::HEVCPROFILE_SCREEN_EXTENDED:
-      return gpu::HEVCPROFILE_SCREEN_EXTENDED;
-    case media::HEVCPROFILE_SCALABLE_REXT:
-      return gpu::HEVCPROFILE_SCALABLE_REXT;
-    case media::HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
-      return gpu::HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED;
-    case media::DOLBYVISION_PROFILE0:
-      return gpu::DOLBYVISION_PROFILE0;
-    case media::DOLBYVISION_PROFILE4:
-      return gpu::DOLBYVISION_PROFILE4;
-    case media::DOLBYVISION_PROFILE5:
-      return gpu::DOLBYVISION_PROFILE5;
-    case media::DOLBYVISION_PROFILE7:
-      return gpu::DOLBYVISION_PROFILE7;
-    case media::THEORAPROFILE_ANY:
-      return gpu::THEORAPROFILE_ANY;
-    case media::AV1PROFILE_PROFILE_MAIN:
-      return gpu::AV1PROFILE_PROFILE_MAIN;
-    case media::AV1PROFILE_PROFILE_HIGH:
-      return gpu::AV1PROFILE_PROFILE_HIGH;
-    case media::AV1PROFILE_PROFILE_PRO:
-      return gpu::AV1PROFILE_PROFILE_PRO;
-    case media::DOLBYVISION_PROFILE8:
-      return gpu::DOLBYVISION_PROFILE8;
-    case media::DOLBYVISION_PROFILE9:
-      return gpu::DOLBYVISION_PROFILE9;
-  }
-  NOTREACHED();
-  return gpu::VIDEO_CODEC_PROFILE_UNKNOWN;
-}
-
 #if BUILDFLAG(IS_WIN)
 void CollectExtraDevicePerfInfo(const gpu::GPUInfo& gpu_info,
                                 gpu::DevicePerfInfo* device_perf_info) {
@@ -952,12 +871,62 @@
            media::VideoDecoderType /* decoder_type */) {
           GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
           DCHECK(manager);
-          manager->UpdateMojoMediaVideoCapabilities(configs);
+          manager->UpdateMojoMediaVideoDecoderCapabilities(configs);
         },
         std::move(remote_decoder), std::move(media_interface_proxy)));
   });
 
   GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(task));
+
+  // Since Android never had PPAPI/NaCl it doesn't initialize encoder profiles
+  // at GPU process startup. Query them now so chrome://gpu is accurate.
+#if BUILDFLAG(IS_ANDROID)
+  auto update_vea_profiles_callback = base::BindPostTask(
+      GetUIThreadTaskRunner({}),
+      base::BindOnce([](const media::VideoEncodeAccelerator::SupportedProfiles&
+                            supported_profiles) {
+        GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+        DCHECK(manager);
+        manager->UpdateMojoMediaVideoEncoderCapabilities(supported_profiles);
+      }));
+
+  using VEAProfileCallback = base::OnceCallback<void(
+      const media::VideoEncodeAccelerator::SupportedProfiles&)>;
+  GpuProcessHost::CallOnIO(
+      GPU_PROCESS_KIND_SANDBOXED, /*force_create=*/false,
+      base::BindOnce(
+          [](VEAProfileCallback update_vea_profiles_callback,
+             GpuProcessHost* host) {
+            if (!host)
+              return;
+
+            mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
+                vea_provider_remote;
+            host->gpu_service()->CreateVideoEncodeAcceleratorProvider(
+                vea_provider_remote.InitWithNewPipeAndPassReceiver());
+
+            mojo::Remote<media::mojom::VideoEncodeAcceleratorProvider>
+                vea_provider;
+            vea_provider.Bind(std::move(vea_provider_remote));
+
+            // Cache pointer locally since we std::move it into the callback.
+            auto* vea_provider_ptr = vea_provider.get();
+            vea_provider_ptr->GetVideoEncodeAcceleratorSupportedProfiles(
+                base::BindOnce(
+                    [](VEAProfileCallback update_vea_profiles_callback,
+                       mojo::Remote<
+                           media::mojom::VideoEncodeAcceleratorProvider>
+                           vea_provider,
+                       const media::VideoEncodeAccelerator::SupportedProfiles&
+                           supported_profiles) {
+                      std::move(update_vea_profiles_callback)
+                          .Run(supported_profiles);
+                    },
+                    std::move(update_vea_profiles_callback),
+                    std::move(vea_provider)));
+          },
+          std::move(update_vea_profiles_callback)));
+#endif
 }
 
 bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const {
@@ -1301,18 +1270,18 @@
                          &GpuDataManagerObserver::OnGpuExtraInfoUpdate);
 }
 
-void GpuDataManagerImplPrivate::UpdateMojoMediaVideoCapabilities(
+void GpuDataManagerImplPrivate::UpdateMojoMediaVideoDecoderCapabilities(
     const media::SupportedVideoDecoderConfigs& configs) {
-  gpu_info_.video_decode_accelerator_supported_profiles.clear();
-  for (const auto& config : configs) {
-    gpu::VideoDecodeAcceleratorSupportedProfile profile;
-    profile.profile = ToGpuVideoCodecProfile(config.profile_min);
-    profile.min_resolution = config.coded_size_min;
-    profile.max_resolution = config.coded_size_max;
-    profile.encrypted_only = config.require_encrypted;
-    gpu_info_.video_decode_accelerator_supported_profiles.push_back(profile);
-  }
+  gpu_info_.video_decode_accelerator_supported_profiles =
+      media::GpuVideoAcceleratorUtil::ConvertMediaConfigsToGpuDecodeProfiles(
+          configs);
+  NotifyGpuInfoUpdate();
+}
 
+void GpuDataManagerImplPrivate::UpdateMojoMediaVideoEncoderCapabilities(
+    const media::VideoEncodeAccelerator::SupportedProfiles& profiles) {
+  gpu_info_.video_encode_accelerator_supported_profiles =
+      media::GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles);
   NotifyGpuInfoUpdate();
 }
 
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h
index 85a4d09a..1aff605f7 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -25,6 +25,8 @@
 #include "build/build_config.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/common/content_export.h"
+#include "media/base/supported_video_decoder_config.h"
+#include "media/video/video_encode_accelerator.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/display/display_observer.h"
 #include "ui/gl/gpu_preference.h"
@@ -33,11 +35,6 @@
 class CommandLine;
 }
 
-namespace media {
-struct SupportedVideoDecoderConfig;
-using SupportedVideoDecoderConfigs = std::vector<SupportedVideoDecoderConfig>;
-}  // namespace media
-
 namespace content {
 
 class CONTENT_EXPORT GpuDataManagerImplPrivate {
@@ -97,8 +94,11 @@
                             const absl::optional<gpu::GpuFeatureInfo>&
                                 gpu_feature_info_for_hardware_gpu);
   void UpdateGpuExtraInfo(const gfx::GpuExtraInfo& process_info);
-  void UpdateMojoMediaVideoCapabilities(
+  void UpdateMojoMediaVideoDecoderCapabilities(
       const media::SupportedVideoDecoderConfigs& configs);
+  void UpdateMojoMediaVideoEncoderCapabilities(
+      const media::VideoEncodeAccelerator::SupportedProfiles&
+          supported_profiles);
 
   gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
   gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
diff --git a/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc b/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
index 219eb0d6..7d6580a8 100644
--- a/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
@@ -151,9 +151,10 @@
 
         // viz::SoftwareRenderer does not do color space management. Otherwise
         // (normal case), be strict about color differences.
-        const int max_color_diff = IsSoftwareCompositingTest()
-                                       ? kVeryLooseMaxColorDifference
-                                       : kMaxColorDifference;
+        const int max_color_diff =
+            (IsSoftwareCompositingTest() || !IsGpuRastrizationEnabled())
+                ? kVeryLooseMaxColorDifference
+                : kMaxColorDifference;
 
         // Determine the average RGB color in the three regions-of-interest in
         // the frame.
@@ -232,7 +233,10 @@
           // point, it means the frame we got did not match both expected and
           // tolerated colors.
           ADD_FAILURE() << "Observed frame that did not match both expected "
-                           "and tolerated colors. PNG dump:\n"
+                           "and tolerated colors. color="
+                        << color_string
+                        << ", tolerated_color=" << tolerated_color_string
+                        << ", PNG dump:\n"
                         << cc::GetPNGDataUrl(rgb_frame);
           return;
         }
@@ -616,14 +620,8 @@
 // whether the browser is running with software compositing or GPU-accelerated
 // compositing, whether the WebContents is visible/hidden or occluded/unoccluded
 // and whether the main document contains a cross-site iframe.
-// TODO the test is flaky on Mac. See https://crbug.com/1345663.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_CapturesContentChanges DISABLED_CapturesContentChanges
-#else
-#define MAYBE_CapturesContentChanges CapturesContentChanges
-#endif
 IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
-                       MAYBE_CapturesContentChanges) {
+                       CapturesContentChanges) {
   media::VideoPixelFormat specified_format = GetVideoPixelFormat();
   media::VideoPixelFormat expected_format = specified_format;
   if (specified_format == media::VideoPixelFormat::PIXEL_FORMAT_UNKNOWN) {
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 0ab1ee90..9dcd01e 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -601,7 +601,7 @@
   return GetCrashHandlersList().Add(std::move(handler));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
   return BrowserMainLoop::GetInstance()->network_change_notifier();
 }
diff --git a/content/browser/renderer_host/private_network_access_browsertest.cc b/content/browser/renderer_host/private_network_access_browsertest.cc
index 4d69d810..b6d0378 100644
--- a/content/browser/renderer_host/private_network_access_browsertest.cc
+++ b/content/browser/renderer_host/private_network_access_browsertest.cc
@@ -37,6 +37,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
 #include "net/test/embedded_test_server/http_request.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/common/features.h"
@@ -604,6 +605,7 @@
                 features::kBlockInsecurePrivateNetworkRequests,
                 features::kBlockInsecurePrivateNetworkRequestsFromPrivate,
                 features::kPrivateNetworkAccessRespectPreflightResults,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -619,6 +621,7 @@
                 features::kBlockInsecurePrivateNetworkRequests,
                 features::kBlockInsecurePrivateNetworkRequestsFromUnknown,
                 features::kPrivateNetworkAccessRespectPreflightResults,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -634,6 +637,7 @@
                 features::kBlockInsecurePrivateNetworkRequestsFromPrivate,
                 features::kBlockInsecurePrivateNetworkRequestsForNavigations,
                 features::kPrivateNetworkAccessRespectPreflightResults,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -647,6 +651,7 @@
       : PrivateNetworkAccessBrowserTestBase(
             {
                 features::kBlockInsecurePrivateNetworkRequests,
+                network::features::kNetworkServiceMemoryCache,
             },
             {
                 features::kPrivateNetworkAccessSendPreflights,
@@ -663,6 +668,7 @@
             {
                 features::kBlockInsecurePrivateNetworkRequests,
                 features::kPrivateNetworkAccessRespectPreflightResults,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -676,6 +682,7 @@
             {
                 features::kBlockInsecurePrivateNetworkRequests,
                 features::kPrivateNetworkAccessForWorkers,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -691,6 +698,7 @@
                 features::kBlockInsecurePrivateNetworkRequests,
                 features::kPrivateNetworkAccessRespectPreflightResults,
                 features::kPrivateNetworkAccessForWorkers,
+                network::features::kNetworkServiceMemoryCache,
             },
             {}) {}
 };
@@ -707,6 +715,7 @@
                 features::kBlockInsecurePrivateNetworkRequestsFromPrivate,
                 features::kBlockInsecurePrivateNetworkRequestsForNavigations,
                 features::kPrivateNetworkAccessSendPreflights,
+                network::features::kNetworkServiceMemoryCache,
             }) {}
 };
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 299adf0..9861a96 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1162,10 +1162,14 @@
 
 bool ValidateUnfencedTopNavigation(
     RenderFrameHostImpl* render_frame_host,
-    const GURL& url,
+    GURL& url,
     int initiator_process_id,
     const scoped_refptr<network::ResourceRequestBody>& post_body,
     bool user_gesture) {
+  // Validate and modify `url` as needed.
+  render_frame_host->GetSiteInstance()->GetProcess()->FilterURL(
+      /*empty_allowed=*/false, &url);
+
   // It should only be possible to send this IPC with this flag from an
   // opaque-ads fenced frame. Opaque-ads fenced frames should always
   // have the sandbox flag `allow-top-navigation-by-user-activation`.
@@ -7102,7 +7106,7 @@
   // inside the MPArch renderer process, so we need to set it here.
   // TODO(crbug.com/1315802): Refactor _unfencedTop handling.
   if (params->is_unfenced_top_navigation) {
-    const GURL validated_params_url = params->url;
+    GURL validated_params_url = params->url;
 
     // Check that the IPC parameters are valid and that the navigation
     // is allowed.
diff --git a/content/browser/resources/quota/quota_internals.ts b/content/browser/resources/quota/quota_internals.ts
index e5211ea..96148ed 100644
--- a/content/browser/resources/quota/quota_internals.ts
+++ b/content/browser/resources/quota/quota_internals.ts
@@ -8,10 +8,16 @@
 
 import {QuotaInternalsBrowserProxy} from './quota_internals_browser_proxy.js';
 
+enum StorageType {
+  TEMPORARY,
+  PERSISTENT,
+  SYNCABLE,
+}
+
 type BucketTableEntry = {
   'bucketId': bigint,
   'storageKey': string,
-  'type': string,
+  'type': StorageType,
   'name': string,
   'usage': bigint,
   'useCount': bigint,
@@ -146,7 +152,7 @@
    *   <storage_key_string>: {
    *     bucketCount: <number>,
    *     storageKeyEntries: {
-   *       <storage_type_string>: [{
+   *       <storage_type>: [{
    *         bucketId: <bigint>,
    *         name: <string>,
    *         usage: <bigint>,
@@ -180,14 +186,16 @@
     }
     if (!(entry.type in bucketTableEntriesByStorageKey[entry.storageKey]
                                                       ['storageKeyEntries'])) {
-      bucketTableEntriesByStorageKey
-          [entry.storageKey]['storageKeyEntries'][entry.type] =
-              [bucketTableEntryObj];
+      bucketTableEntriesByStorageKey[entry
+                                         .storageKey]['storageKeyEntries'][entry
+                                                                               .type] =
+          [bucketTableEntryObj];
       bucketTableEntriesByStorageKey[entry.storageKey]['bucketCount'] += 1;
     } else {
-      bucketTableEntriesByStorageKey
-          [entry.storageKey]['storageKeyEntries'][entry.type]
-              .push(bucketTableEntryObj);
+      bucketTableEntriesByStorageKey[entry
+                                         .storageKey]['storageKeyEntries'][entry
+                                                                               .type]
+          .push(bucketTableEntryObj);
       bucketTableEntriesByStorageKey[entry.storageKey]['bucketCount'] += 1;
     }
   }
@@ -206,11 +214,12 @@
         bucketTableEntriesByStorageKey[storageKey]['bucketCount'];
     const bucketsByStorageType: StorageTypeEntries =
         bucketTableEntriesByStorageKey[storageKey]['storageKeyEntries'];
-    const storageTypes: string[] = Object.keys(bucketsByStorageType);
+    const storageTypes: StorageType[] =
+        Object.keys(bucketsByStorageType).map(typeStr => Number(typeStr));
 
     // Iterate over each storageType for a given storage key.
     for (let j = 0; j < storageTypes.length; j++) {
-      const storageType: string = storageTypes[j];
+      const storageType: StorageType = storageTypes[j];
       const bucketsForStorageType: StorageTypeBucketTableEntry[] =
           bucketsByStorageType[storageType];
       const storageTypeRowSpan: number =
@@ -237,7 +246,7 @@
         usageAndQuotaRow.querySelector('.storage-key')!.setAttribute(
             'rowspan', `${storageKeyRowSpan}`);
         usageAndQuotaRow.querySelector('.storage-type')!.textContent =
-            storageType;
+            StorageType[storageType];
         usageAndQuotaRow.querySelector('.storage-type')!.setAttribute(
             'rowspan', `${storageTypeRowSpan}`);
         usageAndQuotaRow.querySelector('.bucket')!.textContent =
diff --git a/content/browser/resources/quota/quota_internals_browser_proxy.ts b/content/browser/resources/quota/quota_internals_browser_proxy.ts
index 88262b9..d53b80185 100644
--- a/content/browser/resources/quota/quota_internals_browser_proxy.ts
+++ b/content/browser/resources/quota/quota_internals_browser_proxy.ts
@@ -7,10 +7,16 @@
 
 import {QuotaInternalsHandler} from './quota_internals.mojom-webui.js';
 
+enum StorageType {
+  TEMPORARY,
+  PERSISTENT,
+  SYNCABLE,
+}
+
 type BucketTableEntry = {
   'bucketId': bigint,
   'storageKey': string,
-  'type': string,
+  'type': StorageType,
   'name': string,
   'usage': bigint,
   'useCount': bigint,
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 1249b161c..70a6c3d 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -474,46 +474,6 @@
   return url::Origin::Create(url).Serialize();
 }
 
-//
-// SitePerProcessIsolatedSandboxedIframeTest
-//
-class SitePerProcessIsolatedSandboxedIframeTest
-    : public SitePerProcessBrowserTest {
- public:
-  SitePerProcessIsolatedSandboxedIframeTest() {
-    feature_list_.InitAndEnableFeature(features::kIsolateSandboxedIframes);
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-class SitePerProcessNotIsolatedSandboxedIframeTest
-    : public SitePerProcessBrowserTest {
- public:
-  SitePerProcessNotIsolatedSandboxedIframeTest() {
-    feature_list_.InitAndDisableFeature(features::kIsolateSandboxedIframes);
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// A test class to allow testing isolated sandboxed iframes using the per-origin
-// process model.
-class SitePerProcessPerOriginIsolatedSandboxedIframeTest
-    : public SitePerProcessBrowserTest {
- public:
-  SitePerProcessPerOriginIsolatedSandboxedIframeTest() {
-    feature_list_.InitWithFeaturesAndParameters(
-        {{features::kIsolateSandboxedIframes, {{"grouping", "per-origin"}}}},
-        {/* disabled_features */});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
 // SitePerProcessIgnoreCertErrorsBrowserTest
 
 void SitePerProcessIgnoreCertErrorsBrowserTest::SetUpOnMainThread() {
@@ -2359,768 +2319,6 @@
   EXPECT_FALSE(AutoplayAllowed(shell(), false));
 }
 
-// The following test should not crash. In this test the
-// kIsolateSandboxedIframes flag is forced off, so we don't need to verify
-// the process isolation details, as is done in
-// SitePerProcessIsolatedSandboxedIframeTest.SrcdocCspSandboxIsIsolated below.
-// https://crbug.com/1319430
-IN_PROC_BROWSER_TEST_P(SitePerProcessNotIsolatedSandboxedIframeTest,
-                       SrcdocSandboxFlagsCheck) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed srcdoc child frame, with csp sandbox.
-  EXPECT_TRUE(ExecJs(shell(),
-                     "var frame = document.createElement('iframe'); "
-                     "frame.csp = 'sandbox'; "
-                     "frame.srcdoc = 'foo'; "
-                     "document.body.appendChild(frame);"));
-  ASSERT_TRUE(WaitForLoadStop(web_contents()));
-}
-
-// Test that a srcdoc iframe that receives its sandbox flags from the CSP
-// attribute also gets process isolation. This test starts the same as
-// SitePerProcessNotIsolatedSandboxedIframeTest.SrcdocSandboxFlagsCheck, but in
-// this test the kIsolateSandboxedIframes flag is on, so we also verify that
-// the process isolation has indeed occurred.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SrcdocCspSandboxIsIsolated) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed srcdoc child frame, with csp sandbox.
-  EXPECT_TRUE(ExecJs(shell(),
-                     "var frame = document.createElement('iframe'); "
-                     "frame.csp = 'sandbox'; "
-                     "frame.srcdoc = 'foo'; "
-                     "document.body.appendChild(frame);"));
-  ASSERT_TRUE(WaitForLoadStop(web_contents()));
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->current_frame_host()->active_sandbox_flags());
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-// A test to verify that an iframe that is sandboxed using the 'csp' attribute
-// instead of the 'sandbox' attribute gets process isolation when the
-// kIsolatedSandboxedIframes flag is enabled.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       CspIsolatedSandbox) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The child needs to have the same origin as the parent.
-  GURL child_url(main_url);
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create csp-sandboxed child frame, same-origin.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.csp = 'sandbox'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->current_frame_host()->active_sandbox_flags());
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-// A test to verify that an iframe with a fully-restrictive sandbox is rendered
-// in a separate process from its parent frame even if they have the same
-// origin.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       IsolatedSandbox) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The child needs to have the same origin as the parent.
-  GURL child_url(main_url);
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, same-origin.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.sandbox = ''; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-// Test that sandboxed iframes that are same-site with their parent but
-// cross-origin from each other are put in different processes from each other,
-// when the 'per-origin' isolation grouping is active for
-// kIsolateSandboxedIframes. (In 'per-site' isolation mode they would be in the
-// same process.)
-IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
-                       CrossOriginIsolatedSandboxedIframes) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The children need to have the same origin as the parent, but be cross
-  // origin from each other.
-  GURL same_origin_child_url(main_url);
-  GURL cross_origin_child_url(
-      embedded_test_server()->GetURL("sub.a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frames, both same-origin and cross-origin.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame1 = document.createElement('iframe'); "
-        "frame1.sandbox = ''; "
-        "frame1.src = '%s'; "
-        "document.body.appendChild(frame1); "
-        "var frame2 = document.createElement('iframe'); "
-        "frame2.sandbox = ''; "
-        "frame2.src = '%s'; "
-        "document.body.appendChild(frame2);",
-        same_origin_child_url.spec().c_str(),
-        cross_origin_child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(2U, root->child_count());
-
-  FrameTreeNode* child1 = root->child_at(0);  // a.com
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child1->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child1->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child1->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-
-  FrameTreeNode* child2 = root->child_at(1);  // sub.a.com
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child2->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child2->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child2->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  // This is the key result for this test: the sandboxed iframes for 'a.com' and
-  // 'sub.a.com' should be in different SiteInstances.
-  auto* child1_site_instance1 = child1->current_frame_host()->GetSiteInstance();
-  auto* child2_site_instance1 = child2->current_frame_host()->GetSiteInstance();
-  EXPECT_NE(child1_site_instance1, child2_site_instance1);
-  EXPECT_NE(child1_site_instance1->GetProcess(),
-            child2_site_instance1->GetProcess());
-}
-
-// Test that, while using 'per-origin' isolation grouping, navigating a
-// sandboxed iframe from 'a.foo.com' to 'b.foo.com' results in the sandbox using
-// two different SiteInstances.
-IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
-                       CrossOriginNavigationSwitchesSiteInstances) {
-  GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
-  GURL cross_origin_child_url(
-      embedded_test_server()->GetURL("a.foo.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed cross-origin child frame.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'test_frame'; "
-        "frame.sandbox = ''; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        cross_origin_child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-
-  FrameTreeNode* child = root->child_at(0);  // a.foo.com
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->effective_frame_policy().sandbox_flags);
-  scoped_refptr<SiteInstanceImpl> site_instance_root =
-      root->current_frame_host()->GetSiteInstance();
-  scoped_refptr<SiteInstanceImpl> site_instance1 =
-      child->current_frame_host()->GetSiteInstance();
-  EXPECT_NE(site_instance_root, site_instance1);
-  EXPECT_TRUE(site_instance1->GetSiteInfo().is_sandboxed());
-  EXPECT_FALSE(site_instance_root->GetSiteInfo().is_sandboxed());
-
-  // Navigate sandboxed frame cross-origin to b.foo.com.
-  EXPECT_TRUE(NavigateIframeToURL(
-      shell()->web_contents(), "test_frame",
-      GURL(embedded_test_server()->GetURL("b.foo.com", "/title1.html"))));
-
-  scoped_refptr<SiteInstanceImpl> site_instance2 =
-      child->current_frame_host()->GetSiteInstance();
-  EXPECT_NE(site_instance_root, site_instance2);
-  EXPECT_NE(site_instance1, site_instance2);
-  EXPECT_NE(site_instance1->GetProcess(), site_instance2->GetProcess());
-}
-
-// Test that navigating cross-origin from a non-sandboxed iframe to a CSP
-// sandboxed iframe results in switching to a new SiteInstance in a different
-// process.
-IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
-                       CrossOriginNavigationToCSPSwitchesSiteInstances) {
-  GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
-  GURL cross_origin_child_url(
-      embedded_test_server()->GetURL("a.foo.com", "/title1.html"));
-  GURL cross_origin_csp_child_url(
-      embedded_test_server()->GetURL("b.foo.com",
-                                     "/set-header?"
-                                     "Content-Security-Policy: sandbox "));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create non-sandboxed cross-origin child frame.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'test_frame'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        cross_origin_child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-
-  FrameTreeNode* child = root->child_at(0);  // a.foo.com
-  scoped_refptr<SiteInstanceImpl> site_instance_root =
-      root->current_frame_host()->GetSiteInstance();
-  scoped_refptr<SiteInstanceImpl> site_instance1 =
-      child->current_frame_host()->GetSiteInstance();
-  EXPECT_EQ(site_instance_root, site_instance1);
-  EXPECT_FALSE(site_instance1->GetSiteInfo().is_sandboxed());
-
-  // Navigate child frame cross-origin to CSP-isolated b.foo.com.
-  EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test_frame",
-                                  cross_origin_csp_child_url));
-
-  // The child frame should now have a different SiteInstance and process than
-  // it did before the navigation.
-  scoped_refptr<SiteInstanceImpl> site_instance2 =
-      child->current_frame_host()->GetSiteInstance();
-  EXPECT_NE(site_instance1, site_instance2);
-  EXPECT_NE(site_instance1->GetProcess(), site_instance2->GetProcess());
-  EXPECT_TRUE(site_instance2->GetSiteInfo().is_sandboxed());
-}
-
-// Check that two same-site sandboxed iframes in unrelated windows share the
-// same process due to subframe process reuse.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SandboxProcessReuse) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The child needs to have the same origin as the parent.
-  GURL child_url(main_url);
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, same-origin.
-  std::string js_str = base::StringPrintf(
-      "var frame = document.createElement('iframe'); "
-      "frame.sandbox = ''; "
-      "frame.src = '%s'; "
-      "document.body.appendChild(frame);",
-      child_url.spec().c_str());
-  EXPECT_TRUE(ExecJs(shell(), js_str));
-  ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-
-  // Set up an unrelated window with the same frame hierarchy.
-  Shell* new_shell = CreateBrowser();
-  EXPECT_TRUE(NavigateToURL(new_shell, main_url));
-  FrameTreeNode* new_root =
-      static_cast<WebContentsImpl*>(new_shell->web_contents())
-          ->GetPrimaryFrameTree()
-          .root();
-  EXPECT_TRUE(ExecJs(new_shell, js_str));
-  ASSERT_TRUE(WaitForLoadStop(new_shell->web_contents()));
-  FrameTreeNode* new_child = new_root->child_at(0);
-  EXPECT_TRUE(new_child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(new_root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-
-  // Check that the two sandboxed subframes end up in separate
-  // BrowsingInstances but in the same process.
-  EXPECT_FALSE(
-      new_child->current_frame_host()->GetSiteInstance()->IsRelatedSiteInstance(
-          child->current_frame_host()->GetSiteInstance()));
-  EXPECT_EQ(new_child->current_frame_host()->GetProcess(),
-            child->current_frame_host()->GetProcess());
-}
-
-// A test to verify that when an iframe has two sibling subframes, each with a
-// fully-restrictive sandbox, that each of the three gets its own process
-// even though they are all same-origin.
-// Note: using "sandbox = ''" in this and the following tests creates fully
-// restricted sandboxes, which will include the kOrigin case we are interested
-// in.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       IsolatedSandboxSiblingSubframes) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The child needs to have the same origin as the parent.
-  GURL child_url(main_url);
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, same-origin.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame1 = document.createElement('iframe'); "
-        "frame1.sandbox = ''; "
-        "frame1.src = '%s'; "
-        "document.body.appendChild(frame1); "
-        "var frame2 = document.createElement('iframe'); "
-        "frame2.sandbox = ''; "
-        "frame2.src = '%s'; "
-        "document.body.appendChild(frame2);",
-        child_url.spec().c_str(), child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check frame-tree.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(2U, root->child_count());
-  FrameTreeNode* child1 = root->child_at(0);
-  FrameTreeNode* child2 = root->child_at(1);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child1->effective_frame_policy().sandbox_flags);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child2->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child1->current_frame_host()->GetSiteInstance());
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child2->current_frame_host()->GetSiteInstance());
-  // Because the siblings are same-site to each other (in fact, same origin) we
-  // expect them to share a process when sandboxed.
-  EXPECT_EQ(child1->current_frame_host()->GetSiteInstance(),
-            child2->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child1->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_TRUE(child2->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       IsolatedSandboxSrcdocSubframe) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, with srcdoc content.
-  std::string child_inner_text("srcdoc sandboxed subframe");
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.sandbox = 'allow-scripts'; "
-        "frame.srcdoc = '%s'; "
-        "document.body.appendChild(frame);",
-        child_inner_text.c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  // Verify that the child has only the 'allow-scripts' permission set.
-  EXPECT_EQ(child->effective_frame_policy().sandbox_flags,
-            network::mojom::WebSandboxFlags::kAll &
-                ~network::mojom::WebSandboxFlags::kScripts &
-                ~network::mojom::WebSandboxFlags::kAutomaticFeatures);
-  EXPECT_EQ(std::string(url::kAboutSrcdocURL),
-            child->current_frame_host()->GetLastCommittedURL());
-  EXPECT_TRUE(child->current_frame_host()->GetLastCommittedOrigin().opaque());
-  // Verify that the child's precursor origin matches 'a.com'. Note: we create
-  // the expected value using `main_url` so that the test server port will be
-  // correctly matched.
-  EXPECT_EQ(url::SchemeHostPort(main_url),
-            child->current_origin().GetTupleOrPrecursorTupleIfOpaque());
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-  {
-    std::string js_str("document.body.innerText;");
-    EXPECT_EQ(child_inner_text, EvalJs(child->current_frame_host(), js_str));
-  }
-}
-
-// A test to make sure that about:blank in a sandboxed iframe doesn't get
-// process isolation. If it did, it would be impossible for the parent to inject
-// any content, and it would be stuck as empty content.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       NotIsolatedSandboxAboutBlankSubframe) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, with about:blank content.
-  {
-    std::string js_str(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'child_frame'; "
-        "frame.sandbox = ''; "
-        "frame.src = 'about:blank'; "
-        "document.body.appendChild(frame);");
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  // Verify that the child has no permissions set.
-  EXPECT_EQ(child->effective_frame_policy().sandbox_flags,
-            network::mojom::WebSandboxFlags::kAll);
-  EXPECT_EQ(GURL(url::kAboutBlankURL),
-            child->current_frame_host()->GetLastCommittedURL());
-  EXPECT_TRUE(child->current_frame_host()->GetLastCommittedOrigin().opaque());
-  // Verify that the child's precursor origin matches 'a.com'. Note: we create
-  // the expected value using `main_url` so that the test server port will be
-  // correctly matched.
-  EXPECT_EQ(url::SchemeHostPort(main_url),
-            child->current_origin().GetTupleOrPrecursorTupleIfOpaque());
-  // The child needs to be in the parent's SiteInstance.
-  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-
-  // Navigate to a page that should get process isolation.
-  GURL isolated_child_url(
-      embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateFrameToURL(child, isolated_child_url));
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-
-  // Navigate back to about:blank, and verify it's put back into the parent's
-  // SiteInstance.
-  scoped_refptr<SiteInstanceImpl> child_previous_site_instance =
-      child->current_frame_host()->GetSiteInstance();
-  EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "child_frame",
-                                  GURL("about:blank")));
-  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_NE(child_previous_site_instance,
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_FALSE(child->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-// Test to make sure that javascript: urls don't execute in a sandboxed iframe.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SandboxedIframeWithJSUrl) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame with a javascript: URL.
-  std::string js_url_str("javascript:\"foo\"");
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'test_frame'; "
-        "frame.sandbox = 'allow-scripts'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        js_url_str.c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Verify parent and child frames share a SiteInstance. A sandboxed iframe
-  // with a javascript: url shouldn't get its own process.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-
-  // Verify that the javascript: url did not execute. This is expected
-  // regardless of IsolatedSandboxedIframes since sandboxed iframes get opaque
-  // origins, and javascript: urls don't execute in opaque origins.
-  EXPECT_TRUE(
-      EvalJs(child->current_frame_host(), "document.body.innerHTML == ''")
-          .ExtractBool());
-}
-
-// Test to make sure that an iframe with a data:url is process isolated.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SandboxedIframeWithDataURLIsIsolated) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame with a data URL.
-  std::string data_url_str("data:text/html,dataurl");
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'test_frame'; "
-        "frame.sandbox = ''; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        data_url_str.c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Verify parent and child frames don't share a SiteInstance
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-  EXPECT_FALSE(root->current_frame_host()
-                   ->GetSiteInstance()
-                   ->GetSiteInfo()
-                   .is_sandboxed());
-}
-
-// Test to make sure that an iframe with a data:url is appropriately sandboxed.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SandboxedIframeWithDataURL) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create non-sandboxed child frame with a data URL.
-  std::string data_url_str("data:text/html,dataurl");
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.id = 'test_frame'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        data_url_str.c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Verify parent and child frames share a SiteInstance
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-
-  // Now make subframe sandboxed.
-  {
-    std::string js_str(
-        "var frame = document.getElementById('test_frame'); "
-        "frame.sandbox = ''; ");
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-  }
-  NavigateFrameToURL(child,
-                     embedded_test_server()->GetURL("b.com", "/title1.html"));
-  // Child should now be in a different SiteInstance.
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-
-  // Go back and ensure the data: URL committed in the same SiteInstance as the
-  // original navigation.
-  EXPECT_TRUE(web_contents()->GetController().CanGoBack());
-  {
-    TestFrameNavigationObserver frame_observer(child);
-    web_contents()->GetController().GoBack();
-    frame_observer.WaitForCommit();
-  }
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_EQ(GURL(data_url_str),
-            child->current_frame_host()->GetLastCommittedURL());
-}
-
-// Test to make sure that a sandboxed child iframe with a data url and a
-// sandboxed parent end up in the same SiteInstance.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       SandboxedParentWithSandboxedChildWithDataURL) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  std::string parent_url_str = main_url.spec();
-  std::string data_url_str("data:text/html,dataurl");
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Allow "parent" to have the allow-scripts permissions so it can create
-  // a child.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.sandbox = 'allow-scripts'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        parent_url_str.c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-
-  // Give the grandchild the allow-scripts permissions so it matches the child.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.sandbox = 'allow-scripts'; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        data_url_str.c_str());
-    EXPECT_TRUE(ExecJs(child->current_frame_host(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-  ASSERT_EQ(1U, child->child_count());
-  FrameTreeNode* grandchild = child->child_at(0);
-  EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
-            grandchild->current_frame_host()->GetSiteInstance());
-  EXPECT_EQ(GURL(data_url_str),
-            grandchild->current_frame_host()->GetLastCommittedURL());
-}
-
-// Test to make sure that a sandboxed iframe with a (not-explicitly) sandboxed
-// subframe ends up in the same SiteInstance/process as its subframe.
-IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
-                       IsolatedSandboxWithNonSandboxedSubframe) {
-  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
-  // The child needs to have the same origin as the parent.
-  GURL child_url(
-      embedded_test_server()->GetURL("a.com", "/page_with_iframe.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
-  // Create sandboxed child frame, same-origin.
-  {
-    std::string js_str = base::StringPrintf(
-        "var frame = document.createElement('iframe'); "
-        "frame.sandbox = ''; "
-        "frame.src = '%s'; "
-        "document.body.appendChild(frame);",
-        child_url.spec().c_str());
-    EXPECT_TRUE(ExecJs(shell(), js_str));
-    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  }
-
-  // Check child vs. parent.
-  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
-  ASSERT_EQ(1U, root->child_count());
-  FrameTreeNode* child = root->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            child->effective_frame_policy().sandbox_flags);
-  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
-            child->current_frame_host()->GetSiteInstance());
-  EXPECT_TRUE(child->current_frame_host()
-                  ->GetSiteInstance()
-                  ->GetSiteInfo()
-                  .is_sandboxed());
-
-  // Check grandchild vs. child.
-  ASSERT_EQ(1U, child->child_count());
-  FrameTreeNode* grand_child = child->child_at(0);
-  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
-            grand_child->effective_frame_policy().sandbox_flags);
-  EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
-            grand_child->current_frame_host()->GetSiteInstance());
-}
-
 // Check that iframe sandbox flags are replicated correctly.
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, SandboxFlagsReplication) {
   GURL main_url(embedded_test_server()->GetURL("/sandboxed_frames.html"));
@@ -13822,15 +13020,6 @@
                          SitePerProcessBrowserTouchActionTest,
                          testing::ValuesIn(RenderDocumentFeatureLevelValues()));
 INSTANTIATE_TEST_SUITE_P(All,
-                         SitePerProcessIsolatedSandboxedIframeTest,
-                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
-INSTANTIATE_TEST_SUITE_P(All,
-                         SitePerProcessNotIsolatedSandboxedIframeTest,
-                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
-INSTANTIATE_TEST_SUITE_P(All,
-                         SitePerProcessPerOriginIsolatedSandboxedIframeTest,
-                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
-INSTANTIATE_TEST_SUITE_P(All,
                          SitePerProcessIgnoreCertErrorsBrowserTest,
                          testing::ValuesIn(RenderDocumentFeatureLevelValues()));
 INSTANTIATE_TEST_SUITE_P(All,
diff --git a/content/browser/site_per_process_oopsif_browsertest.cc b/content/browser/site_per_process_oopsif_browsertest.cc
new file mode 100644
index 0000000..ed4ce8b
--- /dev/null
+++ b/content/browser/site_per_process_oopsif_browsertest.cc
@@ -0,0 +1,829 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/site_per_process_browsertest.h"
+
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_frame_navigation_observer.h"
+#include "content/test/render_document_feature.h"
+
+namespace content {
+
+// Out-of-process-sandboxed-iframe (OOPSIF) tests.
+//
+// Test classes for isolating sandboxed iframes and documents in a different
+// process from the rest of their site.
+// See https://crbug.com/510122.
+class SitePerProcessIsolatedSandboxedIframeTest
+    : public SitePerProcessBrowserTest {
+ public:
+  SitePerProcessIsolatedSandboxedIframeTest() {
+    feature_list_.InitAndEnableFeature(features::kIsolateSandboxedIframes);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+class SitePerProcessNotIsolatedSandboxedIframeTest
+    : public SitePerProcessBrowserTest {
+ public:
+  SitePerProcessNotIsolatedSandboxedIframeTest() {
+    feature_list_.InitAndDisableFeature(features::kIsolateSandboxedIframes);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// A test class to allow testing isolated sandboxed iframes using the per-origin
+// process model.
+class SitePerProcessPerOriginIsolatedSandboxedIframeTest
+    : public SitePerProcessBrowserTest {
+ public:
+  SitePerProcessPerOriginIsolatedSandboxedIframeTest() {
+    feature_list_.InitWithFeaturesAndParameters(
+        {{features::kIsolateSandboxedIframes, {{"grouping", "per-origin"}}}},
+        {/* disabled_features */});
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// The following test should not crash. In this test the
+// kIsolateSandboxedIframes flag is forced off, so we don't need to verify
+// the process isolation details, as is done in
+// SitePerProcessIsolatedSandboxedIframeTest.SrcdocCspSandboxIsIsolated below.
+// https://crbug.com/1319430
+IN_PROC_BROWSER_TEST_P(SitePerProcessNotIsolatedSandboxedIframeTest,
+                       SrcdocSandboxFlagsCheck) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed srcdoc child frame, with csp sandbox.
+  EXPECT_TRUE(ExecJs(shell(),
+                     "var frame = document.createElement('iframe'); "
+                     "frame.csp = 'sandbox'; "
+                     "frame.srcdoc = 'foo'; "
+                     "document.body.appendChild(frame);"));
+  ASSERT_TRUE(WaitForLoadStop(web_contents()));
+}
+
+// Test that a srcdoc iframe that receives its sandbox flags from the CSP
+// attribute also gets process isolation. This test starts the same as
+// SitePerProcessNotIsolatedSandboxedIframeTest.SrcdocSandboxFlagsCheck, but in
+// this test the kIsolateSandboxedIframes flag is on, so we also verify that
+// the process isolation has indeed occurred.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SrcdocCspSandboxIsIsolated) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed srcdoc child frame, with csp sandbox.
+  EXPECT_TRUE(ExecJs(shell(),
+                     "var frame = document.createElement('iframe'); "
+                     "frame.csp = 'sandbox'; "
+                     "frame.srcdoc = 'foo'; "
+                     "document.body.appendChild(frame);"));
+  ASSERT_TRUE(WaitForLoadStop(web_contents()));
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->current_frame_host()->active_sandbox_flags());
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+// A test to verify that an iframe that is sandboxed using the 'csp' attribute
+// instead of the 'sandbox' attribute gets process isolation when the
+// kIsolatedSandboxedIframes flag is enabled.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       CspIsolatedSandbox) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create csp-sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.csp = 'sandbox'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->current_frame_host()->active_sandbox_flags());
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+// A test to verify that an iframe with a fully-restrictive sandbox is rendered
+// in a separate process from its parent frame even if they have the same
+// origin.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       IsolatedSandbox) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+// Test that sandboxed iframes that are same-site with their parent but
+// cross-origin from each other are put in different processes from each other,
+// when the 'per-origin' isolation grouping is active for
+// kIsolateSandboxedIframes. (In 'per-site' isolation mode they would be in the
+// same process.)
+IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
+                       CrossOriginIsolatedSandboxedIframes) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The children need to have the same origin as the parent, but be cross
+  // origin from each other.
+  GURL same_origin_child_url(main_url);
+  GURL cross_origin_child_url(
+      embedded_test_server()->GetURL("sub.a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frames, both same-origin and cross-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame1 = document.createElement('iframe'); "
+        "frame1.sandbox = ''; "
+        "frame1.src = '%s'; "
+        "document.body.appendChild(frame1); "
+        "var frame2 = document.createElement('iframe'); "
+        "frame2.sandbox = ''; "
+        "frame2.src = '%s'; "
+        "document.body.appendChild(frame2);",
+        same_origin_child_url.spec().c_str(),
+        cross_origin_child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(2U, root->child_count());
+
+  FrameTreeNode* child1 = root->child_at(0);  // a.com
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child1->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child1->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child1->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+
+  FrameTreeNode* child2 = root->child_at(1);  // sub.a.com
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child2->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child2->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child2->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  // This is the key result for this test: the sandboxed iframes for 'a.com' and
+  // 'sub.a.com' should be in different SiteInstances.
+  auto* child1_site_instance1 = child1->current_frame_host()->GetSiteInstance();
+  auto* child2_site_instance1 = child2->current_frame_host()->GetSiteInstance();
+  EXPECT_NE(child1_site_instance1, child2_site_instance1);
+  EXPECT_NE(child1_site_instance1->GetProcess(),
+            child2_site_instance1->GetProcess());
+}
+
+// Test that, while using 'per-origin' isolation grouping, navigating a
+// sandboxed iframe from 'a.foo.com' to 'b.foo.com' results in the sandbox using
+// two different SiteInstances.
+IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
+                       CrossOriginNavigationSwitchesSiteInstances) {
+  GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  GURL cross_origin_child_url(
+      embedded_test_server()->GetURL("a.foo.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed cross-origin child frame.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        cross_origin_child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+
+  FrameTreeNode* child = root->child_at(0);  // a.foo.com
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->effective_frame_policy().sandbox_flags);
+  scoped_refptr<SiteInstanceImpl> site_instance_root =
+      root->current_frame_host()->GetSiteInstance();
+  scoped_refptr<SiteInstanceImpl> site_instance1 =
+      child->current_frame_host()->GetSiteInstance();
+  EXPECT_NE(site_instance_root, site_instance1);
+  EXPECT_TRUE(site_instance1->GetSiteInfo().is_sandboxed());
+  EXPECT_FALSE(site_instance_root->GetSiteInfo().is_sandboxed());
+
+  // Navigate sandboxed frame cross-origin to b.foo.com.
+  EXPECT_TRUE(NavigateIframeToURL(
+      shell()->web_contents(), "test_frame",
+      GURL(embedded_test_server()->GetURL("b.foo.com", "/title1.html"))));
+
+  scoped_refptr<SiteInstanceImpl> site_instance2 =
+      child->current_frame_host()->GetSiteInstance();
+  EXPECT_NE(site_instance_root, site_instance2);
+  EXPECT_NE(site_instance1, site_instance2);
+  EXPECT_NE(site_instance1->GetProcess(), site_instance2->GetProcess());
+}
+
+// Test that navigating cross-origin from a non-sandboxed iframe to a CSP
+// sandboxed iframe results in switching to a new SiteInstance in a different
+// process.
+IN_PROC_BROWSER_TEST_P(SitePerProcessPerOriginIsolatedSandboxedIframeTest,
+                       CrossOriginNavigationToCSPSwitchesSiteInstances) {
+  GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  GURL cross_origin_child_url(
+      embedded_test_server()->GetURL("a.foo.com", "/title1.html"));
+  GURL cross_origin_csp_child_url(
+      embedded_test_server()->GetURL("b.foo.com",
+                                     "/set-header?"
+                                     "Content-Security-Policy: sandbox "));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create non-sandboxed cross-origin child frame.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        cross_origin_child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+
+  FrameTreeNode* child = root->child_at(0);  // a.foo.com
+  scoped_refptr<SiteInstanceImpl> site_instance_root =
+      root->current_frame_host()->GetSiteInstance();
+  scoped_refptr<SiteInstanceImpl> site_instance1 =
+      child->current_frame_host()->GetSiteInstance();
+  EXPECT_EQ(site_instance_root, site_instance1);
+  EXPECT_FALSE(site_instance1->GetSiteInfo().is_sandboxed());
+
+  // Navigate child frame cross-origin to CSP-isolated b.foo.com.
+  EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "test_frame",
+                                  cross_origin_csp_child_url));
+
+  // The child frame should now have a different SiteInstance and process than
+  // it did before the navigation.
+  scoped_refptr<SiteInstanceImpl> site_instance2 =
+      child->current_frame_host()->GetSiteInstance();
+  EXPECT_NE(site_instance1, site_instance2);
+  EXPECT_NE(site_instance1->GetProcess(), site_instance2->GetProcess());
+  EXPECT_TRUE(site_instance2->GetSiteInfo().is_sandboxed());
+}
+
+// Check that two same-site sandboxed iframes in unrelated windows share the
+// same process due to subframe process reuse.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxProcessReuse) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, same-origin.
+  std::string js_str = base::StringPrintf(
+      "var frame = document.createElement('iframe'); "
+      "frame.sandbox = ''; "
+      "frame.src = '%s'; "
+      "document.body.appendChild(frame);",
+      child_url.spec().c_str());
+  EXPECT_TRUE(ExecJs(shell(), js_str));
+  ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+
+  // Set up an unrelated window with the same frame hierarchy.
+  Shell* new_shell = CreateBrowser();
+  EXPECT_TRUE(NavigateToURL(new_shell, main_url));
+  FrameTreeNode* new_root =
+      static_cast<WebContentsImpl*>(new_shell->web_contents())
+          ->GetPrimaryFrameTree()
+          .root();
+  EXPECT_TRUE(ExecJs(new_shell, js_str));
+  ASSERT_TRUE(WaitForLoadStop(new_shell->web_contents()));
+  FrameTreeNode* new_child = new_root->child_at(0);
+  EXPECT_TRUE(new_child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(new_root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+
+  // Check that the two sandboxed subframes end up in separate
+  // BrowsingInstances but in the same process.
+  EXPECT_FALSE(
+      new_child->current_frame_host()->GetSiteInstance()->IsRelatedSiteInstance(
+          child->current_frame_host()->GetSiteInstance()));
+  EXPECT_EQ(new_child->current_frame_host()->GetProcess(),
+            child->current_frame_host()->GetProcess());
+}
+
+// A test to verify that when an iframe has two sibling subframes, each with a
+// fully-restrictive sandbox, that each of the three gets its own process
+// even though they are all same-origin.
+// Note: using "sandbox = ''" in this and the following tests creates fully
+// restricted sandboxes, which will include the kOrigin case we are interested
+// in.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       IsolatedSandboxSiblingSubframes) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame1 = document.createElement('iframe'); "
+        "frame1.sandbox = ''; "
+        "frame1.src = '%s'; "
+        "document.body.appendChild(frame1); "
+        "var frame2 = document.createElement('iframe'); "
+        "frame2.sandbox = ''; "
+        "frame2.src = '%s'; "
+        "document.body.appendChild(frame2);",
+        child_url.spec().c_str(), child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check frame-tree.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(2U, root->child_count());
+  FrameTreeNode* child1 = root->child_at(0);
+  FrameTreeNode* child2 = root->child_at(1);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child1->effective_frame_policy().sandbox_flags);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child2->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child1->current_frame_host()->GetSiteInstance());
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child2->current_frame_host()->GetSiteInstance());
+  // Because the siblings are same-site to each other (in fact, same origin) we
+  // expect them to share a process when sandboxed.
+  EXPECT_EQ(child1->current_frame_host()->GetSiteInstance(),
+            child2->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child1->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_TRUE(child2->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       IsolatedSandboxSrcdocSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, with srcdoc content.
+  std::string child_inner_text("srcdoc sandboxed subframe");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.srcdoc = '%s'; "
+        "document.body.appendChild(frame);",
+        child_inner_text.c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  // Verify that the child has only the 'allow-scripts' permission set.
+  EXPECT_EQ(child->effective_frame_policy().sandbox_flags,
+            network::mojom::WebSandboxFlags::kAll &
+                ~network::mojom::WebSandboxFlags::kScripts &
+                ~network::mojom::WebSandboxFlags::kAutomaticFeatures);
+  EXPECT_EQ(std::string(url::kAboutSrcdocURL),
+            child->current_frame_host()->GetLastCommittedURL());
+  EXPECT_TRUE(child->current_frame_host()->GetLastCommittedOrigin().opaque());
+  // Verify that the child's precursor origin matches 'a.com'. Note: we create
+  // the expected value using `main_url` so that the test server port will be
+  // correctly matched.
+  EXPECT_EQ(url::SchemeHostPort(main_url),
+            child->current_origin().GetTupleOrPrecursorTupleIfOpaque());
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+  {
+    std::string js_str("document.body.innerText;");
+    EXPECT_EQ(child_inner_text, EvalJs(child->current_frame_host(), js_str));
+  }
+}
+
+// A test to make sure that about:blank in a sandboxed iframe doesn't get
+// process isolation. If it did, it would be impossible for the parent to inject
+// any content, and it would be stuck as empty content.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       NotIsolatedSandboxAboutBlankSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, with about:blank content.
+  {
+    std::string js_str(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'child_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = 'about:blank'; "
+        "document.body.appendChild(frame);");
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  // Verify that the child has no permissions set.
+  EXPECT_EQ(child->effective_frame_policy().sandbox_flags,
+            network::mojom::WebSandboxFlags::kAll);
+  EXPECT_EQ(GURL(url::kAboutBlankURL),
+            child->current_frame_host()->GetLastCommittedURL());
+  EXPECT_TRUE(child->current_frame_host()->GetLastCommittedOrigin().opaque());
+  // Verify that the child's precursor origin matches 'a.com'. Note: we create
+  // the expected value using `main_url` so that the test server port will be
+  // correctly matched.
+  EXPECT_EQ(url::SchemeHostPort(main_url),
+            child->current_origin().GetTupleOrPrecursorTupleIfOpaque());
+  // The child needs to be in the parent's SiteInstance.
+  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+
+  // Navigate to a page that should get process isolation.
+  GURL isolated_child_url(
+      embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateFrameToURL(child, isolated_child_url));
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+
+  // Navigate back to about:blank, and verify it's put back into the parent's
+  // SiteInstance.
+  scoped_refptr<SiteInstanceImpl> child_previous_site_instance =
+      child->current_frame_host()->GetSiteInstance();
+  EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "child_frame",
+                                  GURL("about:blank")));
+  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_NE(child_previous_site_instance,
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_FALSE(child->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+// Test to make sure that javascript: urls don't execute in a sandboxed iframe.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxedIframeWithJSUrl) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame with a javascript: URL.
+  std::string js_url_str("javascript:\"foo\"");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        js_url_str.c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Verify parent and child frames share a SiteInstance. A sandboxed iframe
+  // with a javascript: url shouldn't get its own process.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+
+  // Verify that the javascript: url did not execute. This is expected
+  // regardless of IsolatedSandboxedIframes since sandboxed iframes get opaque
+  // origins, and javascript: urls don't execute in opaque origins.
+  EXPECT_TRUE(
+      EvalJs(child->current_frame_host(), "document.body.innerHTML == ''")
+          .ExtractBool());
+}
+
+// Test to make sure that an iframe with a data:url is process isolated.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxedIframeWithDataURLIsIsolated) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame with a data URL.
+  std::string data_url_str("data:text/html,dataurl");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        data_url_str.c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Verify parent and child frames don't share a SiteInstance
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
+// Test to make sure that an iframe with a data:url is appropriately sandboxed.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxedIframeWithDataURL) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create non-sandboxed child frame with a data URL.
+  std::string data_url_str("data:text/html,dataurl");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        data_url_str.c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Verify parent and child frames share a SiteInstance
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+
+  // Now make subframe sandboxed.
+  {
+    std::string js_str(
+        "var frame = document.getElementById('test_frame'); "
+        "frame.sandbox = ''; ");
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+  }
+  NavigateFrameToURL(child,
+                     embedded_test_server()->GetURL("b.com", "/title1.html"));
+  // Child should now be in a different SiteInstance.
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+
+  // Go back and ensure the data: URL committed in the same SiteInstance as the
+  // original navigation.
+  EXPECT_TRUE(web_contents()->GetController().CanGoBack());
+  {
+    TestFrameNavigationObserver frame_observer(child);
+    web_contents()->GetController().GoBack();
+    frame_observer.WaitForCommit();
+  }
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_EQ(GURL(data_url_str),
+            child->current_frame_host()->GetLastCommittedURL());
+}
+
+// Test to make sure that a sandboxed child iframe with a data url and a
+// sandboxed parent end up in the same SiteInstance.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxedParentWithSandboxedChildWithDataURL) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  std::string parent_url_str = main_url.spec();
+  std::string data_url_str("data:text/html,dataurl");
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Allow "parent" to have the allow-scripts permissions so it can create
+  // a child.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        parent_url_str.c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+
+  // Give the grandchild the allow-scripts permissions so it matches the child.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        data_url_str.c_str());
+    EXPECT_TRUE(ExecJs(child->current_frame_host(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+  ASSERT_EQ(1U, child->child_count());
+  FrameTreeNode* grandchild = child->child_at(0);
+  EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
+            grandchild->current_frame_host()->GetSiteInstance());
+  EXPECT_EQ(GURL(data_url_str),
+            grandchild->current_frame_host()->GetLastCommittedURL());
+}
+
+// Test to make sure that a sandboxed iframe with a (not-explicitly) sandboxed
+// subframe ends up in the same SiteInstance/process as its subframe.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       IsolatedSandboxWithNonSandboxedSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(
+      embedded_test_server()->GetURL("a.com", "/page_with_iframe.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Check child vs. parent.
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            child->effective_frame_policy().sandbox_flags);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+
+  // Check grandchild vs. child.
+  ASSERT_EQ(1U, child->child_count());
+  FrameTreeNode* grand_child = child->child_at(0);
+  EXPECT_EQ(network::mojom::WebSandboxFlags::kAll,
+            grand_child->effective_frame_policy().sandbox_flags);
+  EXPECT_EQ(child->current_frame_host()->GetSiteInstance(),
+            grand_child->current_frame_host()->GetSiteInstance());
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         SitePerProcessIsolatedSandboxedIframeTest,
+                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
+INSTANTIATE_TEST_SUITE_P(All,
+                         SitePerProcessNotIsolatedSandboxedIframeTest,
+                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
+INSTANTIATE_TEST_SUITE_P(All,
+                         SitePerProcessPerOriginIsolatedSandboxedIframeTest,
+                         testing::ValuesIn(RenderDocumentFeatureLevelValues()));
+
+}  // namespace content
diff --git a/content/browser/site_per_process_unload_browsertest.cc b/content/browser/site_per_process_unload_browsertest.cc
index 2268324e..70b3e69 100644
--- a/content/browser/site_per_process_unload_browsertest.cc
+++ b/content/browser/site_per_process_unload_browsertest.cc
@@ -1349,7 +1349,7 @@
   RenderFrameHostImpl* A1 = web_contents()->GetPrimaryMainFrame();
   RenderFrameHostImpl* B1 = A1->child_at(0)->current_frame_host();
 
-  A1->DoNotDeleteForTesting();
+  B1->DoNotDeleteForTesting();
   RenderFrameDeletedObserver delete_B1(B1);
   shell()->LoadURL(A3_url);
   delete_B1.WaitUntilDeleted();
diff --git a/content/common/user_agent.cc b/content/common/user_agent.cc
index 90815e4b..8745028 100644
--- a/content/common/user_agent.cc
+++ b/content/common/user_agent.cc
@@ -276,20 +276,21 @@
 }
 
 std::string GetReducedUserAgent(bool mobile, std::string major_version) {
-  std::string user_agent;
 #if BUILDFLAG(IS_ANDROID)
+  // There is an extra field in the template on Android.
   std::string device_compat;
   // Note: The extra space after Mobile is meaningful here, to avoid
   // "MobileSafari", but unneeded for non-mobile Android devices.
   device_compat = mobile ? "Mobile " : "";
-  user_agent = base::StringPrintf(frozen_user_agent_strings::kAndroid,
-                                  GetUnifiedPlatform().c_str(),
-                                  major_version.c_str(), device_compat.c_str());
-#else
-  user_agent =
-      base::StringPrintf(frozen_user_agent_strings::kDesktop,
-                         GetUnifiedPlatform().c_str(), major_version.c_str());
 #endif
+  std::string user_agent =
+      base::StringPrintf(frozen_user_agent_strings::kTemplate,
+                         GetUnifiedPlatform().c_str(), major_version.c_str()
+#if BUILDFLAG(IS_ANDROID)
+                                                           ,
+                         device_compat.c_str()
+#endif
+      );
 
   return user_agent;
 }
diff --git a/content/public/browser/network_service_instance.h b/content/public/browser/network_service_instance.h
index b3d296e..e2fee5f 100644
--- a/content/public/browser/network_service_instance.h
+++ b/content/public/browser/network_service_instance.h
@@ -40,7 +40,7 @@
 CONTENT_EXPORT network::mojom::NetworkService* GetNetworkService();
 
 // Only on ChromeOS since it's only used there.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 // Returns the global NetworkChangeNotifier instance.
 CONTENT_EXPORT net::NetworkChangeNotifier* GetNetworkChangeNotifier();
 #endif
diff --git a/content/public/common/user_agent.h b/content/public/common/user_agent.h
index 9bac45d0..bf6f9af 100644
--- a/content/public/common/user_agent.h
+++ b/content/public/common/user_agent.h
@@ -15,15 +15,12 @@
 
 namespace frozen_user_agent_strings {
 
-#if !BUILDFLAG(IS_ANDROID)
-const char kDesktop[] =
+const char kTemplate[] =
     "Mozilla/5.0 (%s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 "
-    "Safari/537.36";
-#else
-const char kAndroid[] =
-    "Mozilla/5.0 (%s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 "
-    "%sSafari/537.36";
+#if BUILDFLAG(IS_ANDROID)
+    "%s"
 #endif
+    "Safari/537.36";
 
 const char kUnifiedPlatformAndroid[] = "Linux; Android 10; K";
 const char kUnifiedPlatformCrOS[] = "X11; CrOS x86_64 14541.0.0";
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 8eeeee017..24571a0 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -105,7 +105,6 @@
 #if BUILDFLAG(IS_ANDROID)
 bool ContentRendererClient::HandleNavigation(
     RenderFrame* render_frame,
-    bool render_view_was_created_by_renderer,
     blink::WebFrame* frame,
     const blink::WebURLRequest& request,
     blink::WebNavigationType type,
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 1dfe162..d1fa110 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -96,7 +96,8 @@
   virtual void RenderFrameCreated(RenderFrame* render_frame) {}
 
   // Notifies that a new WebView has been created.
-  virtual void WebViewCreated(blink::WebView* web_view) {}
+  virtual void WebViewCreated(blink::WebView* web_view,
+                              bool was_created_by_renderer) {}
 
   // Returns the bitmap to show when a plugin crashed, or NULL for none.
   virtual SkBitmap* GetSadPluginBitmap();
@@ -210,7 +211,6 @@
   // Returns true if the navigation was handled by the embedder and should be
   // ignored by WebKit. This method is used by CEF and android_webview.
   virtual bool HandleNavigation(RenderFrame* render_frame,
-                                bool render_view_was_created_by_renderer,
                                 blink::WebFrame* frame,
                                 const blink::WebURLRequest& request,
                                 blink::WebNavigationType type,
diff --git a/content/public/test/content_browser_test.cc b/content/public/test/content_browser_test.cc
index 09e04eb..9684436 100644
--- a/content/public/test/content_browser_test.cc
+++ b/content/public/test/content_browser_test.cc
@@ -34,7 +34,7 @@
 #include "ui/base/ime/init/input_method_initializer.h"
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "content/public/test/network_connection_change_simulator.h"
 #endif
 
@@ -114,7 +114,7 @@
 }
 
 void ContentBrowserTest::PreRunTestOnMainThread() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   NetworkConnectionChangeSimulator network_change_simulator;
   network_change_simulator.InitializeChromeosConnectionType();
 #endif
diff --git a/content/public/test/network_connection_change_simulator.cc b/content/public/test/network_connection_change_simulator.cc
index d22d290..d59eea9 100644
--- a/content/public/test/network_connection_change_simulator.cc
+++ b/content/public/test/network_connection_change_simulator.cc
@@ -16,7 +16,7 @@
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/network_service_test.mojom.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "net/base/network_change_notifier_posix.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #endif
@@ -35,7 +35,7 @@
 NetworkConnectionChangeSimulator::NetworkConnectionChangeSimulator() = default;
 NetworkConnectionChangeSimulator::~NetworkConnectionChangeSimulator() = default;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 void NetworkConnectionChangeSimulator::InitializeChromeosConnectionType() {
   // Manually set the connection type since ChromeOS's NetworkChangeNotifier
   // implementation relies on some other class controlling it (normally
diff --git a/content/public/test/network_connection_change_simulator.h b/content/public/test/network_connection_change_simulator.h
index 92a7eff..fc77f51 100644
--- a/content/public/test/network_connection_change_simulator.h
+++ b/content/public/test/network_connection_change_simulator.h
@@ -27,7 +27,7 @@
 
   ~NetworkConnectionChangeSimulator() override;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // Initializes the ChromeOS network connection type.
   // This should be used in tests that don't have a DBus set up.
   void InitializeChromeosConnectionType();
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index c072fc2..8bc4d1b 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -90,56 +90,6 @@
 }
 #endif
 
-// Helper function that searches in the subtree of |obj| to a max
-// depth of |max_depth| for an image.
-//
-// Returns true on success, or false if it finds more than one image,
-// or any node with a name, or anything deeper than |max_depth|.
-bool SearchForExactlyOneInnerImage(WebAXObject obj,
-                                   WebAXObject* inner_image,
-                                   int max_depth) {
-  DCHECK(inner_image);
-
-  // If it's the first image, set |inner_image|. If we already
-  // found an image, fail.
-  if (ui::IsImage(obj.Role())) {
-    if (!inner_image->IsDetached())
-      return false;
-    *inner_image = obj;
-  } else {
-    // If we found something else with a name, fail.
-    if (!ui::IsPlatformDocument(obj.Role()) && !ui::IsLink(obj.Role())) {
-      blink::WebString web_name = obj.GetName();
-      if (!base::ContainsOnlyChars(web_name.Utf8(), base::kWhitespaceASCII)) {
-        return false;
-      }
-    }
-  }
-
-  // Fail if we recursed to |max_depth| and there's more of a subtree.
-  if (max_depth == 0 && obj.ChildCount())
-    return false;
-
-  // Don't count ignored nodes toward depth.
-  int next_depth = obj.AccessibilityIsIgnored() ? max_depth : max_depth - 1;
-
-  // Recurse.
-  for (unsigned int i = 0; i < obj.ChildCount(); i++) {
-    if (!SearchForExactlyOneInnerImage(obj.ChildAt(i), inner_image, next_depth))
-      return false;
-  }
-
-  return !inner_image->IsDetached();
-}
-
-// Return true if the subtree of |obj|, to a max depth of 3, contains
-// exactly one image. Return that image in |inner_image|.
-bool FindExactlyOneInnerImageInMaxDepthThree(WebAXObject obj,
-                                             WebAXObject* inner_image) {
-  DCHECK(inner_image);
-  return SearchForExactlyOneInnerImage(obj, inner_image, /* max_depth = */ 3);
-}
-
 // Ignore code that limits based on the protocol (like https, file, etc.)
 // to enable tests to run.
 bool g_ignore_protocol_checks_for_testing;
@@ -468,20 +418,6 @@
     return;
   }
 
-  if (ui::IsImage(dst->role))
-    AddImageAnnotations(src, dst);
-
-  // If a link or web area isn't otherwise labeled and contains exactly one
-  // image (searching only to a max depth of 2), and the link doesn't have
-  // accessible text from an attribute like aria-label, then annotate the
-  // link/web area with the image's annotation, too.
-  if ((ui::IsLink(dst->role) || ui::IsPlatformDocument(dst->role)) &&
-      dst->GetNameFrom() != ax::mojom::NameFrom::kAttribute) {
-    WebAXObject inner_image;
-    if (FindExactlyOneInnerImageInMaxDepthThree(src, &inner_image))
-      AddImageAnnotations(inner_image, dst);
-  }
-
   if (dst->id == image_data_node_id_) {
     // In general, string attributes should be truncated using
     // TruncateAndAddStringAttribute, but ImageDataUrl contains a data url
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h
index 6a6d82b..89f2175 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -123,6 +123,8 @@
   // to enable tests to run.
   static void IgnoreProtocolChecksForTesting();
 
+  void AddImageAnnotations(blink::WebAXObject& src, ui::AXNodeData* dst) const;
+
  private:
   const blink::WebDocument& document() const {
     DCHECK(frozen_);
@@ -150,8 +152,6 @@
       const std::string& value,
       uint32_t max_len = kMaxStringAttributeLength) const;
 
-  void AddImageAnnotations(blink::WebAXObject& src, ui::AXNodeData* dst) const;
-
   RenderFrameImpl* render_frame_;
 
   ui::AXMode accessibility_mode_;
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index d170e36..bc4ac8bc 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -490,6 +490,11 @@
   ScheduleSendPendingAccessibilityEvents();
 }
 
+void RenderAccessibilityImpl::AddImageAnnotations(WebAXObject& obj,
+                                                  ui::AXNodeData* dst) {
+  tree_source_->AddImageAnnotations(obj, dst);
+}
+
 void RenderAccessibilityImpl::HandleAXEvent(const ui::AXEvent& event) {
   const WebDocument& document = GetMainDocument();
   if (document.IsNull())
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h
index 7dddbdd5..b117804 100644
--- a/content/renderer/accessibility/render_accessibility_impl.h
+++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -131,6 +131,7 @@
       ax::mojom::Action event_from_action = ax::mojom::Action::kNone,
       std::vector<ui::AXEventIntent> event_intents = {},
       ax::mojom::Event event_type = ax::mojom::Event::kNone);
+  void AddImageAnnotations(blink::WebAXObject&, ui::AXNodeData* dst);
 
   // Returns the main top-level document for this page, or NULL if there's
   // no view or frame.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2f1283f..2e6e5d6 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4523,6 +4523,15 @@
       ->MarkWebAXObjectDirty(obj, subtree, event_from, event_from_action);
 }
 
+void RenderFrameImpl::AddImageAnnotations(blink::WebAXObject& obj,
+                                          ui::AXNodeData* dst) {
+  if (!IsAccessibilityEnabled())
+    return;
+
+  render_accessibility_manager_->GetRenderAccessibilityImpl()
+      ->AddImageAnnotations(obj, dst);
+}
+
 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -5107,15 +5116,12 @@
   DCHECK(!(use_archive && IsMainFrame()));
 
 #if BUILDFLAG(IS_ANDROID)
-  bool render_view_was_created_by_renderer =
-      render_view_->was_created_by_renderer_;
   // The handlenavigation API is deprecated and will be removed once
   // crbug.com/325351 is resolved.
   if (!url.is_empty() && !use_archive && !IsURLHandledByNetworkStack(url) &&
       GetContentClient()->renderer()->HandleNavigation(
-          this, render_view_was_created_by_renderer, frame_, info->url_request,
-          info->navigation_type, info->navigation_policy,
-          false /* is_redirect */)) {
+          this, frame_, info->url_request, info->navigation_type,
+          info->navigation_policy, false /* is_redirect */)) {
     return;
   }
 #endif
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index a409fae..81d84828 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -625,6 +625,7 @@
                             bool subtree,
                             ax::mojom::EventFrom event_from,
                             ax::mojom::Action event_from_action) override;
+  void AddImageAnnotations(blink::WebAXObject&, ui::AXNodeData* dst) override;
   void CheckIfAudioSinkExistsAndIsAuthorized(
       const blink::WebString& sink_id,
       blink::WebSetSinkIdCompleteCallback callback) override;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 913b3647..fd43658 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -165,13 +165,8 @@
   if (params->window_was_opened_by_another_window)
     GetWebView()->SetOpenedByDOM();
 
-  GetContentClient()->renderer()->WebViewCreated(webview_);
-
-#if BUILDFLAG(IS_ANDROID)
-  // TODO(sgurun): crbug.com/325351 Needed only for android webview's deprecated
-  // HandleNavigation codepath.
-  was_created_by_renderer_ = was_created_by_renderer;
-#endif
+  GetContentClient()->renderer()->WebViewCreated(webview_,
+                                                 was_created_by_renderer);
 }
 
 RenderViewImpl::~RenderViewImpl() {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 2f07347..2887102 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -183,13 +183,6 @@
   // The `AgentSchedulingGroup` this view is associated with.
   AgentSchedulingGroup& agent_scheduling_group_;
 
-#if BUILDFLAG(IS_ANDROID)
-  // Android Specific ----------------------------------------------------------
-
-  // Whether this was a renderer-created or browser-created RenderViewImpl.
-  bool was_created_by_renderer_ = false;
-#endif
-
   // ---------------------------------------------------------------------------
   // ADDING NEW DATA? Please see if it fits appropriately in one of the above
   // sections rather than throwing it randomly at the end. If you're adding a
diff --git a/content/services/auction_worklet/seller_worklet.cc b/content/services/auction_worklet/seller_worklet.cc
index 287934b..aa72572 100644
--- a/content/services/auction_worklet/seller_worklet.cc
+++ b/content/services/auction_worklet/seller_worklet.cc
@@ -454,12 +454,8 @@
 
   std::vector<v8::Local<v8::Value>> args;
   if (!v8_helper_->AppendJsonValue(context, ad_metadata_json, &args)) {
-    PostScoreAdCallbackToUserThread(
-        std::move(callback), /*score=*/0,
-        /*component_auction_modified_bid_params=*/nullptr,
-        /*scoring_signals_data_version=*/absl::nullopt,
-        /*debug_loss_report_url=*/absl::nullopt,
-        /*debug_win_report_url=*/absl::nullopt,
+    PostScoreAdCallbackToUserThreadOnError(
+        std::move(callback),
         /*errors=*/std::vector<std::string>());
     return;
   }
@@ -469,12 +465,8 @@
   if (!AppendAuctionConfig(v8_helper_.get(), context, decision_logic_url_,
                            trusted_scoring_signals_url_, experiment_group_id_,
                            auction_ad_config_non_shared_params, &args)) {
-    PostScoreAdCallbackToUserThread(
-        std::move(callback), /*score=*/0,
-        /*component_auction_modified_bid_params=*/nullptr,
-        /*scoring_signals_data_version=*/absl::nullopt,
-        /*debug_loss_report_url=*/absl::nullopt,
-        /*debug_win_report_url=*/absl::nullopt,
+    PostScoreAdCallbackToUserThreadOnError(
+        std::move(callback),
         /*errors=*/std::vector<std::string>());
     return;
   }
@@ -507,24 +499,16 @@
       (scoring_signals_data_version.has_value() &&
        !browser_signals_dict.Set("dataVersion",
                                  scoring_signals_data_version.value()))) {
-    PostScoreAdCallbackToUserThread(
-        std::move(callback), /*score=*/0,
-        /*component_auction_modified_bid_params=*/nullptr,
-        /*scoring_signals_data_version=*/absl::nullopt,
-        /*debug_loss_report_url=*/absl::nullopt,
-        /*debug_win_report_url=*/absl::nullopt,
+    PostScoreAdCallbackToUserThreadOnError(
+        std::move(callback),
         /*errors=*/std::vector<std::string>());
     return;
   }
   if (!browser_signal_ad_components.empty()) {
     if (!browser_signals_dict.Set("adComponents",
                                   browser_signal_ad_components)) {
-      PostScoreAdCallbackToUserThread(
-          std::move(callback), /*score=*/0,
-          /*component_auction_modified_bid_params=*/nullptr,
-          /*scoring_signals_data_version=*/absl::nullopt,
-          /*debug_loss_report_url=*/absl::nullopt,
-          /*debug_win_report_url=*/absl::nullopt,
+      PostScoreAdCallbackToUserThreadOnError(
+          std::move(callback),
           /*errors=*/std::vector<std::string>());
       return;
     }
@@ -570,12 +554,8 @@
       errors_out.push_back(
           base::StrCat({decision_logic_url_.spec(),
                         " scoreAd() did not return an object or a number."}));
-      PostScoreAdCallbackToUserThread(
-          std::move(callback), /*score=*/0,
-          /*component_auction_modified_bid_params=*/nullptr,
-          /*scoring_signals_data_version=*/absl::nullopt,
-          /*debug_loss_report_url=*/absl::nullopt,
-          /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
+      PostScoreAdCallbackToUserThreadOnError(std::move(callback),
+                                             std::move(errors_out));
       return;
     }
 
@@ -585,12 +565,8 @@
       errors_out.push_back(
           base::StrCat({decision_logic_url_.spec(),
                         " scoreAd() return value has incorrect structure."}));
-      PostScoreAdCallbackToUserThread(
-          std::move(callback), /*score=*/0,
-          /*component_auction_modified_bid_params=*/nullptr,
-          /*scoring_signals_data_version=*/absl::nullopt,
-          /*debug_loss_report_url=*/absl::nullopt,
-          /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
+      PostScoreAdCallbackToUserThreadOnError(std::move(callback),
+                                             std::move(errors_out));
       return;
     }
 
@@ -614,26 +590,9 @@
         component_auction_modified_bid_params->ad = "null";
       }
 
+      component_auction_modified_bid_params->bid = 0;
       component_auction_modified_bid_params->has_bid =
           result_dict.Get("bid", &component_auction_modified_bid_params->bid);
-      if (component_auction_modified_bid_params->has_bid) {
-        // Fail if the new bid is not valid or is 0 or less.
-        if (!std::isfinite(component_auction_modified_bid_params->bid) ||
-            component_auction_modified_bid_params->bid <= 0.0) {
-          errors_out.push_back(
-              base::StrCat({decision_logic_url_.spec(),
-                            " scoreAd() returned an invalid bid."}));
-          PostScoreAdCallbackToUserThread(
-              std::move(callback), /*score=*/0,
-              /*component_auction_modified_bid_params=*/nullptr,
-              /*scoring_signals_data_version=*/absl::nullopt,
-              /*debug_loss_report_url=*/absl::nullopt,
-              /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
-          return;
-        }
-      } else {
-        component_auction_modified_bid_params->bid = 0;
-      }
     }
   }
 
@@ -645,12 +604,8 @@
         {decision_logic_url_.spec(),
          " scoreAd() return value does not have allowComponentAuction set to "
          "true. Ad dropped from component auction."}));
-    PostScoreAdCallbackToUserThread(
-        std::move(callback), /*score=*/0,
-        /*component_auction_modified_bid_params=*/nullptr,
-        /*scoring_signals_data_version=*/absl::nullopt,
-        /*debug_loss_report_url=*/absl::nullopt,
-        /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
+    PostScoreAdCallbackToUserThreadOnError(std::move(callback),
+                                           std::move(errors_out));
     return;
   }
 
@@ -658,12 +613,8 @@
   if (std::isnan(score) || !std::isfinite(score)) {
     errors_out.push_back(base::StrCat(
         {decision_logic_url_.spec(), " scoreAd() returned an invalid score."}));
-    PostScoreAdCallbackToUserThread(
-        std::move(callback), /*score=*/0,
-        /*component_auction_modified_bid_params=*/nullptr,
-        /*scoring_signals_data_version=*/absl::nullopt,
-        /*debug_loss_report_url=*/absl::nullopt,
-        /*debug_win_report_url=*/absl::nullopt, std::move(errors_out));
+    PostScoreAdCallbackToUserThreadOnError(std::move(callback),
+                                           std::move(errors_out));
     return;
   }
 
@@ -680,6 +631,22 @@
     return;
   }
 
+  // If this is a component auction that modified the bid, validate the bid. Do
+  // this after checking the score to avoid validating modified bid values from
+  // reporting errors when desirability is <= 0.
+  if (component_auction_modified_bid_params &&
+      component_auction_modified_bid_params->has_bid) {
+    // Fail if the new bid is not valid or is 0 or less.
+    if (!std::isfinite(component_auction_modified_bid_params->bid) ||
+        component_auction_modified_bid_params->bid <= 0.0) {
+      errors_out.push_back(base::StrCat(
+          {decision_logic_url_.spec(), " scoreAd() returned an invalid bid."}));
+      PostScoreAdCallbackToUserThreadOnError(std::move(callback),
+                                             std::move(errors_out));
+      return;
+    }
+  }
+
   PostScoreAdCallbackToUserThread(
       std::move(callback), score,
       std::move(component_auction_modified_bid_params),
@@ -841,6 +808,17 @@
                         base::BindOnce(&SellerWorklet::ResumeIfPaused, parent));
 }
 
+void SellerWorklet::V8State::PostScoreAdCallbackToUserThreadOnError(
+    ScoreAdCallbackInternal callback,
+    std::vector<std::string> errors) {
+  PostScoreAdCallbackToUserThread(
+      std::move(callback), /*score=*/0,
+      /*component_auction_modified_bid_params=*/nullptr,
+      /*scoring_signals_data_version=*/absl::nullopt,
+      /*debug_loss_report_url=*/absl::nullopt,
+      /*debug_win_report_url=*/absl::nullopt, std::move(errors));
+}
+
 void SellerWorklet::V8State::PostScoreAdCallbackToUserThread(
     ScoreAdCallbackInternal callback,
     double score,
diff --git a/content/services/auction_worklet/seller_worklet.h b/content/services/auction_worklet/seller_worklet.h
index 6194cfc..87c04d5 100644
--- a/content/services/auction_worklet/seller_worklet.h
+++ b/content/services/auction_worklet/seller_worklet.h
@@ -245,6 +245,13 @@
 
     void FinishInit();
 
+    // Calls `PostScoreAdCallbackToUserThread`, passing in a 0 score and null
+    // for all other values. Used on errors, which cause us to drop win/loss
+    // report URLs, even if the methods to set them have been invoked.
+    void PostScoreAdCallbackToUserThreadOnError(
+        ScoreAdCallbackInternal callback,
+        std::vector<std::string> errors);
+
     void PostScoreAdCallbackToUserThread(
         ScoreAdCallbackInternal callback,
         double score,
diff --git a/content/services/auction_worklet/seller_worklet_unittest.cc b/content/services/auction_worklet/seller_worklet_unittest.cc
index e99e5e5..78077162 100644
--- a/content/services/auction_worklet/seller_worklet_unittest.cc
+++ b/content/services/auction_worklet/seller_worklet_unittest.cc
@@ -733,13 +733,14 @@
       "{desirability:1, allowComponentAuction:[32]}", 1,
       /*expected_errors=*/{},
       kExpectedComponentAuctionModifiedBidParams.Clone());
-  // Error for not allowing participation in component auctions takes precedence
-  // over error for not having `ad` field.
+  // Even with a desirability of 0, a false `allowComponentAuction` value is
+  // considered an error.
+  RunScoreAdWithReturnValueExpectingResult(
+      "{desirability:0, allowComponentAuction:false}", 0,
+      kExpectedErrorsOnFailure);
+  // A missing `allowComponentAuction` field is treated as if it were "false".
   RunScoreAdWithReturnValueExpectingResult("{desirability:1}", 0,
                                            kExpectedErrorsOnFailure);
-  RunScoreAdWithReturnValueExpectingResult(
-      "{desirability:1, allowComponentAuction:false}", 0,
-      kExpectedErrorsOnFailure);
 
   // With a component seller in `browser_signals_other_seller_`, an object must
   // be returned, and `allowComponentAuction` must be true.
@@ -858,6 +859,10 @@
 
   // Invalid bids result in errors.
   RunScoreAdWithReturnValueExpectingResult(
+      R"({ad:null, desirability:1, allowComponentAuction:true, bid:0})", 0,
+      /*expected_errors=*/
+      {"https://url.test/ scoreAd() returned an invalid bid."});
+  RunScoreAdWithReturnValueExpectingResult(
       R"({ad:null, desirability:1, allowComponentAuction:true, bid:-1})", 0,
       /*expected_errors=*/
       {"https://url.test/ scoreAd() returned an invalid bid."});
@@ -873,6 +878,11 @@
       "{ad:null, desirability:1, allowComponentAuction:true, bid:0/0}", 0,
       /*expected_errors=*/
       {"https://url.test/ scoreAd() returned an invalid bid."});
+
+  // A 0 bid is normally considered invalid, unless desirability is 0, in which
+  // case it is ignored.
+  RunScoreAdWithReturnValueExpectingResult(
+      "{ad:null, desirability:0, allowComponentAuction:true, bid:0}", 0);
 }
 
 TEST_F(SellerWorkletTest, ScoreAdDateNotAvailable) {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 83254bf..cbdf06c2 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1419,6 +1419,7 @@
     "../browser/site_per_process_hit_test_browsertest.cc",
     "../browser/site_per_process_layout_browsertest.cc",
     "../browser/site_per_process_mixed_content_browsertest.cc",
+    "../browser/site_per_process_oopsif_browsertest.cc",
     "../browser/site_per_process_sad_frame_browsertest.cc",
     "../browser/site_per_process_scroll_browsertest.cc",
     "../browser/site_per_process_unload_browsertest.cc",
@@ -2057,6 +2058,7 @@
     "../browser/accessibility/one_shot_accessibility_tree_search_unittest.cc",
     "../browser/accessibility/touch_passthrough_manager_unittest.cc",
     "../browser/aggregation_service/aggregatable_report_assembler_unittest.cc",
+    "../browser/aggregation_service/aggregatable_report_scheduler_unittest.cc",
     "../browser/aggregation_service/aggregatable_report_sender_unittest.cc",
     "../browser/aggregation_service/aggregatable_report_unittest.cc",
     "../browser/aggregation_service/aggregation_service_impl_unittest.cc",
diff --git a/content/test/data/gpu/pixel_video_from_canvas.js b/content/test/data/gpu/pixel_video_from_canvas.js
new file mode 100644
index 0000000..374da23
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_from_canvas.js
@@ -0,0 +1,137 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function logOutput(s) {
+  if (window.domAutomationController)
+    window.domAutomationController.log(s);
+  else
+    console.log(s);
+}
+
+function fourColorsFrame(ctx) {
+  const width = ctx.canvas.width;
+  const height = ctx.canvas.height;
+  const kYellow = '#FFFF00';
+  const kRed = '#FF0000';
+  const kBlue = '#0000FF';
+  const kGreen = '#00FF00';
+
+  ctx.fillStyle = kYellow;
+  ctx.fillRect(0, 0, width / 2, height / 2);
+
+  ctx.fillStyle = kRed;
+  ctx.fillRect(width / 2, 0, width / 2, height / 2);
+
+  ctx.fillStyle = kBlue;
+  ctx.fillRect(0, height / 2, width / 2, height / 2);
+
+  ctx.fillStyle = kGreen;
+  ctx.fillRect(width / 2, height / 2, width / 2, height / 2);
+}
+
+function waitForNextFrame() {
+  return new Promise((resolve, _) => {
+    window.requestAnimationFrame(resolve);
+  });
+}
+
+function initGL(gl) {
+  const fragment_shader = `
+      void main(void) {
+        gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
+      }
+  `;
+  const vertex_shader = `
+      attribute vec3 c;
+      void main(void) {
+        gl_Position = vec4(c, 1.0);
+      }
+  `;
+
+  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+
+  const vs = gl.createShader(gl.VERTEX_SHADER);
+  gl.shaderSource(vs, vertex_shader);
+  gl.compileShader(vs);
+
+  const fs = gl.createShader(gl.FRAGMENT_SHADER);
+  gl.shaderSource(fs, fragment_shader);
+  gl.compileShader(fs);
+
+  gl.getShaderParameter(fs, gl.COMPILE_STATUS);
+
+  const program = gl.createProgram();
+  gl.attachShader(program, vs);
+  gl.attachShader(program, fs);
+  gl.linkProgram(program);
+  gl.useProgram(program);
+
+  const vb = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vb);
+  gl.bufferData(
+      gl.ARRAY_BUFFER, new Float32Array([
+        -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0,
+        0.0, 0.0, 1.0, -1.0, 0.0
+      ]),
+      gl.STATIC_DRAW);
+
+  const coordLoc = gl.getAttribLocation(program, 'c');
+  gl.vertexAttribPointer(coordLoc, 3, gl.FLOAT, false, 0, 0);
+  gl.enableVertexAttribArray(coordLoc);
+}
+
+function triangleOnFrame(gl) {
+  gl.clearColor(0.0, 0.0, 1, 1);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.drawArrays(gl.TRIANGLE_FAN, 0, 6);
+  gl.finish();
+}
+
+function setupFrameCallback(video) {
+  logOutput(`Expecting frames now`);
+  let vf_counter = 5;
+  function videoFrameCallback(now, md) {
+    logOutput(`Got a video frame: ${now}`);
+    if (vf_counter > 0) {
+      vf_counter--;
+      video.requestVideoFrameCallback(videoFrameCallback);
+      return;
+    }
+
+    logOutput('Test complete.');
+    domAutomationController.send('SUCCESS');
+  }
+  video.requestVideoFrameCallback(videoFrameCallback);
+}
+
+async function runTest(context_type, alpha) {
+  const canvas = document.getElementById('cnv');
+  const video = document.getElementById('vid');
+  const ctx = canvas.getContext(context_type, {alpha: alpha});
+  const fps = 60;
+
+  let draw = null;
+  if (context_type == 'webgl2') {
+    initGL(ctx);
+    draw = triangleOnFrame;
+  } else {
+    draw = fourColorsFrame;
+  }
+
+  draw(ctx);
+  let stream = canvas.captureStream(fps);
+  video.srcObject = stream;
+  video.onerror = e => {
+    logOutput(`Test failed: ${e.message}`);
+    domAutomationController.send('FAIL');
+  };
+  setupFrameCallback(video);
+  video.play();
+
+  while (true) {
+    await waitForNextFrame();
+    draw(ctx);
+  }
+}
diff --git a/content/test/data/gpu/pixel_video_from_canvas_2d.html b/content/test/data/gpu/pixel_video_from_canvas_2d.html
new file mode 100644
index 0000000..34de70d
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_from_canvas_2d.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta name="viewport" content="initial-scale=1">
+<script src="pixel_video_from_canvas.js"></script>
+<script>
+function main() {
+  runTest("2d", false);
+}
+</script>
+<body onload="main()">
+<canvas id='cnv' width='100' height='100'></canvas>
+<video id='vid'></video>
+</body>
\ No newline at end of file
diff --git a/content/test/data/gpu/pixel_video_from_canvas_2d_alpha.html b/content/test/data/gpu/pixel_video_from_canvas_2d_alpha.html
new file mode 100644
index 0000000..8aa02e84
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_from_canvas_2d_alpha.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta name="viewport" content="initial-scale=1">
+<script src="pixel_video_from_canvas.js"></script>
+<script>
+function main() {
+  runTest("2d", true);
+}
+</script>
+<body onload="main()">
+<canvas id='cnv' width='100' height='100'></canvas>
+<video id='vid'></video>
+</body>
\ No newline at end of file
diff --git a/content/test/data/gpu/pixel_video_from_canvas_webgl2.html b/content/test/data/gpu/pixel_video_from_canvas_webgl2.html
new file mode 100644
index 0000000..55be062
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_from_canvas_webgl2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta name="viewport" content="initial-scale=1">
+<script src="pixel_video_from_canvas.js"></script>
+<script>
+function main() {
+  runTest("webgl2", false);
+}
+</script>
+<body onload="main()">
+<canvas id='cnv' width='100' height='100'></canvas>
+<video id='vid'></video>
+</body>
\ No newline at end of file
diff --git a/content/test/data/gpu/pixel_video_from_canvas_webgl2_alpha.html b/content/test/data/gpu/pixel_video_from_canvas_webgl2_alpha.html
new file mode 100644
index 0000000..a9cd4d3
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_from_canvas_webgl2_alpha.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta name="viewport" content="initial-scale=1">
+<script src="pixel_video_from_canvas.js"></script>
+<script>
+function main() {
+  runTest("webgl2", true);
+}
+</script>
+<body onload="main()">
+<canvas id='cnv' width='100' height='100'></canvas>
+<video id='vid'></video>
+</body>
\ No newline at end of file
diff --git a/content/test/data/gpu/pixel_webgpu_canvas_capture_to_video.html b/content/test/data/gpu/pixel_webgpu_canvas_capture_to_video.html
new file mode 100644
index 0000000..3ddd1bcf
--- /dev/null
+++ b/content/test/data/gpu/pixel_webgpu_canvas_capture_to_video.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>WebGPU canvas' capture as video stream test</title>
+  <style type="text/css">
+    .nomargin {
+      margin: 0px auto;
+    }
+  </style>
+  <script type="text/javascript" src="pixel_webgpu_util.js"></script>
+  <script type="text/javascript">
+    var g_swapsBeforeAck = 15;
+
+    async function main() {
+      loadWebrtc();
+
+      const gpuCanvas = document.getElementById('canvas_gpu');
+      const [device, swapChain] = await webGpuUtils.init(gpuCanvas);
+      if (!device || !swapChain) {
+        console.error("Failed to initialize WebGPU - skipping test");
+        domAutomationController.send("FAILURE");
+        return;
+      }
+
+      function render() {
+        const gpuContext = gpuCanvas.getContext('webgpu');
+
+        webGpuUtils.fourColorsTest(device, swapChain, gpuCanvas.width,
+          gpuCanvas.height);
+
+        waitForFinish();
+      }
+
+      function waitForFinish() {
+        if (g_swapsBeforeAck == 0) {
+          domAutomationController.send("SUCCESS");
+        } else {
+          g_swapsBeforeAck--;
+          window.requestAnimationFrame(render);
+        }
+      }
+
+      window.requestAnimationFrame(render);
+    }
+
+    function loadWebrtc() {
+      const gpuCanvas = document.getElementById('canvas_gpu');
+      const video = document.getElementById('video_player');
+
+      const stream = gpuCanvas.captureStream();
+
+      const servers = null;
+      var pc1 = new RTCPeerConnection(servers);
+      pc1.onicecandidate = e => onIceCandidate(pc1, e);
+      var pc2 = new RTCPeerConnection(servers);
+      pc2.onicecandidate = e => onIceCandidate(pc2, e);
+
+      pc1.oniceconnectionstatechange = e => onIceStateChange(pc1, e);
+      pc2.oniceconnectionstatechange = e => onIceStateChange(pc2, e);
+      pc2.ontrack = gotRemoteStream;
+
+      stream.getTracks().forEach(
+        track => {
+          pc1.addTrack(
+            track,
+            stream
+          );
+        }
+      );
+
+      pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError);
+
+      function onCreateSessionDescriptionError(error) {
+        console.error(`Failed to create session description: ${error.toString()}`);
+      }
+
+      function onCreateOfferSuccess(desc) {
+        pc1.setLocalDescription(desc, () => onSetLocalSuccess(pc1), onSetSessionDescriptionError);
+        pc2.setRemoteDescription(desc, () => onSetRemoteSuccess(pc2), onSetSessionDescriptionError);
+        pc2.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
+      }
+
+      function onSetLocalSuccess(pc) {
+      }
+
+      function onSetRemoteSuccess(pc) {
+      }
+
+      function onSetSessionDescriptionError(error) {
+        console.error(`Failed to set session description: ${error.toString()}`);
+      }
+
+      function gotRemoteStream(e) {
+        if (video.srcObject !== e.streams[0]) {
+          video.srcObject = e.streams[0];
+        }
+      }
+
+      function onCreateAnswerSuccess(desc) {
+        pc2.setLocalDescription(desc, () => onSetLocalSuccess(pc2), onSetSessionDescriptionError);
+        pc1.setRemoteDescription(desc, () => onSetRemoteSuccess(pc1), onSetSessionDescriptionError);
+      }
+
+      function onIceCandidate(pc, event) {
+        getOtherPc(pc).addIceCandidate(event.candidate)
+          .then(
+            () => onAddIceCandidateSuccess(pc),
+            err => onAddIceCandidateError(pc, err)
+          );
+      }
+
+      function onAddIceCandidateSuccess(pc) {
+      }
+
+      function onAddIceCandidateError(pc, error) {
+        console.error(`${getName(pc)} failed to add ICE Candidate: ${error.toString()}`);
+      }
+
+      function onIceStateChange(pc, event) {
+      }
+
+      function getName(pc) {
+        return (pc === pc1) ? 'pc1' : 'pc2';
+      }
+
+      function getOtherPc(pc) {
+        return (pc === pc1) ? pc2 : pc1;
+      }
+    }
+  </script>
+</head>
+
+<body onload="main()">
+  <video id="video_player" playsinline autoplay muted width="200" height="200" class="nomargin"></video>
+  <canvas id="canvas_gpu" width="200" height="200" class="nomargin"></canvas>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/pixel_integration_test.py b/content/test/gpu/gpu_tests/pixel_integration_test.py
index 011db874..1abef0e0 100644
--- a/content/test/gpu/gpu_tests/pixel_integration_test.py
+++ b/content/test/gpu/gpu_tests/pixel_integration_test.py
@@ -77,7 +77,9 @@
     pages += namespace.ExperimentalCanvasFeaturesPages(cls.test_base_name)
     pages += namespace.LowLatencyPages(cls.test_base_name)
     pages += namespace.WebGPUPages(cls.test_base_name)
+    pages += namespace.WebGPUCanvasCapturePages(cls.test_base_name)
     pages += namespace.PaintWorkletPages(cls.test_base_name)
+    pages += namespace.VideoFromCanvasPages(cls.test_base_name)
     # pages += namespace.NoGpuProcessPages(cls.test_base_name)
     # The following pages should run only on platforms where SwiftShader is
     # enabled. They are skipped on other platforms through test expectations.
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index a6419bd..6ea139d1 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -11,6 +11,8 @@
 import os
 import typing
 
+from datetime import date
+
 from enum import Enum
 
 from gpu_tests import common_browser_args as cba
@@ -39,6 +41,13 @@
     edge_threshold=0,
     ignored_border_thickness=1)
 
+# The optimizer script spat out pretty similar values for most MP4 tests, so
+# combine into a single set of parameters.
+GENERAL_MP4_ALGO = algo.SobelMatchingAlgorithm(max_different_pixels=56300,
+                                               pixel_delta_threshold=35,
+                                               edge_threshold=80,
+                                               ignored_border_thickness=1)
+
 BrowserArgType = typing.List[str]
 
 
@@ -151,13 +160,6 @@
     sw_compositing_args = [cba.DISABLE_GPU_COMPOSITING]
     browser_args_DXVA = [cba.DISABLE_FEATURES_D3D11_VIDEO_DECODER]
 
-    # The optimizer script spat out pretty similar values for most MP4 tests, so
-    # combine into a single set of parameters.
-    general_mp4_algo = algo.SobelMatchingAlgorithm(max_different_pixels=56300,
-                                                   pixel_delta_threshold=35,
-                                                   edge_threshold=80,
-                                                   ignored_border_thickness=1)
-
     return [
         PixelTestPage('pixel_background_image.html',
                       base_name + '_BackgroundImage',
@@ -216,7 +218,7 @@
             # Most images are actually very similar, but Pixel 2
             # tends to produce images with all colors shifted by a
             # small amount.
-            matching_algorithm=general_mp4_algo),
+            matching_algorithm=GENERAL_MP4_ALGO),
         # Surprisingly stable, does not appear to require inexact matching.
         PixelTestPage('pixel_video_mp4.html?width=240&height=135&use_timer=1',
                       base_name + '_Video_MP4_DXVA',
@@ -237,19 +239,19 @@
             '?width=270&height=240&use_timer=1',
             base_name + '_Video_MP4_FourColors_Rot_90',
             test_rect=[0, 0, 270, 240],
-            matching_algorithm=general_mp4_algo),
+            matching_algorithm=GENERAL_MP4_ALGO),
         PixelTestPage(
             'pixel_video_mp4_four_colors_rot_180.html'
             '?width=240&height=135&use_timer=1',
             base_name + '_Video_MP4_FourColors_Rot_180',
             test_rect=[0, 0, 240, 135],
-            matching_algorithm=general_mp4_algo),
+            matching_algorithm=GENERAL_MP4_ALGO),
         PixelTestPage(
             'pixel_video_mp4_four_colors_rot_270.htm'
             'l?width=270&height=240&use_timer=1',
             base_name + '_Video_MP4_FourColors_Rot_270',
             test_rect=[0, 0, 270, 240],
-            matching_algorithm=general_mp4_algo),
+            matching_algorithm=GENERAL_MP4_ALGO),
         PixelTestPage(
             'pixel_video_mp4_rounded_corner.html'
             '?width=240&height=135&use_timer=1',
@@ -489,6 +491,41 @@
             webgpu_pages_helper(base_name, mode=Mode.WEBGPU_SWIFTSHADER) +
             webgpu_pages_helper(base_name, mode=Mode.VULKAN_SWIFTSHADER))
 
+  @staticmethod
+  def WebGPUCanvasCapturePages(base_name):
+    webgpu_args = [
+        cba.ENABLE_UNSAFE_WEBGPU, cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES
+    ]
+
+    browser_args_canvas_one_copy_capture = webgpu_args + [
+        '--enable-features=OneCopyCanvasCapture'
+    ]
+    other_args_canvas_one_copy_capture = {'one_copy': True}
+
+    browser_args_canvas_disable_one_copy_capture = webgpu_args + [
+        '--disable-features=OneCopyCanvasCapture'
+    ]
+    other_args_canvas_disable_one_copy_capture = {'one_copy': False}
+
+    # Setting grace_period_end to monitor the affects on bots for 2 weeks
+    # without making the bots red unexpectedly.
+    return [
+        PixelTestPage('pixel_webgpu_canvas_capture_to_video.html',
+                      base_name + '_WebGPUCanvasOneCopyCapture',
+                      test_rect=[0, 0, 400, 200],
+                      matching_algorithm=GENERAL_MP4_ALGO,
+                      browser_args=browser_args_canvas_one_copy_capture,
+                      other_args=other_args_canvas_one_copy_capture,
+                      grace_period_end=date(2022, 7, 30)),
+        PixelTestPage('pixel_webgpu_canvas_capture_to_video.html',
+                      base_name + '_WebGPUCanvasDisableOneCopyCapture',
+                      test_rect=[0, 0, 400, 200],
+                      matching_algorithm=GENERAL_MP4_ALGO,
+                      browser_args=browser_args_canvas_disable_one_copy_capture,
+                      other_args=other_args_canvas_disable_one_copy_capture,
+                      grace_period_end=date(2022, 7, 30)),
+    ]
+
 
   # Pages that should be run with GPU rasterization enabled.
   @staticmethod
@@ -1088,6 +1125,47 @@
     ]
 
   @staticmethod
+  def VideoFromCanvasPages(base_name: str) -> typing.List[PixelTestPage]:
+    # Tests for <video> element rendering results of <canvas> capture.
+    # It's important for video conference software.
+
+    # All these tests contain 4 or 8 solid colored rectangles
+    # around 50x100 pixels, this should account for possible antialiasing and
+    # color cenversion during RGB<->YUV conversions.
+    match_algo = algo.FuzzyMatchingAlgorithm(max_different_pixels=3000,
+                                             pixel_delta_threshold=50)
+    return [
+        PixelTestPage('pixel_video_from_canvas_2d.html',
+                      base_name + '_VideoStreamFrom2DCanvas',
+                      test_rect=[0, 0, 200, 200],
+                      browser_args=[],
+                      matching_algorithm=match_algo),
+        PixelTestPage('pixel_video_from_canvas_2d_alpha.html',
+                      base_name + '_VideoStreamFrom2DAlphaCanvas',
+                      test_rect=[0, 0, 200, 200],
+                      browser_args=[],
+                      matching_algorithm=match_algo),
+        PixelTestPage('pixel_video_from_canvas_webgl2_alpha.html',
+                      base_name + '_VideoStreamFromWebGLCanvas',
+                      test_rect=[0, 0, 200, 200],
+                      browser_args=[],
+                      matching_algorithm=match_algo),
+        PixelTestPage('pixel_video_from_canvas_webgl2.html',
+                      base_name + '_VideoStreamFromWebGLAlphaCanvas',
+                      test_rect=[0, 0, 200, 200],
+                      browser_args=[],
+                      matching_algorithm=match_algo),
+
+        # Safeguard against repeating crbug.com/1337101
+        PixelTestPage(
+            'pixel_video_from_canvas_2d_alpha.html',
+            base_name + '_VideoStreamFrom2DAlphaCanvas_DisableOOPRaster',
+            test_rect=[0, 0, 200, 200],
+            browser_args=['--disable-features=CanvasOopRasterization'],
+            matching_algorithm=match_algo),
+    ]
+
+  @staticmethod
   def HdrTestPages(base_name: str) -> typing.List[PixelTestPage]:
     return [
         PixelTestPage(
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index bf2e40f..8bc8c6e 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -219,6 +219,10 @@
 
 crbug.com/1298943 [ chromeos skia-renderer-gl chromeos-board-amd64-generic ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
 
+# WebGPU canvas capture hang on mac ASAN bot (also see crbug.com/1213170)
+crbug.com/1345767 [ mac asan ] Pixel_WebGPUCanvasOneCopyCapture [ Skip ]
+crbug.com/1345767 [ mac asan ] Pixel_WebGPUCanvasDisableOneCopyCapture [ Skip ]
+
 ###################
 # Failures/Flakes #
 ###################
@@ -368,6 +372,9 @@
 crbug.com/1273033 [ android android-pixel-4 ] Pixel_OffscreenCanvasTransferBeforeStyleResize [ Failure ]
 crbug.com/1273033 [ android android-pixel-4 ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Failure ]
 
+# Pixel 4 Flaky Failures - Passthrough and Validating on Chromium
+crbug.com/1346117 [ android android-chromium android-pixel-4 ] Pixel_WebGLPreservedAfterTabSwitch [ RetryOnFailure ]
+
 # Pixel 6 failures.
 crbug.com/1286915 [ android android-pixel-6 ] Pixel_CanvasLowLatencyWebGLAlphaFalse [ Failure ]
 crbug.com/1286919 [ android android-pixel-6 skia-renderer-vulkan android-chromium ] Pixel_Video_MP4 [ Failure ]
@@ -422,6 +429,8 @@
 # Flaking on Linux FYI Release (AMD RX 5500 XT)
 crbug.com/1340081 [ linux release amd-0x7340 ] Pixel_ScissorTestWithPreserveDrawingBuffer [ RetryOnFailure ]
 
+crbug.com/1345777 [ android ] Pixel_VideoStreamFromWebGLAlphaCanvas [ Skip ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index b467564..3cf3a49b 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -125,6 +125,10 @@
 crbug.com/1129879 [ chromeos ] TraceTest_Video_Media_Stream_Incompatible_Stride [ Skip ]
 crbug.com/1129879 [ fuchsia ] TraceTest_Video_Media_Stream_Incompatible_Stride [ Skip ]
 
+# WebGPU canvas capture hang on mac ASAN bot (also see crbug.com/1213170)
+crbug.com/1345767 [ mac asan ] WebGPUTraceTest_WebGPUCanvasOneCopyCapture [ Skip ]
+crbug.com/1345767 [ mac asan ] WebGPUTraceTest_WebGPUCanvasDisableOneCopyCapture [ Skip ]
+
 ###############################
 # Temporary Skip Expectations #
 ###############################
@@ -192,6 +196,15 @@
 crbug.com/1340081 [ linux release amd-0x7340 ] TraceTest_WebGLGreenTriangle_NoAA_NoAlpha [ RetryOnFailure ]
 
 
+# WebGPU is only supported on Win10, Mac, and Linux+SkiaRenderer+Vulkan.
+crbug.com/852089 [ android ] WebGPUTraceTest_* [ Skip ]
+crbug.com/852089 [ linux ] WebGPUTraceTest_* [ Skip ]
+crbug.com/852089 [ chromeos ] WebGPUTraceTest_* [ Skip ]
+crbug.com/852089 [ fuchsia ] WebGPUTraceTest_* [ Skip ]
+
+# one copy feature is only supported on mac for now.
+crbug.com/1298812 [ win ] WebGPUTraceTest_WebGPUCanvasOneCopyCapture [ Failure ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/trace_integration_test.py b/content/test/gpu/gpu_tests/trace_integration_test.py
index 174a88d..8df1f31 100644
--- a/content/test/gpu/gpu_tests/trace_integration_test.py
+++ b/content/test/gpu/gpu_tests/trace_integration_test.py
@@ -110,6 +110,9 @@
 
 _SUPPORTED_WIN_AMD_GPUS_WITH_NV12_ROTATED_OVERLAYS = [0x7340]
 
+_HTML_CANVAS_NOTIFY_LISTENERS_CANVAS_CHANGED_EVENT_NAME =\
+    'HTMLCanvasElement::NotifyListenersCanvasChanged'
+
 
 class _TraceTestArguments():
   """Struct-like object for passing trace test arguments instead of dicts."""
@@ -191,6 +194,16 @@
               success_eval_func='CheckMainSwapChainPath',
               other_args=p.other_args)
       ])
+    for p in namespace.WebGPUCanvasCapturePages('WebGPUTraceTest'):
+      yield (p.name, posixpath.join(gpu_data_relative_path, p.url), [
+          _TraceTestArguments(
+              browser_args=p.browser_args,
+              category='blink',
+              test_harness_script=basic_test_harness_script,
+              finish_js_condition='domAutomationController._finished',
+              success_eval_func='CheckWebGPUCanvasCapture',
+              other_args=p.other_args)
+      ])
 
   def RunActualGpuTest(self, test_path: str, args: ct.TestArgs) -> None:
     test_params = args[0]
@@ -539,6 +552,31 @@
                 (_PRESENT_MAIN_SWAP_CHAIN_EVENT_NAME,
                  'full damage' if expect_full_damage else 'partial damage'))
 
+  def _EvaluateSuccess_CheckWebGPUCanvasCapture(self, category: str,
+                                                event_iterator: typing.Iterator,
+                                                other_args: dict) -> None:
+    expected_one_copy = other_args.get('one_copy', False)
+    found_one_copy_event = False
+    # Verify expectations through captured trace events.
+    for event in event_iterator:
+      if event.category != category:
+        continue
+      if event.name != _HTML_CANVAS_NOTIFY_LISTENERS_CANVAS_CHANGED_EVENT_NAME:
+        continue
+      detected_one_copy = event.args.get('OneCopyCanvasCapture', None)
+      if detected_one_copy is None:
+        detected_one_copy = False
+      else:
+        found_one_copy_event = True
+
+      if expected_one_copy != detected_one_copy:
+        self.fail('OneCopyCanvasCapture mismatch, expected %s got %s' %
+                  (expected_one_copy, detected_one_copy))
+
+    if expected_one_copy and found_one_copy_event is False:
+      self.fail('%s events with OneCopyCanvasCapture were not found' %
+                _HTML_CANVAS_NOTIFY_LISTENERS_CANVAS_CHANGED_EVENT_NAME)
+
   @classmethod
   def ExpectationsFiles(cls) -> typing.List[str]:
     return [
diff --git a/device/bluetooth/floss/floss_dbus_manager.cc b/device/bluetooth/floss/floss_dbus_manager.cc
index 71f370c0..156ef36 100644
--- a/device/bluetooth/floss/floss_dbus_manager.cc
+++ b/device/bluetooth/floss/floss_dbus_manager.cc
@@ -23,7 +23,6 @@
 
 namespace {
 FlossDBusManager* g_floss_dbus_manager = nullptr;
-FlossDBusThreadManager* g_floss_dbus_thread_manager = nullptr;
 }  // namespace
 
 const int FlossDBusManager::kInvalidAdapter = -1;
@@ -66,12 +65,8 @@
   CHECK(!g_floss_dbus_manager);
 
   VLOG(1) << "FlossDBusManager about to initialize thread manager";
-  FlossDBusThreadManager::Initialize();
 
-  // |system_bus| is unused and we re-use the system bus connection created by
-  // FlossDBusThreadManager.
-  CreateGlobalInstance(FlossDBusThreadManager::Get()->GetSystemBus(),
-                       /*use_stubs=*/false);
+  CreateGlobalInstance(system_bus, /*use_stubs=*/false);
 }
 
 void FlossDBusManager::InitializeFake() {
@@ -213,61 +208,6 @@
   FlossDBusManager::Get()->client_bundle_->adapter_client_ = std::move(client);
 }
 
-FlossDBusThreadManager::FlossDBusThreadManager() {
-  base::Thread::Options thread_options;
-  thread_options.message_pump_type = base::MessagePumpType::IO;
-  dbus_thread_ = std::make_unique<base::Thread>("Floss D-Bus thread");
-  dbus_thread_->StartWithOptions(std::move(thread_options));
-
-  // Create the connection to the system bus.
-  dbus::Bus::Options system_bus_options;
-  system_bus_options.bus_type = dbus::Bus::SYSTEM;
-  system_bus_options.connection_type = dbus::Bus::PRIVATE;
-  system_bus_options.dbus_task_runner = dbus_thread_->task_runner();
-  system_bus_ = base::MakeRefCounted<dbus::Bus>(system_bus_options);
-}
-
-FlossDBusThreadManager::~FlossDBusThreadManager() {
-  // Shut down the bus. During the browser shutdown, it's ok to shut down
-  // the bus synchronously.
-  system_bus_->ShutdownOnDBusThreadAndBlock();
-
-  // Stop the D-Bus thread.
-  dbus_thread_->Stop();
-
-  if (!g_floss_dbus_thread_manager)
-    return;  // Called from Shutdown() or local test instance.
-
-  // There should never be both a global instance and a local instance.
-  CHECK(this == g_floss_dbus_thread_manager);
-}
-
-dbus::Bus* FlossDBusThreadManager::GetSystemBus() {
-  return system_bus_.get();
-}
-
-// static
-void FlossDBusThreadManager::Initialize() {
-  CHECK(!g_floss_dbus_thread_manager);
-  g_floss_dbus_thread_manager = new FlossDBusThreadManager();
-}
-
-// static
-void FlossDBusThreadManager::Shutdown() {
-  // Ensure that we only shutdown FlossDBusThreadManager once.
-  CHECK(g_floss_dbus_thread_manager);
-  delete g_floss_dbus_thread_manager;
-  g_floss_dbus_thread_manager = nullptr;
-  DVLOG(1) << "FlossDBusThreadManager Shutdown completed";
-}
-
-// static
-FlossDBusThreadManager* FlossDBusThreadManager::Get() {
-  CHECK(g_floss_dbus_thread_manager)
-      << "FlossDBusThreadManager::Get() called before Initialize()";
-  return g_floss_dbus_thread_manager;
-}
-
 FlossClientBundle::FlossClientBundle(bool use_stubs) : use_stubs_(use_stubs) {
   if (use_stubs) {
     return;
diff --git a/docs/webui_build_configuration.md b/docs/webui_build_configuration.md
index d9a07c71..0ab6b8f 100644
--- a/docs/webui_build_configuration.md
+++ b/docs/webui_build_configuration.md
@@ -396,7 +396,7 @@
 css_to_wrapper("css_wrapper_files")
 copy("copy_mojo")
 ts_library("build_ts")
-optimize_webui("build")
+optimize_webui("build_bundle")
 generate_grd("build_grd")
 grit("resources")
 
@@ -441,6 +441,10 @@
 ts_definitions: See |definitions| in ts_library(). Optional parameter.
 ts_deps: See |deps| in ts_library(). Optional parameter.
 ts_path_mappings: See |path_mappings| in ts_library(). Optional parameter.
+ts_use_local_config: Whether to pass a local "tsconfig_base.json" file as the
+                     |tsconfig_base| to ts_library(). Optional, defaults to true.
+                     If false, the default //tools/typescript/tsconfig_base.json
+                     will be used.
 
 HTML/CSS/JS optimization related params:
 optimize: Specifies whether any optimization steps will be used, defaults to
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc
index 7727b8d..6d564ab 100644
--- a/extensions/browser/api/device_permissions_manager.cc
+++ b/extensions/browser/api/device_permissions_manager.cc
@@ -103,21 +103,21 @@
   devices->Append(std::move(device_entry));
 }
 
-bool MatchesDevicePermissionEntry(const base::DictionaryValue* value,
+bool MatchesDevicePermissionEntry(const base::Value::Dict& value,
                                   scoped_refptr<DevicePermissionEntry> entry) {
-  const std::string* type = value->FindStringKey(kDeviceType);
+  const std::string* type = value.FindString(kDeviceType);
   if (!type || *type != TypeToString(entry->type())) {
     return false;
   }
-  absl::optional<int> vendor_id = value->FindIntKey(kDeviceVendorId);
+  absl::optional<int> vendor_id = value.FindInt(kDeviceVendorId);
   if (!vendor_id || vendor_id.value() != entry->vendor_id()) {
     return false;
   }
-  absl::optional<int> product_id = value->FindIntKey(kDeviceProductId);
+  absl::optional<int> product_id = value.FindInt(kDeviceProductId);
   if (!product_id || product_id.value() != entry->product_id()) {
     return false;
   }
-  const std::string* serial_number = value->FindStringKey(kDeviceSerialNumber);
+  const std::string* serial_number = value.FindString(kDeviceSerialNumber);
   if (!serial_number ||
       base::UTF8ToUTF16(*serial_number) != entry->serial_number()) {
     return false;
@@ -138,11 +138,9 @@
   }
 
   for (auto& value : devices->GetList()) {
-    base::DictionaryValue* dict_value;
-    if (!value.GetAsDictionary(&dict_value)) {
+    if (!value.is_dict())
       continue;
-    }
-    if (!MatchesDevicePermissionEntry(dict_value, entry)) {
+    if (!MatchesDevicePermissionEntry(value.GetDict(), entry)) {
       continue;
     }
 
@@ -164,11 +162,9 @@
 
   for (auto it = devices->GetList().begin(); it != devices->GetList().end();
        ++it) {
-    base::DictionaryValue* dict_value;
-    if (!it->GetAsDictionary(&dict_value)) {
+    if (!it->is_dict())
       continue;
-    }
-    if (!MatchesDevicePermissionEntry(dict_value, entry)) {
+    if (!MatchesDevicePermissionEntry(it->GetDict(), entry)) {
       continue;
     }
     devices->GetList().erase(it);
@@ -183,49 +179,48 @@
 }
 
 scoped_refptr<DevicePermissionEntry> ReadDevicePermissionEntry(
-    const base::DictionaryValue* entry) {
-  absl::optional<int> vendor_id = entry->FindIntKey(kDeviceVendorId);
+    const base::Value::Dict& entry) {
+  absl::optional<int> vendor_id = entry.FindInt(kDeviceVendorId);
   if (!vendor_id || vendor_id.value() < 0 ||
       vendor_id.value() > static_cast<int>(UINT16_MAX)) {
     return nullptr;
   }
 
-  absl::optional<int> product_id = entry->FindIntKey(kDeviceProductId);
+  absl::optional<int> product_id = entry.FindInt(kDeviceProductId);
   if (!product_id || product_id.value() < 0 ||
       product_id.value() > static_cast<int>(UINT16_MAX)) {
     return nullptr;
   }
 
-  const std::string* serial_number_ptr =
-      entry->FindStringKey(kDeviceSerialNumber);
+  const std::string* serial_number_ptr = entry.FindString(kDeviceSerialNumber);
   if (!serial_number_ptr)
     return nullptr;
   std::u16string serial_number = base::UTF8ToUTF16(*serial_number_ptr);
   std::u16string manufacturer_string;
   // Ignore failure as this string is optional.
   const std::string* manufacturer_ptr =
-      entry->FindStringKey(kDeviceManufacturerString);
+      entry.FindString(kDeviceManufacturerString);
   if (manufacturer_ptr) {
     manufacturer_string = base::UTF8ToUTF16(*manufacturer_ptr);
   }
 
   std::u16string product_string;
   // Ignore failure as this string is optional.
-  const std::string* product_ptr = entry->FindStringKey(kDeviceProductString);
+  const std::string* product_ptr = entry.FindString(kDeviceProductString);
   if (product_ptr) {
     product_string = base::UTF8ToUTF16(*product_ptr);
   }
 
   // If a last used time is not stored in ExtensionPrefs last_used.is_null()
   // will be true.
-  const std::string* last_used_ptr = entry->FindStringKey(kDeviceLastUsed);
+  const std::string* last_used_ptr = entry.FindString(kDeviceLastUsed);
   int64_t last_used_i64 = 0;
   base::Time last_used;
   if (last_used_ptr && base::StringToInt64(*last_used_ptr, &last_used_i64)) {
     last_used = base::Time::FromInternalValue(last_used_i64);
   }
 
-  const std::string* device_type_ptr = entry->FindStringKey(kDeviceType);
+  const std::string* device_type_ptr = entry.FindString(kDeviceType);
   if (!device_type_ptr)
     return nullptr;
 
@@ -252,13 +247,10 @@
   }
 
   for (const auto& entry : devices->GetList()) {
-    const base::DictionaryValue* entry_dict;
-    if (entry.GetAsDictionary(&entry_dict)) {
+    if (entry.is_dict()) {
       scoped_refptr<DevicePermissionEntry> device_entry =
-          ReadDevicePermissionEntry(entry_dict);
-      if (entry_dict) {
-        result.insert(device_entry);
-      }
+          ReadDevicePermissionEntry(entry.GetDict());
+      result.insert(device_entry);
     }
   }
   return result;
diff --git a/extensions/browser/api/diagnostics/diagnostics_api.cc b/extensions/browser/api/diagnostics/diagnostics_api.cc
index 6eaae19..ba92259a 100644
--- a/extensions/browser/api/diagnostics/diagnostics_api.cc
+++ b/extensions/browser/api/diagnostics/diagnostics_api.cc
@@ -26,28 +26,25 @@
 
 bool ParseResult(const std::string& status, std::string* ip, double* latency) {
   // Parses the result and returns IP and latency.
-  std::unique_ptr<base::Value> parsed_value(
-      base::JSONReader::ReadDeprecated(status));
-  if (!parsed_value)
+  absl::optional<base::Value> parsed_value(base::JSONReader::Read(status));
+  if (!parsed_value || !parsed_value->is_dict())
     return false;
 
-  base::DictionaryValue* result = NULL;
-  if (!parsed_value->GetAsDictionary(&result) || result->DictSize() != 1)
+  base::Value::Dict& result = parsed_value->GetDict();
+  if (result.size() != 1)
     return false;
 
   // Returns the first item.
-  base::DictionaryValue::Iterator iterator(*result);
-
-  const base::DictionaryValue* info;
-  if (!iterator.value().GetAsDictionary(&info))
+  base::Value::Dict::iterator iterator = result.begin();
+  if (!iterator->second.is_dict())
     return false;
 
-  absl::optional<double> avg = info->FindDoubleKey("avg");
+  absl::optional<double> avg = iterator->second.GetDict().FindDouble("avg");
   if (!avg)
     return false;
   *latency = *avg;
 
-  *ip = iterator.key();
+  *ip = iterator->first;
   return true;
 }
 
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.cc b/extensions/browser/api/guest_view/guest_view_internal_api.cc
index 8b69b7a..828917b 100644
--- a/extensions/browser/api/guest_view/guest_view_internal_api.cc
+++ b/extensions/browser/api/guest_view/guest_view_internal_api.cc
@@ -59,8 +59,7 @@
   create_params.SetBoolKey(guest_view::kElementSizeIsLogical, true);
 
   guest_view_manager->CreateGuest(view_type, sender_web_contents,
-                                  base::Value::AsDictionaryValue(create_params),
-                                  std::move(callback));
+                                  create_params.GetDict(), std::move(callback));
   return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
index f99d6c30a..41ff89d8 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
@@ -5,7 +5,6 @@
 #ifndef EXTENSIONS_BROWSER_API_VIRTUAL_KEYBOARD_PRIVATE_VIRTUAL_KEYBOARD_DELEGATE_H_
 #define EXTENSIONS_BROWSER_API_VIRTUAL_KEYBOARD_PRIVATE_VIRTUAL_KEYBOARD_DELEGATE_H_
 
-#include <memory>
 #include <set>
 #include <string>
 
@@ -14,6 +13,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/api/virtual_keyboard.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace extensions {
@@ -23,7 +23,7 @@
   virtual ~VirtualKeyboardDelegate() {}
 
   using OnKeyboardSettingsCallback =
-      base::OnceCallback<void(std::unique_ptr<base::DictionaryValue> settings)>;
+      base::OnceCallback<void(absl::optional<base::Value::Dict> settings)>;
 
   using OnSetModeCallback = base::OnceCallback<void(bool success)>;
 
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
index de4ab92..9bd400ad 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
@@ -128,10 +128,9 @@
 }
 
 void VirtualKeyboardPrivateGetKeyboardConfigFunction::OnKeyboardConfig(
-    std::unique_ptr<base::DictionaryValue> results) {
-  Respond(results
-              ? OneArgument(base::Value::FromUniquePtrValue(std::move(results)))
-              : Error(kUnknownError));
+    absl::optional<base::Value::Dict> results) {
+  Respond(results ? OneArgument(base::Value(std::move(*results)))
+                  : Error(kUnknownError));
 }
 
 ExtensionFunction::ResponseAction
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
index 1c0f5f2..feb267e 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
@@ -7,12 +7,10 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/raw_ptr.h"
+#include "base/values.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/extension_function.h"
-
-namespace base {
-class DictionaryValue;
-}
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 class BrowserContext;
@@ -125,7 +123,7 @@
   ResponseAction Run() override;
 
  private:
-  void OnKeyboardConfig(std::unique_ptr<base::DictionaryValue> results);
+  void OnKeyboardConfig(absl::optional<base::Value::Dict> results);
 };
 
 class VirtualKeyboardPrivateOpenSettingsFunction
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 21e0058..897e41dbe 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1750,6 +1750,7 @@
   SIDEPANEL_SETOPTIONS = 1687,
   ENTERPRISEREPORTINGPRIVATE_GETFILESYSTEMINFO = 1688,
   FILEMANAGERPRIVATE_GETDRIVEQUOTAMETADATA = 1689,
+  DOWNLOADS_SETUIOPTIONS = 1690,
   // Last entry: Add new entries above, then run:
   // tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc
index 7fd0458..46d69b3 100644
--- a/extensions/browser/guest_view/app_view/app_view_guest.cc
+++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -166,9 +166,9 @@
       render_frame_host, security_origin, type, guest_extension);
 }
 
-void AppViewGuest::CreateWebContents(const base::DictionaryValue& create_params,
+void AppViewGuest::CreateWebContents(const base::Value::Dict& create_params,
                                      WebContentsCreatedCallback callback) {
-  const std::string* app_id = create_params.FindStringKey(appview::kAppID);
+  const std::string* app_id = create_params.FindString(appview::kAppID);
   if (!app_id) {
     std::move(callback).Run(nullptr);
     return;
@@ -179,7 +179,7 @@
     return;
   }
 
-  const base::Value* data = create_params.FindDictKey(appview::kData);
+  const base::Value::Dict* data = create_params.FindDict(appview::kData);
   if (!data) {
     std::move(callback).Run(nullptr);
     return;
@@ -200,12 +200,10 @@
   const LazyContextId context_id(browser_context(), guest_extension->id());
   LazyContextTaskQueue* queue = context_id.GetTaskQueue();
   if (queue->ShouldEnqueueTask(browser_context(), guest_extension)) {
-    queue->AddPendingTask(
-        context_id,
-        base::BindOnce(&AppViewGuest::LaunchAppAndFireEvent,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       base::Value::AsDictionaryValue(*data).CreateDeepCopy(),
-                       std::move(callback)));
+    queue->AddPendingTask(context_id,
+                          base::BindOnce(&AppViewGuest::LaunchAppAndFireEvent,
+                                         weak_ptr_factory_.GetWeakPtr(),
+                                         data->Clone(), std::move(callback)));
     return;
   }
 
@@ -214,12 +212,11 @@
       process_manager->GetBackgroundHostForExtension(guest_extension->id());
   DCHECK(host);
   LaunchAppAndFireEvent(
-      base::Value::AsDictionaryValue(*data).CreateDeepCopy(),
-      std::move(callback),
+      data->Clone(), std::move(callback),
       std::make_unique<LazyContextTaskQueue::ContextInfo>(host));
 }
 
-void AppViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
+void AppViewGuest::DidInitialize(const base::Value::Dict& create_params) {
   ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
 
   if (!url_.is_valid())
@@ -259,7 +256,7 @@
 }
 
 void AppViewGuest::LaunchAppAndFireEvent(
-    std::unique_ptr<base::DictionaryValue> data,
+    base::Value::Dict data,
     WebContentsCreatedCallback callback,
     std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info) {
   bool has_event_listener = EventRouter::Get(browser_context())
@@ -285,8 +282,7 @@
       new base::DictionaryValue());
   embed_request->SetIntKey(appview::kGuestInstanceID, guest_instance_id());
   embed_request->SetStringKey(appview::kEmbedderID, owner_host());
-  embed_request->SetKey(appview::kData,
-                        base::Value::FromUniquePtrValue(std::move(data)));
+  embed_request->SetKey(appview::kData, base::Value(std::move(data)));
   AppRuntimeEventRouter::DispatchOnEmbedRequestedEvent(
       browser_context(), std::move(embed_request), extension);
 }
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.h b/extensions/browser/guest_view/app_view/app_view_guest.h
index c2143e41..7a40ac4 100644
--- a/extensions/browser/guest_view/app_view/app_view_guest.h
+++ b/extensions/browser/guest_view/app_view/app_view_guest.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/containers/id_map.h"
+#include "base/values.h"
 #include "components/guest_view/browser/guest_view.h"
 #include "extensions/browser/guest_view/app_view/app_view_guest_delegate.h"
 #include "extensions/browser/lazy_context_task_queue.h"
@@ -55,9 +56,9 @@
   ~AppViewGuest() override;
 
   // GuestViewBase implementation.
-  void CreateWebContents(const base::DictionaryValue& create_params,
+  void CreateWebContents(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) final;
-  void DidInitialize(const base::DictionaryValue& create_params) final;
+  void DidInitialize(const base::Value::Dict& create_params) final;
   const char* GetAPINamespace() const final;
   int GetTaskPrefix() const final;
 
@@ -77,7 +78,7 @@
                                  WebContentsCreatedCallback callback);
 
   void LaunchAppAndFireEvent(
-      std::unique_ptr<base::DictionaryValue> data,
+      base::Value::Dict data,
       WebContentsCreatedCallback callback,
       std::unique_ptr<LazyContextTaskQueue::ContextInfo> context_info);
 
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
index 8349c8c..cf38ea90 100644
--- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc
+++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -59,11 +59,11 @@
 }
 
 void ExtensionOptionsGuest::CreateWebContents(
-    const base::DictionaryValue& create_params,
+    const base::Value::Dict& create_params,
     WebContentsCreatedCallback callback) {
   // Get the extension's base URL.
   const std::string* extension_id =
-      create_params.FindStringKey(extensionoptions::kExtensionId);
+      create_params.FindString(extensionoptions::kExtensionId);
 
   if (!extension_id || !crx_file::id_util::IdIsValid(*extension_id)) {
     std::move(callback).Run(nullptr);
@@ -116,7 +116,7 @@
 }
 
 void ExtensionOptionsGuest::DidInitialize(
-    const base::DictionaryValue& create_params) {
+    const base::Value::Dict& create_params) {
   ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
   web_contents()->GetController().LoadURL(options_page_,
                                           content::Referrer(),
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.h b/extensions/browser/guest_view/extension_options/extension_options_guest.h
index 7350382..f1c47414 100644
--- a/extensions/browser/guest_view/extension_options/extension_options_guest.h
+++ b/extensions/browser/guest_view/extension_options/extension_options_guest.h
@@ -31,9 +31,9 @@
   ~ExtensionOptionsGuest() override;
 
   // GuestViewBase implementation.
-  void CreateWebContents(const base::DictionaryValue& create_params,
+  void CreateWebContents(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) final;
-  void DidInitialize(const base::DictionaryValue& create_params) final;
+  void DidInitialize(const base::Value::Dict& create_params) final;
   void GuestViewDidStopLoading() final;
   const char* GetAPINamespace() const final;
   int GetTaskPrefix() const final;
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc
index 48f7c1a..374acc8 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc
@@ -187,8 +187,8 @@
         ExtensionsAPIClient::Get()->CreateGuestViewManagerDelegate(
             browser_context));
   }
-  base::DictionaryValue create_params;
-  create_params.SetStringKey(mime_handler_view::kStreamId, stream_id_);
+  base::Value::Dict create_params;
+  create_params.Set(mime_handler_view::kStreamId, stream_id_);
   manager->CreateGuest(
       MimeHandlerViewGuest::Type, web_contents(), create_params,
       base::BindOnce(&MimeHandlerViewEmbedder::DidCreateMimeHandlerViewGuest,
@@ -224,7 +224,7 @@
       web_contents()->GetBrowserContext())
       ->AttachGuest(embedder_frame_process_id, element_instance_id,
                     guest_instance_id,
-                    base::DictionaryValue() /* unused attach_params */);
+                    base::Value::Dict() /* unused attach_params */);
   // Full page plugin refers to <iframe> or main frame navigations to a
   // MimeHandlerView resource. In such cases MHVG does not have a frame
   // container.
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index 9fa230c..55a78179 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -163,10 +163,10 @@
 }
 
 void MimeHandlerViewGuest::CreateWebContents(
-    const base::DictionaryValue& create_params,
+    const base::Value::Dict& create_params,
     WebContentsCreatedCallback callback) {
   const std::string* stream_id =
-      create_params.FindStringKey(mime_handler_view::kStreamId);
+      create_params.FindString(mime_handler_view::kStreamId);
   if (!stream_id || stream_id->empty()) {
     std::move(callback).Run(nullptr);
     return;
@@ -245,7 +245,7 @@
 }
 
 void MimeHandlerViewGuest::DidInitialize(
-    const base::DictionaryValue& create_params) {
+    const base::Value::Dict& create_params) {
   ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
 }
 
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
index ef6faf31..af1cf98 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -136,10 +136,10 @@
   // GuestViewBase implementation.
   const char* GetAPINamespace() const final;
   int GetTaskPrefix() const final;
-  void CreateWebContents(const base::DictionaryValue& create_params,
+  void CreateWebContents(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) override;
   void DidAttachToEmbedder() override;
-  void DidInitialize(const base::DictionaryValue& create_params) final;
+  void DidInitialize(const base::Value::Dict& create_params) final;
   void EmbedderFullscreenToggled(bool entered_fullscreen) final;
   bool ZoomPropagatesFromEmbedderToGuest() const final;
   bool ShouldDestroyOnDetach() const final;
diff --git a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
index 052fc12..4505e5c 100644
--- a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
@@ -39,7 +39,7 @@
 }
 
 void TestMimeHandlerViewGuest::CreateWebContents(
-    const base::DictionaryValue& create_params,
+    const base::Value::Dict& create_params,
     WebContentsCreatedCallback callback) {
   // Delay the creation of the guest's WebContents if |delay_| is set.
   if (delay_) {
@@ -47,8 +47,8 @@
     content::GetUIThreadTaskRunner({})->PostDelayedTask(
         FROM_HERE,
         base::BindOnce(&TestMimeHandlerViewGuest::CallBaseCreateWebContents,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       create_params.CreateDeepCopy(), std::move(callback)),
+                       weak_ptr_factory_.GetWeakPtr(), create_params.Clone(),
+                       std::move(callback)),
         delta);
 
     // Reset the delay for the next creation.
@@ -66,10 +66,10 @@
 }
 
 void TestMimeHandlerViewGuest::CallBaseCreateWebContents(
-    std::unique_ptr<base::DictionaryValue> create_params,
+    base::Value::Dict create_params,
     WebContentsCreatedCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  MimeHandlerViewGuest::CreateWebContents(*create_params, std::move(callback));
+  MimeHandlerViewGuest::CreateWebContents(create_params, std::move(callback));
 }
 
 // static
diff --git a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h
index 4f22a58e..57d0dd688 100644
--- a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h
+++ b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h
@@ -37,7 +37,7 @@
   void WaitForGuestAttached();
 
   // MimeHandlerViewGuest override:
-  void CreateWebContents(const base::DictionaryValue& create_params,
+  void CreateWebContents(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) override;
   void DidAttachToEmbedder() override;
 
@@ -47,9 +47,8 @@
 
   // Used to call MimeHandlerViewGuest::CreateWebContents using a scoped_ptr for
   // |create_params|.
-  void CallBaseCreateWebContents(
-      std::unique_ptr<base::DictionaryValue> create_params,
-      WebContentsCreatedCallback callback);
+  void CallBaseCreateWebContents(base::Value::Dict create_params,
+                                 WebContentsCreatedCallback callback);
 
   // A value in milliseconds that the next creation of a guest's WebContents
   // will be delayed. After this creation is delayed, |delay_| will be reset to
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 8a47e41..5838b00 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -171,11 +171,12 @@
   return (persist_storage ? webview::kPersistPrefix : "") + partition_id;
 }
 
-void ParsePartitionParam(const base::DictionaryValue& create_params,
+void ParsePartitionParam(const base::Value::Dict& create_params,
                          std::string* storage_partition_id,
                          bool* persist_storage) {
-  std::string partition_str;
-  if (!create_params.GetString(webview::kStoragePartitionId, &partition_str)) {
+  const std::string* partition_str =
+      create_params.FindString(webview::kStoragePartitionId);
+  if (!partition_str) {
     return;
   }
 
@@ -183,12 +184,12 @@
   // UTF-8 encoded |partition_id|. If the prefix is a match, we can safely
   // remove the prefix without splicing in the middle of a multi-byte codepoint.
   // We can use the rest of the string as UTF-8 encoded one.
-  if (base::StartsWith(partition_str, "persist:",
-                       base::CompareCase::SENSITIVE)) {
-    size_t index = partition_str.find(":");
+  if (base::StartsWith(*partition_str,
+                       "persist:", base::CompareCase::SENSITIVE)) {
+    size_t index = partition_str->find(":");
     CHECK(index != std::string::npos);
     // It is safe to do index + 1, since we tested for the full prefix above.
-    *storage_partition_id = partition_str.substr(index + 1);
+    *storage_partition_id = partition_str->substr(index + 1);
 
     if (storage_partition_id->empty()) {
       // TODO(lazyboy): Better way to deal with this error.
@@ -196,7 +197,7 @@
     }
     *persist_storage = true;
   } else {
-    *storage_partition_id = partition_str;
+    *storage_partition_id = *partition_str;
     *persist_storage = false;
   }
 }
@@ -305,7 +306,7 @@
   return rules_registry_id;
 }
 
-void WebViewGuest::CreateWebContents(const base::DictionaryValue& create_params,
+void WebViewGuest::CreateWebContents(const base::Value::Dict& create_params,
                                      WebContentsCreatedCallback callback) {
   RenderProcessHost* owner_render_process_host =
       owner_web_contents()->GetPrimaryMainFrame()->GetProcess();
@@ -382,10 +383,10 @@
 }
 
 void WebViewGuest::DidAttachToEmbedder() {
-  ApplyAttributes(*attach_params());
+  ApplyAttributes(attach_params());
 }
 
-void WebViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
+void WebViewGuest::DidInitialize(const base::Value::Dict& create_params) {
   script_executor_ = std::make_unique<ScriptExecutor>(web_contents());
 
   ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
@@ -616,9 +617,8 @@
       web_contents()->GetSiteInstance()->GetStoragePartitionConfig();
   const std::string storage_partition_id =
       GetStoragePartitionIdFromPartitionConfig(storage_partition_config);
-  base::DictionaryValue create_params;
-  create_params.SetStringKey(webview::kStoragePartitionId,
-                             storage_partition_id);
+  base::Value::Dict create_params;
+  create_params.Set(webview::kStoragePartitionId, storage_partition_id);
 
   guest_manager->CreateGuest(
       WebViewGuest::Type, embedder_web_contents(), create_params,
@@ -1144,24 +1144,23 @@
   return false;
 }
 
-void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) {
-  std::string name;
-  if (params.GetString(webview::kAttributeName, &name)) {
+void WebViewGuest::ApplyAttributes(const base::Value::Dict& params) {
+  if (const std::string* name = params.FindString(webview::kAttributeName)) {
     // If the guest window's name is empty, then the WebView tag's name is
     // assigned. Otherwise, the guest window's name takes precedence over the
     // WebView tag's name.
     if (name_.empty())
-      SetName(name);
+      SetName(*name);
   }
   if (attached())
     ReportFrameNameChange(name_);
 
-  std::string user_agent_override;
-  params.GetString(webview::kParameterUserAgentOverride, &user_agent_override);
-  SetUserAgentOverride(user_agent_override);
+  const std::string* user_agent_override =
+      params.FindString(webview::kParameterUserAgentOverride);
+  SetUserAgentOverride(user_agent_override ? *user_agent_override : "");
 
   absl::optional<bool> allow_transparency =
-      params.FindBoolKey(webview::kAttributeAllowTransparency);
+      params.FindBool(webview::kAttributeAllowTransparency);
   if (allow_transparency) {
     // We need to set the background opaque flag after navigation to ensure that
     // there is a RenderWidgetHostView available.
@@ -1169,12 +1168,12 @@
   }
 
   absl::optional<bool> allow_scaling =
-      params.FindBoolKey(webview::kAttributeAllowScaling);
+      params.FindBool(webview::kAttributeAllowScaling);
   if (allow_scaling)
     SetAllowScaling(*allow_scaling);
 
   // Check for a pending zoom from before the first navigation.
-  pending_zoom_factor_ = params.FindDoubleKey(webview::kInitialZoomFactor)
+  pending_zoom_factor_ = params.FindDouble(webview::kInitialZoomFactor)
                              .value_or(pending_zoom_factor_);
 
   bool is_pending_new_window = false;
@@ -1203,9 +1202,8 @@
 
   // Only read the src attribute if this is not a New Window API flow.
   if (!is_pending_new_window) {
-    std::string src;
-    if (params.GetString(webview::kAttributeSrc, &src))
-      NavigateGuest(src, true /* force_navigation */);
+    if (const std::string* src = params.FindString(webview::kAttributeSrc))
+      NavigateGuest(*src, true /* force_navigation */);
   }
 }
 
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h
index 44b5e823..ffb9a2c 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "base/values.h"
 #include "components/guest_view/browser/guest_view.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 #include "extensions/browser/guest_view/web_view/javascript_dialog_helper.h"
@@ -167,10 +168,10 @@
                                     base::OnceCallback<void(bool)> callback);
 
   // GuestViewBase implementation.
-  void CreateWebContents(const base::DictionaryValue& create_params,
+  void CreateWebContents(const base::Value::Dict& create_params,
                          WebContentsCreatedCallback callback) final;
   void DidAttachToEmbedder() final;
-  void DidInitialize(const base::DictionaryValue& create_params) final;
+  void DidInitialize(const base::Value::Dict& create_params) final;
   void EmbedderFullscreenToggled(bool entered_fullscreen) final;
   void FindReply(content::WebContents* source,
                  int request_id,
@@ -301,7 +302,7 @@
 
   bool HandleKeyboardShortcuts(const content::NativeWebKeyboardEvent& event);
 
-  void ApplyAttributes(const base::DictionaryValue& params);
+  void ApplyAttributes(const base::Value::Dict& params);
 
   void SetTransparency();
 
diff --git a/extensions/browser/permissions_manager.cc b/extensions/browser/permissions_manager.cc
index b850c9e..6dd493a3 100644
--- a/extensions/browser/permissions_manager.cc
+++ b/extensions/browser/permissions_manager.cc
@@ -254,16 +254,22 @@
   std::unique_ptr<const PermissionSet> bounded_desired =
       GetBoundedExtensionDesiredPermissions(extension);
 
-  // 3) Finalize the allowed set. Since we don't allow withholding of API and
-  // manifest permissions, the allowed set always contains all (bounded)
-  // requested API and manifest permissions.
+  // 3) Add in any always-approved hosts that shouldn't be removed (such as
+  //    chrome://favicon).
+  allowed_permissions =
+      ExtensionsBrowserClient::Get()->AddAdditionalAllowedHosts(
+          *bounded_desired, *allowed_permissions);
+
+  // 4) Finalize the allowed set. Since we don't allow withholding of API and
+  //    manifest permissions, the allowed set always contains all (bounded)
+  //    requested API and manifest permissions.
   allowed_permissions = std::make_unique<const PermissionSet>(
       bounded_desired->apis().Clone(),
       bounded_desired->manifest_permissions().Clone(),
       allowed_permissions->explicit_hosts().Clone(),
       allowed_permissions->scriptable_hosts().Clone());
 
-  // 4) Calculate the new active and withheld permissions. The active
+  // 5) Calculate the new active and withheld permissions. The active
   //    permissions are the intersection of all permissions the extension is
   //    allowed to have with all permissions the extension elected to have.
   //    Said differently, we grant a permission if both the extension and the
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index a6ce61f..bb5bae5 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -569,7 +569,7 @@
     "contexts": ["webui_untrusted"],
     "matches": [
       // Allow only terminal_ssh.html in Terminal System Web App.
-      "chrome-untrusted://terminal/html/terminal_ssh.html"
+      "chrome-untrusted://terminal/html/terminal_ssh.html*"
     ]
   }],
   "runtime.sendNativeMessage": {
diff --git a/extensions/common/api/bluetooth.idl b/extensions/common/api/bluetooth.idl
index a1703762..ac04983 100644
--- a/extensions/common/api/bluetooth.idl
+++ b/extensions/common/api/bluetooth.idl
@@ -98,10 +98,6 @@
     Transport? transport;
 
     // The remaining battery of the device.
-    // TODO(https://crbug.com/973237): This field is only used by Chrome OS and
-    // it is different from others because it is not filled by the platform. In
-    // the future, when there is a unified Mojo service, this field will be
-    // moved to BluetoothDeviceInfo.
     long? batteryPercentage;
   };
 
diff --git a/extensions/common/mojom/api_permission_id.mojom b/extensions/common/mojom/api_permission_id.mojom
index 7adee8f..1bbc637 100644
--- a/extensions/common/mojom/api_permission_id.mojom
+++ b/extensions/common/mojom/api_permission_id.mojom
@@ -265,6 +265,7 @@
   kEnterpriseRemoteApps = 239,
   kOffscreen = 240,
   kSidePanel = 241,
+  kDownloadsUi = 242,
 
   // Add new entries at the end of the enum and be sure to update the
   // "ExtensionPermission3" enum in tools/metrics/histograms/enums.xml
diff --git a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
index 12d98bf8..ef5581d 100644
--- a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
+++ b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
@@ -177,10 +177,11 @@
   content::RenderFrame* render_frame = GetRenderFrame(args[3]);
   RenderFrameStatus render_frame_status(render_frame);
 
-  std::unique_ptr<base::DictionaryValue> params = base::DictionaryValue::From(
-      content::V8ValueConverter::Create()->FromV8Value(
-          args[2], context()->v8_context()));
+  std::unique_ptr<base::Value> params =
+      content::V8ValueConverter::Create()->FromV8Value(args[2],
+                                                       context()->v8_context());
   CHECK(params);
+  CHECK(params->is_dict());
 
   if (!render_frame_status.is_ok())
     return;
@@ -213,7 +214,7 @@
   std::unique_ptr<guest_view::GuestViewAttachRequest> request =
       std::make_unique<guest_view::GuestViewAttachRequest>(
           guest_view_container, render_frame->GetRoutingID(), guest_instance_id,
-          std::move(params),
+          std::move(params->GetDict()),
           args.Length() == (num_required_params + 1)
               ? args[num_required_params].As<v8::Function>()
               : v8::Local<v8::Function>(),
diff --git a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
index 0722fe0..6bca51b 100644
--- a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
+++ b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
@@ -16,8 +16,8 @@
 
 void ShellVirtualKeyboardDelegate::GetKeyboardConfig(
     OnKeyboardSettingsCallback on_settings_callback) {
-  std::unique_ptr<base::DictionaryValue> settings(new base::DictionaryValue());
-  settings->GetDict().Set("hotrodmode", is_hotrod_keyboard_);
+  base::Value::Dict settings;
+  settings.Set("hotrodmode", is_hotrod_keyboard_);
   std::move(on_settings_callback).Run(std::move(settings));
 }
 
diff --git a/extensions/shell/test/shell_test.cc b/extensions/shell/test/shell_test.cc
index 523b492..76fcea9 100644
--- a/extensions/shell/test/shell_test.cc
+++ b/extensions/shell/test/shell_test.cc
@@ -16,7 +16,7 @@
 #include "extensions/shell/browser/shell_content_browser_client.h"
 #include "extensions/shell/browser/shell_extension_system.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "content/public/test/network_connection_change_simulator.h"
 #endif
 
@@ -36,7 +36,7 @@
 }
 
 void AppShellTest::PreRunTestOnMainThread() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   content::NetworkConnectionChangeSimulator network_change_simulator;
   network_change_simulator.InitializeChromeosConnectionType();
 #endif
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index 06f6604d..5e55c88 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1347,8 +1347,7 @@
   preamble.post_translation = post_translate;
   preamble.post_scale = post_scale;
   preamble.requires_clear = requires_clear;
-  // TODO(aaronhk): change the preamble to float color
-  preamble.background_color = raster_properties_->background_color.toSkColor();
+  preamble.background_color = raster_properties_->background_color;
 
   // Wrap the provided provider in a stashing provider so that we can delay
   // unrefing images until we have serialized dependent commands.
diff --git a/gpu/command_buffer/service/dxgi_shared_handle_manager_unittest.cc b/gpu/command_buffer/service/dxgi_shared_handle_manager_unittest.cc
index a0341b34..bf5c84a 100644
--- a/gpu/command_buffer/service/dxgi_shared_handle_manager_unittest.cc
+++ b/gpu/command_buffer/service/dxgi_shared_handle_manager_unittest.cc
@@ -22,7 +22,7 @@
  protected:
   void SetUp() override {
     // Using DXGI NT handles is universally supported only on Win8 and above.
-    // TODO(sunnyps): Unify this with the check in SharedImageBackingFactoryD3D.
+    // TODO(sunnyps): Unify this with the check in D3DImageBackingFactory.
     const bool shared_handles_supported =
         base::win::GetVersion() >= base::win::Version::WIN8;
     d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 26cf037..559c131 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -985,21 +985,24 @@
     validators_.texture_sized_texture_filterable_internal_format.AddValue(
         GL_BGRA8_EXT);
     feature_flags_.gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRA_8888);
-#if BUILDFLAG(IS_MAC)
-    // TODO(sugoi): Remove this once crbug.com/1276529 is fixed.
-    // On Mac OS, DrawingBuffer is using an IOSurface as its backing storage,
-    // this allows WebGL-rendered canvases to be composited by the OS rather
-    // than Chrome. Currently, this causes an issue on MacOS with SwANGLE when
-    // alpha is false, so disable that case for now so that we go through
-    // emulation.
-    if (!gl_version_info_->is_angle_swiftshader)
-#endif
-    {
-      feature_flags_.gpu_memory_buffer_formats.Add(
-          gfx::BufferFormat::BGRX_8888);
-    }
+    feature_flags_.gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRX_8888);
   }
 
+#if BUILDFLAG(IS_MAC)
+  // TODO(sugoi): Remove this once crbug.com/1276529 is fixed.
+  // On Mac OS, DrawingBuffer is using an IOSurface as its backing storage,
+  // this allows WebGL-rendered canvases to be composited by the OS rather
+  // than Chrome. Currently, this causes an issue on MacOS with SwANGLE when
+  // alpha is false, so disable that case for now so that we go through
+  // emulation.
+  if (gl_version_info_->is_angle_swiftshader) {
+    feature_flags_.gpu_memory_buffer_formats.Remove(
+        gfx::BufferFormat::RGBX_8888);
+    feature_flags_.gpu_memory_buffer_formats.Remove(
+        gfx::BufferFormat::BGRX_8888);
+  }
+#endif
+
   // On desktop, all devices support BGRA render buffers (note that on desktop
   // BGRA internal formats are converted to RGBA in the API implementation).
   // For ES, there is no extension that exposes BGRA renderbuffers, however
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 53ab7f18..357d1c9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -18485,7 +18485,7 @@
     return;
   }
 
-  std::unique_ptr<SharedImageRepresentationGLTexture> shared_image;
+  std::unique_ptr<GLTextureImageRepresentation> shared_image;
   if (internal_format == GL_RGB) {
     shared_image = group_->shared_image_representation_factory()
                        ->ProduceRGBEmulationGLTexture(mailbox);
@@ -18523,8 +18523,7 @@
     return;
   }
 
-  SharedImageRepresentationGLTexture* shared_image =
-      texture_ref->shared_image();
+  GLTextureImageRepresentation* shared_image = texture_ref->shared_image();
   if (!shared_image) {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "DoBeginSharedImageAccessCHROMIUM",
                        "bound texture is not a shared image");
@@ -18552,8 +18551,7 @@
     return;
   }
 
-  SharedImageRepresentationGLTexture* shared_image =
-      texture_ref->shared_image();
+  GLTextureImageRepresentation* shared_image = texture_ref->shared_image();
   if (!shared_image) {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "DoEndSharedImageAccessCHROMIUM",
                        "bound texture is not a shared image");
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 4bb1a0c9..b23732b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -398,8 +398,7 @@
 
 PassthroughResources::SharedImageData::SharedImageData() = default;
 PassthroughResources::SharedImageData::SharedImageData(
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-        representation,
+    std::unique_ptr<GLTexturePassthroughImageRepresentation> representation,
     gl::GLApi* api)
     : representation_(std::move(representation)) {
   DCHECK(representation_);
@@ -1697,12 +1696,10 @@
   caps.protected_video_swap_chain = surface_->SupportsProtectedVideo();
   caps.gpu_vsync = surface_->SupportsGpuVSync();
 #if BUILDFLAG(IS_WIN)
-  caps.shared_image_d3d =
-      SharedImageBackingFactoryD3D::IsD3DSharedImageSupported(
-          group_->gpu_preferences());
+  caps.shared_image_d3d = D3DImageBackingFactory::IsD3DSharedImageSupported(
+      group_->gpu_preferences());
   caps.shared_image_swap_chain =
-      caps.shared_image_d3d &&
-      SharedImageBackingFactoryD3D::IsSwapChainSupported();
+      caps.shared_image_d3d && D3DImageBackingFactory::IsSwapChainSupported();
 #endif  // BUILDFLAG(IS_WIN)
   caps.texture_npot = feature_info_->feature_flags().npot_ok;
   caps.texture_storage_image =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 676c1d3..c09f1a4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -43,7 +43,7 @@
 }
 
 namespace gpu {
-class SharedImageRepresentationGLTexturePassthrough;
+class GLTexturePassthroughImageRepresentation;
 
 namespace gles2 {
 
@@ -98,8 +98,7 @@
    public:
     SharedImageData();
     explicit SharedImageData(
-        std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-            representation,
+        std::unique_ptr<GLTexturePassthroughImageRepresentation> representation,
         gl::GLApi* api);
     SharedImageData(SharedImageData&& other);
 
@@ -109,7 +108,7 @@
     ~SharedImageData();
     SharedImageData& operator=(SharedImageData&& other);
 
-    SharedImageRepresentationGLTexturePassthrough* representation() const {
+    GLTexturePassthroughImageRepresentation* representation() const {
       return representation_.get();
     }
 
@@ -125,15 +124,13 @@
     bool is_being_accessed() const { return !!scoped_access_; }
 
    private:
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-        representation_;
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+    std::unique_ptr<GLTexturePassthroughImageRepresentation> representation_;
+    std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
         scoped_access_;
   };
-  // Mapping of client texture IDs to
-  // SharedImageRepresentationGLTexturePassthroughs.
+  // Mapping of client texture IDs to GLTexturePassthroughImageRepresentations.
   // TODO(ericrk): Remove this once TexturePassthrough holds a reference to
-  // the SharedImageRepresentationGLTexturePassthrough itself.
+  // the GLTexturePassthroughImageRepresentation itself.
   base::flat_map<GLuint, SharedImageData> texture_shared_image_map;
 
   // A set of yet-to-be-deleted TexturePassthrough, which should be tossed
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
index 57612d7..3afa579 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc
@@ -13,7 +13,7 @@
 namespace gpu {
 namespace gles2 {
 namespace {
-std::unique_ptr<TestSharedImageBacking> AllocateTextureAndCreateSharedImage(
+std::unique_ptr<TestImageBacking> AllocateTextureAndCreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -27,9 +27,9 @@
   glTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size.width(),
                size.height(), 0, GLDataFormat(format), GLDataType(format),
                nullptr /* data */);
-  return std::make_unique<TestSharedImageBacking>(
-      mailbox, format, size, color_space, surface_origin, alpha_type, usage,
-      0 /* estimated_size */, service_id);
+  return std::make_unique<TestImageBacking>(mailbox, format, size, color_space,
+                                            surface_origin, alpha_type, usage,
+                                            0 /* estimated_size */, service_id);
 }
 
 }  // namespace
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
index 302c9e6..fbda9dd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -3077,7 +3077,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
-          std::make_unique<TestSharedImageBacking>(
+          std::make_unique<TestImageBacking>(
               mailbox, viz::ResourceFormat::RGBA_8888, gfx::Size(10, 10),
               gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
               0, 0, kNewServiceId),
@@ -3139,7 +3139,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
-          std::make_unique<TestSharedImageBacking>(
+          std::make_unique<TestImageBacking>(
               mailbox, viz::ResourceFormat::RGBA_8888, gfx::Size(10, 10),
               gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
               0, 0, kNewServiceId),
@@ -3163,7 +3163,7 @@
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       GetSharedImageManager()->Register(
-          std::make_unique<TestSharedImageBacking>(
+          std::make_unique<TestImageBacking>(
               mailbox, viz::ResourceFormat::RGBA_8888, gfx::Size(10, 10),
               gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
               0, 0, kNewServiceId),
@@ -3222,7 +3222,7 @@
   // Create a shared image.
   MemoryTypeTracker memory_tracker(memory_tracker_.get());
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
-  auto shared_image_backing = std::make_unique<TestSharedImageBacking>(
+  auto shared_image_backing = std::make_unique<TestImageBacking>(
       mailbox, viz::ResourceFormat::RGBA_8888, gfx::Size(10, 10),
       gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, 0, 0,
       kNewServiceId);
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 93506c1..94d72bf 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -331,8 +331,8 @@
   raw_ptr<Bug1307307Tracker> bug_1307307_tracker_;
 
   struct SharedImageReadAccess {
-    std::unique_ptr<SharedImageRepresentationSkia> shared_image_skia;
-    std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+    std::unique_ptr<SkiaImageRepresentation> shared_image_skia;
+    std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
         scoped_read_access;
     sk_sp<SkImage> read_access_sk_image;
   };
@@ -706,8 +706,8 @@
       gfx::Rect dest_cleared_rect,
       GLboolean unpack_flip_y,
       const Mailbox& source_mailbox,
-      SharedImageRepresentationSkia* dest_shared_image,
-      SharedImageRepresentationSkia::ScopedWriteAccess* dest_scoped_access,
+      SkiaImageRepresentation* dest_shared_image,
+      SkiaImageRepresentation::ScopedWriteAccess* dest_scoped_access,
       const std::vector<GrBackendSemaphore>& begin_semaphores,
       std::vector<GrBackendSemaphore>& end_semaphores);
   void DoWritePixelsINTERNAL(GLint x_offset,
@@ -722,7 +722,7 @@
                              GLuint shm_size,
                              const volatile GLbyte* mailbox);
   bool DoWritePixelsINTERNALDirectTextureUpload(
-      SharedImageRepresentationSkia* dest_shared_image,
+      SkiaImageRepresentation* dest_shared_image,
       const SkImageInfo& src_info,
       const void* pixel_data,
       size_t row_bytes);
@@ -754,19 +754,18 @@
   // `sk_subsampling`, `rgba_image, `num_yuva_images`, and `yuva_images` were
   // successfully populated. Return false on error. If this returns false, some
   // of the output arguments may be left populated.
-  bool ConvertYUVACommon(
-      const char* function_name,
-      GLenum yuv_color_space,
-      GLenum plane_config,
-      GLenum subsampling,
-      const volatile GLbyte* raw_mailboxes,
-      SkYUVColorSpace& sk_yuv_color_space,
-      SkYUVAInfo::PlaneConfig& sk_plane_config,
-      SkYUVAInfo::Subsampling& sk_subsampling,
-      std::unique_ptr<SharedImageRepresentationSkia>& rgba_image,
-      int& num_yuva_images,
-      std::array<std::unique_ptr<SharedImageRepresentationSkia>,
-                 SkYUVAInfo::kMaxPlanes>& yuva_images);
+  bool ConvertYUVACommon(const char* function_name,
+                         GLenum yuv_color_space,
+                         GLenum plane_config,
+                         GLenum subsampling,
+                         const volatile GLbyte* raw_mailboxes,
+                         SkYUVColorSpace& sk_yuv_color_space,
+                         SkYUVAInfo::PlaneConfig& sk_plane_config,
+                         SkYUVAInfo::Subsampling& sk_subsampling,
+                         std::unique_ptr<SkiaImageRepresentation>& rgba_image,
+                         int& num_yuva_images,
+                         std::array<std::unique_ptr<SkiaImageRepresentation>,
+                                    SkYUVAInfo::kMaxPlanes>& yuva_images);
 
   void DoConvertYUVAMailboxesToRGBINTERNAL(GLenum yuv_color_space,
                                            GLenum plane_config,
@@ -953,12 +952,12 @@
 
   // Raster helpers.
   scoped_refptr<ServiceFontManager> font_manager_;
-  std::unique_ptr<SharedImageRepresentationSkia> shared_image_;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation> shared_image_;
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_shared_image_write_;
 
-  std::unique_ptr<SharedImageRepresentationRaster> shared_image_raster_;
-  std::unique_ptr<SharedImageRepresentationRaster::ScopedWriteAccess>
+  std::unique_ptr<RasterImageRepresentation> shared_image_raster_;
+  std::unique_ptr<RasterImageRepresentation::ScopedWriteAccess>
       scoped_shared_image_raster_write_;
 
   Bug1307307Tracker bug_1307307_tracker_;
@@ -1344,8 +1343,7 @@
         feature_info()->feature_flags().enable_texture_half_float_linear;
   }
 #if BUILDFLAG(IS_WIN)
-  caps.shared_image_swap_chain =
-      SharedImageBackingFactoryD3D::IsSwapChainSupported();
+  caps.shared_image_swap_chain = D3DImageBackingFactory::IsSwapChainSupported();
 #endif  // BUILDFLAG(IS_WIN)
   caps.disable_legacy_mailbox = disable_legacy_mailbox_;
   return caps;
@@ -2177,7 +2175,7 @@
   std::vector<GrBackendSemaphore> end_semaphores;
 
   // Allow uncleared access, as we manually handle clear tracking.
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       dest_scoped_access = dest_shared_image->BeginScopedWriteAccess(
           &begin_semaphores, &end_semaphores,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -2226,7 +2224,7 @@
     return;
   }
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       source_scoped_access = source_shared_image->BeginScopedReadAccess(
           &begin_semaphores, &end_semaphores);
 
@@ -2289,8 +2287,8 @@
     gfx::Rect dest_cleared_rect,
     GLboolean unpack_flip_y,
     const Mailbox& source_mailbox,
-    SharedImageRepresentationSkia* dest_shared_image,
-    SharedImageRepresentationSkia::ScopedWriteAccess* dest_scoped_access,
+    SkiaImageRepresentation* dest_shared_image,
+    SkiaImageRepresentation::ScopedWriteAccess* dest_scoped_access,
     const std::vector<GrBackendSemaphore>& begin_semaphores,
     std::vector<GrBackendSemaphore>& end_semaphores) {
   if (unpack_flip_y)
@@ -2444,7 +2442,7 @@
   std::vector<GrBackendSemaphore> end_semaphores;
 
   // Allow uncleared access, as we manually handle clear tracking.
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       dest_scoped_access = dest_shared_image->BeginScopedWriteAccess(
           &begin_semaphores, &end_semaphores,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -2483,7 +2481,7 @@
 }
 
 bool RasterDecoderImpl::DoWritePixelsINTERNALDirectTextureUpload(
-    SharedImageRepresentationSkia* dest_shared_image,
+    SkiaImageRepresentation* dest_shared_image,
     const SkImageInfo& src_info,
     const void* pixel_data,
     size_t row_bytes) {
@@ -2491,7 +2489,7 @@
   std::vector<GrBackendSemaphore> end_semaphores;
 
   // Allow uncleared access, as we manually handle clear tracking.
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       dest_scoped_access = dest_shared_image->BeginScopedWriteAccess(
           &begin_semaphores, &end_semaphores,
           SharedImageRepresentation::AllowUnclearedAccess::kYes,
@@ -2627,7 +2625,7 @@
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       source_scoped_access = source_shared_image->BeginScopedReadAccess(
           &begin_semaphores, &end_semaphores);
 
@@ -2736,7 +2734,7 @@
 
   // We don't use |end_semaphores| here because we're going to sync with
   // with the CPU later regardless.
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       source_scoped_access = source_shared_image->BeginScopedReadAccess(
           &begin_semaphores, &end_semaphores);
 
@@ -2904,9 +2902,9 @@
     SkYUVColorSpace& sk_yuv_color_space,
     SkYUVAInfo::PlaneConfig& sk_plane_config,
     SkYUVAInfo::Subsampling& sk_subsampling,
-    std::unique_ptr<SharedImageRepresentationSkia>& rgba_image,
+    std::unique_ptr<SkiaImageRepresentation>& rgba_image,
     int& num_yuva_planes,
-    std::array<std::unique_ptr<SharedImageRepresentationSkia>,
+    std::array<std::unique_ptr<SkiaImageRepresentation>,
                SkYUVAInfo::kMaxPlanes>& yuva_images) {
   if (yuv_color_space_in > kLastEnum_SkYUVColorSpace) {
     LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, function_name,
@@ -2978,10 +2976,9 @@
   SkYUVColorSpace src_color_space;
   SkYUVAInfo::PlaneConfig src_plane_config;
   SkYUVAInfo::Subsampling src_subsampling;
-  std::unique_ptr<SharedImageRepresentationSkia> rgba_image;
+  std::unique_ptr<SkiaImageRepresentation> rgba_image;
   int num_src_planes;
-  std::array<std::unique_ptr<SharedImageRepresentationSkia>,
-             SkYUVAInfo::kMaxPlanes>
+  std::array<std::unique_ptr<SkiaImageRepresentation>, SkYUVAInfo::kMaxPlanes>
       yuva_images;
   if (!ConvertYUVACommon("ConvertYUVAMailboxesToRGB", planes_yuv_color_space,
                          plane_config, subsampling, mailboxes_in,
@@ -3004,7 +3001,7 @@
   }
 
   bool source_access_valid = true;
-  std::array<std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>,
+  std::array<std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>,
              SkYUVAInfo::kMaxPlanes>
       source_scoped_access;
   for (int i = 0; i < num_src_planes; ++i) {
@@ -3076,10 +3073,9 @@
   SkYUVColorSpace dst_color_space;
   SkYUVAInfo::PlaneConfig dst_plane_config;
   SkYUVAInfo::Subsampling dst_subsampling;
-  std::unique_ptr<SharedImageRepresentationSkia> rgba_image;
+  std::unique_ptr<SkiaImageRepresentation> rgba_image;
   int num_yuva_planes;
-  std::array<std::unique_ptr<SharedImageRepresentationSkia>,
-             SkYUVAInfo::kMaxPlanes>
+  std::array<std::unique_ptr<SkiaImageRepresentation>, SkYUVAInfo::kMaxPlanes>
       yuva_images;
   if (!ConvertYUVACommon("ConvertYUVAMailboxesToRGB", yuv_color_space,
                          plane_config, subsampling, mailboxes_in,
@@ -3107,7 +3103,7 @@
     return;
   }
 
-  std::array<std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>,
+  std::array<std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>,
              SkYUVAInfo::kMaxPlanes>
       yuva_scoped_access;
   for (int i = 0; i < num_yuva_planes; ++i) {
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc
index 7bfa4ba9c..3904ecc 100644
--- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc
@@ -119,24 +119,25 @@
 // Implementation of SharedImageBacking that holds an AHardwareBuffer. This
 // can be used to create a GL texture or a VK Image from the AHardwareBuffer
 // backing.
-class SharedImageBackingAHB : public SharedImageBackingAndroid {
+class AHardwareBufferImageBacking : public AndroidImageBacking {
  public:
-  SharedImageBackingAHB(const Mailbox& mailbox,
-                        viz::ResourceFormat format,
-                        const gfx::Size& size,
-                        const gfx::ColorSpace& color_space,
-                        GrSurfaceOrigin surface_origin,
-                        SkAlphaType alpha_type,
-                        uint32_t usage,
-                        base::android::ScopedHardwareBufferHandle handle,
-                        size_t estimated_size,
-                        bool is_thread_safe,
-                        base::ScopedFD initial_upload_fd);
+  AHardwareBufferImageBacking(const Mailbox& mailbox,
+                              viz::ResourceFormat format,
+                              const gfx::Size& size,
+                              const gfx::ColorSpace& color_space,
+                              GrSurfaceOrigin surface_origin,
+                              SkAlphaType alpha_type,
+                              uint32_t usage,
+                              base::android::ScopedHardwareBufferHandle handle,
+                              size_t estimated_size,
+                              bool is_thread_safe,
+                              base::ScopedFD initial_upload_fd);
 
-  SharedImageBackingAHB(const SharedImageBackingAHB&) = delete;
-  SharedImageBackingAHB& operator=(const SharedImageBackingAHB&) = delete;
+  AHardwareBufferImageBacking(const AHardwareBufferImageBacking&) = delete;
+  AHardwareBufferImageBacking& operator=(const AHardwareBufferImageBacking&) =
+      delete;
 
-  ~SharedImageBackingAHB() override;
+  ~AHardwareBufferImageBacking() override;
 
   // SharedImageBacking implementation.
   SharedImageBackingType GetType() const override;
@@ -152,20 +153,20 @@
   void EndOverlayAccess();
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
@@ -178,20 +179,18 @@
   scoped_refptr<OverlayImage> overlay_image_ GUARDED_BY(lock_);
 };
 
-// Vk backed Skia representation of SharedImageBackingAHB.
-class SharedImageRepresentationSkiaVkAHB
-    : public SharedImageRepresentationSkiaVkAndroid {
+// Vk backed Skia representation of AHardwareBufferImageBacking.
+class SkiaVkAHBImageRepresentation : public SkiaVkAndroidImageRepresentation {
  public:
-  SharedImageRepresentationSkiaVkAHB(
-      SharedImageManager* manager,
-      SharedImageBackingAndroid* backing,
-      scoped_refptr<SharedContextState> context_state,
-      std::unique_ptr<VulkanImage> vulkan_image,
-      MemoryTypeTracker* tracker)
-      : SharedImageRepresentationSkiaVkAndroid(manager,
-                                               backing,
-                                               std::move(context_state),
-                                               tracker) {
+  SkiaVkAHBImageRepresentation(SharedImageManager* manager,
+                               AndroidImageBacking* backing,
+                               scoped_refptr<SharedContextState> context_state,
+                               std::unique_ptr<VulkanImage> vulkan_image,
+                               MemoryTypeTracker* tracker)
+      : SkiaVkAndroidImageRepresentation(manager,
+                                         backing,
+                                         std::move(context_state),
+                                         tracker) {
     DCHECK(vulkan_image);
 
     vulkan_image_ = std::move(vulkan_image);
@@ -204,19 +203,18 @@
   }
 };
 
-class SharedImageRepresentationOverlayAHB
-    : public SharedImageRepresentationOverlay {
+class OverlayAHBImageRepresentation : public OverlayImageRepresentation {
  public:
-  SharedImageRepresentationOverlayAHB(SharedImageManager* manager,
-                                      SharedImageBacking* backing,
-                                      MemoryTypeTracker* tracker)
-      : SharedImageRepresentationOverlay(manager, backing, tracker) {}
+  OverlayAHBImageRepresentation(SharedImageManager* manager,
+                                SharedImageBacking* backing,
+                                MemoryTypeTracker* tracker)
+      : OverlayImageRepresentation(manager, backing, tracker) {}
 
-  ~SharedImageRepresentationOverlayAHB() override { EndReadAccess({}); }
+  ~OverlayAHBImageRepresentation() override { EndReadAccess({}); }
 
  private:
-  SharedImageBackingAHB* ahb_backing() {
-    return static_cast<SharedImageBackingAHB*>(backing());
+  AHardwareBufferImageBacking* ahb_backing() {
+    return static_cast<AHardwareBufferImageBacking*>(backing());
   }
 
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override {
@@ -242,7 +240,7 @@
   raw_ptr<gl::GLImage> gl_image_ = nullptr;
 };
 
-SharedImageBackingAHB::SharedImageBackingAHB(
+AHardwareBufferImageBacking::AHardwareBufferImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -254,21 +252,21 @@
     size_t estimated_size,
     bool is_thread_safe,
     base::ScopedFD initial_upload_fd)
-    : SharedImageBackingAndroid(mailbox,
-                                format,
-                                size,
-                                color_space,
-                                surface_origin,
-                                alpha_type,
-                                usage,
-                                estimated_size,
-                                is_thread_safe,
-                                std::move(initial_upload_fd)),
+    : AndroidImageBacking(mailbox,
+                          format,
+                          size,
+                          color_space,
+                          surface_origin,
+                          alpha_type,
+                          usage,
+                          estimated_size,
+                          is_thread_safe,
+                          std::move(initial_upload_fd)),
       hardware_buffer_handle_(std::move(handle)) {
   DCHECK(hardware_buffer_handle_.is_valid());
 }
 
-SharedImageBackingAHB::~SharedImageBackingAHB() {
+AHardwareBufferImageBacking::~AHardwareBufferImageBacking() {
   // Locking here in destructor since we are accessing member variable
   // |have_context_| via have_context().
   AutoLock auto_lock(this);
@@ -279,11 +277,11 @@
   }
 }
 
-SharedImageBackingType SharedImageBackingAHB::GetType() const {
-  return SharedImageBackingType::kAHB;
+SharedImageBackingType AHardwareBufferImageBacking::GetType() const {
+  return SharedImageBackingType::kAHardwareBuffer;
 }
 
-gfx::Rect SharedImageBackingAHB::ClearedRect() const {
+gfx::Rect AHardwareBufferImageBacking::ClearedRect() const {
   AutoLock auto_lock(this);
   // If a |legacy_texture_| exists, defer to that. Once created,
   // |legacy_texture_| is never destroyed, so no need to synchronize with
@@ -295,7 +293,8 @@
   }
 }
 
-void SharedImageBackingAHB::SetClearedRect(const gfx::Rect& cleared_rect) {
+void AHardwareBufferImageBacking::SetClearedRect(
+    const gfx::Rect& cleared_rect) {
   AutoLock auto_lock(this);
   // If a |legacy_texture_| exists, defer to that. Once created,
   // |legacy_texture_| is never destroyed, so no need to synchronize with
@@ -308,11 +307,12 @@
   }
 }
 
-void SharedImageBackingAHB::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
+void AHardwareBufferImageBacking::Update(
+    std::unique_ptr<gfx::GpuFence> in_fence) {
   DCHECK(!in_fence);
 }
 
-bool SharedImageBackingAHB::ProduceLegacyMailbox(
+bool AHardwareBufferImageBacking::ProduceLegacyMailbox(
     MailboxManager* mailbox_manager) {
   // Legacy mailboxes cannot be used safely in threadsafe mode.
   if (is_thread_safe())
@@ -335,14 +335,14 @@
   return true;
 }
 
-base::android::ScopedHardwareBufferHandle SharedImageBackingAHB::GetAhbHandle()
-    const {
+base::android::ScopedHardwareBufferHandle
+AHardwareBufferImageBacking::GetAhbHandle() const {
   return hardware_buffer_handle_.Clone();
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingAHB::ProduceGLTexture(SharedImageManager* manager,
-                                        MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+AHardwareBufferImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                              MemoryTypeTracker* tracker) {
   // Use same texture for all the texture representations generated from same
   // backing.
   DCHECK(hardware_buffer_handle_.is_valid());
@@ -358,13 +358,14 @@
   if (!texture)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationGLTextureAndroid>(
+  return std::make_unique<GLTextureAndroidImageRepresentation>(
       manager, this, tracker, std::move(texture));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingAHB::ProduceGLTexturePassthrough(SharedImageManager* manager,
-                                                   MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+AHardwareBufferImageBacking::ProduceGLTexturePassthrough(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
   // Use same texture for all the texture representations generated from same
   // backing.
   DCHECK(hardware_buffer_handle_.is_valid());
@@ -380,12 +381,12 @@
   if (!texture)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughAndroid>(
+  return std::make_unique<GLTexturePassthroughAndroidImageRepresentation>(
       manager, this, tracker, std::move(texture));
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingAHB::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation>
+AHardwareBufferImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -406,7 +407,7 @@
     if (!vulkan_image)
       return nullptr;
 
-    return std::make_unique<SharedImageRepresentationSkiaVkAHB>(
+    return std::make_unique<SkiaVkAHBImageRepresentation>(
         manager, this, std::move(context_state), std::move(vulkan_image),
         tracker);
   }
@@ -418,21 +419,21 @@
   if (!texture)
     return nullptr;
   auto gl_representation =
-      std::make_unique<SharedImageRepresentationGLTextureAndroid>(
+      std::make_unique<GLTextureAndroidImageRepresentation>(
           manager, this, tracker, std::move(texture));
-  return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation),
-                                                 std::move(context_state),
-                                                 manager, this, tracker);
+  return SkiaGLImageRepresentation::Create(std::move(gl_representation),
+                                           std::move(context_state), manager,
+                                           this, tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingAHB::ProduceOverlay(SharedImageManager* manager,
-                                      MemoryTypeTracker* tracker) {
-  return std::make_unique<SharedImageRepresentationOverlayAHB>(manager, this,
-                                                               tracker);
+std::unique_ptr<OverlayImageRepresentation>
+AHardwareBufferImageBacking::ProduceOverlay(SharedImageManager* manager,
+                                            MemoryTypeTracker* tracker) {
+  return std::make_unique<OverlayAHBImageRepresentation>(manager, this,
+                                                         tracker);
 }
 
-gl::GLImage* SharedImageBackingAHB::BeginOverlayAccess(
+gl::GLImage* AHardwareBufferImageBacking::BeginOverlayAccess(
     gfx::GpuFenceHandle& begin_read_fence) {
   AutoLock auto_lock(this);
 
@@ -461,7 +462,7 @@
   return overlay_image_.get();
 }
 
-void SharedImageBackingAHB::EndOverlayAccess() {
+void AHardwareBufferImageBacking::EndOverlayAccess() {
   AutoLock auto_lock(this);
 
   DCHECK(is_overlay_accessing_);
@@ -471,7 +472,7 @@
   read_sync_fd_ = gl::MergeFDs(std::move(read_sync_fd_), std::move(fence_fd));
 }
 
-SharedImageBackingFactoryAHB::SharedImageBackingFactoryAHB(
+AHardwareBufferImageBackingFactory::AHardwareBufferImageBackingFactory(
     const gles2::FeatureInfo* feature_info) {
   DCHECK(base::AndroidHardwareBufferCompat::IsSupportAvailable());
   const gles2::Validators* validators = feature_info->validators();
@@ -536,9 +537,10 @@
   max_gl_texture_size_ = std::min(max_gl_texture_size_, INT_MAX - 1);
 }
 
-SharedImageBackingFactoryAHB::~SharedImageBackingFactoryAHB() = default;
+AHardwareBufferImageBackingFactory::~AHardwareBufferImageBackingFactory() =
+    default;
 
-bool SharedImageBackingFactoryAHB::ValidateUsage(
+bool AHardwareBufferImageBackingFactory::ValidateUsage(
     uint32_t usage,
     const gfx::Size& size,
     viz::ResourceFormat format) const {
@@ -587,7 +589,8 @@
   return true;
 }
 
-std::unique_ptr<SharedImageBacking> SharedImageBackingFactoryAHB::MakeBacking(
+std::unique_ptr<SharedImageBacking>
+AHardwareBufferImageBackingFactory::MakeBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -681,7 +684,7 @@
     initial_upload_fd = base::ScopedFD(fence);
   }
 
-  auto backing = std::make_unique<SharedImageBackingAHB>(
+  auto backing = std::make_unique<AHardwareBufferImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(handle), estimated_size, is_thread_safe,
       std::move(initial_upload_fd));
@@ -694,7 +697,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAHB::CreateSharedImage(
+AHardwareBufferImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -709,7 +712,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAHB::CreateSharedImage(
+AHardwareBufferImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -722,12 +725,12 @@
                      alpha_type, usage, false, pixel_data);
 }
 
-bool SharedImageBackingFactoryAHB::CanImportGpuMemoryBuffer(
+bool AHardwareBufferImageBackingFactory::CanImportGpuMemoryBuffer(
     gfx::GpuMemoryBufferType memory_buffer_type) {
   return memory_buffer_type == gfx::ANDROID_HARDWARE_BUFFER;
 }
 
-bool SharedImageBackingFactoryAHB::IsSupported(
+bool AHardwareBufferImageBackingFactory::IsSupported(
     uint32_t usage,
     viz::ResourceFormat format,
     bool thread_safe,
@@ -753,7 +756,7 @@
   return true;
 }
 
-bool SharedImageBackingFactoryAHB::IsFormatSupported(
+bool AHardwareBufferImageBackingFactory::IsFormatSupported(
     viz::ResourceFormat format) {
   DCHECK_GE(format, 0);
   DCHECK_LE(format, viz::RESOURCE_FORMAT_MAX);
@@ -761,11 +764,11 @@
   return format_info_[format].ahb_supported;
 }
 
-SharedImageBackingFactoryAHB::FormatInfo::FormatInfo() = default;
-SharedImageBackingFactoryAHB::FormatInfo::~FormatInfo() = default;
+AHardwareBufferImageBackingFactory::FormatInfo::FormatInfo() = default;
+AHardwareBufferImageBackingFactory::FormatInfo::~FormatInfo() = default;
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAHB::CreateSharedImage(
+AHardwareBufferImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -800,7 +803,7 @@
     return nullptr;
   }
 
-  auto backing = std::make_unique<SharedImageBackingAHB>(
+  auto backing = std::make_unique<AHardwareBufferImageBacking>(
       mailbox, resource_format, size, color_space, surface_origin, alpha_type,
       usage, std::move(handle.android_hardware_buffer), estimated_size, false,
       base::ScopedFD());
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.h b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.h
index ae89122..3d770835 100644
--- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.h
@@ -26,16 +26,18 @@
 
 // Implementation of SharedImageBackingFactory that produces AHardwareBuffer
 // backed SharedImages. This is meant to be used on Android only.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryAHB
+class GPU_GLES2_EXPORT AHardwareBufferImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  explicit SharedImageBackingFactoryAHB(const gles2::FeatureInfo* feature_info);
+  explicit AHardwareBufferImageBackingFactory(
+      const gles2::FeatureInfo* feature_info);
 
-  SharedImageBackingFactoryAHB(const SharedImageBackingFactoryAHB&) = delete;
-  SharedImageBackingFactoryAHB& operator=(const SharedImageBackingFactoryAHB&) =
-      delete;
+  AHardwareBufferImageBackingFactory(
+      const AHardwareBufferImageBackingFactory&) = delete;
+  AHardwareBufferImageBackingFactory& operator=(
+      const AHardwareBufferImageBackingFactory&) = delete;
 
-  ~SharedImageBackingFactoryAHB() override;
+  ~AHardwareBufferImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation.
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
index 8fec8bee..f6c529e9 100644
--- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
@@ -39,7 +39,7 @@
 namespace gpu {
 namespace {
 
-class SharedImageBackingFactoryAHBTest : public testing::Test {
+class AHardwareBufferImageBackingFactoryTest : public testing::Test {
  public:
   void SetUp() override {
     // AHardwareBuffer is only supported on ANDROID O+. Hence these tests
@@ -66,7 +66,7 @@
         base::MakeRefCounted<gles2::FeatureInfo>(workarounds, GpuFeatureInfo());
     context_state_->InitializeGL(GpuPreferences(), std::move(feature_info));
 
-    backing_factory_ = std::make_unique<SharedImageBackingFactoryAHB>(
+    backing_factory_ = std::make_unique<AHardwareBufferImageBackingFactory>(
         context_state_->feature_info());
 
     memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr);
@@ -81,7 +81,7 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<SharedContextState> context_state_;
-  std::unique_ptr<SharedImageBackingFactoryAHB> backing_factory_;
+  std::unique_ptr<AHardwareBufferImageBackingFactory> backing_factory_;
   gles2::MailboxManagerImpl mailbox_manager_;
   SharedImageManager shared_image_manager_;
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
@@ -92,7 +92,7 @@
 class GlLegacySharedImage {
  public:
   GlLegacySharedImage(
-      SharedImageBackingFactoryAHB* backing_factory,
+      AHardwareBufferImageBackingFactory* backing_factory,
       bool is_thread_safe,
       gles2::MailboxManagerImpl* mailbox_manager,
       SharedImageManager* shared_image_manager,
@@ -112,7 +112,7 @@
 };
 
 // Basic test to check creation and deletion of AHB backed shared image.
-TEST_F(SharedImageBackingFactoryAHBTest, Basic) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, Basic) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -121,13 +121,13 @@
       &mailbox_manager_,          &shared_image_manager_,
       memory_type_tracker_.get(), shared_image_representation_factory_.get()};
 
-  // Finally, validate a SharedImageRepresentationSkia.
+  // Finally, validate a SkiaImageRepresentation.
   auto skia_representation = shared_image_representation_factory_->ProduceSkia(
       gl_legacy_shared_image.mailbox(), context_state_.get());
   EXPECT_TRUE(skia_representation);
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -141,8 +141,7 @@
   EXPECT_EQ(0u, end_semaphores.size());
   scoped_write_access.reset();
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   EXPECT_TRUE(scoped_read_access);
@@ -161,7 +160,7 @@
 // Test to check interaction between Gl and skia GL representations.
 // We write to a GL texture using gl representation and then read from skia
 // representation.
-TEST_F(SharedImageBackingFactoryAHBTest, GLSkiaGL) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, GLSkiaGL) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -184,7 +183,7 @@
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
 
-  // Create a SharedImageRepresentationGLTexture.
+  // Create a GLTextureImageRepresentation.
   auto gl_representation =
       shared_image_representation_factory_->ProduceGLTexture(mailbox);
   EXPECT_TRUE(gl_representation);
@@ -223,7 +222,7 @@
   EXPECT_FALSE(mailbox_manager_.ConsumeTexture(mailbox));
 }
 
-TEST_F(SharedImageBackingFactoryAHBTest, InitialData) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, InitialData) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -262,7 +261,7 @@
 }
 
 // Test to check invalid format support.
-TEST_F(SharedImageBackingFactoryAHBTest, InvalidFormat) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, InvalidFormat) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -281,7 +280,7 @@
 }
 
 // Test to check invalid size support.
-TEST_F(SharedImageBackingFactoryAHBTest, InvalidSize) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, InvalidSize) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -305,7 +304,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_F(SharedImageBackingFactoryAHBTest, EstimatedSize) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, EstimatedSize) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -335,7 +334,7 @@
 
 // TODO(crbug/994720): Failing on Android builders.
 // Test to check that only one context can write at a time
-TEST_F(SharedImageBackingFactoryAHBTest, DISABLED_OnlyOneWriter) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, DISABLED_OnlyOneWriter) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -349,7 +348,7 @@
 
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -362,7 +361,7 @@
       gl_legacy_shared_image.mailbox(), context_state_.get());
   std::vector<GrBackendSemaphore> begin_semaphores2;
   std::vector<GrBackendSemaphore> end_semaphores2;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access2;
   scoped_write_access2 = skia_representation2->BeginScopedWriteAccess(
       &begin_semaphores2, &end_semaphores2,
@@ -377,7 +376,7 @@
 }
 
 // Test to check that multiple readers are allowed
-TEST_F(SharedImageBackingFactoryAHBTest, CanHaveMultipleReaders) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, CanHaveMultipleReaders) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -393,15 +392,14 @@
 
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   EXPECT_TRUE(scoped_read_access);
   EXPECT_EQ(0u, begin_semaphores.size());
   EXPECT_EQ(0u, end_semaphores.size());
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       scoped_read_access2;
   scoped_read_access2 = skia_representation2->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
@@ -416,7 +414,7 @@
 }
 
 // Test to check that a context cannot write while another context is reading
-TEST_F(SharedImageBackingFactoryAHBTest, CannotWriteWhileReading) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, CannotWriteWhileReading) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -431,8 +429,7 @@
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   EXPECT_TRUE(scoped_read_access);
@@ -445,7 +442,7 @@
   std::vector<GrBackendSemaphore> begin_semaphores2;
   std::vector<GrBackendSemaphore> end_semaphores2;
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation2->BeginScopedWriteAccess(
       &begin_semaphores2, &end_semaphores2,
@@ -460,7 +457,7 @@
 }
 
 // Test to check that a context cannot read while another context is writing
-TEST_F(SharedImageBackingFactoryAHBTest, CannotReadWhileWriting) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, CannotReadWhileWriting) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -473,7 +470,7 @@
       gl_legacy_shared_image.mailbox(), context_state_.get());
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -486,8 +483,7 @@
       gl_legacy_shared_image.mailbox(), context_state_.get());
   std::vector<GrBackendSemaphore> begin_semaphores2;
   std::vector<GrBackendSemaphore> end_semaphores2;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation2->BeginScopedReadAccess(
       &begin_semaphores2, &end_semaphores2);
   EXPECT_FALSE(scoped_read_access);
@@ -501,7 +497,7 @@
 
 // Test to check that setting/unsetting legacy shared image mailboxes works as
 // expected.
-TEST_F(SharedImageBackingFactoryAHBTest, LegacyClearing) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, LegacyClearing) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
@@ -557,7 +553,7 @@
 }
 
 GlLegacySharedImage::GlLegacySharedImage(
-    SharedImageBackingFactoryAHB* backing_factory,
+    AHardwareBufferImageBackingFactory* backing_factory,
     bool is_thread_safe,
     gles2::MailboxManagerImpl* mailbox_manager,
     SharedImageManager* shared_image_manager,
@@ -634,7 +630,7 @@
   EXPECT_FALSE(mailbox_manager_->ConsumeTexture(mailbox_));
 }
 
-TEST_F(SharedImageBackingFactoryAHBTest, Overlay) {
+TEST_F(AHardwareBufferImageBackingFactoryTest, Overlay) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
diff --git a/gpu/command_buffer/service/shared_image/android_image_backing.cc b/gpu/command_buffer/service/shared_image/android_image_backing.cc
index 4b966b3..45cc8fd3 100644
--- a/gpu/command_buffer/service/shared_image/android_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/android_image_backing.cc
@@ -10,17 +10,16 @@
 
 namespace gpu {
 
-SharedImageBackingAndroid::SharedImageBackingAndroid(
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage,
-    size_t estimated_size,
-    bool is_thread_safe,
-    base::ScopedFD initial_upload_fd)
+AndroidImageBacking::AndroidImageBacking(const Mailbox& mailbox,
+                                         viz::ResourceFormat format,
+                                         const gfx::Size& size,
+                                         const gfx::ColorSpace& color_space,
+                                         GrSurfaceOrigin surface_origin,
+                                         SkAlphaType alpha_type,
+                                         uint32_t usage,
+                                         size_t estimated_size,
+                                         bool is_thread_safe,
+                                         base::ScopedFD initial_upload_fd)
     : ClearTrackingSharedImageBacking(mailbox,
                                       format,
                                       size,
@@ -32,9 +31,9 @@
                                       is_thread_safe),
       write_sync_fd_(std::move(initial_upload_fd)) {}
 
-SharedImageBackingAndroid::~SharedImageBackingAndroid() = default;
+AndroidImageBacking::~AndroidImageBacking() = default;
 
-bool SharedImageBackingAndroid::BeginWrite(base::ScopedFD* fd_to_wait_on) {
+bool AndroidImageBacking::BeginWrite(base::ScopedFD* fd_to_wait_on) {
   AutoLock auto_lock(this);
 
   if (is_writing_ || !active_readers_.empty() || is_overlay_accessing_) {
@@ -50,7 +49,7 @@
   return true;
 }
 
-void SharedImageBackingAndroid::EndWrite(base::ScopedFD end_write_fd) {
+void AndroidImageBacking::EndWrite(base::ScopedFD end_write_fd) {
   AutoLock auto_lock(this);
 
   if (!is_writing_) {
@@ -64,9 +63,8 @@
   write_sync_fd_ = std::move(end_write_fd);
 }
 
-bool SharedImageBackingAndroid::BeginRead(
-    const SharedImageRepresentation* reader,
-    base::ScopedFD* fd_to_wait_on) {
+bool AndroidImageBacking::BeginRead(const SharedImageRepresentation* reader,
+                                    base::ScopedFD* fd_to_wait_on) {
   AutoLock auto_lock(this);
 
   if (is_writing_) {
@@ -90,8 +88,8 @@
   return true;
 }
 
-void SharedImageBackingAndroid::EndRead(const SharedImageRepresentation* reader,
-                                        base::ScopedFD end_read_fd) {
+void AndroidImageBacking::EndRead(const SharedImageRepresentation* reader,
+                                  base::ScopedFD end_read_fd) {
   AutoLock auto_lock(this);
 
   if (!active_readers_.contains(reader)) {
@@ -106,7 +104,7 @@
       gl::MergeFDs(std::move(read_sync_fd_), std::move(end_read_fd));
 }
 
-base::ScopedFD SharedImageBackingAndroid::TakeReadFence() {
+base::ScopedFD AndroidImageBacking::TakeReadFence() {
   AutoLock auto_lock(this);
 
   return std::move(read_sync_fd_);
diff --git a/gpu/command_buffer/service/shared_image/android_image_backing.h b/gpu/command_buffer/service/shared_image/android_image_backing.h
index 5f79967..a2fae31e 100644
--- a/gpu/command_buffer/service/shared_image/android_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/android_image_backing.h
@@ -11,20 +11,22 @@
 
 namespace gpu {
 
-class SharedImageBackingAndroid : public ClearTrackingSharedImageBacking {
+class AndroidImageBacking : public ClearTrackingSharedImageBacking {
  public:
-  SharedImageBackingAndroid(const Mailbox& mailbox,
-                            viz::ResourceFormat format,
-                            const gfx::Size& size,
-                            const gfx::ColorSpace& color_space,
-                            GrSurfaceOrigin surface_origin,
-                            SkAlphaType alpha_type,
-                            uint32_t usage,
-                            size_t estimated_size,
-                            bool is_thread_safe,
-                            base::ScopedFD initial_upload_fd);
+  AndroidImageBacking(const Mailbox& mailbox,
+                      viz::ResourceFormat format,
+                      const gfx::Size& size,
+                      const gfx::ColorSpace& color_space,
+                      GrSurfaceOrigin surface_origin,
+                      SkAlphaType alpha_type,
+                      uint32_t usage,
+                      size_t estimated_size,
+                      bool is_thread_safe,
+                      base::ScopedFD initial_upload_fd);
 
-  ~SharedImageBackingAndroid() override;
+  ~AndroidImageBacking() override;
+  AndroidImageBacking(const AndroidImageBacking&) = delete;
+  AndroidImageBacking& operator=(const AndroidImageBacking&) = delete;
 
   virtual bool BeginWrite(base::ScopedFD* fd_to_wait_on);
   virtual void EndWrite(base::ScopedFD end_write_fd);
@@ -45,10 +47,6 @@
       GUARDED_BY(lock_);
 
   bool is_overlay_accessing_ GUARDED_BY(lock_) = false;
-
-  SharedImageBackingAndroid(const SharedImageBackingAndroid&) = delete;
-  SharedImageBackingAndroid& operator=(const SharedImageBackingAndroid&) =
-      delete;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
index d13ec80f05..5bb51dd 100644
--- a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
@@ -22,13 +22,14 @@
 
 namespace gpu {
 
-SharedImageVideo::SharedImageVideo(const Mailbox& mailbox,
-                                   const gfx::Size& size,
-                                   const gfx::ColorSpace color_space,
-                                   GrSurfaceOrigin surface_origin,
-                                   SkAlphaType alpha_type,
-                                   bool is_thread_safe)
-    : SharedImageBackingAndroid(
+AndroidVideoImageBacking::AndroidVideoImageBacking(
+    const Mailbox& mailbox,
+    const gfx::Size& size,
+    const gfx::ColorSpace color_space,
+    GrSurfaceOrigin surface_origin,
+    SkAlphaType alpha_type,
+    bool is_thread_safe)
+    : AndroidImageBacking(
           mailbox,
           viz::RGBA_8888,
           size,
@@ -41,10 +42,10 @@
           is_thread_safe,
           base::ScopedFD()) {}
 
-SharedImageVideo::~SharedImageVideo() {}
+AndroidVideoImageBacking::~AndroidVideoImageBacking() {}
 
 // Static.
-std::unique_ptr<SharedImageVideo> SharedImageVideo::Create(
+std::unique_ptr<AndroidVideoImageBacking> AndroidVideoImageBacking::Create(
     const Mailbox& mailbox,
     const gfx::Size& size,
     const gfx::ColorSpace color_space,
@@ -54,20 +55,20 @@
     scoped_refptr<SharedContextState> context_state,
     scoped_refptr<RefCountedLock> drdc_lock) {
   if (features::IsAImageReaderEnabled()) {
-    return std::make_unique<SharedImageVideoImageReader>(
+    return std::make_unique<VideoImageReaderImageBacking>(
         mailbox, size, color_space, surface_origin, alpha_type,
         std::move(stream_texture_sii), std::move(context_state),
         std::move(drdc_lock));
   } else {
     DCHECK(!drdc_lock);
-    return std::make_unique<SharedImageVideoSurfaceTexture>(
+    return std::make_unique<VideoSurfaceTextureImageBacking>(
         mailbox, size, color_space, surface_origin, alpha_type,
         std::move(stream_texture_sii), std::move(context_state));
   }
 }
 
 // Static.
-absl::optional<VulkanYCbCrInfo> SharedImageVideo::GetYcbcrInfo(
+absl::optional<VulkanYCbCrInfo> AndroidVideoImageBacking::GetYcbcrInfo(
     TextureOwner* texture_owner,
     viz::VulkanContextProvider* vulkan_context_provider) {
   if (!vulkan_context_provider)
@@ -93,8 +94,8 @@
   return absl::optional<VulkanYCbCrInfo>(ycbcr_info);
 }
 
-std::unique_ptr<gles2::AbstractTexture> SharedImageVideo::GenAbstractTexture(
-    const bool passthrough) {
+std::unique_ptr<gles2::AbstractTexture>
+AndroidVideoImageBacking::GenAbstractTexture(const bool passthrough) {
   std::unique_ptr<gles2::AbstractTexture> texture;
   if (passthrough) {
     texture = std::make_unique<gles2::AbstractTextureImplPassthrough>(
@@ -108,24 +109,25 @@
   return texture;
 }
 
-SharedImageBackingType SharedImageVideo::GetType() const {
+SharedImageBackingType AndroidVideoImageBacking::GetType() const {
   return SharedImageBackingType::kVideo;
 }
 
-gfx::Rect SharedImageVideo::ClearedRect() const {
-  // SharedImageVideo objects are always created from pre-initialized textures
-  // provided by the media decoder. Always treat these as cleared (return the
-  // full rectangle).
+gfx::Rect AndroidVideoImageBacking::ClearedRect() const {
+  // AndroidVideoImageBacking objects are always created from pre-initialized
+  // textures provided by the media decoder. Always treat these as cleared
+  // (return the full rectangle).
   return gfx::Rect(size());
 }
 
-void SharedImageVideo::SetClearedRect(const gfx::Rect& cleared_rect) {}
+void AndroidVideoImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {}
 
-void SharedImageVideo::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
+void AndroidVideoImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   DCHECK(!in_fence);
 }
 
-bool SharedImageVideo::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
+bool AndroidVideoImageBacking::ProduceLegacyMailbox(
+    MailboxManager* mailbox_manager) {
   // Android does not use legacy mailbox anymore. Hence marking this as
   // NOTREACHED() now. Once all platform stops using legacy mailbox, this
   // method can be removed.
diff --git a/gpu/command_buffer/service/shared_image/android_video_image_backing.h b/gpu/command_buffer/service/shared_image/android_video_image_backing.h
index e2f31ed..1f37ff7 100644
--- a/gpu/command_buffer/service/shared_image/android_video_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/android_video_image_backing.h
@@ -30,9 +30,9 @@
 
 // Implementation of SharedImageBacking that renders MediaCodec buffers to a
 // TextureOwner or overlay as needed in order to draw them.
-class GPU_GLES2_EXPORT SharedImageVideo : public SharedImageBackingAndroid {
+class GPU_GLES2_EXPORT AndroidVideoImageBacking : public AndroidImageBacking {
  public:
-  static std::unique_ptr<SharedImageVideo> Create(
+  static std::unique_ptr<AndroidVideoImageBacking> Create(
       const Mailbox& mailbox,
       const gfx::Size& size,
       const gfx::ColorSpace color_space,
@@ -48,11 +48,11 @@
       TextureOwner* texture_owner,
       viz::VulkanContextProvider* vulkan_context_provider);
 
-  ~SharedImageVideo() override;
+  ~AndroidVideoImageBacking() override;
 
   // Disallow copy and assign.
-  SharedImageVideo(const SharedImageVideo&) = delete;
-  SharedImageVideo& operator=(const SharedImageVideo&) = delete;
+  AndroidVideoImageBacking(const AndroidVideoImageBacking&) = delete;
+  AndroidVideoImageBacking& operator=(const AndroidVideoImageBacking&) = delete;
 
   // SharedImageBacking implementation.
   SharedImageBackingType GetType() const override;
@@ -62,12 +62,12 @@
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
 
  protected:
-  SharedImageVideo(const Mailbox& mailbox,
-                   const gfx::Size& size,
-                   const gfx::ColorSpace color_space,
-                   GrSurfaceOrigin surface_origin,
-                   SkAlphaType alpha_type,
-                   bool is_thread_safe);
+  AndroidVideoImageBacking(const Mailbox& mailbox,
+                           const gfx::Size& size,
+                           const gfx::ColorSpace color_space,
+                           GrSurfaceOrigin surface_origin,
+                           SkAlphaType alpha_type,
+                           bool is_thread_safe);
 
   std::unique_ptr<gles2::AbstractTexture> GenAbstractTexture(
       const bool passthrough);
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
index a26f124..2487a39 100644
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
@@ -42,21 +42,21 @@
 }
 
 using ScopedResetAndRestoreUnpackState =
-    SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState;
+    GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState;
 
-using ScopedRestoreTexture = SharedImageBackingGLCommon::ScopedRestoreTexture;
+using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture;
 
-class AngleVulkanBacking : public ClearTrackingSharedImageBacking,
-                           public SharedImageRepresentationGLTextureClient {
+class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
+                                public GLTextureImageRepresentationClient {
  public:
-  AngleVulkanBacking(const raw_ptr<SharedContextState>& context_state,
-                     const Mailbox& mailbox,
-                     viz::ResourceFormat format,
-                     const gfx::Size& size,
-                     const gfx::ColorSpace& color_space,
-                     GrSurfaceOrigin surface_origin,
-                     SkAlphaType alpha_type,
-                     uint32_t usage)
+  AngleVulkanImageBacking(const raw_ptr<SharedContextState>& context_state,
+                          const Mailbox& mailbox,
+                          viz::ResourceFormat format,
+                          const gfx::Size& size,
+                          const gfx::ColorSpace& color_space,
+                          GrSurfaceOrigin surface_origin,
+                          SkAlphaType alpha_type,
+                          uint32_t usage)
       : ClearTrackingSharedImageBacking(mailbox,
                                         format,
                                         size,
@@ -68,7 +68,7 @@
                                         false /* is_thread_safe */),
         context_state_(context_state) {}
 
-  ~AngleVulkanBacking() override {
+  ~AngleVulkanImageBacking() override {
     DCHECK(!is_gl_write_in_process_);
     DCHECK(!is_skia_write_in_process_);
     DCHECK_EQ(gl_reads_in_process_, 0);
@@ -93,9 +93,8 @@
     }
   }
 
-  bool Initialize(
-      const SharedImageBackingFactoryAngleVulkan::FormatInfo& format_info,
-      const base::span<const uint8_t>& data) {
+  bool Initialize(const AngleVulkanImageBackingFactory::FormatInfo& format_info,
+                  const base::span<const uint8_t>& data) {
     auto* device_queue =
         context_state_->vk_context_provider()->GetDeviceQueue();
     VkFormat vk_format = ToVkFormat(format());
@@ -185,23 +184,23 @@
     }
   }
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override {
     if (!passthrough_texture_ && !InitializePassthroughTexture())
       return nullptr;
 
-    return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
+    return std::make_unique<GLTexturePassthroughGLCommonRepresentation>(
         manager, this, this, tracker, passthrough_texture_);
   }
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
-  // SharedImageRepresentationGLTextureClient implementation.
-  bool SharedImageRepresentationGLTextureBeginAccess(bool readonly) override {
+  // GLTextureImageRepresentationClient implementation.
+  bool GLTextureImageRepresentationBeginAccess(bool readonly) override {
     if (!readonly) {
       // For GL write access.
       if (is_gl_write_in_process_) {
@@ -259,7 +258,7 @@
     return true;
   }
 
-  void SharedImageRepresentationGLTextureEndAccess(bool readonly) override {
+  void GLTextureImageRepresentationEndAccess(bool readonly) override {
     if (readonly) {
       // For GL read access.
       if (gl_reads_in_process_ == 0) {
@@ -286,10 +285,10 @@
     ReleaseTextureANGLE();
   }
 
-  void SharedImageRepresentationGLTextureRelease(bool have_context) override {}
+  void GLTextureImageRepresentationRelease(bool have_context) override {}
 
  private:
-  class SkiaRepresentation;
+  class SkiaAngleVulkanImageRepresentation;
 
   void AcquireTextureANGLE() {
     gl::GLApi* api = gl::g_current_gl_context;
@@ -410,7 +409,7 @@
     }
 
     scoped_refptr<gles2::TexturePassthrough> passthrough_texture;
-    SharedImageBackingGLCommon::MakeTextureAndSetParameters(
+    GLTextureImageBackingHelper::MakeTextureAndSetParameters(
         GL_TEXTURE_2D, /*service_id=*/0,
         /*framebuffer_attachment_angle=*/true, &passthrough_texture, nullptr);
     passthrough_texture->SetEstimatedSize(estimated_size());
@@ -455,19 +454,19 @@
   int gl_reads_in_process_ = 0;
 };
 
-class AngleVulkanBacking::SkiaRepresentation
-    : public SharedImageRepresentationSkia {
+class AngleVulkanImageBacking::SkiaAngleVulkanImageRepresentation
+    : public SkiaImageRepresentation {
  public:
-  SkiaRepresentation(SharedImageManager* manager,
-                     AngleVulkanBacking* backing,
-                     MemoryTypeTracker* tracker)
-      : SharedImageRepresentationSkia(manager, backing, tracker) {}
+  SkiaAngleVulkanImageRepresentation(SharedImageManager* manager,
+                                     AngleVulkanImageBacking* backing,
+                                     MemoryTypeTracker* tracker)
+      : SkiaImageRepresentation(manager, backing, tracker) {}
 
-  ~SkiaRepresentation() override {
+  ~SkiaAngleVulkanImageRepresentation() override {
     backing_impl()->context_state_->EraseCachedSkSurface(this);
   }
 
-  // SharedImageRepresentationSkia implementation.
+  // SkiaImageRepresentation implementation.
   sk_sp<SkPromiseImageTexture> BeginReadAccess(
       std::vector<GrBackendSemaphore>* begin_semaphores,
       std::vector<GrBackendSemaphore>* end_semaphores,
@@ -535,41 +534,41 @@
   }
 
  private:
-  AngleVulkanBacking* backing_impl() const {
-    return static_cast<AngleVulkanBacking*>(backing());
+  AngleVulkanImageBacking* backing_impl() const {
+    return static_cast<AngleVulkanImageBacking*>(backing());
   }
 
   int surface_msaa_count_ = 0;
 };
 
-std::unique_ptr<SharedImageRepresentationSkia> AngleVulkanBacking::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> AngleVulkanImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
   DCHECK_EQ(context_state_, context_state.get());
-  return std::make_unique<SkiaRepresentation>(manager, this, tracker);
+  return std::make_unique<SkiaAngleVulkanImageRepresentation>(manager, this,
+                                                              tracker);
 }
 
 }  // namespace
 
-SharedImageBackingFactoryAngleVulkan::SharedImageBackingFactoryAngleVulkan(
+AngleVulkanImageBackingFactory::AngleVulkanImageBackingFactory(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
     SharedContextState* context_state)
-    : SharedImageBackingFactoryGLCommon(gpu_preferences,
-                                        workarounds,
-                                        context_state->feature_info(),
-                                        context_state->progress_reporter()),
+    : GLCommonImageBackingFactory(gpu_preferences,
+                                  workarounds,
+                                  context_state->feature_info(),
+                                  context_state->progress_reporter()),
       context_state_(context_state) {
   DCHECK(context_state_->GrContextIsVulkan());
   DCHECK(gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_ANGLE_vulkan_image);
 }
 
-SharedImageBackingFactoryAngleVulkan::~SharedImageBackingFactoryAngleVulkan() =
-    default;
+AngleVulkanImageBackingFactory::~AngleVulkanImageBackingFactory() = default;
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAngleVulkan::CreateSharedImage(
+AngleVulkanImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -585,7 +584,7 @@
     return nullptr;
   }
 
-  auto backing = std::make_unique<AngleVulkanBacking>(
+  auto backing = std::make_unique<AngleVulkanImageBacking>(
       context_state_, mailbox, format, size, color_space, surface_origin,
       alpha_type, usage);
 
@@ -596,7 +595,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAngleVulkan::CreateSharedImage(
+AngleVulkanImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -609,7 +608,7 @@
   if (!CanCreateSharedImage(size, data, format_info, GL_TEXTURE_2D))
     return nullptr;
 
-  auto backing = std::make_unique<AngleVulkanBacking>(
+  auto backing = std::make_unique<AngleVulkanImageBacking>(
       context_state_, mailbox, format, size, color_space, surface_origin,
       alpha_type, usage);
 
@@ -620,7 +619,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryAngleVulkan::CreateSharedImage(
+AngleVulkanImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -636,7 +635,7 @@
   return nullptr;
 }
 
-bool SharedImageBackingFactoryAngleVulkan::CanUseAngleVulkanBacking(
+bool AngleVulkanImageBackingFactory::CanUseAngleVulkanImageBacking(
     uint32_t usage) const {
   // Ignore for mipmap usage.
   usage &= ~SHARED_IMAGE_USAGE_MIPMAP;
@@ -660,7 +659,7 @@
   return usage & SHARED_IMAGE_USAGE_GLES2;
 }
 
-bool SharedImageBackingFactoryAngleVulkan::IsSupported(
+bool AngleVulkanImageBackingFactory::IsSupported(
     uint32_t usage,
     viz::ResourceFormat format,
     bool thread_safe,
@@ -669,7 +668,7 @@
     bool* allow_legacy_mailbox,
     bool is_pixel_used) {
   DCHECK_EQ(gr_context_type, GrContextType::kVulkan);
-  if (!CanUseAngleVulkanBacking(usage))
+  if (!CanUseAngleVulkanImageBacking(usage))
     return false;
 
   if (thread_safe)
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.h b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.h
index 6e5361b4..37cdcd1 100644
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.h
@@ -11,14 +11,12 @@
 
 class SharedContextState;
 
-class SharedImageBackingFactoryAngleVulkan
-    : public SharedImageBackingFactoryGLCommon {
+class AngleVulkanImageBackingFactory : public GLCommonImageBackingFactory {
  public:
-  SharedImageBackingFactoryAngleVulkan(
-      const GpuPreferences& gpu_preferences,
-      const GpuDriverBugWorkarounds& workarounds,
-      SharedContextState* context_state);
-  ~SharedImageBackingFactoryAngleVulkan() override;
+  AngleVulkanImageBackingFactory(const GpuPreferences& gpu_preferences,
+                                 const GpuDriverBugWorkarounds& workarounds,
+                                 SharedContextState* context_state);
+  ~AngleVulkanImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation:
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
@@ -61,7 +59,7 @@
                    bool is_pixel_used) override;
 
  private:
-  bool CanUseAngleVulkanBacking(uint32_t usage) const;
+  bool CanUseAngleVulkanImageBacking(uint32_t usage) const;
 
   raw_ptr<SharedContextState> context_state_;
 };
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
index ad3ce31..f5f135f 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -55,24 +55,24 @@
 // Wrapped representation types are not in the anonymous namespace because they
 // need to be friend classes to real representations to access protected
 // virtual functions.
-class WrappedGLTextureRepresentation
-    : public SharedImageRepresentationGLTexture {
+class WrappedGLTextureCompoundImageRepresentation
+    : public GLTextureImageRepresentation {
  public:
-  WrappedGLTextureRepresentation(
+  WrappedGLTextureCompoundImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      std::unique_ptr<SharedImageRepresentationGLTexture> wrapped)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
+      std::unique_ptr<GLTextureImageRepresentation> wrapped)
+      : GLTextureImageRepresentation(manager, backing, tracker),
         wrapped_(std::move(wrapped)) {
     DCHECK(wrapped_);
   }
 
-  SharedImageBackingCompound* compound_backing() {
-    return static_cast<SharedImageBackingCompound*>(backing());
+  CompoundImageBacking* compound_backing() {
+    return static_cast<CompoundImageBacking*>(backing());
   }
 
-  // SharedImageRepresentationGLTexture implementation.
+  // GLTextureImageRepresentation implementation.
   bool BeginAccess(GLenum mode) final {
     AccessMode access_mode =
         mode == kReadAccessMode ? AccessMode::kRead : AccessMode::kWrite;
@@ -94,29 +94,27 @@
   gles2::Texture* GetTexture() final { return wrapped_->GetTexture(); }
 
  private:
-  std::unique_ptr<SharedImageRepresentationGLTexture> wrapped_;
+  std::unique_ptr<GLTextureImageRepresentation> wrapped_;
 };
 
-class WrappedGLTexturePassthroughRepresentation
-    : public SharedImageRepresentationGLTexturePassthrough {
+class WrappedGLTexturePassthroughCompoundImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  WrappedGLTexturePassthroughRepresentation(
+  WrappedGLTexturePassthroughCompoundImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      std::unique_ptr<SharedImageRepresentationGLTexturePassthrough> wrapped)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
+      std::unique_ptr<GLTexturePassthroughImageRepresentation> wrapped)
+      : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
         wrapped_(std::move(wrapped)) {
     DCHECK(wrapped_);
   }
 
-  SharedImageBackingCompound* compound_backing() {
-    return static_cast<SharedImageBackingCompound*>(backing());
+  CompoundImageBacking* compound_backing() {
+    return static_cast<CompoundImageBacking*>(backing());
   }
 
-  // SharedImageRepresentationGLTexturePassthrough implementation.
+  // GLTexturePassthroughImageRepresentation implementation.
   bool BeginAccess(GLenum mode) final {
     AccessMode access_mode =
         mode == kReadAccessMode ? AccessMode::kRead : AccessMode::kWrite;
@@ -140,26 +138,26 @@
   }
 
  private:
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough> wrapped_;
+  std::unique_ptr<GLTexturePassthroughImageRepresentation> wrapped_;
 };
 
-class WrappedSkiaRepresentation : public SharedImageRepresentationSkia {
+class WrappedSkiaCompoundImageRepresentation : public SkiaImageRepresentation {
  public:
-  WrappedSkiaRepresentation(
+  WrappedSkiaCompoundImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      std::unique_ptr<SharedImageRepresentationSkia> wrapped)
-      : SharedImageRepresentationSkia(manager, backing, tracker),
+      std::unique_ptr<SkiaImageRepresentation> wrapped)
+      : SkiaImageRepresentation(manager, backing, tracker),
         wrapped_(std::move(wrapped)) {
     DCHECK(wrapped_);
   }
 
-  SharedImageBackingCompound* compound_backing() {
-    return static_cast<SharedImageBackingCompound*>(backing());
+  CompoundImageBacking* compound_backing() {
+    return static_cast<CompoundImageBacking*>(backing());
   }
 
-  // SharedImageRepresentationSkia implementation.
+  // SkiaImageRepresentation implementation.
   bool SupportsMultipleConcurrentReadAccess() final {
     return wrapped_->SupportsMultipleConcurrentReadAccess();
   }
@@ -218,26 +216,26 @@
   void EndReadAccess() final { wrapped_->EndReadAccess(); }
 
  private:
-  std::unique_ptr<SharedImageRepresentationSkia> wrapped_;
+  std::unique_ptr<SkiaImageRepresentation> wrapped_;
 };
 
-class WrappedDawnRepresentation : public SharedImageRepresentationDawn {
+class WrappedDawnCompoundImageRepresentation : public DawnImageRepresentation {
  public:
-  WrappedDawnRepresentation(
+  WrappedDawnCompoundImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      std::unique_ptr<SharedImageRepresentationDawn> wrapped)
-      : SharedImageRepresentationDawn(manager, backing, tracker),
+      std::unique_ptr<DawnImageRepresentation> wrapped)
+      : DawnImageRepresentation(manager, backing, tracker),
         wrapped_(std::move(wrapped)) {
     DCHECK(wrapped_);
   }
 
-  SharedImageBackingCompound* compound_backing() {
-    return static_cast<SharedImageBackingCompound*>(backing());
+  CompoundImageBacking* compound_backing() {
+    return static_cast<CompoundImageBacking*>(backing());
   }
 
-  // SharedImageRepresentationDawn implementation.
+  // DawnImageRepresentation implementation.
   WGPUTexture BeginAccess(WGPUTextureUsage webgpu_usage) final {
     AccessMode access_mode =
         webgpu_usage & kWriteUsage ? AccessMode::kWrite : AccessMode::kRead;
@@ -248,26 +246,27 @@
   void EndAccess() final { wrapped_->EndAccess(); }
 
  private:
-  std::unique_ptr<SharedImageRepresentationDawn> wrapped_;
+  std::unique_ptr<DawnImageRepresentation> wrapped_;
 };
 
-class WrappedOverlayRepresentation : public SharedImageRepresentationOverlay {
+class WrappedOverlayCompoundImageRepresentation
+    : public OverlayImageRepresentation {
  public:
-  WrappedOverlayRepresentation(
+  WrappedOverlayCompoundImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      std::unique_ptr<SharedImageRepresentationOverlay> wrapped)
-      : SharedImageRepresentationOverlay(manager, backing, tracker),
+      std::unique_ptr<OverlayImageRepresentation> wrapped)
+      : OverlayImageRepresentation(manager, backing, tracker),
         wrapped_(std::move(wrapped)) {
     DCHECK(wrapped_);
   }
 
-  SharedImageBackingCompound* compound_backing() {
-    return static_cast<SharedImageBackingCompound*>(backing());
+  CompoundImageBacking* compound_backing() {
+    return static_cast<CompoundImageBacking*>(backing());
   }
 
-  // SharedImageRepresentationOverlay implementation.
+  // OverlayImageRepresentation implementation.
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) final {
     compound_backing()->NotifyBeginAccess(SharedImageAccessStream::kOverlay,
                                           AccessMode::kRead);
@@ -280,12 +279,11 @@
   gl::GLImage* GetGLImage() final { return wrapped_->GetGLImage(); }
 
  private:
-  std::unique_ptr<SharedImageRepresentationOverlay> wrapped_;
+  std::unique_ptr<OverlayImageRepresentation> wrapped_;
 };
 
 // static
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingCompound::CreateSharedMemory(
+std::unique_ptr<SharedImageBacking> CompoundImageBacking::CreateSharedMemory(
     SharedImageBackingFactory* gpu_backing_factory,
     const Mailbox& mailbox,
     gfx::GpuMemoryBufferHandle handle,
@@ -307,7 +305,7 @@
     return nullptr;
   }
 
-  auto shm_backing = std::make_unique<SharedImageBackingSharedMemory>(
+  auto shm_backing = std::make_unique<SharedMemoryImageBacking>(
       gpu::Mailbox(), format, size, color_space, surface_origin, alpha_type,
       SHARED_IMAGE_USAGE_CPU_WRITE, std::move(shm_wrapper));
 
@@ -320,12 +318,12 @@
     return nullptr;
   }
 
-  return std::make_unique<SharedImageBackingCompound>(
+  return std::make_unique<CompoundImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(shm_backing), std::move(gpu_backing));
 }
 
-SharedImageBackingCompound::SharedImageBackingCompound(
+CompoundImageBacking::CompoundImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -333,7 +331,7 @@
     GrSurfaceOrigin surface_origin,
     SkAlphaType alpha_type,
     uint32_t usage,
-    std::unique_ptr<SharedImageBackingSharedMemory> shm_backing,
+    std::unique_ptr<SharedMemoryImageBacking> shm_backing,
     std::unique_ptr<SharedImageBacking> gpu_backing)
     : SharedImageBacking(mailbox,
                          format,
@@ -357,11 +355,10 @@
   SetClearedRect(gfx::Rect(size));
 }
 
-SharedImageBackingCompound::~SharedImageBackingCompound() = default;
+CompoundImageBacking::~CompoundImageBacking() = default;
 
-void SharedImageBackingCompound::NotifyBeginAccess(
-    SharedImageAccessStream stream,
-    RepresentationAccessMode mode) {
+void CompoundImageBacking::NotifyBeginAccess(SharedImageAccessStream stream,
+                                             RepresentationAccessMode mode) {
   // Compound backings don't support CPU access directly or copying
   // from GPU back to CPU yet. Also no support for VAAPI.
   DCHECK_NE(stream, SharedImageAccessStream::kMemory);
@@ -371,9 +368,8 @@
   // only want to update a backing if it's not currently being accessed.
 
   if (shm_has_update_) {
-    auto& wrapper =
-        static_cast<SharedImageBackingSharedMemory*>(shm_backing_.get())
-            ->shared_memory_wrapper();
+    auto& wrapper = static_cast<SharedMemoryImageBacking*>(shm_backing_.get())
+                        ->shared_memory_wrapper();
     DCHECK(wrapper.IsValid());
 
     SkPixmap pixmap(shm_backing_->AsSkImageInfo(), wrapper.GetMemory(),
@@ -387,69 +383,67 @@
   }
 }
 
-SharedImageBackingType SharedImageBackingCompound::GetType() const {
+SharedImageBackingType CompoundImageBacking::GetType() const {
   return SharedImageBackingType::kCompound;
 }
 
-void SharedImageBackingCompound::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {
+void CompoundImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   DCHECK(!in_fence);
   shm_has_update_ = true;
 }
 
-bool SharedImageBackingCompound::ProduceLegacyMailbox(
+bool CompoundImageBacking::ProduceLegacyMailbox(
     MailboxManager* mailbox_manager) {
   return gpu_backing_->ProduceLegacyMailbox(mailbox_manager);
 }
 
-gfx::Rect SharedImageBackingCompound::ClearedRect() const {
+gfx::Rect CompoundImageBacking::ClearedRect() const {
   return gpu_backing_->ClearedRect();
 }
 
-void SharedImageBackingCompound::SetClearedRect(const gfx::Rect& cleared_rect) {
+void CompoundImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   // Shared memory backing doesn't track cleared rect.
   gpu_backing_->SetClearedRect(cleared_rect);
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingCompound::ProduceDawn(SharedImageManager* manager,
-                                        MemoryTypeTracker* tracker,
-                                        WGPUDevice device,
-                                        WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> CompoundImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
   auto real_rep =
       gpu_backing_->ProduceDawn(manager, tracker, device, backend_type);
   if (!real_rep)
     return nullptr;
 
-  return std::make_unique<WrappedDawnRepresentation>(manager, this, tracker,
-                                                     std::move(real_rep));
+  return std::make_unique<WrappedDawnCompoundImageRepresentation>(
+      manager, this, tracker, std::move(real_rep));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingCompound::ProduceGLTexture(SharedImageManager* manager,
-                                             MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+CompoundImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                       MemoryTypeTracker* tracker) {
   auto real_rep = gpu_backing_->ProduceGLTexture(manager, tracker);
   if (!real_rep)
     return nullptr;
 
-  return std::make_unique<WrappedGLTextureRepresentation>(
+  return std::make_unique<WrappedGLTextureCompoundImageRepresentation>(
       manager, this, tracker, std::move(real_rep));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingCompound::ProduceGLTexturePassthrough(
-    SharedImageManager* manager,
-    MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+CompoundImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                                  MemoryTypeTracker* tracker) {
   auto real_rep = gpu_backing_->ProduceGLTexturePassthrough(manager, tracker);
   if (!real_rep)
     return nullptr;
 
-  return std::make_unique<WrappedGLTexturePassthroughRepresentation>(
+  return std::make_unique<
+      WrappedGLTexturePassthroughCompoundImageRepresentation>(
       manager, this, tracker, std::move(real_rep));
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingCompound::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> CompoundImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -458,22 +452,22 @@
   if (!real_rep)
     return nullptr;
 
-  return std::make_unique<WrappedSkiaRepresentation>(manager, this, tracker,
-                                                     std::move(real_rep));
+  return std::make_unique<WrappedSkiaCompoundImageRepresentation>(
+      manager, this, tracker, std::move(real_rep));
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingCompound::ProduceOverlay(SharedImageManager* manager,
-                                           MemoryTypeTracker* tracker) {
+std::unique_ptr<OverlayImageRepresentation>
+CompoundImageBacking::ProduceOverlay(SharedImageManager* manager,
+                                     MemoryTypeTracker* tracker) {
   auto real_rep = gpu_backing_->ProduceOverlay(manager, tracker);
   if (!real_rep)
     return nullptr;
 
-  return std::make_unique<WrappedOverlayRepresentation>(manager, this, tracker,
-                                                        std::move(real_rep));
+  return std::make_unique<WrappedOverlayCompoundImageRepresentation>(
+      manager, this, tracker, std::move(real_rep));
 }
 
-void SharedImageBackingCompound::OnMemoryDump(
+void CompoundImageBacking::OnMemoryDump(
     const std::string& dump_name,
     base::trace_event::MemoryAllocatorDump* dump,
     base::trace_event::ProcessMemoryDump* pmd,
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.h b/gpu/command_buffer/service/shared_image/compound_image_backing.h
index e733a0f4..71a04d4 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.h
@@ -24,7 +24,7 @@
 
 class SharedImageBackingFactory;
 
-// TODO(kylechar): Merge with SharedImageBackingOzone::AccessStream enum.
+// TODO(kylechar): Merge with OzoneImageBacking::AccessStream enum.
 enum class SharedImageAccessStream {
   kSkia,
   kOverlay,
@@ -38,7 +38,7 @@
 // backing. The real GPU backing must implement `UploadFromMemory()` and not
 // have it's own shared memory segment.
 // TODO(crbug.com/1293509): Support multiple GPU backings.
-class GPU_GLES2_EXPORT SharedImageBackingCompound : public SharedImageBacking {
+class GPU_GLES2_EXPORT CompoundImageBacking : public SharedImageBacking {
  public:
   // Creates a backing that contains a shared memory backing and GPU backing
   // provided by `gpu_backing_factory`.
@@ -55,18 +55,17 @@
       SkAlphaType alpha_type,
       uint32_t usage);
 
-  SharedImageBackingCompound(
-      const Mailbox& mailbox,
-      viz::ResourceFormat format,
-      const gfx::Size& size,
-      const gfx::ColorSpace& color_space,
-      GrSurfaceOrigin surface_origin,
-      SkAlphaType alpha_type,
-      uint32_t usage,
-      std::unique_ptr<SharedImageBackingSharedMemory> shm_backing,
-      std::unique_ptr<SharedImageBacking> gpu_backing);
+  CompoundImageBacking(const Mailbox& mailbox,
+                       viz::ResourceFormat format,
+                       const gfx::Size& size,
+                       const gfx::ColorSpace& color_space,
+                       GrSurfaceOrigin surface_origin,
+                       SkAlphaType alpha_type,
+                       uint32_t usage,
+                       std::unique_ptr<SharedMemoryImageBacking> shm_backing,
+                       std::unique_ptr<SharedImageBacking> gpu_backing);
 
-  ~SharedImageBackingCompound() override;
+  ~CompoundImageBacking() override;
 
   // Called by wrapped representations before access. This will update
   // the backing that is going to be accessed if most recent pixels are in
@@ -83,22 +82,22 @@
 
  protected:
   // SharedImageBacking implementation.
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) override;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc b/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
index 3af2d74..a34bdb6 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing_unittest.cc
@@ -36,9 +36,9 @@
       SkAlphaType alpha_type,
       uint32_t usage,
       bool is_thread_safe) override {
-    return std::make_unique<TestSharedImageBacking>(mailbox, format, size,
-                                                    color_space, surface_origin,
-                                                    alpha_type, usage, 0);
+    return std::make_unique<TestImageBacking>(mailbox, format, size,
+                                              color_space, surface_origin,
+                                              alpha_type, usage, 0);
   }
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
       const Mailbox& mailbox,
@@ -80,10 +80,10 @@
 
 class CompoundImageBackingTest : public testing::Test {
  public:
-  TestSharedImageBacking* GetGpuBacking(SharedImageBackingCompound* backing) {
+  TestImageBacking* GetGpuBacking(CompoundImageBacking* backing) {
     auto* gpu_backing = backing->gpu_backing_.get();
     DCHECK_EQ(gpu_backing->GetType(), SharedImageBackingType::kTest);
-    return static_cast<TestSharedImageBacking*>(gpu_backing);
+    return static_cast<TestImageBacking*>(gpu_backing);
   }
 
   // Create a compound backing containing shared memory + GPU backing.
@@ -98,7 +98,7 @@
             static_cast<gfx::GpuMemoryBufferId>(1), size, buffer_format,
             buffer_usage);
 
-    return SharedImageBackingCompound::CreateSharedMemory(
+    return CompoundImageBacking::CreateSharedMemory(
         &test_factory_, Mailbox::GenerateForSharedImage(), std::move(handle),
         buffer_format, gfx::BufferPlane::DEFAULT, kNullSurfaceHandle, size,
         gfx::ColorSpace(), kBottomLeft_GrSurfaceOrigin, kOpaque_SkAlphaType,
@@ -115,8 +115,7 @@
 TEST_F(CompoundImageBackingTest, References) {
   auto backing = CreateCompoundBacking();
 
-  auto* compound_backing =
-      static_cast<SharedImageBackingCompound*>(backing.get());
+  auto* compound_backing = static_cast<CompoundImageBacking*>(backing.get());
   EXPECT_NE(compound_backing, nullptr);
 
   auto* gpu_backing = GetGpuBacking(compound_backing);
@@ -151,8 +150,7 @@
 
 TEST_F(CompoundImageBackingTest, UploadOnAccess) {
   auto backing = CreateCompoundBacking();
-  auto* compound_backing =
-      static_cast<SharedImageBackingCompound*>(backing.get());
+  auto* compound_backing = static_cast<CompoundImageBacking*>(backing.get());
   auto* gpu_backing = GetGpuBacking(compound_backing);
 
   auto factory_rep = manager_.Register(std::move(backing), &tracker_);
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
index adb03cf..9a7eab4 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -198,8 +198,7 @@
 }  // namespace
 
 // static
-std::unique_ptr<SharedImageBackingD3D>
-SharedImageBackingD3D::CreateFromSwapChainBuffer(
+std::unique_ptr<D3DImageBacking> D3DImageBacking::CreateFromSwapChainBuffer(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -216,7 +215,7 @@
     LOG(ERROR) << "Failed to create GL texture";
     return nullptr;
   }
-  return base::WrapUnique(new SharedImageBackingD3D(
+  return base::WrapUnique(new D3DImageBacking(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(d3d11_texture), std::move(gl_texture),
       /*dxgi_shared_handle_state=*/{}, /*shared_memory_handle=*/{},
@@ -224,8 +223,7 @@
 }
 
 // static
-std::unique_ptr<SharedImageBackingD3D>
-SharedImageBackingD3D::CreateFromDXGISharedHandle(
+std::unique_ptr<D3DImageBacking> D3DImageBacking::CreateFromDXGISharedHandle(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -254,15 +252,14 @@
       return nullptr;
     }
   }
-  auto backing = base::WrapUnique(new SharedImageBackingD3D(
+  auto backing = base::WrapUnique(new D3DImageBacking(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(d3d11_texture), std::move(gl_texture),
       std::move(dxgi_shared_handle_state)));
   return backing;
 }
 
-std::unique_ptr<SharedImageBackingD3D>
-SharedImageBackingD3D::CreateFromGLTexture(
+std::unique_ptr<D3DImageBacking> D3DImageBacking::CreateFromGLTexture(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -272,14 +269,14 @@
     uint32_t usage,
     Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
     scoped_refptr<gles2::TexturePassthrough> gl_texture) {
-  return base::WrapUnique(new SharedImageBackingD3D(
+  return base::WrapUnique(new D3DImageBacking(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(d3d11_texture), std::move(gl_texture)));
 }
 
 // static
 std::vector<std::unique_ptr<SharedImageBacking>>
-SharedImageBackingD3D::CreateFromVideoTexture(
+D3DImageBacking::CreateFromVideoTexture(
     base::span<const Mailbox> mailboxes,
     DXGI_FORMAT dxgi_format,
     const gfx::Size& size,
@@ -321,7 +318,7 @@
       return {};
     }
 
-    shared_images[plane_index] = base::WrapUnique(new SharedImageBackingD3D(
+    shared_images[plane_index] = base::WrapUnique(new D3DImageBacking(
         mailbox, plane_format, plane_size, kInvalidColorSpace,
         kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, d3d11_texture,
         std::move(gl_texture), dxgi_shared_handle_state));
@@ -332,8 +329,7 @@
 }
 
 // static
-std::unique_ptr<SharedImageBackingD3D>
-SharedImageBackingD3D::CreateFromSharedMemoryHandle(
+std::unique_ptr<D3DImageBacking> D3DImageBacking::CreateFromSharedMemoryHandle(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -349,14 +345,14 @@
     LOG(ERROR) << "Failed to create GL texture";
     return nullptr;
   }
-  auto backing = base::WrapUnique(new SharedImageBackingD3D(
+  auto backing = base::WrapUnique(new D3DImageBacking(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(d3d11_texture), std::move(gl_texture),
       /*dxgi_shared_handle_state=*/{}, std::move(shared_memory_handle)));
   return backing;
 }
 
-SharedImageBackingD3D::SharedImageBackingD3D(
+D3DImageBacking::D3DImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -392,7 +388,7 @@
   DCHECK(has_webgpu_usage || gl_texture_);
 }
 
-SharedImageBackingD3D::~SharedImageBackingD3D() {
+D3DImageBacking::~D3DImageBacking() {
   if (!have_context())
     gl_texture_->MarkContextLost();
   gl_texture_.reset();
@@ -404,7 +400,7 @@
 #endif  // BUILDFLAG(USE_DAWN)
 }
 
-ID3D11Texture2D* SharedImageBackingD3D::GetOrCreateStagingTexture() {
+ID3D11Texture2D* D3DImageBacking::GetOrCreateStagingTexture() {
   if (!staging_texture_) {
     Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device;
     DCHECK(d3d11_texture_);
@@ -440,17 +436,17 @@
   return staging_texture_.Get();
 }
 
-SharedImageBackingType SharedImageBackingD3D::GetType() const {
+SharedImageBackingType D3DImageBacking::GetType() const {
   return SharedImageBackingType::kD3D;
 }
 
-void SharedImageBackingD3D::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
+void D3DImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   DCHECK(!in_fence);
   if (!shared_memory_handle_.is_null())
     needs_upload_to_gpu_ = true;
 }
 
-bool SharedImageBackingD3D::UploadToGpuIfNeeded() {
+bool D3DImageBacking::UploadToGpuIfNeeded() {
   if (!needs_upload_to_gpu_)
     return true;
 
@@ -514,7 +510,7 @@
   return true;
 }
 
-bool SharedImageBackingD3D::CopyToGpuMemoryBuffer() {
+bool D3DImageBacking::CopyToGpuMemoryBuffer() {
   if (shared_memory_handle_.is_null()) {
     LOG(ERROR)
         << "Called CopyToGpuMemoryBuffer for backing without shared memory GMB";
@@ -580,13 +576,12 @@
   return true;
 }
 
-bool SharedImageBackingD3D::ProduceLegacyMailbox(
-    MailboxManager* mailbox_manager) {
+bool D3DImageBacking::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
   mailbox_manager->ProduceTexture(mailbox(), gl_texture_.get());
   return true;
 }
 
-WGPUTextureUsageFlags SharedImageBackingD3D::GetAllowedDawnUsages(
+WGPUTextureUsageFlags D3DImageBacking::GetAllowedDawnUsages(
     const WGPUTextureFormat wgpu_format) const {
   // TODO(crbug.com/2709243): Figure out other SI flags, if any.
   DCHECK(usage() & gpu::SHARED_IMAGE_USAGE_WEBGPU);
@@ -604,15 +599,15 @@
   }
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingD3D::ProduceDawn(SharedImageManager* manager,
-                                   MemoryTypeTracker* tracker,
-                                   WGPUDevice device,
-                                   WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> D3DImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
 #if BUILDFLAG(USE_DAWN)
 #if BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
   if (backend_type == WGPUBackendType_OpenGLES) {
-    return std::make_unique<SharedImageRepresentationDawnEGLImage>(
+    return std::make_unique<DawnEGLImageRepresentation>(
         ProduceGLTexturePassthrough(manager, tracker), manager, this, tracker,
         device);
   }
@@ -680,18 +675,17 @@
   }
   DCHECK(external_image_ptr);
   DCHECK(external_image_ptr->IsValid());
-  return std::make_unique<SharedImageRepresentationDawnD3D>(
+  return std::make_unique<DawnD3DImageRepresentation>(
       manager, this, tracker, device, external_image_ptr);
 #else
   return nullptr;
 #endif  // BUILDFLAG(USE_DAWN)
 }
 
-void SharedImageBackingD3D::OnMemoryDump(
-    const std::string& dump_name,
-    base::trace_event::MemoryAllocatorDump* dump,
-    base::trace_event::ProcessMemoryDump* pmd,
-    uint64_t client_tracing_id) {
+void D3DImageBacking::OnMemoryDump(const std::string& dump_name,
+                                   base::trace_event::MemoryAllocatorDump* dump,
+                                   base::trace_event::ProcessMemoryDump* pmd,
+                                   uint64_t client_tracing_id) {
   // Add a |service_guid| which expresses shared ownership between the
   // various GPU dumps.
   auto client_guid = GetSharedImageGUIDForTracing(mailbox());
@@ -706,36 +700,36 @@
   GetGLImage()->OnMemoryDump(pmd, client_tracing_id, dump_name);
 }
 
-bool SharedImageBackingD3D::BeginAccessD3D12() {
+bool D3DImageBacking::BeginAccessD3D12() {
   if (dxgi_shared_handle_state_)
     return dxgi_shared_handle_state_->BeginAccessD3D12();
   // D3D12 access is only allowed with shared handle and keyed mutex.
   return false;
 }
 
-void SharedImageBackingD3D::EndAccessD3D12() {
+void D3DImageBacking::EndAccessD3D12() {
   if (dxgi_shared_handle_state_)
     dxgi_shared_handle_state_->EndAccessD3D12();
 }
 
-bool SharedImageBackingD3D::BeginAccessD3D11() {
+bool D3DImageBacking::BeginAccessD3D11() {
   if (dxgi_shared_handle_state_)
     return dxgi_shared_handle_state_->BeginAccessD3D11();
   // D3D11 access is allowed without shared handle and keyed mutex.
   return true;
 }
 
-void SharedImageBackingD3D::EndAccessD3D11() {
+void D3DImageBacking::EndAccessD3D11() {
   if (dxgi_shared_handle_state_)
     dxgi_shared_handle_state_->EndAccessD3D11();
 }
 
-gl::GLImage* SharedImageBackingD3D::GetGLImage() const {
+gl::GLImage* D3DImageBacking::GetGLImage() const {
   return gl_texture_->GetLevelImage(gl_texture_->target(), 0u);
 }
 
-bool SharedImageBackingD3D::PresentSwapChain() {
-  TRACE_EVENT0("gpu", "SharedImageBackingD3D::PresentSwapChain");
+bool D3DImageBacking::PresentSwapChain() {
+  TRACE_EVENT0("gpu", "D3DImageBacking::PresentSwapChain");
   if (!swap_chain_ || !is_back_buffer_) {
     LOG(ERROR) << "Backing does not correspond to back buffer of swap chain";
     return false;
@@ -764,16 +758,16 @@
     return false;
   }
 
-  TRACE_EVENT0("gpu", "SharedImageBackingD3D::PresentSwapChain::Flush");
+  TRACE_EVENT0("gpu", "D3DImageBacking::PresentSwapChain::Flush");
   // Flush device context through ANGLE otherwise present could be deferred.
   api->glFlushFn();
   return true;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingD3D::ProduceGLTexturePassthrough(SharedImageManager* manager,
-                                                   MemoryTypeTracker* tracker) {
-  TRACE_EVENT0("gpu", "SharedImageBackingD3D::ProduceGLTexturePassthrough");
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+D3DImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                             MemoryTypeTracker* tracker) {
+  TRACE_EVENT0("gpu", "D3DImageBacking::ProduceGLTexturePassthrough");
   if (!UploadToGpuIfNeeded()) {
     LOG(ERROR) << "UploadToGpuIfNeeded failed";
     return nullptr;
@@ -788,24 +782,23 @@
       return nullptr;
     }
   }
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughD3D>(
+  return std::make_unique<GLTexturePassthroughD3DImageRepresentation>(
       manager, this, tracker, std::move(gl_texture));
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingD3D::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> D3DImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
-  return SharedImageRepresentationSkiaGL::Create(
+  return SkiaGLImageRepresentation::Create(
       ProduceGLTexturePassthrough(manager, tracker), std::move(context_state),
       manager, this, tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingD3D::ProduceOverlay(SharedImageManager* manager,
-                                      MemoryTypeTracker* tracker) {
-  TRACE_EVENT0("gpu", "SharedImageBackingD3D::ProduceOverlay");
+std::unique_ptr<OverlayImageRepresentation> D3DImageBacking::ProduceOverlay(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  TRACE_EVENT0("gpu", "D3DImageBacking::ProduceOverlay");
   // Prefer GLImageMemory for shared memory case so that we don't upload to a
   // texture if it ends up in an overlay.
   if (!shared_memory_handle_.is_null()) {
@@ -817,11 +810,11 @@
       LOG(ERROR) << "Failed to initialize GLImageSharedMemory";
       return nullptr;
     }
-    return std::make_unique<SharedImageRepresentationOverlayD3D>(
+    return std::make_unique<OverlayD3DImageRepresentation>(
         manager, this, tracker, std::move(gl_image));
   }
-  return std::make_unique<SharedImageRepresentationOverlayD3D>(
-      manager, this, tracker, GetGLImage());
+  return std::make_unique<OverlayD3DImageRepresentation>(manager, this, tracker,
+                                                         GetGLImage());
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.h b/gpu/command_buffer/service/shared_image/d3d_image_backing.h
index bb092cb..b656816 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.h
@@ -40,10 +40,10 @@
 // Implementation of SharedImageBacking that holds buffer (front buffer/back
 // buffer of swap chain) texture (as gles2::Texture/gles2::TexturePassthrough)
 // and a reference to created swap chain.
-class GPU_GLES2_EXPORT SharedImageBackingD3D
+class GPU_GLES2_EXPORT D3DImageBacking
     : public ClearTrackingSharedImageBacking {
  public:
-  static std::unique_ptr<SharedImageBackingD3D> CreateFromSwapChainBuffer(
+  static std::unique_ptr<D3DImageBacking> CreateFromSwapChainBuffer(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
@@ -55,7 +55,7 @@
       Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain,
       bool is_back_buffer);
 
-  static std::unique_ptr<SharedImageBackingD3D> CreateFromDXGISharedHandle(
+  static std::unique_ptr<D3DImageBacking> CreateFromDXGISharedHandle(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
@@ -67,7 +67,7 @@
       scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state);
 
   // TODO(sunnyps): Remove this after migrating DXVA decoder to EGLImage.
-  static std::unique_ptr<SharedImageBackingD3D> CreateFromGLTexture(
+  static std::unique_ptr<D3DImageBacking> CreateFromGLTexture(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
@@ -88,7 +88,7 @@
       unsigned array_slice,
       scoped_refptr<DXGISharedHandleState> dxgi_shared_handle_state = nullptr);
 
-  static std::unique_ptr<SharedImageBackingD3D> CreateFromSharedMemoryHandle(
+  static std::unique_ptr<D3DImageBacking> CreateFromSharedMemoryHandle(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
@@ -99,10 +99,10 @@
       Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture,
       gfx::GpuMemoryBufferHandle shared_memory_handle);
 
-  SharedImageBackingD3D(const SharedImageBackingD3D&) = delete;
-  SharedImageBackingD3D& operator=(const SharedImageBackingD3D&) = delete;
+  D3DImageBacking(const D3DImageBacking&) = delete;
+  D3DImageBacking& operator=(const D3DImageBacking&) = delete;
 
-  ~SharedImageBackingD3D() override;
+  ~D3DImageBacking() override;
 
   // SharedImageBacking implementation.
   SharedImageBackingType GetType() const override;
@@ -110,7 +110,7 @@
   bool CopyToGpuMemoryBuffer() override;
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
   bool PresentSwapChain() override;
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
@@ -136,21 +136,21 @@
   }
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
  private:
-  SharedImageBackingD3D(
+  D3DImageBacking(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
index 75aa0e8d..71bc3d2 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
@@ -151,7 +151,7 @@
 
 }  // anonymous namespace
 
-SharedImageBackingFactoryD3D::SharedImageBackingFactoryD3D(
+D3DImageBackingFactory::D3DImageBackingFactory(
     Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
     scoped_refptr<DXGISharedHandleManager> dxgi_shared_handle_manager)
     : d3d11_device_(std::move(d3d11_device)),
@@ -159,25 +159,25 @@
   DCHECK(d3d11_device_);
 }
 
-SharedImageBackingFactoryD3D::~SharedImageBackingFactoryD3D() = default;
+D3DImageBackingFactory::~D3DImageBackingFactory() = default;
 
-SharedImageBackingFactoryD3D::SwapChainBackings::SwapChainBackings(
+D3DImageBackingFactory::SwapChainBackings::SwapChainBackings(
     std::unique_ptr<SharedImageBacking> front_buffer,
     std::unique_ptr<SharedImageBacking> back_buffer)
     : front_buffer(std::move(front_buffer)),
       back_buffer(std::move(back_buffer)) {}
 
-SharedImageBackingFactoryD3D::SwapChainBackings::~SwapChainBackings() = default;
+D3DImageBackingFactory::SwapChainBackings::~SwapChainBackings() = default;
 
-SharedImageBackingFactoryD3D::SwapChainBackings::SwapChainBackings(
-    SharedImageBackingFactoryD3D::SwapChainBackings&&) = default;
+D3DImageBackingFactory::SwapChainBackings::SwapChainBackings(
+    D3DImageBackingFactory::SwapChainBackings&&) = default;
 
-SharedImageBackingFactoryD3D::SwapChainBackings&
-SharedImageBackingFactoryD3D::SwapChainBackings::operator=(
-    SharedImageBackingFactoryD3D::SwapChainBackings&&) = default;
+D3DImageBackingFactory::SwapChainBackings&
+D3DImageBackingFactory::SwapChainBackings::operator=(
+    D3DImageBackingFactory::SwapChainBackings&&) = default;
 
 // static
-bool SharedImageBackingFactoryD3D::IsD3DSharedImageSupported(
+bool D3DImageBackingFactory::IsD3DSharedImageSupported(
     const GpuPreferences& gpu_preferences) {
   // Only supported for passthrough command decoder and Skia-GL.
   const bool using_passthrough = gpu_preferences.use_passthrough_cmd_decoder &&
@@ -189,22 +189,21 @@
 }
 
 // static
-bool SharedImageBackingFactoryD3D::IsSwapChainSupported() {
+bool D3DImageBackingFactory::IsSwapChainSupported() {
   return gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported() &&
          gl::DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
 }
 
-SharedImageBackingFactoryD3D::SwapChainBackings
-SharedImageBackingFactoryD3D::CreateSwapChain(
-    const Mailbox& front_buffer_mailbox,
-    const Mailbox& back_buffer_mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage) {
-  if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+D3DImageBackingFactory::SwapChainBackings
+D3DImageBackingFactory::CreateSwapChain(const Mailbox& front_buffer_mailbox,
+                                        const Mailbox& back_buffer_mailbox,
+                                        viz::ResourceFormat format,
+                                        const gfx::Size& size,
+                                        const gfx::ColorSpace& color_space,
+                                        GrSurfaceOrigin surface_origin,
+                                        SkAlphaType alpha_type,
+                                        uint32_t usage) {
+  if (!D3DImageBackingFactory::IsSwapChainSupported())
     return {nullptr, nullptr};
 
   DXGI_FORMAT swap_chain_format;
@@ -281,7 +280,7 @@
     LOG(ERROR) << "GetBuffer failed with error " << std::hex;
     return {nullptr, nullptr};
   }
-  auto back_buffer_backing = SharedImageBackingD3D::CreateFromSwapChainBuffer(
+  auto back_buffer_backing = D3DImageBacking::CreateFromSwapChainBuffer(
       back_buffer_mailbox, format, size, color_space, surface_origin,
       alpha_type, usage, std::move(back_buffer_texture), swap_chain,
       /*is_back_buffer=*/true);
@@ -295,7 +294,7 @@
     LOG(ERROR) << "GetBuffer failed with error " << std::hex;
     return {nullptr, nullptr};
   }
-  auto front_buffer_backing = SharedImageBackingD3D::CreateFromSwapChainBuffer(
+  auto front_buffer_backing = D3DImageBacking::CreateFromSwapChainBuffer(
       front_buffer_mailbox, format, size, color_space, surface_origin,
       alpha_type, usage, std::move(front_buffer_texture), swap_chain,
       /*is_back_buffer=*/false);
@@ -306,8 +305,7 @@
   return {std::move(front_buffer_backing), std::move(back_buffer_backing)};
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryD3D::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> D3DImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -360,7 +358,7 @@
 
   const std::string debug_label =
       "SharedImage_Texture2D" + CreateLabelForSharedImageUsage(usage);
-  d3d11_device_->SetPrivateData(WKPDID_D3DDebugObjectName, debug_label.length(),
+  d3d11_texture->SetPrivateData(WKPDID_D3DDebugObjectName, debug_label.length(),
                                 debug_label.c_str());
 
   Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
@@ -385,13 +383,12 @@
       dxgi_shared_handle_manager_->CreateAnonymousSharedHandleState(
           base::win::ScopedHandle(shared_handle), d3d11_texture);
 
-  return SharedImageBackingD3D::CreateFromDXGISharedHandle(
+  return D3DImageBacking::CreateFromDXGISharedHandle(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(d3d11_texture), std::move(dxgi_shared_handle_state));
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryD3D::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> D3DImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -404,8 +401,7 @@
   return nullptr;
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryD3D::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> D3DImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -436,7 +432,7 @@
 
     auto d3d11_texture = dxgi_shared_handle_state->d3d11_texture();
 
-    auto backing = SharedImageBackingD3D::CreateFromDXGISharedHandle(
+    auto backing = D3DImageBacking::CreateFromDXGISharedHandle(
         mailbox, viz::GetResourceFormat(format), size, color_space,
         surface_origin, alpha_type, usage, std::move(d3d11_texture),
         std::move(dxgi_shared_handle_state));
@@ -493,7 +489,7 @@
   const size_t plane_index = plane == gfx::BufferPlane::UV ? 1 : 0;
   handle.offset += gfx::BufferOffsetForBufferFormat(size, format, plane_index);
 
-  auto backing = SharedImageBackingD3D::CreateFromSharedMemoryHandle(
+  auto backing = D3DImageBacking::CreateFromSharedMemoryHandle(
       mailbox, plane_format, plane_size, color_space, surface_origin,
       alpha_type, usage, std::move(d3d11_texture), std::move(handle));
   if (backing) {
@@ -509,7 +505,7 @@
 }
 
 std::vector<std::unique_ptr<SharedImageBacking>>
-SharedImageBackingFactoryD3D::CreateSharedImageVideoPlanes(
+D3DImageBackingFactory::CreateSharedImageVideoPlanes(
     base::span<const Mailbox> mailboxes,
     gfx::GpuMemoryBufferHandle handle,
     gfx::BufferFormat format,
@@ -529,12 +525,12 @@
 
   auto d3d11_texture = dxgi_shared_handle_state->d3d11_texture();
 
-  return SharedImageBackingD3D::CreateFromVideoTexture(
+  return D3DImageBacking::CreateFromVideoTexture(
       mailboxes, GetDXGIFormat(format), size, usage, std::move(d3d11_texture),
       /*array_slice=*/0, std::move(dxgi_shared_handle_state));
 }
 
-bool SharedImageBackingFactoryD3D::UseMapOnDefaultTextures() {
+bool D3DImageBackingFactory::UseMapOnDefaultTextures() {
   if (!map_on_default_textures_.has_value()) {
     D3D11_FEATURE_DATA_D3D11_OPTIONS2 features;
     HRESULT hr = d3d11_device_->CheckFeatureSupport(
@@ -555,7 +551,7 @@
 
 // Returns true if the specified GpuMemoryBufferType can be imported using
 // this factory.
-bool SharedImageBackingFactoryD3D::CanImportGpuMemoryBuffer(
+bool D3DImageBackingFactory::CanImportGpuMemoryBuffer(
     gfx::GpuMemoryBufferType gmb_type,
     viz::ResourceFormat format) {
   return gmb_type == gfx::DXGI_SHARED_HANDLE ||
@@ -565,14 +561,13 @@
           format == viz::YUV_420_BIPLANAR);
 }
 
-bool SharedImageBackingFactoryD3D::IsSupported(
-    uint32_t usage,
-    viz::ResourceFormat format,
-    bool thread_safe,
-    gfx::GpuMemoryBufferType gmb_type,
-    GrContextType gr_context_type,
-    bool* allow_legacy_mailbox,
-    bool is_pixel_used) {
+bool D3DImageBackingFactory::IsSupported(uint32_t usage,
+                                         viz::ResourceFormat format,
+                                         bool thread_safe,
+                                         gfx::GpuMemoryBufferType gmb_type,
+                                         GrContextType gr_context_type,
+                                         bool* allow_legacy_mailbox,
+                                         bool is_pixel_used) {
   if (is_pixel_used) {
     return false;
   }
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
index 83dbd12..0e06ca9 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
@@ -27,18 +27,17 @@
 class SharedImageBacking;
 struct Mailbox;
 
-class GPU_GLES2_EXPORT SharedImageBackingFactoryD3D
+class GPU_GLES2_EXPORT D3DImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  SharedImageBackingFactoryD3D(
+  D3DImageBackingFactory(
       Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
       scoped_refptr<DXGISharedHandleManager> dxgi_shared_handle_manager);
 
-  SharedImageBackingFactoryD3D(const SharedImageBackingFactoryD3D&) = delete;
-  SharedImageBackingFactoryD3D& operator=(const SharedImageBackingFactoryD3D&) =
-      delete;
+  D3DImageBackingFactory(const D3DImageBackingFactory&) = delete;
+  D3DImageBackingFactory& operator=(const D3DImageBackingFactory&) = delete;
 
-  ~SharedImageBackingFactoryD3D() override;
+  ~D3DImageBackingFactory() override;
 
   // Returns true if D3D shared images are supported and this factory should be
   // used. Generally this means Skia-GL, passthrough decoder, and ANGLE-D3D11.
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
index 44d9e491..b1e3e910 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory_unittest.cc
@@ -130,7 +130,7 @@
   return true;
 }
 
-class SharedImageBackingFactoryD3DTestBase : public testing::Test {
+class D3DImageBackingFactoryTestBase : public testing::Test {
  public:
   void SetUp() override {
     if (!IsD3DSharedImageSupported())
@@ -148,7 +148,7 @@
     shared_image_representation_factory_ =
         std::make_unique<SharedImageRepresentationFactory>(
             &shared_image_manager_, nullptr);
-    shared_image_factory_ = std::make_unique<SharedImageBackingFactoryD3D>(
+    shared_image_factory_ = std::make_unique<D3DImageBackingFactory>(
         gl::QueryD3D11DeviceObjectFromANGLE(),
         shared_image_manager_.dxgi_shared_handle_manager());
   }
@@ -160,21 +160,21 @@
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
   std::unique_ptr<SharedImageRepresentationFactory>
       shared_image_representation_factory_;
-  std::unique_ptr<SharedImageBackingFactoryD3D> shared_image_factory_;
+  std::unique_ptr<D3DImageBackingFactory> shared_image_factory_;
 };
 
-class SharedImageBackingFactoryD3DTestSwapChain
-    : public SharedImageBackingFactoryD3DTestBase {
+class D3DImageBackingFactoryTestSwapChain
+    : public D3DImageBackingFactoryTestBase {
  public:
   void SetUp() override {
-    if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+    if (!D3DImageBackingFactory::IsSwapChainSupported())
       return;
-    SharedImageBackingFactoryD3DTestBase::SetUp();
+    D3DImageBackingFactoryTestBase::SetUp();
   }
 };
 
-TEST_F(SharedImageBackingFactoryD3DTestSwapChain, InvalidFormat) {
-  if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+TEST_F(D3DImageBackingFactoryTestSwapChain, InvalidFormat) {
+  if (!D3DImageBackingFactory::IsSwapChainSupported())
     return;
 
   auto front_buffer_mailbox = Mailbox::GenerateForSharedImage();
@@ -218,8 +218,8 @@
   }
 }
 
-TEST_F(SharedImageBackingFactoryD3DTestSwapChain, CreateAndPresentSwapChain) {
-  if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+TEST_F(D3DImageBackingFactoryTestSwapChain, CreateAndPresentSwapChain) {
+  if (!D3DImageBackingFactory::IsSwapChainSupported())
     return;
 
   auto front_buffer_mailbox = Mailbox::GenerateForSharedImage();
@@ -444,14 +444,13 @@
   api->glDeleteFramebuffersEXTFn(1, &fbo);
 }
 
-class SharedImageBackingFactoryD3DTest
-    : public SharedImageBackingFactoryD3DTestBase {
+class D3DImageBackingFactoryTest : public D3DImageBackingFactoryTestBase {
  public:
   void SetUp() override {
     if (!IsD3DSharedImageSupported())
       return;
 
-    SharedImageBackingFactoryD3DTestBase::SetUp();
+    D3DImageBackingFactoryTestBase::SetUp();
     GpuDriverBugWorkarounds workarounds;
     scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup();
     context_state_ = base::MakeRefCounted<SharedContextState>(
@@ -474,7 +473,7 @@
                                                           context_state_);
     ASSERT_NE(skia_representation, nullptr);
 
-    std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+    std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
         scoped_read_access =
             skia_representation->BeginScopedReadAccess(nullptr, nullptr);
     EXPECT_TRUE(scoped_read_access);
@@ -529,7 +528,7 @@
 // Test to check interaction between Gl and skia GL representations.
 // We write to a GL texture using gl representation and then read from skia
 // representation.
-TEST_F(SharedImageBackingFactoryD3DTest, GL_SkiaGL) {
+TEST_F(D3DImageBackingFactoryTest, GL_SkiaGL) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -551,14 +550,14 @@
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
 
-  // Create a SharedImageRepresentationGLTexture.
+  // Create a GLTextureImageRepresentation.
   auto gl_representation =
       shared_image_representation_factory_->ProduceGLTexturePassthrough(
           mailbox);
   EXPECT_EQ(expected_target,
             gl_representation->GetTexturePassthrough()->target());
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
       scoped_access = gl_representation->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -591,7 +590,7 @@
 
 #if BUILDFLAG(USE_DAWN)
 // Test to check interaction between Dawn and skia GL representations.
-TEST_F(SharedImageBackingFactoryD3DTest, Dawn_SkiaGL) {
+TEST_F(D3DImageBackingFactoryTest, Dawn_SkiaGL) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -637,7 +636,7 @@
 
   // Clear the shared image to green using Dawn.
   {
-    // Create a SharedImageRepresentationDawn.
+    // Create a DawnImageRepresentation.
     auto dawn_representation =
         shared_image_representation_factory_->ProduceDawn(
             mailbox, device.Get(), WGPUBackendType_D3D12);
@@ -684,7 +683,7 @@
 // 2. Do not call SetCleared so we can test Dawn Lazy clear
 // 3. Begin render pass in Dawn, but do not do anything
 // 4. Verify through CheckSkiaPixel that GL drawn color not seen
-TEST_F(SharedImageBackingFactoryD3DTest, GL_Dawn_Skia_UnclearTexture) {
+TEST_F(D3DImageBackingFactoryTest, GL_Dawn_Skia_UnclearTexture) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -707,14 +706,14 @@
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
   {
-    // Create a SharedImageRepresentationGLTexture.
+    // Create a GLTextureImageRepresentation.
     auto gl_representation =
         shared_image_representation_factory_->ProduceGLTexturePassthrough(
             mailbox);
     EXPECT_EQ(expected_target,
               gl_representation->GetTexturePassthrough()->target());
 
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+    std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
         gl_scoped_access = gl_representation->BeginScopedAccess(
             GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM,
             SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -810,7 +809,7 @@
 // 3. Texture in Dawn will stay as uninitialized
 // 3. Expect skia to fail to access the texture because texture is not
 // initialized
-TEST_F(SharedImageBackingFactoryD3DTest, UnclearDawn_SkiaFails) {
+TEST_F(D3DImageBackingFactoryTest, UnclearDawn_SkiaFails) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -899,7 +898,7 @@
   ASSERT_NE(skia_representation, nullptr);
 
   // Expect BeginScopedReadAccess to fail because sharedImage is uninitialized
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       scoped_read_access =
           skia_representation->BeginScopedReadAccess(nullptr, nullptr);
   EXPECT_EQ(scoped_read_access, nullptr);
@@ -907,7 +906,7 @@
 #endif  // BUILDFLAG(USE_DAWN)
 
 // Test that Skia trying to access uninitialized SharedImage will fail
-TEST_F(SharedImageBackingFactoryD3DTest, SkiaAccessFirstFails) {
+TEST_F(D3DImageBackingFactoryTest, SkiaAccessFirstFails) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -935,13 +934,13 @@
   EXPECT_FALSE(skia_representation->IsCleared());
 
   // Expect BeginScopedReadAccess to fail because sharedImage is uninitialized
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       scoped_read_access =
           skia_representation->BeginScopedReadAccess(nullptr, nullptr);
   EXPECT_EQ(scoped_read_access, nullptr);
 }
 
-void SharedImageBackingFactoryD3DTest::RunCreateSharedImageFromHandleTest(
+void D3DImageBackingFactoryTest::RunCreateSharedImageFromHandleTest(
     DXGI_FORMAT dxgi_format) {
   if (!IsD3DSharedImageSupported())
     return;
@@ -1009,8 +1008,7 @@
   EXPECT_EQ(backing->mailbox(), mailbox);
   EXPECT_TRUE(backing->IsCleared());
 
-  SharedImageBackingD3D* backing_d3d =
-      static_cast<SharedImageBackingD3D*>(backing.get());
+  D3DImageBacking* backing_d3d = static_cast<D3DImageBacking*>(backing.get());
   EXPECT_EQ(
       backing_d3d->dxgi_shared_handle_state_for_testing()->GetSharedHandle(),
       shared_handle);
@@ -1031,8 +1029,8 @@
   EXPECT_EQ(dup_backing->mailbox(), dup_mailbox);
   EXPECT_TRUE(dup_backing->IsCleared());
 
-  SharedImageBackingD3D* dup_backing_d3d =
-      static_cast<SharedImageBackingD3D*>(dup_backing.get());
+  D3DImageBacking* dup_backing_d3d =
+      static_cast<D3DImageBacking*>(dup_backing.get());
   EXPECT_EQ(dup_backing_d3d->dxgi_shared_handle_state_for_testing(),
             backing_d3d->dxgi_shared_handle_state_for_testing());
   EXPECT_EQ(dup_backing_d3d->d3d11_texture_for_testing(),
@@ -1052,7 +1050,7 @@
           mailbox);
   EXPECT_TRUE(gl_representation);
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
       scoped_access = gl_representation->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -1063,26 +1061,24 @@
           dup_mailbox);
   EXPECT_TRUE(dup_gl_representation);
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
       dup_scoped_access = dup_gl_representation->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
   EXPECT_TRUE(dup_scoped_access);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest,
-       CreateSharedImageFromHandleFormatUNORM) {
+TEST_F(D3DImageBackingFactoryTest, CreateSharedImageFromHandleFormatUNORM) {
   RunCreateSharedImageFromHandleTest(DXGI_FORMAT_R8G8B8A8_UNORM);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest,
-       CreateSharedImageFromHandleFormatTYPELESS) {
+TEST_F(D3DImageBackingFactoryTest, CreateSharedImageFromHandleFormatTYPELESS) {
   RunCreateSharedImageFromHandleTest(DXGI_FORMAT_R8G8B8A8_TYPELESS);
 }
 
 #if BUILDFLAG(USE_DAWN)
 // Test to check external image stored in the backing can be reused
-TEST_F(SharedImageBackingFactoryD3DTest, Dawn_ReuseExternalImage) {
+TEST_F(D3DImageBackingFactoryTest, Dawn_ReuseExternalImage) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -1212,7 +1208,7 @@
 }
 
 // Check if making Dawn have the last ref works without a current GL context.
-TEST_F(SharedImageBackingFactoryD3DTest, Dawn_HasLastRef) {
+TEST_F(D3DImageBackingFactoryTest, Dawn_HasLastRef) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -1287,12 +1283,12 @@
 #endif  // BUILDFLAG(USE_DAWN)
 
 std::vector<std::unique_ptr<SharedImageRepresentationFactoryRef>>
-SharedImageBackingFactoryD3DTest::CreateVideoImages(const gfx::Size& size,
-                                                    uint8_t y_fill_value,
-                                                    uint8_t u_fill_value,
-                                                    uint8_t v_fill_value,
-                                                    bool use_shared_handle,
-                                                    bool use_factory) {
+D3DImageBackingFactoryTest::CreateVideoImages(const gfx::Size& size,
+                                              uint8_t y_fill_value,
+                                              uint8_t u_fill_value,
+                                              uint8_t v_fill_value,
+                                              bool use_shared_handle,
+                                              bool use_factory) {
   DCHECK(IsD3DSharedImageSupported());
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
@@ -1364,7 +1360,7 @@
               ->CreateAnonymousSharedHandleState(std::move(shared_handle),
                                                  d3d11_texture);
     }
-    shared_image_backings = SharedImageBackingD3D::CreateFromVideoTexture(
+    shared_image_backings = D3DImageBacking::CreateFromVideoTexture(
         mailboxes, DXGI_FORMAT_NV12, size, usage, d3d11_texture,
         /*array_slice=*/0, std::move(dxgi_shared_handle_state));
   }
@@ -1397,8 +1393,8 @@
   return shared_image_refs;
 }
 
-void SharedImageBackingFactoryD3DTest::RunVideoTest(bool use_shared_handle,
-                                                    bool use_factory) {
+void D3DImageBackingFactoryTest::RunVideoTest(bool use_shared_handle,
+                                              bool use_factory) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -1558,20 +1554,20 @@
   // TODO(dawn:551): Test Dawn access after multi-planar support lands in Dawn.
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateFromVideoTexture) {
+TEST_F(D3DImageBackingFactoryTest, CreateFromVideoTexture) {
   RunVideoTest(/*use_shared_handle=*/false, /*use_factory=*/false);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateFromVideoTextureSharedHandle) {
+TEST_F(D3DImageBackingFactoryTest, CreateFromVideoTextureSharedHandle) {
   RunVideoTest(/*use_shared_handle=*/true, /*use_factory=*/false);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateSharedImageVideoPlanes) {
+TEST_F(D3DImageBackingFactoryTest, CreateSharedImageVideoPlanes) {
   RunVideoTest(/*use_shared_handle=*/true, /*use_factory=*/true);
 }
 
-void SharedImageBackingFactoryD3DTest::RunOverlayTest(bool use_shared_handle,
-                                                      bool use_factory) {
+void D3DImageBackingFactoryTest::RunOverlayTest(bool use_shared_handle,
+                                                bool use_factory) {
   if (!IsD3DSharedImageSupported())
     return;
 
@@ -1627,20 +1623,19 @@
   device_context->Unmap(staging_texture.Get(), 0);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateFromVideoTextureOverlay) {
+TEST_F(D3DImageBackingFactoryTest, CreateFromVideoTextureOverlay) {
   RunOverlayTest(/*use_shared_handle=*/false, /*use_factory=*/false);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest,
-       CreateFromVideoTextureSharedHandleOverlay) {
+TEST_F(D3DImageBackingFactoryTest, CreateFromVideoTextureSharedHandleOverlay) {
   RunOverlayTest(/*use_shared_handle=*/true, /*use_factory=*/false);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateSharedImageVideoPlanesOverlay) {
+TEST_F(D3DImageBackingFactoryTest, CreateSharedImageVideoPlanesOverlay) {
   RunOverlayTest(/*use_shared_handle=*/true, /*use_factory=*/true);
 }
 
-TEST_F(SharedImageBackingFactoryD3DTest, CreateFromSharedMemory) {
+TEST_F(D3DImageBackingFactoryTest, CreateFromSharedMemory) {
   if (!IsD3DSharedImageSupported())
     return;
 
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_representation.cc b/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
index 4126625..5da2dcf 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_representation.cc
@@ -11,44 +11,41 @@
 
 namespace gpu {
 
-SharedImageRepresentationGLTexturePassthroughD3D::
-    SharedImageRepresentationGLTexturePassthroughD3D(
+GLTexturePassthroughD3DImageRepresentation::
+    GLTexturePassthroughD3DImageRepresentation(
         SharedImageManager* manager,
         SharedImageBacking* backing,
         MemoryTypeTracker* tracker,
         scoped_refptr<gles2::TexturePassthrough> texture)
-    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+    : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
       texture_(std::move(texture)) {}
 
 const scoped_refptr<gles2::TexturePassthrough>&
-SharedImageRepresentationGLTexturePassthroughD3D::GetTexturePassthrough() {
+GLTexturePassthroughD3DImageRepresentation::GetTexturePassthrough() {
   return texture_;
 }
 
-SharedImageRepresentationGLTexturePassthroughD3D::
-    ~SharedImageRepresentationGLTexturePassthroughD3D() = default;
+GLTexturePassthroughD3DImageRepresentation::
+    ~GLTexturePassthroughD3DImageRepresentation() = default;
 
-bool SharedImageRepresentationGLTexturePassthroughD3D::BeginAccess(
-    GLenum mode) {
-  SharedImageBackingD3D* d3d_image_backing =
-      static_cast<SharedImageBackingD3D*>(backing());
+bool GLTexturePassthroughD3DImageRepresentation::BeginAccess(GLenum mode) {
+  D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
   return d3d_image_backing->BeginAccessD3D11();
 }
 
-void SharedImageRepresentationGLTexturePassthroughD3D::EndAccess() {
-  SharedImageBackingD3D* d3d_image_backing =
-      static_cast<SharedImageBackingD3D*>(backing());
+void GLTexturePassthroughD3DImageRepresentation::EndAccess() {
+  D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
   d3d_image_backing->EndAccessD3D11();
 }
 
 #if BUILDFLAG(USE_DAWN)
-SharedImageRepresentationDawnD3D::SharedImageRepresentationDawnD3D(
+DawnD3DImageRepresentation::DawnD3DImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     WGPUDevice device,
     dawn::native::d3d12::ExternalImageDXGI* external_image)
-    : SharedImageRepresentationDawn(manager, backing, tracker),
+    : DawnImageRepresentation(manager, backing, tracker),
       device_(device),
       external_image_(external_image),
       dawn_procs_(dawn::native::GetProcs()) {
@@ -60,15 +57,13 @@
   dawn_procs_.deviceReference(device_);
 }
 
-SharedImageRepresentationDawnD3D::~SharedImageRepresentationDawnD3D() {
+DawnD3DImageRepresentation::~DawnD3DImageRepresentation() {
   EndAccess();
   dawn_procs_.deviceRelease(device_);
 }
 
-WGPUTexture SharedImageRepresentationDawnD3D::BeginAccess(
-    WGPUTextureUsage usage) {
-  SharedImageBackingD3D* d3d_image_backing =
-      static_cast<SharedImageBackingD3D*>(backing());
+WGPUTexture DawnD3DImageRepresentation::BeginAccess(WGPUTextureUsage usage) {
+  D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
 
   if (!d3d_image_backing->BeginAccessD3D12())
     return nullptr;
@@ -91,13 +86,12 @@
   return texture_;
 }
 
-void SharedImageRepresentationDawnD3D::EndAccess() {
+void DawnD3DImageRepresentation::EndAccess() {
   if (!texture_) {
     return;
   }
 
-  SharedImageBackingD3D* d3d_image_backing =
-      static_cast<SharedImageBackingD3D*>(backing());
+  D3DImageBacking* d3d_image_backing = static_cast<D3DImageBacking*>(backing());
 
   if (dawn::native::IsTextureSubresourceInitialized(texture_, 0, 1, 0, 1)) {
     SetCleared();
@@ -115,34 +109,33 @@
 }
 #endif  // BUILDFLAG(USE_DAWN)
 
-SharedImageRepresentationOverlayD3D::SharedImageRepresentationOverlayD3D(
+OverlayD3DImageRepresentation::OverlayD3DImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     scoped_refptr<gl::GLImage> gl_image)
-    : SharedImageRepresentationOverlay(manager, backing, tracker),
+    : OverlayImageRepresentation(manager, backing, tracker),
       gl_image_(std::move(gl_image)) {}
 
-SharedImageRepresentationOverlayD3D::~SharedImageRepresentationOverlayD3D() =
-    default;
+OverlayD3DImageRepresentation::~OverlayD3DImageRepresentation() = default;
 
-bool SharedImageRepresentationOverlayD3D::BeginReadAccess(
+bool OverlayD3DImageRepresentation::BeginReadAccess(
     gfx::GpuFenceHandle& acquire_fence) {
   // Only D3D images need keyed mutex synchronization.
   if (gl_image_->GetType() == gl::GLImage::Type::D3D)
-    return static_cast<SharedImageBackingD3D*>(backing())->BeginAccessD3D11();
+    return static_cast<D3DImageBacking*>(backing())->BeginAccessD3D11();
   return true;
 }
 
-void SharedImageRepresentationOverlayD3D::EndReadAccess(
+void OverlayD3DImageRepresentation::EndReadAccess(
     gfx::GpuFenceHandle release_fence) {
   DCHECK(release_fence.is_null());
   // Only D3D images need keyed mutex synchronization.
   if (gl_image_->GetType() == gl::GLImage::Type::D3D)
-    static_cast<SharedImageBackingD3D*>(backing())->EndAccessD3D11();
+    static_cast<D3DImageBacking*>(backing())->EndAccessD3D11();
 }
 
-gl::GLImage* SharedImageRepresentationOverlayD3D::GetGLImage() {
+gl::GLImage* OverlayD3DImageRepresentation::GetGLImage() {
   return gl_image_.get();
 }
 
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_representation.h b/gpu/command_buffer/service/shared_image/d3d_image_representation.h
index 2e31442..376f87b 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_representation.h
@@ -21,18 +21,18 @@
 
 namespace gpu {
 
-class SharedImageBackingD3D;
+class D3DImageBacking;
 
-// Representation of a SharedImageBackingD3D as a GL TexturePassthrough.
-class SharedImageRepresentationGLTexturePassthroughD3D
-    : public SharedImageRepresentationGLTexturePassthrough {
+// Representation of a D3DImageBacking as a GL TexturePassthrough.
+class GLTexturePassthroughD3DImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  SharedImageRepresentationGLTexturePassthroughD3D(
+  GLTexturePassthroughD3DImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<gles2::TexturePassthrough> texture);
-  ~SharedImageRepresentationGLTexturePassthroughD3D() override;
+  ~GLTexturePassthroughD3DImageRepresentation() override;
 
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override;
@@ -44,18 +44,18 @@
   scoped_refptr<gles2::TexturePassthrough> texture_;
 };
 
-// Representation of a SharedImageBackingD3D as a Dawn Texture
+// Representation of a D3DImageBacking as a Dawn Texture
 #if BUILDFLAG(USE_DAWN)
-class SharedImageRepresentationDawnD3D : public SharedImageRepresentationDawn {
+class DawnD3DImageRepresentation : public DawnImageRepresentation {
  public:
-  SharedImageRepresentationDawnD3D(
+  DawnD3DImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       dawn::native::d3d12::ExternalImageDXGI* external_image);
 
-  ~SharedImageRepresentationDawnD3D() override;
+  ~DawnD3DImageRepresentation() override;
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
   void EndAccess() override;
@@ -71,15 +71,14 @@
 };
 #endif  // BUILDFLAG(USE_DAWN)
 
-// Representation of a SharedImageBackingD3D as an overlay.
-class SharedImageRepresentationOverlayD3D
-    : public SharedImageRepresentationOverlay {
+// Representation of a D3DImageBacking as an overlay.
+class OverlayD3DImageRepresentation : public OverlayImageRepresentation {
  public:
-  SharedImageRepresentationOverlayD3D(SharedImageManager* manager,
-                                      SharedImageBacking* backing,
-                                      MemoryTypeTracker* tracker,
-                                      scoped_refptr<gl::GLImage> gl_image);
-  ~SharedImageRepresentationOverlayD3D() override;
+  OverlayD3DImageRepresentation(SharedImageManager* manager,
+                                SharedImageBacking* backing,
+                                MemoryTypeTracker* tracker,
+                                scoped_refptr<gl::GLImage> gl_image);
+  ~OverlayD3DImageRepresentation() override;
 
  private:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
diff --git a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc
index 7a73540..a105d05 100644
--- a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.cc
@@ -24,13 +24,13 @@
 
 namespace gpu {
 
-SharedImageRepresentationDawnEGLImage::SharedImageRepresentationDawnEGLImage(
-    std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+DawnEGLImageRepresentation::DawnEGLImageRepresentation(
+    std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     WGPUDevice device)
-    : SharedImageRepresentationDawn(manager, backing, tracker),
+    : DawnImageRepresentation(manager, backing, tracker),
       gl_representation_(std::move(gl_representation)),
       device_(device),
       dawn_procs_(dawn::native::GetProcs()) {
@@ -40,15 +40,13 @@
   dawn_procs_.deviceReference(device_);
 }
 
-SharedImageRepresentationDawnEGLImage::
-    ~SharedImageRepresentationDawnEGLImage() {
+DawnEGLImageRepresentation::~DawnEGLImageRepresentation() {
   EndAccess();
 
   dawn_procs_.deviceRelease(device_);
 }
 
-WGPUTexture SharedImageRepresentationDawnEGLImage::BeginAccess(
-    WGPUTextureUsage usage) {
+WGPUTexture DawnEGLImageRepresentation::BeginAccess(WGPUTextureUsage usage) {
   gl_representation_->BeginAccess(ToSharedImageAccessGLMode(usage));
   WGPUTextureDescriptor texture_descriptor = {};
   texture_descriptor.nextInChain = nullptr;
@@ -80,7 +78,7 @@
   return texture_;
 }
 
-void SharedImageRepresentationDawnEGLImage::EndAccess() {
+void DawnEGLImageRepresentation::EndAccess() {
   if (!texture_) {
     return;
   }
diff --git a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.h b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.h
index d910b8b..89cae08 100644
--- a/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/dawn_egl_image_representation.h
@@ -11,23 +11,23 @@
 
 namespace gpu {
 
-class GPU_GLES2_EXPORT SharedImageRepresentationDawnEGLImage
-    : public SharedImageRepresentationDawn {
+class GPU_GLES2_EXPORT DawnEGLImageRepresentation
+    : public DawnImageRepresentation {
  public:
-  SharedImageRepresentationDawnEGLImage(
-      std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+  DawnEGLImageRepresentation(
+      std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       WGPUDevice device);
-  ~SharedImageRepresentationDawnEGLImage() override;
+  ~DawnEGLImageRepresentation() override;
 
  private:
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
   void EndAccess() override;
 
  private:
-  std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation_;
+  std::unique_ptr<GLTextureImageRepresentationBase> gl_representation_;
   WGPUDevice device_;
   DawnProcTable dawn_procs_;
   WGPUTexture texture_ = nullptr;
diff --git a/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.cc b/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.cc
index 394f8b3..591c725c 100644
--- a/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.cc
@@ -19,7 +19,7 @@
 
 namespace gpu {
 
-SharedImageRepresentationDawnOzone::SharedImageRepresentationDawnOzone(
+DawnOzoneImageRepresentation::DawnOzoneImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
@@ -27,7 +27,7 @@
     WGPUTextureFormat format,
     scoped_refptr<gfx::NativePixmap> pixmap,
     scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs)
-    : SharedImageRepresentationDawn(manager, backing, tracker),
+    : DawnImageRepresentation(manager, backing, tracker),
       device_(device),
       format_(format),
       pixmap_(pixmap),
@@ -39,13 +39,12 @@
   dawn_procs_->data.deviceReference(device_);
 }
 
-SharedImageRepresentationDawnOzone::~SharedImageRepresentationDawnOzone() {
+DawnOzoneImageRepresentation::~DawnOzoneImageRepresentation() {
   EndAccess();
   dawn_procs_->data.deviceRelease(device_);
 }
 
-WGPUTexture SharedImageRepresentationDawnOzone::BeginAccess(
-    WGPUTextureUsage usage) {
+WGPUTexture DawnOzoneImageRepresentation::BeginAccess(WGPUTextureUsage usage) {
   // It doesn't make sense to have two overlapping BeginAccess calls on the same
   // representation.
   if (texture_) {
@@ -68,8 +67,8 @@
   std::vector<gfx::GpuFenceHandle> fences;
   bool need_end_fence;
   if (!ozone_backing()->BeginAccess(
-          /*readonly=*/false, SharedImageBackingOzone::AccessStream::kWebGPU,
-          &fences, need_end_fence)) {
+          /*readonly=*/false, OzoneImageBacking::AccessStream::kWebGPU, &fences,
+          need_end_fence)) {
     return nullptr;
   }
   DCHECK(need_end_fence);
@@ -122,7 +121,7 @@
   texture_ = dawn::native::vulkan::WrapVulkanImage(device_, &descriptor);
   if (!texture_) {
     ozone_backing()->EndAccess(/*readonly=*/false,
-                               SharedImageBackingOzone::AccessStream::kWebGPU,
+                               OzoneImageBacking::AccessStream::kWebGPU,
                                gfx::GpuFenceHandle());
     close(fd);
   }
@@ -130,7 +129,7 @@
   return texture_;
 }
 
-void SharedImageRepresentationDawnOzone::EndAccess() {
+void DawnOzoneImageRepresentation::EndAccess() {
   if (!texture_) {
     return;
   }
@@ -150,7 +149,7 @@
     gfx::GpuFenceHandle fence;
     fence.owned_fd = base::ScopedFD(export_info.semaphoreHandles[0]);
     ozone_backing()->EndAccess(/*readonly=*/false,
-                               SharedImageBackingOzone::AccessStream::kWebGPU,
+                               OzoneImageBacking::AccessStream::kWebGPU,
                                std::move(fence));
   }
   dawn_procs_->data.textureDestroy(texture_);
diff --git a/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.h b/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.h
index 3b7cc3f..0e767e9 100644
--- a/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/dawn_ozone_image_representation.h
@@ -21,10 +21,9 @@
 // SharedImageRepresentation of a Ozone-backed SharedImage to be used by Dawn.
 // On access, the pixmap backing the SharedImage is imported into Dawn for
 // rendering.
-class SharedImageRepresentationDawnOzone
-    : public SharedImageRepresentationDawn {
+class DawnOzoneImageRepresentation : public DawnImageRepresentation {
  public:
-  SharedImageRepresentationDawnOzone(
+  DawnOzoneImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
@@ -33,12 +32,11 @@
       scoped_refptr<gfx::NativePixmap> pixmap,
       scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs);
 
-  SharedImageRepresentationDawnOzone(
-      const SharedImageRepresentationDawnOzone&) = delete;
-  SharedImageRepresentationDawnOzone& operator=(
-      const SharedImageRepresentationDawnOzone&) = delete;
+  DawnOzoneImageRepresentation(const DawnOzoneImageRepresentation&) = delete;
+  DawnOzoneImageRepresentation& operator=(const DawnOzoneImageRepresentation&) =
+      delete;
 
-  ~SharedImageRepresentationDawnOzone() override;
+  ~DawnOzoneImageRepresentation() override;
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
 
@@ -46,9 +44,9 @@
 
  private:
   // TODO(andrescj): move other shared image representations into
-  // SharedImageBackingOzone.
-  SharedImageBackingOzone* ozone_backing() {
-    return static_cast<SharedImageBackingOzone*>(backing());
+  // OzoneImageBacking.
+  OzoneImageBacking* ozone_backing() {
+    return static_cast<OzoneImageBacking*>(backing());
   }
   const WGPUDevice device_;
   const WGPUTextureFormat format_;
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.cc b/gpu/command_buffer/service/shared_image/egl_image_backing.cc
index 2f81ad0a..b14dde0 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing.cc
@@ -18,8 +18,7 @@
 
 namespace gpu {
 
-class SharedImageBackingEglImage::TextureHolder
-    : public base::RefCounted<TextureHolder> {
+class EGLImageBacking::TextureHolder : public base::RefCounted<TextureHolder> {
  public:
   explicit TextureHolder(gles2::Texture* texture) : texture_(texture) {}
   explicit TextureHolder(
@@ -50,19 +49,19 @@
   bool context_lost_ = false;
 };
 
-// Implementation of SharedImageRepresentationGLTexture which uses GL texture
+// Implementation of GLTextureImageRepresentation which uses GL texture
 // which is an EGLImage sibling.
-class SharedImageBackingEglImage::RepresentationGLShared {
+class EGLImageBacking::GLRepresentationShared {
  public:
-  using TextureHolder = SharedImageBackingEglImage::TextureHolder;
-  RepresentationGLShared(SharedImageBackingEglImage* backing,
+  using TextureHolder = EGLImageBacking::TextureHolder;
+  GLRepresentationShared(EGLImageBacking* backing,
                          scoped_refptr<TextureHolder> texture_holder)
       : backing_(backing), texture_holder_(std::move(texture_holder)) {}
 
-  RepresentationGLShared(const RepresentationGLShared&) = delete;
-  RepresentationGLShared& operator=(const RepresentationGLShared&) = delete;
+  GLRepresentationShared(const GLRepresentationShared&) = delete;
+  GLRepresentationShared& operator=(const GLRepresentationShared&) = delete;
 
-  ~RepresentationGLShared() {
+  ~GLRepresentationShared() {
     EndAccess();
     if (!backing_->have_context())
       texture_holder_->MarkContextLost();
@@ -105,25 +104,27 @@
   }
 
  private:
-  const raw_ptr<SharedImageBackingEglImage> backing_;
+  const raw_ptr<EGLImageBacking> backing_;
   scoped_refptr<TextureHolder> texture_holder_;
   RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
 };
 
-class SharedImageBackingEglImage::RepresentationGLTexture
-    : public SharedImageRepresentationGLTexture {
+class EGLImageBacking::GLTextureEGLImageRepresentation
+    : public GLTextureImageRepresentation {
  public:
-  RepresentationGLTexture(SharedImageManager* manager,
-                          SharedImageBackingEglImage* backing,
-                          MemoryTypeTracker* tracker,
-                          scoped_refptr<TextureHolder> texture_holder)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
+  GLTextureEGLImageRepresentation(SharedImageManager* manager,
+                                  EGLImageBacking* backing,
+                                  MemoryTypeTracker* tracker,
+                                  scoped_refptr<TextureHolder> texture_holder)
+      : GLTextureImageRepresentation(manager, backing, tracker),
         shared_(backing, std::move(texture_holder)) {}
 
-  RepresentationGLTexture(const RepresentationGLTexture&) = delete;
-  RepresentationGLTexture& operator=(const RepresentationGLTexture&) = delete;
+  GLTextureEGLImageRepresentation(const GLTextureEGLImageRepresentation&) =
+      delete;
+  GLTextureEGLImageRepresentation& operator=(
+      const GLTextureEGLImageRepresentation&) = delete;
 
-  ~RepresentationGLTexture() override = default;
+  ~GLTextureEGLImageRepresentation() override = default;
 
   bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
 
@@ -136,28 +137,26 @@
   bool SupportsMultipleConcurrentReadAccess() override { return true; }
 
  private:
-  RepresentationGLShared shared_;
+  GLRepresentationShared shared_;
 };
 
-class SharedImageBackingEglImage::RepresentationGLTexturePassthrough
-    : public SharedImageRepresentationGLTexturePassthrough {
+class EGLImageBacking::GLTexturePassthroughEGLImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  RepresentationGLTexturePassthrough(
+  GLTexturePassthroughEGLImageRepresentation(
       SharedImageManager* manager,
-      SharedImageBackingEglImage* backing,
+      EGLImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<TextureHolder> texture_holder)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
+      : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
         shared_(backing, std::move(texture_holder)) {}
 
-  RepresentationGLTexturePassthrough(
-      const RepresentationGLTexturePassthrough&) = delete;
-  RepresentationGLTexturePassthrough& operator=(
-      const RepresentationGLTexturePassthrough&) = delete;
+  GLTexturePassthroughEGLImageRepresentation(
+      const GLTexturePassthroughEGLImageRepresentation&) = delete;
+  GLTexturePassthroughEGLImageRepresentation& operator=(
+      const GLTexturePassthroughEGLImageRepresentation&) = delete;
 
-  ~RepresentationGLTexturePassthrough() override = default;
+  ~GLTexturePassthroughEGLImageRepresentation() override = default;
 
   bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
 
@@ -173,10 +172,10 @@
   bool SupportsMultipleConcurrentReadAccess() override { return true; }
 
  private:
-  RepresentationGLShared shared_;
+  GLRepresentationShared shared_;
 };
 
-SharedImageBackingEglImage::SharedImageBackingEglImage(
+EGLImageBacking::EGLImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -185,9 +184,9 @@
     SkAlphaType alpha_type,
     uint32_t usage,
     size_t estimated_size,
-    const SharedImageBackingFactoryGLCommon::FormatInfo format_info,
+    const GLCommonImageBackingFactory::FormatInfo format_info,
     const GpuDriverBugWorkarounds& workarounds,
-    const SharedImageBackingGLCommon::UnpackStateAttribs& attribs,
+    const GLTextureImageBackingHelper::UnpackStateAttribs& attribs,
     bool use_passthrough,
     base::span<const uint8_t> pixel_data)
     : ClearTrackingSharedImageBacking(mailbox,
@@ -215,27 +214,25 @@
     auto texture_holder = GenEGLImageSibling(pixel_data);
 }
 
-SharedImageBackingEglImage::~SharedImageBackingEglImage() {
+EGLImageBacking::~EGLImageBacking() {
   DCHECK(!source_texture_holder_);
 }
 
-SharedImageBackingType SharedImageBackingEglImage::GetType() const {
-  return SharedImageBackingType::kEglImage;
+SharedImageBackingType EGLImageBacking::GetType() const {
+  return SharedImageBackingType::kEGLImage;
 }
 
-void SharedImageBackingEglImage::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {
+void EGLImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   NOTREACHED();
 }
 
-bool SharedImageBackingEglImage::ProduceLegacyMailbox(
-    MailboxManager* mailbox_manager) {
+bool EGLImageBacking::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
   // This backing doe not support legacy mailbox system.
   return false;
 }
 
 template <class T>
-std::unique_ptr<T> SharedImageBackingEglImage::ProduceGLTextureInternal(
+std::unique_ptr<T> EGLImageBacking::ProduceGLTextureInternal(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   // On some GPUs (Mali, mostly Android 9, like J7) glTexSubImage fails on egl
@@ -256,22 +253,21 @@
   return std::make_unique<T>(manager, this, tracker, std::move(texture_holder));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingEglImage::ProduceGLTexture(SharedImageManager* manager,
-                                             MemoryTypeTracker* tracker) {
-  return ProduceGLTextureInternal<RepresentationGLTexture>(manager, tracker);
-}
-
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingEglImage::ProduceGLTexturePassthrough(
+std::unique_ptr<GLTextureImageRepresentation> EGLImageBacking::ProduceGLTexture(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
-  return ProduceGLTextureInternal<RepresentationGLTexturePassthrough>(manager,
-                                                                      tracker);
+  return ProduceGLTextureInternal<GLTextureEGLImageRepresentation>(manager,
+                                                                   tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingEglImage::ProduceSkia(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+EGLImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                             MemoryTypeTracker* tracker) {
+  return ProduceGLTextureInternal<GLTexturePassthroughEGLImageRepresentation>(
+      manager, tracker);
+}
+
+std::unique_ptr<SkiaImageRepresentation> EGLImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -279,20 +275,20 @@
     auto gl_representation = ProduceGLTexturePassthrough(manager, tracker);
     if (!gl_representation)
       return nullptr;
-    return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation),
-                                                   std::move(context_state),
-                                                   manager, this, tracker);
+    return SkiaGLImageRepresentation::Create(std::move(gl_representation),
+                                             std::move(context_state), manager,
+                                             this, tracker);
   } else {
     auto gl_representation = ProduceGLTexture(manager, tracker);
     if (!gl_representation)
       return nullptr;
-    return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation),
-                                                   std::move(context_state),
-                                                   manager, this, tracker);
+    return SkiaGLImageRepresentation::Create(std::move(gl_representation),
+                                             std::move(context_state), manager,
+                                             this, tracker);
   }
 }
 
-bool SharedImageBackingEglImage::BeginWrite() {
+bool EGLImageBacking::BeginWrite() {
   AutoLock auto_lock(this);
 
   if (is_writing_ || !active_readers_.empty()) {
@@ -320,7 +316,7 @@
   return true;
 }
 
-void SharedImageBackingEglImage::EndWrite() {
+void EGLImageBacking::EndWrite() {
   AutoLock auto_lock(this);
 
   if (!is_writing_) {
@@ -333,8 +329,7 @@
   write_fence_ = gl::GLFenceEGL::Create();
 }
 
-bool SharedImageBackingEglImage::BeginRead(
-    const RepresentationGLShared* reader) {
+bool EGLImageBacking::BeginRead(const GLRepresentationShared* reader) {
   AutoLock auto_lock(this);
 
   if (is_writing_) {
@@ -353,7 +348,7 @@
   return true;
 }
 
-void SharedImageBackingEglImage::EndRead(const RepresentationGLShared* reader) {
+void EGLImageBacking::EndRead(const GLRepresentationShared* reader) {
   {
     AutoLock auto_lock(this);
 
@@ -370,9 +365,8 @@
       base::MakeRefCounted<gl::SharedGLFenceEGL>();
 }
 
-scoped_refptr<SharedImageBackingEglImage::TextureHolder>
-SharedImageBackingEglImage::GenEGLImageSibling(
-    base::span<const uint8_t> pixel_data) {
+scoped_refptr<EGLImageBacking::TextureHolder>
+EGLImageBacking::GenEGLImageSibling(base::span<const uint8_t> pixel_data) {
   // Create a gles2::texture.
   GLenum target = GL_TEXTURE_2D;
   gl::GLApi* api = gl::g_current_gl_context;
@@ -410,7 +404,7 @@
                                  size().width(), size().height());
 
         if (!pixel_data.empty()) {
-          SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState
+          GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState
               scoped_unpack_state(api, gl_unpack_attribs_,
                                   true /* uploading_data */);
           api->glTexSubImage2DFn(target, 0, 0, 0, size().width(),
@@ -418,13 +412,13 @@
                                  format_info_.gl_type, pixel_data.data());
         }
       } else if (format_info_.is_compressed) {
-        SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState
+        GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState
             scoped_unpack_state(api, gl_unpack_attribs_, !pixel_data.empty());
         api->glCompressedTexImage2DFn(
             target, 0, format_info_.image_internal_format, size().width(),
             size().height(), 0, pixel_data.size(), pixel_data.data());
       } else {
-        SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState
+        GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState
             scoped_unpack_state(api, gl_unpack_attribs_, !pixel_data.empty());
 
         api->glTexImage2DFn(target, 0, format_info_.image_internal_format,
@@ -483,13 +477,13 @@
   return base::MakeRefCounted<TextureHolder>(std::move(texture));
 }
 
-void SharedImageBackingEglImage::SetEndReadFence(
+void EGLImageBacking::SetEndReadFence(
     scoped_refptr<gl::SharedGLFenceEGL> shared_egl_fence) {
   AutoLock auto_lock(this);
   read_fences_[gl::g_current_gl_context] = std::move(shared_egl_fence);
 }
 
-void SharedImageBackingEglImage::MarkForDestruction() {
+void EGLImageBacking::MarkForDestruction() {
   AutoLock auto_lock(this);
   DCHECK(!have_context() || created_on_context_ == gl::g_current_gl_context);
 
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.h b/gpu/command_buffer/service/shared_image/egl_image_backing.h
index c9fe734..e2d2902 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing.h
@@ -21,8 +21,8 @@
 
 namespace gpu {
 class GpuDriverBugWorkarounds;
-class SharedImageRepresentationGLTexture;
-class SharedImageRepresentationSkia;
+class GLTextureImageRepresentation;
+class SkiaImageRepresentation;
 struct Mailbox;
 
 namespace gles2 {
@@ -34,9 +34,9 @@
 // this backing uses EGL Image siblings. This backing is thread safe across
 // different threads running different GL contexts not part of same shared
 // group. This is achieved by using locks and fences for proper synchronization.
-class SharedImageBackingEglImage : public ClearTrackingSharedImageBacking {
+class EGLImageBacking : public ClearTrackingSharedImageBacking {
  public:
-  SharedImageBackingEglImage(
+  EGLImageBacking(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       const gfx::Size& size,
@@ -45,17 +45,16 @@
       SkAlphaType alpha_type,
       uint32_t usage,
       size_t estimated_size,
-      const SharedImageBackingFactoryGLCommon::FormatInfo format_into,
+      const GLCommonImageBackingFactory::FormatInfo format_into,
       const GpuDriverBugWorkarounds& workarounds,
-      const SharedImageBackingGLCommon::UnpackStateAttribs& attribs,
+      const GLTextureImageBackingHelper::UnpackStateAttribs& attribs,
       bool use_passthrough,
       base::span<const uint8_t> pixel_data);
 
-  SharedImageBackingEglImage(const SharedImageBackingEglImage&) = delete;
-  SharedImageBackingEglImage& operator=(const SharedImageBackingEglImage&) =
-      delete;
+  EGLImageBacking(const EGLImageBacking&) = delete;
+  EGLImageBacking& operator=(const EGLImageBacking&) = delete;
 
-  ~SharedImageBackingEglImage() override;
+  ~EGLImageBacking() override;
 
   // SharedImageBacking implementation.
   SharedImageBackingType GetType() const override;
@@ -64,24 +63,24 @@
   void MarkForDestruction() override;
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
  private:
   class TextureHolder;
-  class RepresentationGLShared;
-  class RepresentationGLTexture;
-  class RepresentationGLTexturePassthrough;
+  class GLRepresentationShared;
+  class GLTextureEGLImageRepresentation;
+  class GLTexturePassthroughEGLImageRepresentation;
 
   template <class T>
   std::unique_ptr<T> ProduceGLTextureInternal(SharedImageManager* manager,
@@ -89,8 +88,8 @@
 
   bool BeginWrite();
   void EndWrite();
-  bool BeginRead(const RepresentationGLShared* reader);
-  void EndRead(const RepresentationGLShared* reader);
+  bool BeginRead(const GLRepresentationShared* reader);
+  void EndRead(const GLRepresentationShared* reader);
 
   // Use to create EGLImage texture target from the same EGLImage object.
   // Optional |pixel_data| to initialize a texture with before EGLImage object
@@ -100,7 +99,7 @@
 
   void SetEndReadFence(scoped_refptr<gl::SharedGLFenceEGL> shared_egl_fence);
 
-  const SharedImageBackingFactoryGLCommon::FormatInfo format_info_;
+  const GLCommonImageBackingFactory::FormatInfo format_info_;
   scoped_refptr<TextureHolder> source_texture_holder_;
   raw_ptr<gl::GLApi> created_on_context_;
 
@@ -120,10 +119,10 @@
   // signalled.
   base::flat_map<gl::GLApi*, scoped_refptr<gl::SharedGLFenceEGL>> read_fences_
       GUARDED_BY(lock_);
-  base::flat_set<const RepresentationGLShared*> active_readers_
+  base::flat_set<const GLRepresentationShared*> active_readers_
       GUARDED_BY(lock_);
 
-  const SharedImageBackingGLCommon::UnpackStateAttribs gl_unpack_attribs_;
+  const GLTextureImageBackingHelper::UnpackStateAttribs gl_unpack_attribs_;
   const bool use_passthrough_;
 };
 
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
index 58f56621..c269777 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
@@ -23,21 +23,20 @@
 namespace gpu {
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingFactoryEGL
+// EGLImageBackingFactory
 
-SharedImageBackingFactoryEGL::SharedImageBackingFactoryEGL(
+EGLImageBackingFactory::EGLImageBackingFactory(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
     const gles2::FeatureInfo* feature_info)
-    : SharedImageBackingFactoryGLCommon(gpu_preferences,
-                                        workarounds,
-                                        feature_info,
-                                        /*progress_reporter=*/nullptr) {}
+    : GLCommonImageBackingFactory(gpu_preferences,
+                                  workarounds,
+                                  feature_info,
+                                  /*progress_reporter=*/nullptr) {}
 
-SharedImageBackingFactoryEGL::~SharedImageBackingFactoryEGL() = default;
+EGLImageBackingFactory::~EGLImageBackingFactory() = default;
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryEGL::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> EGLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -51,8 +50,7 @@
                              alpha_type, usage, base::span<const uint8_t>());
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryEGL::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> EGLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -65,8 +63,7 @@
                              alpha_type, usage, pixel_data);
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryEGL::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> EGLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -82,14 +79,13 @@
   return nullptr;
 }
 
-bool SharedImageBackingFactoryEGL::IsSupported(
-    uint32_t usage,
-    viz::ResourceFormat format,
-    bool thread_safe,
-    gfx::GpuMemoryBufferType gmb_type,
-    GrContextType gr_context_type,
-    bool* allow_legacy_mailbox,
-    bool is_pixel_used) {
+bool EGLImageBackingFactory::IsSupported(uint32_t usage,
+                                         viz::ResourceFormat format,
+                                         bool thread_safe,
+                                         gfx::GpuMemoryBufferType gmb_type,
+                                         GrContextType gr_context_type,
+                                         bool* allow_legacy_mailbox,
+                                         bool is_pixel_used) {
   if (is_pixel_used && gr_context_type != GrContextType::kGL) {
     return false;
   }
@@ -115,8 +111,7 @@
   return true;
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryEGL::MakeEglImageBacking(
+std::unique_ptr<SharedImageBacking> EGLImageBackingFactory::MakeEglImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -140,7 +135,7 @@
     return nullptr;
   }
 
-  return std::make_unique<SharedImageBackingEglImage>(
+  return std::make_unique<EGLImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       estimated_size, format_info, workarounds_, attribs_, use_passthrough_,
       pixel_data);
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.h b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.h
index c9f18596..3c3a6b4 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.h
@@ -29,13 +29,13 @@
 
 // Implementation of SharedImageBackingFactory that produces EGL backed
 // SharedImages.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryEGL
-    : public SharedImageBackingFactoryGLCommon {
+class GPU_GLES2_EXPORT EGLImageBackingFactory
+    : public GLCommonImageBackingFactory {
  public:
-  SharedImageBackingFactoryEGL(const GpuPreferences& gpu_preferences,
-                               const GpuDriverBugWorkarounds& workarounds,
-                               const gles2::FeatureInfo* feature_info);
-  ~SharedImageBackingFactoryEGL() override;
+  EGLImageBackingFactory(const GpuPreferences& gpu_preferences,
+                         const GpuDriverBugWorkarounds& workarounds,
+                         const gles2::FeatureInfo* feature_info);
+  ~EGLImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation.
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
index da774e9..b46518b 100644
--- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -71,12 +71,12 @@
   context_state->InitializeGL(GpuPreferences(), feature_info);
 }
 
-class SharedImageBackingFactoryEGLThreadSafeTest
+class EGLImageBackingFactoryThreadSafeTest
     : public testing::TestWithParam<std::tuple<bool, viz::ResourceFormat>> {
  public:
-  SharedImageBackingFactoryEGLThreadSafeTest()
+  EGLImageBackingFactoryThreadSafeTest()
       : shared_image_manager_(std::make_unique<SharedImageManager>(true)) {}
-  ~SharedImageBackingFactoryEGLThreadSafeTest() {
+  ~EGLImageBackingFactoryThreadSafeTest() override {
     // |context_state_| and |context_state2_| must be destroyed on its own
     // context.
     context_state2_->MakeCurrent(surface2_.get(), true /* needs_gl */);
@@ -94,7 +94,7 @@
 
     GpuPreferences preferences;
     preferences.use_passthrough_cmd_decoder = use_passthrough();
-    backing_factory_ = std::make_unique<SharedImageBackingFactoryEGL>(
+    backing_factory_ = std::make_unique<EGLImageBackingFactory>(
         preferences, workarounds, context_state_->feature_info());
 
     memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr);
@@ -120,7 +120,7 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<SharedContextState> context_state_;
-  std::unique_ptr<SharedImageBackingFactoryEGL> backing_factory_;
+  std::unique_ptr<EGLImageBackingFactory> backing_factory_;
   gles2::MailboxManagerImpl mailbox_manager_;
   std::unique_ptr<SharedImageManager> shared_image_manager_;
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
@@ -136,7 +136,7 @@
 class CreateAndValidateSharedImageRepresentations {
  public:
   CreateAndValidateSharedImageRepresentations(
-      SharedImageBackingFactoryEGL* backing_factory,
+      EGLImageBackingFactory* backing_factory,
       viz::ResourceFormat format,
       bool is_thread_safe,
       gles2::MailboxManagerImpl* mailbox_manager,
@@ -160,7 +160,7 @@
 
 // Intent of this test is to create at thread safe backing and test if all
 // representations are working.
-TEST_P(SharedImageBackingFactoryEGLThreadSafeTest, BasicThreadSafe) {
+TEST_P(EGLImageBackingFactoryThreadSafeTest, BasicThreadSafe) {
   CreateAndValidateSharedImageRepresentations shared_image(
       backing_factory_.get(), get_format(), true /* is_thread_safe */,
       &mailbox_manager_, shared_image_manager_.get(),
@@ -170,7 +170,7 @@
 
 // Intent of this test is to create at thread safe backing with initial pixel
 // data and test if all representations are working.
-TEST_P(SharedImageBackingFactoryEGLThreadSafeTest, BasicInitialData) {
+TEST_P(EGLImageBackingFactoryThreadSafeTest, BasicInitialData) {
   CreateAndValidateSharedImageRepresentations shared_image(
       backing_factory_.get(), get_format(), true /* is_thread_safe */,
       &mailbox_manager_, shared_image_manager_.get(),
@@ -182,7 +182,7 @@
 // threads each running their own GL context which are not part of same shared
 // group. One thread will be writing to the backing and other thread will be
 // reading from it.
-TEST_P(SharedImageBackingFactoryEGLThreadSafeTest, OneWriterOneReader) {
+TEST_P(EGLImageBackingFactoryThreadSafeTest, OneWriterOneReader) {
   // Create it on 1st SharedContextState |context_state_|.
   CreateAndValidateSharedImageRepresentations shared_image(
       backing_factory_.get(), get_format(), true /* is_thread_safe */,
@@ -200,7 +200,7 @@
   EXPECT_TRUE(gl_representation);
 
   // Begin writing to the underlying texture of the backing via ScopedAccess.
-  std::unique_ptr<SharedImageRepresentationGLTexture::ScopedAccess>
+  std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>
       writer_scoped_access = gl_representation->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kNo);
@@ -230,10 +230,11 @@
   gl_representation.reset();
 
   // Read from the backing in a separate thread. Read is done via
-  // SkiaGLRepresentation. ReadPixels() creates/produces a SkiaGLRepresentation
-  // which in turn wraps a GLTextureRepresentation when for GL mode. Hence
-  // testing reading via SkiaGLRepresentation is equivalent to testing via
-  // GLTextureRepresentation.
+  // SkiaGLImageRepresentation. ReadPixels() creates/produces a
+  // SkiaGLImageRepresentation which in turn wraps a
+  // GLTextureImageRepresentation when for GL mode. Hence testing reading via
+  // SkiaGLImageRepresentation is equivalent to testing via
+  // GLTextureImageRepresentation.
   std::vector<uint8_t> dst_pixels;
 
   // Launch 2nd thread.
@@ -255,7 +256,7 @@
 
 CreateAndValidateSharedImageRepresentations::
     CreateAndValidateSharedImageRepresentations(
-        SharedImageBackingFactoryEGL* backing_factory,
+        EGLImageBackingFactory* backing_factory,
         viz::ResourceFormat format,
         bool is_thread_safe,
         gles2::MailboxManagerImpl* mailbox_manager,
@@ -339,7 +340,7 @@
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -364,8 +365,7 @@
   EXPECT_TRUE(end_semaphores.empty());
   scoped_write_access.reset();
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   auto* promise_texture = scoped_read_access->promise_image_texture();
@@ -400,7 +400,7 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(Service,
-                         SharedImageBackingFactoryEGLThreadSafeTest,
+                         EGLImageBackingFactoryThreadSafeTest,
                          ::testing::Combine(::testing::Bool(),
                                             kResourceFormats),
                          TestParamToString);
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
index e2de365..489b3b8 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
@@ -571,11 +571,11 @@
   pending_semaphores_.clear();
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-ExternalVkImageBacking::ProduceDawn(SharedImageManager* manager,
-                                    MemoryTypeTracker* tracker,
-                                    WGPUDevice wgpuDevice,
-                                    WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> ExternalVkImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice wgpuDevice,
+    WGPUBackendType backend_type) {
 #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && BUILDFLAG(USE_DAWN)
   auto wgpu_format = viz::ToWGPUFormat(format());
 
@@ -593,7 +593,7 @@
     return nullptr;
   }
 
-  return std::make_unique<ExternalVkImageDawnRepresentation>(
+  return std::make_unique<ExternalVkImageDawnImageRepresentation>(
       manager, this, tracker, wgpuDevice, wgpu_format, std::move(memory_fd));
 #else  // (!BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)) ||
        // !BUILDFLAG(USE_DAWN)
@@ -693,7 +693,7 @@
   return texture_service_id;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 ExternalVkImageBacking::ProduceGLTexture(SharedImageManager* manager,
                                          MemoryTypeTracker* tracker) {
   DCHECK(!texture_passthrough_);
@@ -730,7 +730,7 @@
       manager, this, tracker, texture_, texture_->service_id());
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
 ExternalVkImageBacking::ProduceGLTexturePassthrough(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
@@ -762,8 +762,7 @@
       manager, this, tracker, texture_passthrough_->service_id());
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-ExternalVkImageBacking::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> ExternalVkImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -771,15 +770,15 @@
   // should also be using Vulkan.
   DCHECK_EQ(context_state_, context_state);
   DCHECK(context_state->GrContextIsVulkan());
-  return std::make_unique<ExternalVkImageSkiaRepresentation>(manager, this,
-                                                             tracker);
+  return std::make_unique<ExternalVkImageSkiaImageRepresentation>(manager, this,
+                                                                  tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
+std::unique_ptr<OverlayImageRepresentation>
 ExternalVkImageBacking::ProduceOverlay(SharedImageManager* manager,
                                        MemoryTypeTracker* tracker) {
-  return std::make_unique<ExternalVkImageOverlayRepresentation>(manager, this,
-                                                                tracker);
+  return std::make_unique<ExternalVkImageOverlayImageRepresentation>(
+      manager, this, tracker);
 }
 
 void ExternalVkImageBacking::InstallSharedMemory(
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.h b/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
index 0747ca5e..6e203ba 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.h
@@ -153,22 +153,22 @@
   void EndAccessInternal(bool readonly, ExternalSemaphore external_semaphore);
 
   // SharedImageBacking implementation.
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice dawnDevice,
       WGPUBackendType backend_type) override;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
index d2eab4c..b2f4642 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
@@ -74,7 +74,7 @@
 
 }  // namespace
 
-ExternalVkImageFactory::ExternalVkImageFactory(
+ExternalVkImageBackingFactory::ExternalVkImageBackingFactory(
     scoped_refptr<SharedContextState> context_state)
     : context_state_(std::move(context_state)),
       command_pool_(context_state_->vk_context_provider()
@@ -85,7 +85,7 @@
                                     ->GetDeviceQueue()
                                     ->GetVulkanPhysicalDevice())) {}
 
-ExternalVkImageFactory::~ExternalVkImageFactory() {
+ExternalVkImageBackingFactory::~ExternalVkImageBackingFactory() {
   if (command_pool_) {
     context_state_->vk_context_provider()
         ->GetDeviceQueue()
@@ -94,7 +94,8 @@
   }
 }
 
-std::unique_ptr<SharedImageBacking> ExternalVkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+ExternalVkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -111,7 +112,8 @@
       base::span<const uint8_t>());
 }
 
-std::unique_ptr<SharedImageBacking> ExternalVkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+ExternalVkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -125,7 +127,8 @@
       surface_origin, alpha_type, usage, &image_usage_cache_, pixel_data);
 }
 
-std::unique_ptr<SharedImageBacking> ExternalVkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+ExternalVkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -148,7 +151,7 @@
       &image_usage_cache_);
 }
 
-bool ExternalVkImageFactory::CanImportGpuMemoryBuffer(
+bool ExternalVkImageBackingFactory::CanImportGpuMemoryBuffer(
     gfx::GpuMemoryBufferType memory_buffer_type) {
   auto* device_queue = context_state_->vk_context_provider()->GetDeviceQueue();
   return context_state_->vk_context_provider()
@@ -157,13 +160,14 @@
          memory_buffer_type == gfx::SHARED_MEMORY_BUFFER;
 }
 
-bool ExternalVkImageFactory::IsSupported(uint32_t usage,
-                                         viz::ResourceFormat format,
-                                         bool thread_safe,
-                                         gfx::GpuMemoryBufferType gmb_type,
-                                         GrContextType gr_context_type,
-                                         bool* allow_legacy_mailbox,
-                                         bool is_pixel_used) {
+bool ExternalVkImageBackingFactory::IsSupported(
+    uint32_t usage,
+    viz::ResourceFormat format,
+    bool thread_safe,
+    gfx::GpuMemoryBufferType gmb_type,
+    GrContextType gr_context_type,
+    bool* allow_legacy_mailbox,
+    bool is_pixel_used) {
   if (gmb_type != gfx::EMPTY_BUFFER && !CanImportGpuMemoryBuffer(gmb_type)) {
     return false;
   }
@@ -176,7 +180,7 @@
     return false;
   }
   if (thread_safe) {
-    LOG(ERROR) << "ExternalVkImageFactory currently do not support "
+    LOG(ERROR) << "ExternalVkImageBackingFactory currently do not support "
                   "cross-thread usage.";
     return false;
   }
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.h b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.h
index 815265dd..a7068e0 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.h
@@ -21,16 +21,17 @@
 // can be exported out of Vulkan and be used in GL. Synchronization between
 // Vulkan and GL is done using VkSemaphores that are created with special flags
 // that allow it to be exported out and shared with GL.
-class GPU_GLES2_EXPORT ExternalVkImageFactory
+class GPU_GLES2_EXPORT ExternalVkImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  explicit ExternalVkImageFactory(
+  explicit ExternalVkImageBackingFactory(
       scoped_refptr<SharedContextState> context_state);
 
-  ExternalVkImageFactory(const ExternalVkImageFactory&) = delete;
-  ExternalVkImageFactory& operator=(const ExternalVkImageFactory&) = delete;
+  ExternalVkImageBackingFactory(const ExternalVkImageBackingFactory&) = delete;
+  ExternalVkImageBackingFactory& operator=(
+      const ExternalVkImageBackingFactory&) = delete;
 
-  ~ExternalVkImageFactory() override;
+  ~ExternalVkImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation.
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
index faaf5262..706b863 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory_unittest.cc
@@ -40,7 +40,7 @@
 namespace gpu {
 namespace {
 
-class ExternalVkImageFactoryTest : public testing::Test {
+class ExternalVkImageBackingFactoryTest : public testing::Test {
  protected:
   bool VulkanSupported() const {
     // crbug.com(941685, 1139366): Vulkan driver crashes on Linux FYI Release
@@ -88,7 +88,7 @@
         std::make_unique<SharedImageRepresentationFactory>(
             &shared_image_manager_, nullptr);
     shared_image_factory_ =
-        std::make_unique<ExternalVkImageFactory>(context_state_);
+        std::make_unique<ExternalVkImageBackingFactory>(context_state_);
 
 #if BUILDFLAG(USE_DAWN)
     // Create a Dawn Vulkan device
@@ -135,7 +135,7 @@
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
   std::unique_ptr<SharedImageRepresentationFactory>
       shared_image_representation_factory_;
-  std::unique_ptr<ExternalVkImageFactory> shared_image_factory_;
+  std::unique_ptr<ExternalVkImageBackingFactory> shared_image_factory_;
 
 #if BUILDFLAG(USE_DAWN)
   dawn::native::Instance dawn_instance_;
@@ -145,7 +145,7 @@
 
 #if BUILDFLAG(USE_DAWN)
 
-TEST_F(ExternalVkImageFactoryTest, DawnWrite_SkiaVulkanRead) {
+TEST_F(ExternalVkImageBackingFactoryTest, DawnWrite_SkiaVulkanRead) {
   if (!VulkanSupported()) {
     DLOG(ERROR) << "Test skipped because Vulkan isn't supported.";
     return;
@@ -268,7 +268,7 @@
   }
 }
 
-TEST_F(ExternalVkImageFactoryTest, SkiaVulkanWrite_DawnRead) {
+TEST_F(ExternalVkImageBackingFactoryTest, SkiaVulkanWrite_DawnRead) {
   if (!VulkanSupported()) {
     DLOG(ERROR) << "Test skipped because Vulkan isn't supported.";
     return;
@@ -291,7 +291,7 @@
                                      memory_type_tracker_.get());
 
   {
-    // Create a SkiaRepresentation
+    // Create a SkiaImageRepresentation
     auto skia_representation =
         shared_image_representation_factory_->ProduceSkia(mailbox,
                                                           context_state_.get());
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.cc b/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.cc
index 2741b6b6..ecc2574 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.cc
@@ -14,14 +14,14 @@
 
 namespace gpu {
 
-ExternalVkImageDawnRepresentation::ExternalVkImageDawnRepresentation(
+ExternalVkImageDawnImageRepresentation::ExternalVkImageDawnImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     WGPUDevice device,
     WGPUTextureFormat wgpu_format,
     base::ScopedFD memory_fd)
-    : SharedImageRepresentationDawn(manager, backing, tracker),
+    : DawnImageRepresentation(manager, backing, tracker),
       device_(device),
       wgpu_format_(wgpu_format),
       memory_fd_(std::move(memory_fd)),
@@ -33,12 +33,13 @@
   dawn_procs_.deviceReference(device_);
 }
 
-ExternalVkImageDawnRepresentation::~ExternalVkImageDawnRepresentation() {
+ExternalVkImageDawnImageRepresentation::
+    ~ExternalVkImageDawnImageRepresentation() {
   EndAccess();
   dawn_procs_.deviceRelease(device_);
 }
 
-WGPUTexture ExternalVkImageDawnRepresentation::BeginAccess(
+WGPUTexture ExternalVkImageDawnImageRepresentation::BeginAccess(
     WGPUTextureUsage usage) {
   DCHECK(begin_access_semaphores_.empty());
   if (!backing_impl()->BeginAccess(false, &begin_access_semaphores_,
@@ -95,7 +96,7 @@
   return texture_;
 }
 
-void ExternalVkImageDawnRepresentation::EndAccess() {
+void ExternalVkImageDawnImageRepresentation::EndAccess() {
   if (!texture_) {
     return;
   }
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.h b/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.h
index 21b4abe..4033c51 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_dawn_representation.h
@@ -10,21 +10,21 @@
 
 namespace gpu {
 
-class ExternalVkImageDawnRepresentation : public SharedImageRepresentationDawn {
+class ExternalVkImageDawnImageRepresentation : public DawnImageRepresentation {
  public:
-  ExternalVkImageDawnRepresentation(SharedImageManager* manager,
-                                    SharedImageBacking* backing,
-                                    MemoryTypeTracker* tracker,
-                                    WGPUDevice device,
-                                    WGPUTextureFormat dawn_format,
-                                    base::ScopedFD memory_fd);
+  ExternalVkImageDawnImageRepresentation(SharedImageManager* manager,
+                                         SharedImageBacking* backing,
+                                         MemoryTypeTracker* tracker,
+                                         WGPUDevice device,
+                                         WGPUTextureFormat dawn_format,
+                                         base::ScopedFD memory_fd);
 
-  ExternalVkImageDawnRepresentation(const ExternalVkImageDawnRepresentation&) =
-      delete;
-  ExternalVkImageDawnRepresentation& operator=(
-      const ExternalVkImageDawnRepresentation&) = delete;
+  ExternalVkImageDawnImageRepresentation(
+      const ExternalVkImageDawnImageRepresentation&) = delete;
+  ExternalVkImageDawnImageRepresentation& operator=(
+      const ExternalVkImageDawnImageRepresentation&) = delete;
 
-  ~ExternalVkImageDawnRepresentation() override;
+  ~ExternalVkImageDawnImageRepresentation() override;
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override;
   void EndAccess() override;
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.cc b/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.cc
index 02cfb60..fb5a8fa 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.cc
@@ -158,7 +158,7 @@
     MemoryTypeTracker* tracker,
     gles2::Texture* texture,
     GLuint texture_service_id)
-    : SharedImageRepresentationGLTexture(manager, backing, tracker),
+    : GLTextureImageRepresentation(manager, backing, tracker),
       texture_(texture),
       representation_shared_(backing, texture_service_id) {
   DCHECK(texture_);
@@ -182,7 +182,7 @@
                                                SharedImageBacking* backing,
                                                MemoryTypeTracker* tracker,
                                                GLuint texture_service_id)
-    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+    : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
       representation_shared_(backing, texture_service_id) {
   DCHECK(representation_shared_.backing_impl()->GetTexturePassthrough());
 }
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.h b/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.h
index 0b90a9928..3391278 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_gl_representation.h
@@ -50,8 +50,7 @@
   std::vector<ExternalSemaphore> begin_access_semaphores_;
 };
 
-class ExternalVkImageGLRepresentation
-    : public SharedImageRepresentationGLTexture {
+class ExternalVkImageGLRepresentation : public GLTextureImageRepresentation {
  public:
   ExternalVkImageGLRepresentation(SharedImageManager* manager,
                                   SharedImageBacking* backing,
@@ -66,7 +65,7 @@
 
   ~ExternalVkImageGLRepresentation() override;
 
-  // SharedImageRepresentationGLTexture implementation.
+  // GLTextureImageRepresentation implementation.
   gles2::Texture* GetTexture() override;
   bool BeginAccess(GLenum mode) override;
   void EndAccess() override;
@@ -77,7 +76,7 @@
 };
 
 class ExternalVkImageGLPassthroughRepresentation
-    : public SharedImageRepresentationGLTexturePassthrough {
+    : public GLTexturePassthroughImageRepresentation {
  public:
   ExternalVkImageGLPassthroughRepresentation(SharedImageManager* manager,
                                              SharedImageBacking* backing,
@@ -91,7 +90,7 @@
 
   ~ExternalVkImageGLPassthroughRepresentation() override;
 
-  // SharedImageRepresentationGLTexturePassthrough implementation.
+  // GLTexturePassthroughImageRepresentation implementation.
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override;
   bool BeginAccess(GLenum mode) override;
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.cc b/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.cc
index c48e178..56e2d33 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.cc
@@ -15,17 +15,17 @@
 
 namespace gpu {
 
-ExternalVkImageOverlayRepresentation::ExternalVkImageOverlayRepresentation(
-    SharedImageManager* manager,
-    ExternalVkImageBacking* backing,
-    MemoryTypeTracker* tracker)
-    : gpu::SharedImageRepresentationOverlay(manager, backing, tracker),
+ExternalVkImageOverlayImageRepresentation::
+    ExternalVkImageOverlayImageRepresentation(SharedImageManager* manager,
+                                              ExternalVkImageBacking* backing,
+                                              MemoryTypeTracker* tracker)
+    : gpu::OverlayImageRepresentation(manager, backing, tracker),
       vk_image_backing_(backing) {}
 
-ExternalVkImageOverlayRepresentation::~ExternalVkImageOverlayRepresentation() =
-    default;
+ExternalVkImageOverlayImageRepresentation::
+    ~ExternalVkImageOverlayImageRepresentation() = default;
 
-bool ExternalVkImageOverlayRepresentation::BeginReadAccess(
+bool ExternalVkImageOverlayImageRepresentation::BeginReadAccess(
     gfx::GpuFenceHandle& acquire_fence) {
   DCHECK(read_begin_semaphores_.empty());
   if (!vk_image_backing_->BeginAccess(/*readonly=*/true,
@@ -38,7 +38,7 @@
   return true;
 }
 
-void ExternalVkImageOverlayRepresentation::EndReadAccess(
+void ExternalVkImageOverlayImageRepresentation::EndReadAccess(
     gfx::GpuFenceHandle release_fence) {
   ExternalSemaphore read_end_semaphore;
 
@@ -61,12 +61,12 @@
   read_begin_semaphores_.clear();
 }
 
-gl::GLImage* ExternalVkImageOverlayRepresentation::GetGLImage() {
+gl::GLImage* ExternalVkImageOverlayImageRepresentation::GetGLImage() {
   NOTREACHED();
   return nullptr;
 }
 
-void ExternalVkImageOverlayRepresentation::GetAcquireFence(
+void ExternalVkImageOverlayImageRepresentation::GetAcquireFence(
     gfx::GpuFenceHandle& fence) {
   const VkDevice& device = vk_image_backing_->context_provider()
                                ->GetDeviceQueue()
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.h b/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.h
index eb804da2..4d1b936 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_overlay_representation.h
@@ -12,20 +12,20 @@
 
 namespace gpu {
 
-class ExternalVkImageOverlayRepresentation
-    : public SharedImageRepresentationOverlay {
+class ExternalVkImageOverlayImageRepresentation
+    : public OverlayImageRepresentation {
  public:
-  ExternalVkImageOverlayRepresentation(gpu::SharedImageManager* manager,
-                                       ExternalVkImageBacking* backing,
-                                       gpu::MemoryTypeTracker* tracker);
-  ~ExternalVkImageOverlayRepresentation() override;
-  ExternalVkImageOverlayRepresentation(
-      const ExternalVkImageOverlayRepresentation&) = delete;
-  ExternalVkImageOverlayRepresentation& operator=(
-      const ExternalVkImageOverlayRepresentation&) = delete;
+  ExternalVkImageOverlayImageRepresentation(gpu::SharedImageManager* manager,
+                                            ExternalVkImageBacking* backing,
+                                            MemoryTypeTracker* tracker);
+  ~ExternalVkImageOverlayImageRepresentation() override;
+  ExternalVkImageOverlayImageRepresentation(
+      const ExternalVkImageOverlayImageRepresentation&) = delete;
+  ExternalVkImageOverlayImageRepresentation& operator=(
+      const ExternalVkImageOverlayImageRepresentation&) = delete;
 
  protected:
-  // SharedImageRepresentationOverlay implementation
+  // OverlayImageRepresentation implementation
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
   void EndReadAccess(gfx::GpuFenceHandle release_fence) override;
   gl::GLImage* GetGLImage() override;
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.cc b/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.cc
index fa3eab3..f30d5c9 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.cc
@@ -17,19 +17,20 @@
 
 namespace gpu {
 
-ExternalVkImageSkiaRepresentation::ExternalVkImageSkiaRepresentation(
+ExternalVkImageSkiaImageRepresentation::ExternalVkImageSkiaImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker)
-    : SharedImageRepresentationSkia(manager, backing, tracker) {}
+    : SkiaImageRepresentation(manager, backing, tracker) {}
 
-ExternalVkImageSkiaRepresentation::~ExternalVkImageSkiaRepresentation() {
+ExternalVkImageSkiaImageRepresentation::
+    ~ExternalVkImageSkiaImageRepresentation() {
   DCHECK_EQ(access_mode_, kNone) << "Previous access hasn't end yet.";
   DCHECK(!end_access_semaphore_);
   backing_impl()->context_state()->EraseCachedSkSurface(this);
 }
 
-sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess(
+sk_sp<SkSurface> ExternalVkImageSkiaImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -91,7 +92,7 @@
 }
 
 sk_sp<SkPromiseImageTexture>
-ExternalVkImageSkiaRepresentation::BeginWriteAccess(
+ExternalVkImageSkiaImageRepresentation::BeginWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -120,7 +121,7 @@
   return promise_texture;
 }
 
-void ExternalVkImageSkiaRepresentation::EndWriteAccess(
+void ExternalVkImageSkiaImageRepresentation::EndWriteAccess(
     sk_sp<SkSurface> surface) {
   if (access_mode_ != kWrite) {
     LOG(DFATAL) << "BeginWriteAccess is not called mode=" << access_mode_;
@@ -135,7 +136,8 @@
   access_mode_ = kNone;
 }
 
-sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess(
+sk_sp<SkPromiseImageTexture>
+ExternalVkImageSkiaImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -163,7 +165,7 @@
   return promise_texture;
 }
 
-void ExternalVkImageSkiaRepresentation::EndReadAccess() {
+void ExternalVkImageSkiaImageRepresentation::EndReadAccess() {
   if (access_mode_ != kRead) {
     LOG(DFATAL) << "BeginReadAccess is not called. mode=" << access_mode_;
     return;
@@ -173,7 +175,8 @@
   access_mode_ = kNone;
 }
 
-sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginAccess(
+sk_sp<SkPromiseImageTexture>
+ExternalVkImageSkiaImageRepresentation::BeginAccess(
     bool readonly,
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
@@ -209,7 +212,7 @@
   return SkPromiseImageTexture::Make(backing_impl()->backend_texture());
 }
 
-void ExternalVkImageSkiaRepresentation::EndAccess(bool readonly) {
+void ExternalVkImageSkiaImageRepresentation::EndAccess(bool readonly) {
   DCHECK_NE(access_mode_, kNone);
   DCHECK(backing_impl()->need_synchronization() || !end_access_semaphore_);
 
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.h b/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.h
index 39c799d..1d93c56 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.h
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_skia_representation.h
@@ -13,14 +13,14 @@
 
 namespace gpu {
 
-class ExternalVkImageSkiaRepresentation : public SharedImageRepresentationSkia {
+class ExternalVkImageSkiaImageRepresentation : public SkiaImageRepresentation {
  public:
-  ExternalVkImageSkiaRepresentation(SharedImageManager* manager,
-                                    SharedImageBacking* backing,
-                                    MemoryTypeTracker* tracker);
-  ~ExternalVkImageSkiaRepresentation() override;
+  ExternalVkImageSkiaImageRepresentation(SharedImageManager* manager,
+                                         SharedImageBacking* backing,
+                                         MemoryTypeTracker* tracker);
+  ~ExternalVkImageSkiaImageRepresentation() override;
 
-  // SharedImageRepresentationSkia implementation.
+  // SkiaImageRepresentation implementation.
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
diff --git a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc
index ca78440..606ff3f 100644
--- a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc
@@ -18,9 +18,9 @@
 
 namespace gpu {
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingFactoryGLCommon
+// GLCommonImageBackingFactory
 
-SharedImageBackingFactoryGLCommon::SharedImageBackingFactoryGLCommon(
+GLCommonImageBackingFactory::GLCommonImageBackingFactory(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
     const gles2::FeatureInfo* feature_info,
@@ -91,10 +91,9 @@
   }
 }
 
-SharedImageBackingFactoryGLCommon::~SharedImageBackingFactoryGLCommon() =
-    default;
+GLCommonImageBackingFactory::~GLCommonImageBackingFactory() = default;
 
-bool SharedImageBackingFactoryGLCommon::CanCreateSharedImage(
+bool GLCommonImageBackingFactory::CanCreateSharedImage(
     const gfx::Size& size,
     base::span<const uint8_t> pixel_data,
     const FormatInfo& format_info,
@@ -171,11 +170,11 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingFactoryGLCommon::FormatInfo
+// GLCommonImageBackingFactory::FormatInfo
 
-SharedImageBackingFactoryGLCommon::FormatInfo::FormatInfo() = default;
-SharedImageBackingFactoryGLCommon::FormatInfo::FormatInfo(
-    const FormatInfo& other) = default;
-SharedImageBackingFactoryGLCommon::FormatInfo::~FormatInfo() = default;
+GLCommonImageBackingFactory::FormatInfo::FormatInfo() = default;
+GLCommonImageBackingFactory::FormatInfo::FormatInfo(const FormatInfo& other) =
+    default;
+GLCommonImageBackingFactory::FormatInfo::~FormatInfo() = default;
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h
index 2db0d02..2273649 100644
--- a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h
@@ -28,8 +28,8 @@
 struct GpuPreferences;
 
 // Common constructor and helper functions for
-// SharedImageBackingFactoryGLTexture and SharedImageBackingFactoryGLImage.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryGLCommon
+// GLTextureImageBackingFactory and GLImageBackingFactory.
+class GPU_GLES2_EXPORT GLCommonImageBackingFactory
     : public SharedImageBackingFactory {
  public:
   struct FormatInfo {
@@ -61,11 +61,11 @@
   };
 
  protected:
-  SharedImageBackingFactoryGLCommon(const GpuPreferences& gpu_preferences,
-                                    const GpuDriverBugWorkarounds& workarounds,
-                                    const gles2::FeatureInfo* feature_info,
-                                    gl::ProgressReporter* progress_reporter);
-  ~SharedImageBackingFactoryGLCommon() override;
+  GLCommonImageBackingFactory(const GpuPreferences& gpu_preferences,
+                              const GpuDriverBugWorkarounds& workarounds,
+                              const gles2::FeatureInfo* feature_info,
+                              gl::ProgressReporter* progress_reporter);
+  ~GLCommonImageBackingFactory() override;
 
   bool CanCreateSharedImage(const gfx::Size& size,
                             base::span<const uint8_t> pixel_data,
@@ -79,7 +79,7 @@
   FormatInfo format_info_[viz::RESOURCE_FORMAT_MAX + 1];
   int32_t max_texture_size_ = 0;
   bool texture_usage_angle_ = false;
-  SharedImageBackingGLCommon::UnpackStateAttribs attribs_;
+  GLTextureImageBackingHelper::UnpackStateAttribs attribs_;
   GpuDriverBugWorkarounds workarounds_;
   WebGPUAdapterName use_webgpu_adapter_ = WebGPUAdapterName::kDefault;
 
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_image_backing.cc
index 3da35a7..fa4ae16 100644
--- a/gpu/command_buffer/service/shared_image/gl_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/gl_image_backing.cc
@@ -37,120 +37,118 @@
   return estimated_size;
 }
 
-using UnpackStateAttribs = SharedImageBackingGLCommon::UnpackStateAttribs;
+using UnpackStateAttribs = GLTextureImageBackingHelper::UnpackStateAttribs;
 
 using ScopedResetAndRestoreUnpackState =
-    SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState;
+    GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState;
 
-using ScopedRestoreTexture = SharedImageBackingGLCommon::ScopedRestoreTexture;
+using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture;
 
 using InitializeGLTextureParams =
-    SharedImageBackingGLCommon::InitializeGLTextureParams;
+    GLTextureImageBackingHelper::InitializeGLTextureParams;
 
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageRepresentationGLTextureImpl
+// GLTextureGLCommonRepresentation
 
-// Representation of a SharedImageBackingGLTexture as a GL Texture.
-SharedImageRepresentationGLTextureImpl::SharedImageRepresentationGLTextureImpl(
+// Representation of a GLTextureImageBacking as a GL Texture.
+GLTextureGLCommonRepresentation::GLTextureGLCommonRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
-    SharedImageRepresentationGLTextureClient* client,
+    GLTextureImageRepresentationClient* client,
     MemoryTypeTracker* tracker,
     gles2::Texture* texture)
-    : SharedImageRepresentationGLTexture(manager, backing, tracker),
+    : GLTextureImageRepresentation(manager, backing, tracker),
       client_(client),
       texture_(texture) {}
 
-SharedImageRepresentationGLTextureImpl::
-    ~SharedImageRepresentationGLTextureImpl() {
+GLTextureGLCommonRepresentation::~GLTextureGLCommonRepresentation() {
   texture_ = nullptr;
   if (client_)
-    client_->SharedImageRepresentationGLTextureRelease(has_context());
+    client_->GLTextureImageRepresentationRelease(has_context());
 }
 
-gles2::Texture* SharedImageRepresentationGLTextureImpl::GetTexture() {
+gles2::Texture* GLTextureGLCommonRepresentation::GetTexture() {
   return texture_;
 }
 
-bool SharedImageRepresentationGLTextureImpl::BeginAccess(GLenum mode) {
+bool GLTextureGLCommonRepresentation::BeginAccess(GLenum mode) {
   DCHECK(mode_ == 0);
   mode_ = mode;
   bool readonly = mode_ != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM;
   if (client_ && mode != GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM)
-    return client_->SharedImageRepresentationGLTextureBeginAccess(readonly);
+    return client_->GLTextureImageRepresentationBeginAccess(readonly);
   return true;
 }
 
-void SharedImageRepresentationGLTextureImpl::EndAccess() {
+void GLTextureGLCommonRepresentation::EndAccess() {
   DCHECK(mode_ != 0);
   GLenum current_mode = mode_;
   mode_ = 0;
   if (client_)
-    return client_->SharedImageRepresentationGLTextureEndAccess(
+    return client_->GLTextureImageRepresentationEndAccess(
         current_mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageRepresentationGLTexturePassthroughImpl
+// GLTexturePassthroughGLCommonRepresentation
 
-SharedImageRepresentationGLTexturePassthroughImpl::
-    SharedImageRepresentationGLTexturePassthroughImpl(
+GLTexturePassthroughGLCommonRepresentation::
+    GLTexturePassthroughGLCommonRepresentation(
         SharedImageManager* manager,
         SharedImageBacking* backing,
-        SharedImageRepresentationGLTextureClient* client,
+        GLTextureImageRepresentationClient* client,
         MemoryTypeTracker* tracker,
         scoped_refptr<gles2::TexturePassthrough> texture_passthrough)
-    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+    : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
       client_(client),
       texture_passthrough_(std::move(texture_passthrough)) {
   // TODO(https://crbug.com/1172769): Remove this CHECK.
   CHECK(texture_passthrough_);
 }
 
-SharedImageRepresentationGLTexturePassthroughImpl::
-    ~SharedImageRepresentationGLTexturePassthroughImpl() {
+GLTexturePassthroughGLCommonRepresentation::
+    ~GLTexturePassthroughGLCommonRepresentation() {
   texture_passthrough_.reset();
   if (client_)
-    client_->SharedImageRepresentationGLTextureRelease(has_context());
+    client_->GLTextureImageRepresentationRelease(has_context());
 }
 
 const scoped_refptr<gles2::TexturePassthrough>&
-SharedImageRepresentationGLTexturePassthroughImpl::GetTexturePassthrough() {
+GLTexturePassthroughGLCommonRepresentation::GetTexturePassthrough() {
   return texture_passthrough_;
 }
 
-bool SharedImageRepresentationGLTexturePassthroughImpl::BeginAccess(
-    GLenum mode) {
+bool GLTexturePassthroughGLCommonRepresentation::BeginAccess(GLenum mode) {
   DCHECK(mode_ == 0);
   mode_ = mode;
   bool readonly = mode_ != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM;
   if (client_ && mode != GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM)
-    return client_->SharedImageRepresentationGLTextureBeginAccess(readonly);
+    return client_->GLTextureImageRepresentationBeginAccess(readonly);
   return true;
 }
 
-void SharedImageRepresentationGLTexturePassthroughImpl::EndAccess() {
+void GLTexturePassthroughGLCommonRepresentation::EndAccess() {
   DCHECK(mode_ != 0);
   GLenum current_mode = mode_;
   mode_ = 0;
   if (client_)
-    return client_->SharedImageRepresentationGLTextureEndAccess(
+    return client_->GLTextureImageRepresentationEndAccess(
         current_mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageRepresentationSkiaImpl
+// SkiaGLCommonRepresentation
 
-SharedImageRepresentationSkiaImpl::SharedImageRepresentationSkiaImpl(
+SkiaGLCommonRepresentation::SkiaGLCommonRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
-    SharedImageRepresentationGLTextureClient* client,
+    GLTextureImageRepresentationClient* client,
     scoped_refptr<SharedContextState> context_state,
     sk_sp<SkPromiseImageTexture> promise_texture,
     MemoryTypeTracker* tracker)
-    : SharedImageRepresentationSkia(manager, backing, tracker),
+    : SkiaImageRepresentation(manager, backing, tracker),
       client_(client),
       context_state_(std::move(context_state)),
       promise_texture_(promise_texture) {
@@ -161,19 +159,19 @@
 #endif
 }
 
-SharedImageRepresentationSkiaImpl::~SharedImageRepresentationSkiaImpl() {
+SkiaGLCommonRepresentation::~SkiaGLCommonRepresentation() {
   if (write_surface_) {
-    DLOG(ERROR) << "SharedImageRepresentationSkia was destroyed while still "
+    DLOG(ERROR) << "SkiaImageRepresentation was destroyed while still "
                 << "open for write access.";
   }
   promise_texture_.reset();
   if (client_) {
     DCHECK(context_state_->GrContextIsGL());
-    client_->SharedImageRepresentationGLTextureRelease(has_context());
+    client_->GLTextureImageRepresentationRelease(has_context());
   }
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkiaImpl::BeginWriteAccess(
+sk_sp<SkSurface> SkiaGLCommonRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -181,7 +179,7 @@
   CheckContext();
   if (client_) {
     DCHECK(context_state_->GrContextIsGL());
-    if (!client_->SharedImageRepresentationGLTextureBeginAccess(
+    if (!client_->GLTextureImageRepresentationBeginAccess(
             /*readonly=*/false)) {
       return nullptr;
     }
@@ -207,15 +205,14 @@
   return surface;
 }
 
-sk_sp<SkPromiseImageTexture>
-SharedImageRepresentationSkiaImpl::BeginWriteAccess(
+sk_sp<SkPromiseImageTexture> SkiaGLCommonRepresentation::BeginWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
   CheckContext();
   if (client_) {
     DCHECK(context_state_->GrContextIsGL());
-    if (!client_->SharedImageRepresentationGLTextureBeginAccess(
+    if (!client_->GLTextureImageRepresentationBeginAccess(
             /*readonly=*/false)) {
       return nullptr;
     }
@@ -223,8 +220,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaImpl::EndWriteAccess(
-    sk_sp<SkSurface> surface) {
+void SkiaGLCommonRepresentation::EndWriteAccess(sk_sp<SkSurface> surface) {
   if (surface) {
     DCHECK_EQ(surface.get(), write_surface_);
     DCHECK(surface->unique());
@@ -234,16 +230,16 @@
   }
 
   if (client_)
-    client_->SharedImageRepresentationGLTextureEndAccess(false /* readonly */);
+    client_->GLTextureImageRepresentationEndAccess(false /* readonly */);
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaImpl::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaGLCommonRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
   CheckContext();
   if (client_) {
     DCHECK(context_state_->GrContextIsGL());
-    if (!client_->SharedImageRepresentationGLTextureBeginAccess(
+    if (!client_->GLTextureImageRepresentationBeginAccess(
             /*readonly=*/true)) {
       return nullptr;
     }
@@ -251,16 +247,16 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaImpl::EndReadAccess() {
+void SkiaGLCommonRepresentation::EndReadAccess() {
   if (client_)
-    client_->SharedImageRepresentationGLTextureEndAccess(true /* readonly */);
+    client_->GLTextureImageRepresentationEndAccess(true /* readonly */);
 }
 
-bool SharedImageRepresentationSkiaImpl::SupportsMultipleConcurrentReadAccess() {
+bool SkiaGLCommonRepresentation::SupportsMultipleConcurrentReadAccess() {
   return true;
 }
 
-void SharedImageRepresentationSkiaImpl::CheckContext() {
+void SkiaGLCommonRepresentation::CheckContext() {
 #if DCHECK_IS_ON()
   if (!context_state_->context_lost() && context_)
     DCHECK(gl::GLContext::GetCurrent() == context_);
@@ -268,44 +264,42 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageRepresentationOverlayImpl
+// OverlayGLImageRepresentation
 
-SharedImageRepresentationOverlayImpl::SharedImageRepresentationOverlayImpl(
+OverlayGLImageRepresentation::OverlayGLImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     scoped_refptr<gl::GLImage> gl_image)
-    : SharedImageRepresentationOverlay(manager, backing, tracker),
+    : OverlayImageRepresentation(manager, backing, tracker),
       gl_image_(gl_image) {}
 
-SharedImageRepresentationOverlayImpl::~SharedImageRepresentationOverlayImpl() =
-    default;
+OverlayGLImageRepresentation::~OverlayGLImageRepresentation() = default;
 
-bool SharedImageRepresentationOverlayImpl::BeginReadAccess(
+bool OverlayGLImageRepresentation::BeginReadAccess(
     gfx::GpuFenceHandle& acquire_fence) {
-  auto* gl_backing = static_cast<SharedImageBackingGLImage*>(backing());
+  auto* gl_backing = static_cast<GLImageBacking*>(backing());
   std::unique_ptr<gfx::GpuFence> fence = gl_backing->GetLastWriteGpuFence();
   if (fence)
     acquire_fence = fence->GetGpuFenceHandle().Clone();
   return true;
 }
 
-void SharedImageRepresentationOverlayImpl::EndReadAccess(
+void OverlayGLImageRepresentation::EndReadAccess(
     gfx::GpuFenceHandle release_fence) {
-  auto* gl_backing = static_cast<SharedImageBackingGLImage*>(backing());
+  auto* gl_backing = static_cast<GLImageBacking*>(backing());
   gl_backing->SetReleaseFence(std::move(release_fence));
 }
 
-gl::GLImage* SharedImageRepresentationOverlayImpl::GetGLImage() {
+gl::GLImage* OverlayGLImageRepresentation::GetGLImage() {
   return gl_image_.get();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingGLImage
+// GLImageBacking
 
 // static
-std::unique_ptr<SharedImageBackingGLImage>
-SharedImageBackingGLImage::CreateFromGLTexture(
+std::unique_ptr<GLImageBacking> GLImageBacking::CreateFromGLTexture(
     scoped_refptr<gl::GLImage> image,
     const Mailbox& mailbox,
     viz::ResourceFormat format,
@@ -325,7 +319,7 @@
   params.target = texture_target;
   UnpackStateAttribs attribs;
 
-  auto shared_image = std::make_unique<SharedImageBackingGLImage>(
+  auto shared_image = std::make_unique<GLImageBacking>(
       std::move(image), mailbox, format, size, color_space, surface_origin,
       alpha_type, usage, params, attribs, true);
 
@@ -337,18 +331,17 @@
   return shared_image;
 }
 
-SharedImageBackingGLImage::SharedImageBackingGLImage(
-    scoped_refptr<gl::GLImage> image,
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage,
-    const InitializeGLTextureParams& params,
-    const UnpackStateAttribs& attribs,
-    bool is_passthrough)
+GLImageBacking::GLImageBacking(scoped_refptr<gl::GLImage> image,
+                               const Mailbox& mailbox,
+                               viz::ResourceFormat format,
+                               const gfx::Size& size,
+                               const gfx::ColorSpace& color_space,
+                               GrSurfaceOrigin surface_origin,
+                               SkAlphaType alpha_type,
+                               uint32_t usage,
+                               const InitializeGLTextureParams& params,
+                               const UnpackStateAttribs& attribs,
+                               bool is_passthrough)
     : SharedImageBacking(mailbox,
                          format,
                          size,
@@ -367,19 +360,19 @@
   DCHECK(image_);
 }
 
-SharedImageBackingGLImage::~SharedImageBackingGLImage() {
+GLImageBacking::~GLImageBacking() {
   if (gl_texture_retained_for_legacy_mailbox_)
     ReleaseGLTexture(have_context());
   DCHECK_EQ(gl_texture_retain_count_, 0u);
 }
 
-void SharedImageBackingGLImage::RetainGLTexture() {
+void GLImageBacking::RetainGLTexture() {
   gl_texture_retain_count_ += 1;
   if (gl_texture_retain_count_ > 1)
     return;
 
   // Allocate the GL texture.
-  SharedImageBackingGLCommon::MakeTextureAndSetParameters(
+  GLTextureImageBackingHelper::MakeTextureAndSetParameters(
       gl_params_.target, 0 /* service_id */,
       gl_params_.framebuffer_attachment_angle,
       is_passthrough_ ? &passthrough_texture_ : nullptr,
@@ -401,7 +394,7 @@
   }
 }
 
-void SharedImageBackingGLImage::ReleaseGLTexture(bool have_context) {
+void GLImageBacking::ReleaseGLTexture(bool have_context) {
   DCHECK_GT(gl_texture_retain_count_, 0u);
   gl_texture_retain_count_ -= 1;
   if (gl_texture_retain_count_ > 0)
@@ -443,11 +436,11 @@
   }
 }
 
-GLenum SharedImageBackingGLImage::GetGLTarget() const {
+GLenum GLImageBacking::GetGLTarget() const {
   return gl_params_.target;
 }
 
-GLuint SharedImageBackingGLImage::GetGLServiceId() const {
+GLuint GLImageBacking::GetGLServiceId() const {
   if (texture_)
     return texture_->service_id();
   if (passthrough_texture_)
@@ -455,25 +448,22 @@
   return 0;
 }
 
-std::unique_ptr<gfx::GpuFence>
-SharedImageBackingGLImage::GetLastWriteGpuFence() {
+std::unique_ptr<gfx::GpuFence> GLImageBacking::GetLastWriteGpuFence() {
   return last_write_gl_fence_ ? last_write_gl_fence_->GetGpuFence() : nullptr;
 }
 
-void SharedImageBackingGLImage::SetReleaseFence(
-    gfx::GpuFenceHandle release_fence) {
+void GLImageBacking::SetReleaseFence(gfx::GpuFenceHandle release_fence) {
   release_fence_ = std::move(release_fence);
 }
 
-scoped_refptr<gfx::NativePixmap> SharedImageBackingGLImage::GetNativePixmap() {
+scoped_refptr<gfx::NativePixmap> GLImageBacking::GetNativePixmap() {
   return image_->GetNativePixmap();
 }
 
-void SharedImageBackingGLImage::OnMemoryDump(
-    const std::string& dump_name,
-    base::trace_event::MemoryAllocatorDump* dump,
-    base::trace_event::ProcessMemoryDump* pmd,
-    uint64_t client_tracing_id) {
+void GLImageBacking::OnMemoryDump(const std::string& dump_name,
+                                  base::trace_event::MemoryAllocatorDump* dump,
+                                  base::trace_event::ProcessMemoryDump* pmd,
+                                  uint64_t client_tracing_id) {
   // Add a |service_guid| which expresses shared ownership between the
   // various GPU dumps.
   auto client_guid = GetSharedImageGUIDForTracing(mailbox());
@@ -487,25 +477,24 @@
   image_->OnMemoryDump(pmd, client_tracing_id, dump_name);
 }
 
-SharedImageBackingType SharedImageBackingGLImage::GetType() const {
+SharedImageBackingType GLImageBacking::GetType() const {
   return SharedImageBackingType::kGLImage;
 }
 
-gfx::Rect SharedImageBackingGLImage::ClearedRect() const {
+gfx::Rect GLImageBacking::ClearedRect() const {
   if (texture_)
     return texture_->GetLevelClearedRect(texture_->target(), 0);
   return cleared_rect_;
 }
 
-void SharedImageBackingGLImage::SetClearedRect(const gfx::Rect& cleared_rect) {
+void GLImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   if (texture_)
     texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
   else
     cleared_rect_ = cleared_rect;
 }
 
-bool SharedImageBackingGLImage::ProduceLegacyMailbox(
-    MailboxManager* mailbox_manager) {
+bool GLImageBacking::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
   if (!gl_texture_retained_for_legacy_mailbox_) {
     RetainGLTexture();
     gl_texture_retained_for_legacy_mailbox_ = true;
@@ -518,46 +507,45 @@
   return true;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingGLImage::ProduceGLTexture(SharedImageManager* manager,
-                                            MemoryTypeTracker* tracker) {
-  // The corresponding release will be done when the returned representation is
-  // destroyed, in SharedImageRepresentationGLTextureRelease.
-  RetainGLTexture();
-  DCHECK(texture_);
-  return std::make_unique<SharedImageRepresentationGLTextureImpl>(
-      manager, this, this, tracker, texture_);
-}
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingGLImage::ProduceGLTexturePassthrough(
+std::unique_ptr<GLTextureImageRepresentation> GLImageBacking::ProduceGLTexture(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   // The corresponding release will be done when the returned representation is
-  // destroyed, in SharedImageRepresentationGLTextureRelease.
+  // destroyed, in GLTextureImageRepresentationRelease.
+  RetainGLTexture();
+  DCHECK(texture_);
+  return std::make_unique<GLTextureGLCommonRepresentation>(manager, this, this,
+                                                           tracker, texture_);
+}
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+GLImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                            MemoryTypeTracker* tracker) {
+  // The corresponding release will be done when the returned representation is
+  // destroyed, in GLTextureImageRepresentationRelease.
   RetainGLTexture();
   DCHECK(passthrough_texture_);
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
+  return std::make_unique<GLTexturePassthroughGLCommonRepresentation>(
       manager, this, this, tracker, passthrough_texture_);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingGLImage::ProduceOverlay(SharedImageManager* manager,
-                                          MemoryTypeTracker* tracker) {
+std::unique_ptr<OverlayImageRepresentation> GLImageBacking::ProduceOverlay(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
 #if BUILDFLAG(IS_MAC) || defined(USE_OZONE) || BUILDFLAG(IS_WIN)
-  return std::make_unique<SharedImageRepresentationOverlayImpl>(
-      manager, this, tracker, image_);
+  return std::make_unique<OverlayGLImageRepresentation>(manager, this, tracker,
+                                                        image_);
 #else   // !(BUILDFLAG(IS_MAC) || defined(USE_OZONE) || BUILDFLAG(IS_WIN))
   return SharedImageBacking::ProduceOverlay(manager, tracker);
 #endif  // BUILDFLAG(IS_MAC) || defined(USE_OZONE) || BUILDFLAG(IS_WIN)
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingGLImage::ProduceDawn(SharedImageManager* manager,
-                                       MemoryTypeTracker* tracker,
-                                       WGPUDevice device,
-                                       WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> GLImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
 #if BUILDFLAG(IS_MAC)
-  auto result = SharedImageBackingFactoryIOSurface::ProduceDawn(
+  auto result = IOSurfaceImageBackingFactory::ProduceDawn(
       manager, this, tracker, device, image_);
   if (result)
     return result;
@@ -567,19 +555,18 @@
     return nullptr;
   }
 
-  return SharedImageBackingGLCommon::ProduceDawnCommon(
+  return GLTextureImageBackingHelper::ProduceDawnCommon(
       factory(), manager, tracker, device, backend_type, this, IsPassthrough());
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingGLImage::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> GLImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
-  SharedImageRepresentationGLTextureClient* gl_client = nullptr;
+  GLTextureImageRepresentationClient* gl_client = nullptr;
   if (context_state->GrContextIsGL()) {
     // The corresponding release will be done when the returned representation
-    // is destroyed, in SharedImageRepresentationGLTextureRelease.
+    // is destroyed, in GLTextureImageRepresentationRelease.
     RetainGLTexture();
     gl_client = this;
   }
@@ -588,7 +575,7 @@
     if (context_state->GrContextIsMetal()) {
 #if BUILDFLAG(IS_MAC)
       cached_promise_texture_ =
-          SharedImageBackingFactoryIOSurface::ProduceSkiaPromiseTextureMetal(
+          IOSurfaceImageBackingFactory::ProduceSkiaPromiseTextureMetal(
               this, context_state, image_);
       DCHECK(cached_promise_texture_);
 #endif
@@ -601,43 +588,41 @@
       cached_promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
     }
   }
-  return std::make_unique<SharedImageRepresentationSkiaImpl>(
+  return std::make_unique<SkiaGLCommonRepresentation>(
       manager, this, gl_client, std::move(context_state),
       cached_promise_texture_, tracker);
 }
 
-SharedImageRepresentationMemoryImpl::SharedImageRepresentationMemoryImpl(
+MemoryGLImageRepresentation::MemoryGLImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
     scoped_refptr<gl::GLImageMemory> image_memory)
-    : SharedImageRepresentationMemory(manager, backing, tracker),
+    : MemoryImageRepresentation(manager, backing, tracker),
       image_memory_(std::move(image_memory)) {}
 
-SharedImageRepresentationMemoryImpl::~SharedImageRepresentationMemoryImpl() =
-    default;
+MemoryGLImageRepresentation::~MemoryGLImageRepresentation() = default;
 
-SkPixmap SharedImageRepresentationMemoryImpl::BeginReadAccess() {
+SkPixmap MemoryGLImageRepresentation::BeginReadAccess() {
   return SkPixmap(backing()->AsSkImageInfo(), image_memory_->memory(),
                   image_memory_->stride());
 }
 
-std::unique_ptr<SharedImageRepresentationMemory>
-SharedImageBackingGLImage::ProduceMemory(SharedImageManager* manager,
-                                         MemoryTypeTracker* tracker) {
+std::unique_ptr<MemoryImageRepresentation> GLImageBacking::ProduceMemory(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
   gl::GLImageMemory* image_memory =
       gl::GLImageMemory::FromGLImage(image_.get());
   if (!image_memory)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationMemoryImpl>(
+  return std::make_unique<MemoryGLImageRepresentation>(
       manager, this, tracker, base::WrapRefCounted(image_memory));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingGLImage::ProduceRGBEmulationGLTexture(
-    SharedImageManager* manager,
-    MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+GLImageBacking::ProduceRGBEmulationGLTexture(SharedImageManager* manager,
+                                             MemoryTypeTracker* tracker) {
   if (IsPassthrough())
     return nullptr;
 
@@ -649,7 +634,7 @@
 
     // Set to false as this code path is only used on Mac.
     const bool framebuffer_attachment_angle = false;
-    SharedImageBackingGLCommon::MakeTextureAndSetParameters(
+    GLTextureImageBackingHelper::MakeTextureAndSetParameters(
         target, 0 /* service_id */, framebuffer_attachment_angle, nullptr,
         &rgb_emulation_texture_);
     api->glBindTextureFn(target, rgb_emulation_texture_->service_id());
@@ -681,12 +666,11 @@
     rgb_emulation_texture_->SetImmutable(true, false);
   }
 
-  return std::make_unique<SharedImageRepresentationGLTextureImpl>(
+  return std::make_unique<GLTextureGLCommonRepresentation>(
       manager, this, this, tracker, rgb_emulation_texture_);
 }
 
-void SharedImageBackingGLImage::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {
+void GLImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   if (in_fence) {
     // TODO(dcastagna): Don't wait for the fence if the SharedImage is going
     // to be scanned out as an HW overlay. Currently we don't know that at
@@ -699,8 +683,7 @@
   image_bind_or_copy_needed_ = true;
 }
 
-bool SharedImageBackingGLImage::SharedImageRepresentationGLTextureBeginAccess(
-    bool readonly) {
+bool GLImageBacking::GLTextureImageRepresentationBeginAccess(bool readonly) {
   if (!release_fence_.is_null()) {
     auto fence = gfx::GpuFence(std::move(release_fence_));
     if (gl::GLFence::IsGpuFenceSupported()) {
@@ -712,8 +695,7 @@
   return BindOrCopyImageIfNeeded();
 }
 
-void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess(
-    bool readonly) {
+void GLImageBacking::GLTextureImageRepresentationEndAccess(bool readonly) {
 #if BUILDFLAG(IS_MAC)
   // If this image could potentially be shared with Metal via WebGPU, then flush
   // the GL context to ensure Metal will see it.
@@ -762,12 +744,11 @@
 #endif
 }
 
-void SharedImageBackingGLImage::SharedImageRepresentationGLTextureRelease(
-    bool has_context) {
+void GLImageBacking::GLTextureImageRepresentationRelease(bool has_context) {
   ReleaseGLTexture(has_context);
 }
 
-bool SharedImageBackingGLImage::BindOrCopyImageIfNeeded() {
+bool GLImageBacking::BindOrCopyImageIfNeeded() {
   // This is called by code that has retained the GL texture.
   DCHECK(texture_ || passthrough_texture_);
   if (!image_bind_or_copy_needed_)
@@ -828,12 +809,12 @@
   return true;
 }
 
-void SharedImageBackingGLImage::InitializePixels(GLenum format,
-                                                 GLenum type,
-                                                 const uint8_t* data) {
+void GLImageBacking::InitializePixels(GLenum format,
+                                      GLenum type,
+                                      const uint8_t* data) {
   DCHECK_EQ(image_->ShouldBindOrCopy(), gl::GLImage::BIND);
 #if BUILDFLAG(IS_MAC)
-  if (SharedImageBackingFactoryIOSurface::InitializePixels(this, image_, data))
+  if (IOSurfaceImageBackingFactory::InitializePixels(this, image_, data))
     return;
 #else
   RetainGLTexture();
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing.h b/gpu/command_buffer/service/shared_image/gl_image_backing.h
index 4234c4f8..9e01970 100644
--- a/gpu/command_buffer/service/shared_image/gl_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/gl_image_backing.h
@@ -16,88 +16,85 @@
 
 // Interface through which a representation that has a GL texture calls into its
 // GLImage backing.
-class SharedImageRepresentationGLTextureClient {
+class GLTextureImageRepresentationClient {
  public:
-  virtual bool SharedImageRepresentationGLTextureBeginAccess(bool readonly) = 0;
-  virtual void SharedImageRepresentationGLTextureEndAccess(bool readonly) = 0;
-  virtual void SharedImageRepresentationGLTextureRelease(bool have_context) = 0;
+  virtual bool GLTextureImageRepresentationBeginAccess(bool readonly) = 0;
+  virtual void GLTextureImageRepresentationEndAccess(bool readonly) = 0;
+  virtual void GLTextureImageRepresentationRelease(bool have_context) = 0;
 };
 
-// Representation of a SharedImageBackingGLTexture or SharedImageBackingGLImage
+// Representation of a GLTextureImageBacking or GLImageBacking
 // as a GL Texture.
-class SharedImageRepresentationGLTextureImpl
-    : public SharedImageRepresentationGLTexture {
+class GLTextureGLCommonRepresentation : public GLTextureImageRepresentation {
  public:
-  SharedImageRepresentationGLTextureImpl(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      SharedImageRepresentationGLTextureClient* client,
-      MemoryTypeTracker* tracker,
-      gles2::Texture* texture);
-  ~SharedImageRepresentationGLTextureImpl() override;
+  GLTextureGLCommonRepresentation(SharedImageManager* manager,
+                                  SharedImageBacking* backing,
+                                  GLTextureImageRepresentationClient* client,
+                                  MemoryTypeTracker* tracker,
+                                  gles2::Texture* texture);
+  ~GLTextureGLCommonRepresentation() override;
 
  private:
-  // SharedImageRepresentationGLTexture:
+  // GLTextureImageRepresentation:
   gles2::Texture* GetTexture() override;
   bool BeginAccess(GLenum mode) override;
   void EndAccess() override;
 
-  const raw_ptr<SharedImageRepresentationGLTextureClient> client_ = nullptr;
+  const raw_ptr<GLTextureImageRepresentationClient> client_ = nullptr;
   raw_ptr<gles2::Texture> texture_;
   GLenum mode_ = 0;
 };
 
-// Representation of a SharedImageBackingGLTexture or
-// SharedImageBackingGLTexturePassthrough as a GL TexturePassthrough.
-class SharedImageRepresentationGLTexturePassthroughImpl
-    : public SharedImageRepresentationGLTexturePassthrough {
+// Representation of a GLTextureImageBacking or
+// GLTextureImageBackingPassthrough as a GL TexturePassthrough.
+class GLTexturePassthroughGLCommonRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
   class Client {
    public:
     virtual bool OnGLTexturePassthroughBeginAccess(GLenum mode) = 0;
   };
-  SharedImageRepresentationGLTexturePassthroughImpl(
+  GLTexturePassthroughGLCommonRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
-      SharedImageRepresentationGLTextureClient* client,
+      GLTextureImageRepresentationClient* client,
       MemoryTypeTracker* tracker,
       scoped_refptr<gles2::TexturePassthrough> texture_passthrough);
-  ~SharedImageRepresentationGLTexturePassthroughImpl() override;
+  ~GLTexturePassthroughGLCommonRepresentation() override;
 
  private:
-  // SharedImageRepresentationGLTexturePassthrough:
+  // GLTexturePassthroughImageRepresentation:
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override;
   bool BeginAccess(GLenum mode) override;
   void EndAccess() override;
 
-  const raw_ptr<SharedImageRepresentationGLTextureClient> client_ = nullptr;
+  const raw_ptr<GLTextureImageRepresentationClient> client_ = nullptr;
   scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
   GLenum mode_ = 0;
 };
 
-// Skia representation for both SharedImageBackingGLCommon.
-class SharedImageRepresentationSkiaImpl : public SharedImageRepresentationSkia {
+// Skia representation for both GLTextureImageBackingHelper.
+class SkiaGLCommonRepresentation : public SkiaImageRepresentation {
  public:
   class Client {
    public:
     virtual bool OnSkiaBeginReadAccess() = 0;
     virtual bool OnSkiaBeginWriteAccess() = 0;
   };
-  SharedImageRepresentationSkiaImpl(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      SharedImageRepresentationGLTextureClient* client,
-      scoped_refptr<SharedContextState> context_state,
-      sk_sp<SkPromiseImageTexture> promise_texture,
-      MemoryTypeTracker* tracker);
-  ~SharedImageRepresentationSkiaImpl() override;
+  SkiaGLCommonRepresentation(SharedImageManager* manager,
+                             SharedImageBacking* backing,
+                             GLTextureImageRepresentationClient* client,
+                             scoped_refptr<SharedContextState> context_state,
+                             sk_sp<SkPromiseImageTexture> promise_texture,
+                             MemoryTypeTracker* tracker);
+  ~SkiaGLCommonRepresentation() override;
 
   void SetBeginReadAccessCallback(
       base::RepeatingClosure begin_read_access_callback);
 
  private:
-  // SharedImageRepresentationSkia:
+  // SkiaImageRepresentation:
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
       const SkSurfaceProps& surface_props,
@@ -116,7 +113,7 @@
 
   void CheckContext();
 
-  const raw_ptr<SharedImageRepresentationGLTextureClient> client_ = nullptr;
+  const raw_ptr<GLTextureImageRepresentationClient> client_ = nullptr;
   scoped_refptr<SharedContextState> context_state_;
   sk_sp<SkPromiseImageTexture> promise_texture_;
 
@@ -126,15 +123,14 @@
 #endif
 };
 
-// Overlay representation for a SharedImageBackingGLImage.
-class SharedImageRepresentationOverlayImpl
-    : public SharedImageRepresentationOverlay {
+// Overlay representation for a GLImageBacking.
+class OverlayGLImageRepresentation : public OverlayImageRepresentation {
  public:
-  SharedImageRepresentationOverlayImpl(SharedImageManager* manager,
-                                       SharedImageBacking* backing,
-                                       MemoryTypeTracker* tracker,
-                                       scoped_refptr<gl::GLImage> gl_image);
-  ~SharedImageRepresentationOverlayImpl() override;
+  OverlayGLImageRepresentation(SharedImageManager* manager,
+                               SharedImageBacking* backing,
+                               MemoryTypeTracker* tracker,
+                               scoped_refptr<gl::GLImage> gl_image);
+  ~OverlayGLImageRepresentation() override;
 
  private:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override;
@@ -144,15 +140,13 @@
   scoped_refptr<gl::GLImage> gl_image_;
 };
 
-class SharedImageRepresentationMemoryImpl
-    : public SharedImageRepresentationMemory {
+class MemoryGLImageRepresentation : public MemoryImageRepresentation {
  public:
-  SharedImageRepresentationMemoryImpl(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      MemoryTypeTracker* tracker,
-      scoped_refptr<gl::GLImageMemory> image_memory);
-  ~SharedImageRepresentationMemoryImpl() override;
+  MemoryGLImageRepresentation(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker,
+                              scoped_refptr<gl::GLImageMemory> image_memory);
+  ~MemoryGLImageRepresentation() override;
 
  protected:
   SkPixmap BeginReadAccess() override;
@@ -164,14 +158,14 @@
 // Implementation of SharedImageBacking that creates a GL Texture that is backed
 // by a GLImage and stores it as a gles2::Texture. Can be used with the legacy
 // mailbox implementation.
-class GPU_GLES2_EXPORT SharedImageBackingGLImage
+class GPU_GLES2_EXPORT GLImageBacking
     : public SharedImageBacking,
-      public SharedImageRepresentationGLTextureClient {
+      public GLTextureImageRepresentationClient {
  public:
-  // Used when SharedImageBackingGLImage is serving as a temporary SharedImage
+  // Used when GLImageBacking is serving as a temporary SharedImage
   // wrapper to an already-allocated texture. The returned backing will not
   // create any new textures.
-  static std::unique_ptr<SharedImageBackingGLImage> CreateFromGLTexture(
+  static std::unique_ptr<GLImageBacking> CreateFromGLTexture(
       scoped_refptr<gl::GLImage> image,
       const Mailbox& mailbox,
       viz::ResourceFormat format,
@@ -183,7 +177,7 @@
       GLenum texture_target,
       scoped_refptr<gles2::TexturePassthrough> wrapped_gl_texture);
 
-  SharedImageBackingGLImage(
+  GLImageBacking(
       scoped_refptr<gl::GLImage> image,
       const Mailbox& mailbox,
       viz::ResourceFormat format,
@@ -192,13 +186,12 @@
       GrSurfaceOrigin surface_origin,
       SkAlphaType alpha_type,
       uint32_t usage,
-      const SharedImageBackingGLCommon::InitializeGLTextureParams& params,
-      const SharedImageBackingGLCommon::UnpackStateAttribs& attribs,
+      const GLTextureImageBackingHelper::InitializeGLTextureParams& params,
+      const GLTextureImageBackingHelper::UnpackStateAttribs& attribs,
       bool is_passthrough);
-  SharedImageBackingGLImage(const SharedImageBackingGLImage& other) = delete;
-  SharedImageBackingGLImage& operator=(const SharedImageBackingGLImage& other) =
-      delete;
-  ~SharedImageBackingGLImage() override;
+  GLImageBacking(const GLImageBacking& other) = delete;
+  GLImageBacking& operator=(const GLImageBacking& other) = delete;
+  ~GLImageBacking() override;
 
   void InitializePixels(GLenum format, GLenum type, const uint8_t* data);
 
@@ -218,36 +211,36 @@
   gfx::Rect ClearedRect() const final;
   void SetClearedRect(const gfx::Rect& cleared_rect) final;
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) final;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) final;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) final;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) final;
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) final;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationMemory> ProduceMemory(
+  std::unique_ptr<MemoryImageRepresentation> ProduceMemory(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexture>
-  ProduceRGBEmulationGLTexture(SharedImageManager* manager,
-                               MemoryTypeTracker* tracker) override;
+  std::unique_ptr<GLTextureImageRepresentation> ProduceRGBEmulationGLTexture(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker) override;
   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
 
-  // SharedImageRepresentationGLTextureClient:
-  bool SharedImageRepresentationGLTextureBeginAccess(bool readonly) override;
-  void SharedImageRepresentationGLTextureEndAccess(bool readonly) override;
-  void SharedImageRepresentationGLTextureRelease(bool have_context) override;
+  // GLTextureImageRepresentationClient:
+  bool GLTextureImageRepresentationBeginAccess(bool readonly) override;
+  void GLTextureImageRepresentationEndAccess(bool readonly) override;
+  void GLTextureImageRepresentationRelease(bool have_context) override;
 
   bool IsPassthrough() const { return is_passthrough_; }
 
@@ -263,8 +256,8 @@
   size_t gl_texture_retain_count_ = 0;
   bool gl_texture_retained_for_legacy_mailbox_ = false;
 
-  const SharedImageBackingGLCommon::InitializeGLTextureParams gl_params_;
-  const SharedImageBackingGLCommon::UnpackStateAttribs gl_unpack_attribs_;
+  const GLTextureImageBackingHelper::InitializeGLTextureParams gl_params_;
+  const GLTextureImageBackingHelper::UnpackStateAttribs gl_unpack_attribs_;
   const bool is_passthrough_;
 
   // This is the cleared rect used by ClearedRect and SetClearedRect when
@@ -282,7 +275,7 @@
   // Wait on this fence before allowing another access.
   gfx::GpuFenceHandle release_fence_;
 
-  base::WeakPtrFactory<SharedImageBackingGLImage> weak_factory_;
+  base::WeakPtrFactory<GLImageBacking> weak_factory_;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc
index d437fcee..544fceb9 100644
--- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc
@@ -29,24 +29,24 @@
 namespace {
 
 using InitializeGLTextureParams =
-    SharedImageBackingGLCommon::InitializeGLTextureParams;
+    GLTextureImageBackingHelper::InitializeGLTextureParams;
 
 }  // anonymous namespace
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingFactoryGLImage
+// GLImageBackingFactory
 
-SharedImageBackingFactoryGLImage::SharedImageBackingFactoryGLImage(
+GLImageBackingFactory::GLImageBackingFactory(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
     const gles2::FeatureInfo* feature_info,
     ImageFactory* image_factory,
     gl::ProgressReporter* progress_reporter,
     const bool for_shared_memory_gmbs)
-    : SharedImageBackingFactoryGLCommon(gpu_preferences,
-                                        workarounds,
-                                        feature_info,
-                                        progress_reporter),
+    : GLCommonImageBackingFactory(gpu_preferences,
+                                  workarounds,
+                                  feature_info,
+                                  progress_reporter),
       image_factory_(image_factory),
       for_shared_memory_gmbs_(for_shared_memory_gmbs) {
   gpu_memory_buffer_formats_ =
@@ -65,7 +65,9 @@
     const gfx::BufferFormat buffer_format = viz::BufferFormat(format);
     switch (buffer_format) {
       case gfx::BufferFormat::RGBA_8888:
+      case gfx::BufferFormat::RGBX_8888:
       case gfx::BufferFormat::BGRA_8888:
+      case gfx::BufferFormat::BGRX_8888:
       case gfx::BufferFormat::RGBA_F16:
       case gfx::BufferFormat::R_8:
       case gfx::BufferFormat::BGRA_1010102:
@@ -89,10 +91,9 @@
   }
 }
 
-SharedImageBackingFactoryGLImage::~SharedImageBackingFactoryGLImage() = default;
+GLImageBackingFactory::~GLImageBackingFactory() = default;
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLImage::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> GLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -108,8 +109,7 @@
                                    usage, base::span<const uint8_t>());
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLImage::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> GLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -123,8 +123,7 @@
                                    usage, pixel_data);
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLImage::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> GLImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -209,12 +208,12 @@
   params.is_rgb_emulation = is_rgb_emulation;
   params.framebuffer_attachment_angle =
       for_framebuffer_attachment && texture_usage_angle_;
-  return std::make_unique<SharedImageBackingGLImage>(
+  return std::make_unique<GLImageBacking>(
       image, mailbox, plane_format, plane_size, color_space, surface_origin,
       alpha_type, usage, params, attribs_, use_passthrough_);
 }
 
-scoped_refptr<gl::GLImage> SharedImageBackingFactoryGLImage::MakeGLImage(
+scoped_refptr<gl::GLImage> GLImageBackingFactory::MakeGLImage(
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
     gfx::BufferFormat format,
@@ -246,14 +245,13 @@
       surface_handle);
 }
 
-bool SharedImageBackingFactoryGLImage::IsSupported(
-    uint32_t usage,
-    viz::ResourceFormat format,
-    bool thread_safe,
-    gfx::GpuMemoryBufferType gmb_type,
-    GrContextType gr_context_type,
-    bool* allow_legacy_mailbox,
-    bool is_pixel_used) {
+bool GLImageBackingFactory::IsSupported(uint32_t usage,
+                                        viz::ResourceFormat format,
+                                        bool thread_safe,
+                                        gfx::GpuMemoryBufferType gmb_type,
+                                        GrContextType gr_context_type,
+                                        bool* allow_legacy_mailbox,
+                                        bool is_pixel_used) {
   if (is_pixel_used && gr_context_type != GrContextType::kGL) {
     return false;
   }
@@ -292,7 +290,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLImage::CreateSharedImageInternal(
+GLImageBackingFactory::CreateSharedImageInternal(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -371,7 +369,7 @@
       for_framebuffer_attachment && texture_usage_angle_;
 
   DCHECK(!format_info.swizzle);
-  auto result = std::make_unique<SharedImageBackingGLImage>(
+  auto result = std::make_unique<GLImageBacking>(
       image, mailbox, format, size, color_space, surface_origin, alpha_type,
       usage, params, attribs_, use_passthrough_);
   if (!pixel_data.empty()) {
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.h b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.h
index cbb5ca43..a7b6a8083 100644
--- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.h
@@ -31,21 +31,21 @@
 
 // Implementation of SharedImageBackingFactory that produces GL-image backed
 // SharedImages.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryGLImage
-    : public SharedImageBackingFactoryGLCommon {
+class GPU_GLES2_EXPORT GLImageBackingFactory
+    : public GLCommonImageBackingFactory {
  public:
   // for_shared_memory_gmbs is a temporary parameter which is used for checking
   // if gfx::SHARED_MEMORY_BUFFER is supported by the factory.
   // It is used for migrating GLImage backing, for part that works with
-  // SharedMemory GMB with SharedMemoryBacking and Composite backings, and all
-  // other parts with OzoneBacking and other backings.
-  SharedImageBackingFactoryGLImage(const GpuPreferences& gpu_preferences,
-                                   const GpuDriverBugWorkarounds& workarounds,
-                                   const gles2::FeatureInfo* feature_info,
-                                   ImageFactory* image_factory,
-                                   gl::ProgressReporter* progress_reporter,
-                                   const bool for_shared_memory_gmbs);
-  ~SharedImageBackingFactoryGLImage() override;
+  // SharedMemory GMB with SharedMemoryImageBacking and Composite backings, and
+  // all other parts with OzoneImageBacking and other backings.
+  GLImageBackingFactory(const GpuPreferences& gpu_preferences,
+                        const GpuDriverBugWorkarounds& workarounds,
+                        const gles2::FeatureInfo* feature_info,
+                        ImageFactory* image_factory,
+                        gl::ProgressReporter* progress_reporter,
+                        const bool for_shared_memory_gmbs);
+  ~GLImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation.
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc
index 4bf6c444..8ff5f049 100644
--- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc
@@ -81,13 +81,13 @@
   MOCK_METHOD0(ReportProgress, void());
 };
 
-class SharedImageBackingFactoryGLImageTestBase
+class GLImageBackingFactoryTestBase
     : public testing::TestWithParam<std::tuple<bool, viz::ResourceFormat>> {
  public:
-  explicit SharedImageBackingFactoryGLImageTestBase(bool is_thread_safe)
+  explicit GLImageBackingFactoryTestBase(bool is_thread_safe)
       : shared_image_manager_(
             std::make_unique<SharedImageManager>(is_thread_safe)) {}
-  ~SharedImageBackingFactoryGLImageTestBase() override {
+  ~GLImageBackingFactoryTestBase() override {
     // |context_state_| must be destroyed on its own context.
     context_state_->MakeCurrent(surface_.get(), true /* needs_gl */);
   }
@@ -105,10 +105,10 @@
 
     GpuPreferences preferences;
     preferences.use_passthrough_cmd_decoder = use_passthrough();
-    backing_factory_ = std::make_unique<SharedImageBackingFactoryGLImage>(
+    backing_factory_ = std::make_unique<GLImageBackingFactory>(
         preferences, workarounds, context_state_->feature_info(), factory,
         &progress_reporter_, /*for_shared_memory_gmbs=*/false);
-    backing_factory_shmem_ = std::make_unique<SharedImageBackingFactoryGLImage>(
+    backing_factory_shmem_ = std::make_unique<GLImageBackingFactory>(
         preferences, workarounds, context_state_->feature_info(), factory,
         &progress_reporter_, /*for_shared_memory_gmbs=*/true);
 
@@ -139,8 +139,8 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<SharedContextState> context_state_;
-  std::unique_ptr<SharedImageBackingFactoryGLImage> backing_factory_;
-  std::unique_ptr<SharedImageBackingFactoryGLImage> backing_factory_shmem_;
+  std::unique_ptr<GLImageBackingFactory> backing_factory_;
+  std::unique_ptr<GLImageBackingFactory> backing_factory_shmem_;
   gles2::MailboxManagerImpl mailbox_manager_;
   std::unique_ptr<SharedImageManager> shared_image_manager_;
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
@@ -151,11 +151,9 @@
   bool supports_ab30_ = false;
 };
 
-class SharedImageBackingFactoryGLImageTest
-    : public SharedImageBackingFactoryGLImageTestBase {
+class GLImageBackingFactoryTest : public GLImageBackingFactoryTestBase {
  public:
-  SharedImageBackingFactoryGLImageTest()
-      : SharedImageBackingFactoryGLImageTestBase(false) {}
+  GLImageBackingFactoryTest() : GLImageBackingFactoryTestBase(false) {}
   void SetUp() override {
     GpuDriverBugWorkarounds workarounds;
     SetUpBase(workarounds, &image_factory_);
@@ -165,7 +163,7 @@
   TextureImageFactory image_factory_;
 };
 
-TEST_P(SharedImageBackingFactoryGLImageTest, Basic) {
+TEST_P(GLImageBackingFactoryTest, Basic) {
   // TODO(jonahr): Test crashes on Mac with ANGLE/passthrough
   // (crbug.com/1100975)
   gpu::GPUTestBotConfig bot_config;
@@ -219,7 +217,7 @@
   ASSERT_TRUE(image);
   EXPECT_EQ(size, image->GetSize());
 
-  // Next, validate via a SharedImageRepresentationGLTexture.
+  // Next, validate via a GLTextureImageRepresentation.
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       shared_image_manager_->Register(std::move(backing),
                                       memory_type_tracker_.get());
@@ -247,7 +245,7 @@
     gl_representation_rgb.reset();
   }
 
-  // Next, validate a SharedImageRepresentationGLTexturePassthrough.
+  // Next, validate a GLTexturePassthroughImageRepresentation.
   if (use_passthrough()) {
     auto gl_representation =
         shared_image_representation_factory_->ProduceGLTexturePassthrough(
@@ -261,13 +259,13 @@
     gl_representation.reset();
   }
 
-  // Finally, validate a SharedImageRepresentationSkia.
+  // Finally, validate a SkiaImageRepresentation.
   auto skia_representation = shared_image_representation_factory_->ProduceSkia(
       mailbox, context_state_.get());
   EXPECT_TRUE(skia_representation);
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -278,8 +276,7 @@
   EXPECT_EQ(size.height(), surface->height());
   scoped_write_access.reset();
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   auto* promise_texture = scoped_read_access->promise_image_texture();
@@ -325,7 +322,7 @@
   }
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, InitialData) {
+TEST_P(GLImageBackingFactoryTest, InitialData) {
   // TODO(andrescj): these loop over the formats can be replaced by test
   // parameters.
   for (auto format :
@@ -360,7 +357,7 @@
     ASSERT_TRUE(texture_base);
     GLenum expected_target = texture_base->target();
 
-    // Validate via a SharedImageRepresentationGLTexture(Passthrough).
+    // Validate via a GLTextureImageRepresentation(Passthrough).
     std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
         shared_image_manager_->Register(std::move(backing),
                                         memory_type_tracker_.get());
@@ -397,7 +394,7 @@
   }
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, InitialDataImage) {
+TEST_P(GLImageBackingFactoryTest, InitialDataImage) {
   const bool should_succeed =
       can_create_scanout_or_gmb_shared_image(get_format());
   if (should_succeed)
@@ -419,7 +416,7 @@
   }
   ASSERT_TRUE(backing);
 
-  // Validate via a SharedImageRepresentationGLTexture(Passthrough).
+  // Validate via a GLTextureImageRepresentation(Passthrough).
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       shared_image_manager_->Register(std::move(backing),
                                       memory_type_tracker_.get());
@@ -448,7 +445,7 @@
   }
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, InitialDataWrongSize) {
+TEST_P(GLImageBackingFactoryTest, InitialDataWrongSize) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = get_format();
   gfx::Size size(256, 256);
@@ -468,7 +465,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, InvalidFormat) {
+TEST_P(GLImageBackingFactoryTest, InvalidFormat) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = viz::ResourceFormat::YUV_420_BIPLANAR;
   gfx::Size size(256, 256);
@@ -483,7 +480,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, InvalidSize) {
+TEST_P(GLImageBackingFactoryTest, InvalidSize) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = get_format();
   gfx::Size size(0, 0);
@@ -504,7 +501,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLImageTest, EstimatedSize) {
+TEST_P(GLImageBackingFactoryTest, EstimatedSize) {
   const bool should_succeed =
       can_create_scanout_or_gmb_shared_image(get_format());
   if (should_succeed)
@@ -541,7 +538,7 @@
 // Ensures that the various conversion functions used w/ TexStorage2D match
 // their TexImage2D equivalents, allowing us to minimize the amount of parallel
 // data tracked in the SharedImageFactoryGLImage.
-TEST_P(SharedImageBackingFactoryGLImageTest, TexImageTexStorageEquivalence) {
+TEST_P(GLImageBackingFactoryTest, TexImageTexStorageEquivalence) {
   scoped_refptr<gles2::FeatureInfo> feature_info =
       new gles2::FeatureInfo(GpuDriverBugWorkarounds(), GpuFeatureInfo());
   feature_info->Initialize(ContextType::CONTEXT_TYPE_OPENGLES2,
@@ -635,12 +632,10 @@
   unsigned internal_format_ = GL_RGBA;
 };
 
-class SharedImageBackingFactoryGLImageWithGMBTest
-    : public SharedImageBackingFactoryGLImageTestBase,
-      public gpu::ImageFactory {
+class GLImageBackingFactoryWithGMBTest : public GLImageBackingFactoryTestBase,
+                                         public gpu::ImageFactory {
  public:
-  SharedImageBackingFactoryGLImageWithGMBTest()
-      : SharedImageBackingFactoryGLImageTestBase(false) {}
+  GLImageBackingFactoryWithGMBTest() : GLImageBackingFactoryTestBase(false) {}
   void SetUp() override { SetUpBase(GpuDriverBugWorkarounds(), this); }
 
   scoped_refptr<gl::GLImage> GetImageFromMailbox(Mailbox mailbox) {
@@ -680,8 +675,7 @@
   static constexpr int kClientId = 3;
 };
 
-TEST_P(SharedImageBackingFactoryGLImageWithGMBTest,
-       GpuMemoryBufferImportEmpty) {
+TEST_P(GLImageBackingFactoryWithGMBTest, GpuMemoryBufferImportEmpty) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   gfx::Size size(256, 256);
   gfx::BufferFormat format = viz::BufferFormat(get_format());
@@ -697,8 +691,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLImageWithGMBTest,
-       GpuMemoryBufferImportNative) {
+TEST_P(GLImageBackingFactoryWithGMBTest, GpuMemoryBufferImportNative) {
   // TODO(jonahr): Test crashes on Mac with ANGLE/passthrough
   // (crbug.com/1100975)
   gpu::GPUTestBotConfig bot_config;
@@ -743,7 +736,7 @@
                                                           context_state_);
     std::vector<GrBackendSemaphore> begin_semaphores;
     std::vector<GrBackendSemaphore> end_semaphores;
-    std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+    std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
         scoped_read_access;
     skia_representation->BeginScopedReadAccess(&begin_semaphores,
                                                &end_semaphores);
@@ -756,8 +749,7 @@
   EXPECT_GT(stub_image->update_counter(), update_counter);
 }
 
-TEST_P(SharedImageBackingFactoryGLImageWithGMBTest,
-       GpuMemoryBufferImportSharedMemory) {
+TEST_P(GLImageBackingFactoryWithGMBTest, GpuMemoryBufferImportSharedMemory) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   gfx::Size size(256, 256);
   gfx::BufferFormat format = viz::BufferFormat(get_format());
@@ -795,7 +787,7 @@
   EXPECT_EQ(format, shm_image->format());
 }
 
-TEST_P(SharedImageBackingFactoryGLImageWithGMBTest,
+TEST_P(GLImageBackingFactoryWithGMBTest,
        GpuMemoryBufferImportNative_WithRGBEmulation) {
   if (use_passthrough())
     return;
@@ -862,12 +854,12 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(Service,
-                         SharedImageBackingFactoryGLImageTest,
+                         GLImageBackingFactoryTest,
                          ::testing::Combine(::testing::Bool(),
                                             kResourceFormats),
                          TestParamToString);
 INSTANTIATE_TEST_SUITE_P(Service,
-                         SharedImageBackingFactoryGLImageWithGMBTest,
+                         GLImageBackingFactoryWithGMBTest,
                          ::testing::Combine(::testing::Bool(),
                                             kResourceFormats),
                          TestParamToString);
diff --git a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc
index 09926660..2d606ab 100644
--- a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc
@@ -27,14 +27,13 @@
 
 namespace gpu {
 
-bool SharedImageRepresentationGLOzoneShared::BeginAccess(
+bool GLOzoneImageRepresentationShared::BeginAccess(
     GLenum mode,
-    SharedImageBackingOzone* ozone_backing,
+    OzoneImageBacking* ozone_backing,
     bool& need_end_fence) {
   bool readonly = mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM;
   std::vector<gfx::GpuFenceHandle> fences;
-  ozone_backing->BeginAccess(readonly,
-                             SharedImageBackingOzone::AccessStream::kGL,
+  ozone_backing->BeginAccess(readonly, OzoneImageBacking::AccessStream::kGL,
                              &fences, need_end_fence);
 
   // ChromeOS VMs don't support gpu fences, so there is no good way to
@@ -53,10 +52,10 @@
   return ozone_backing->VaSync();
 }
 
-void SharedImageRepresentationGLOzoneShared::EndAccess(
+void GLOzoneImageRepresentationShared::EndAccess(
     bool need_end_fence,
     GLenum mode,
-    SharedImageBackingOzone* ozone_backing) {
+    OzoneImageBacking* ozone_backing) {
   gfx::GpuFenceHandle fence;
   // ChromeOS VMs don't support gpu fences, so there is no good way to
   // synchronize with GL.
@@ -66,12 +65,12 @@
     fence = gl_fence->GetGpuFence()->GetGpuFenceHandle().Clone();
   }
   bool readonly = mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM;
-  ozone_backing->EndAccess(readonly, SharedImageBackingOzone::AccessStream::kGL,
+  ozone_backing->EndAccess(readonly, OzoneImageBacking::AccessStream::kGL,
                            std::move(fence));
 }
 
 std::unique_ptr<ui::NativePixmapGLBinding>
-SharedImageRepresentationGLOzoneShared::GetBinding(
+GLOzoneImageRepresentationShared::GetBinding(
     SharedImageBacking* backing,
     scoped_refptr<gfx::NativePixmap> pixmap,
     gfx::BufferPlane plane,
@@ -108,8 +107,8 @@
 }
 
 // static
-std::unique_ptr<SharedImageRepresentationGLTextureOzone>
-SharedImageRepresentationGLTextureOzone::Create(
+std::unique_ptr<GLTextureOzoneImageRepresentation>
+GLTextureOzoneImageRepresentation::Create(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
@@ -118,7 +117,7 @@
   GLenum target;
   GLuint gl_texture_service_id;
   std::unique_ptr<ui::NativePixmapGLBinding> np_gl_binding =
-      SharedImageRepresentationGLOzoneShared::GetBinding(
+      GLOzoneImageRepresentationShared::GetBinding(
           backing, std::move(pixmap), plane, gl_texture_service_id, target);
   if (!np_gl_binding) {
     return nullptr;
@@ -135,44 +134,43 @@
                         backing->ClearedRect());
   texture->SetImmutable(true, true);
 
-  return base::WrapUnique<SharedImageRepresentationGLTextureOzone>(
-      new SharedImageRepresentationGLTextureOzone(manager, backing, tracker,
-                                                  texture));
+  return base::WrapUnique<GLTextureOzoneImageRepresentation>(
+      new GLTextureOzoneImageRepresentation(manager, backing, tracker,
+                                            texture));
 }
 
-SharedImageRepresentationGLTextureOzone::
-    SharedImageRepresentationGLTextureOzone(SharedImageManager* manager,
-                                            SharedImageBacking* backing,
-                                            MemoryTypeTracker* tracker,
-                                            gles2::Texture* texture)
-    : SharedImageRepresentationGLTexture(manager, backing, tracker),
+GLTextureOzoneImageRepresentation::GLTextureOzoneImageRepresentation(
+    SharedImageManager* manager,
+    SharedImageBacking* backing,
+    MemoryTypeTracker* tracker,
+    gles2::Texture* texture)
+    : GLTextureImageRepresentation(manager, backing, tracker),
       texture_(texture) {}
 
-SharedImageRepresentationGLTextureOzone::
-    ~SharedImageRepresentationGLTextureOzone() {
+GLTextureOzoneImageRepresentation::~GLTextureOzoneImageRepresentation() {
   texture_->RemoveLightweightRef(has_context());
 }
 
-gles2::Texture* SharedImageRepresentationGLTextureOzone::GetTexture() {
+gles2::Texture* GLTextureOzoneImageRepresentation::GetTexture() {
   return texture_;
 }
 
-bool SharedImageRepresentationGLTextureOzone::BeginAccess(GLenum mode) {
+bool GLTextureOzoneImageRepresentation::BeginAccess(GLenum mode) {
   DCHECK(!current_access_mode_);
   current_access_mode_ = mode;
-  return SharedImageRepresentationGLOzoneShared::BeginAccess(
+  return GLOzoneImageRepresentationShared::BeginAccess(
       current_access_mode_, ozone_backing(), need_end_fence_);
 }
 
-void SharedImageRepresentationGLTextureOzone::EndAccess() {
-  SharedImageRepresentationGLOzoneShared::EndAccess(
+void GLTextureOzoneImageRepresentation::EndAccess() {
+  GLOzoneImageRepresentationShared::EndAccess(
       need_end_fence_, current_access_mode_, ozone_backing());
   current_access_mode_ = 0;
 }
 
 // static
-std::unique_ptr<SharedImageRepresentationGLTexturePassthroughOzone>
-SharedImageRepresentationGLTexturePassthroughOzone::Create(
+std::unique_ptr<GLTexturePassthroughOzoneImageRepresentation>
+GLTexturePassthroughOzoneImageRepresentation::Create(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
@@ -181,7 +179,7 @@
   GLenum target;
   GLuint gl_texture_service_id;
   std::unique_ptr<ui::NativePixmapGLBinding> np_gl_binding =
-      SharedImageRepresentationGLOzoneShared::GetBinding(
+      GLOzoneImageRepresentationShared::GetBinding(
           backing, std::move(pixmap), plane, gl_texture_service_id, target);
   if (!np_gl_binding) {
     return nullptr;
@@ -197,38 +195,37 @@
           backing->size().width(), backing->size().height(),
           /*depth=*/1, /*border=*/0, gl_format, gl_type);
 
-  return base::WrapUnique<SharedImageRepresentationGLTexturePassthroughOzone>(
-      new SharedImageRepresentationGLTexturePassthroughOzone(
+  return base::WrapUnique<GLTexturePassthroughOzoneImageRepresentation>(
+      new GLTexturePassthroughOzoneImageRepresentation(
           manager, backing, tracker, texture_passthrough));
 }
 
-SharedImageRepresentationGLTexturePassthroughOzone::
-    SharedImageRepresentationGLTexturePassthroughOzone(
+GLTexturePassthroughOzoneImageRepresentation::
+    GLTexturePassthroughOzoneImageRepresentation(
         SharedImageManager* manager,
         SharedImageBacking* backing,
         MemoryTypeTracker* tracker,
         scoped_refptr<gles2::TexturePassthrough> texture_passthrough)
-    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+    : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
       texture_passthrough_(texture_passthrough) {}
 
-SharedImageRepresentationGLTexturePassthroughOzone::
-    ~SharedImageRepresentationGLTexturePassthroughOzone() = default;
+GLTexturePassthroughOzoneImageRepresentation::
+    ~GLTexturePassthroughOzoneImageRepresentation() = default;
 
 const scoped_refptr<gles2::TexturePassthrough>&
-SharedImageRepresentationGLTexturePassthroughOzone::GetTexturePassthrough() {
+GLTexturePassthroughOzoneImageRepresentation::GetTexturePassthrough() {
   return texture_passthrough_;
 }
 
-bool SharedImageRepresentationGLTexturePassthroughOzone::BeginAccess(
-    GLenum mode) {
+bool GLTexturePassthroughOzoneImageRepresentation::BeginAccess(GLenum mode) {
   DCHECK(!current_access_mode_);
   current_access_mode_ = mode;
-  return SharedImageRepresentationGLOzoneShared::BeginAccess(
+  return GLOzoneImageRepresentationShared::BeginAccess(
       current_access_mode_, ozone_backing(), need_end_fence_);
 }
 
-void SharedImageRepresentationGLTexturePassthroughOzone::EndAccess() {
-  SharedImageRepresentationGLOzoneShared::EndAccess(
+void GLTexturePassthroughOzoneImageRepresentation::EndAccess() {
+  GLOzoneImageRepresentationShared::EndAccess(
       need_end_fence_, current_access_mode_, ozone_backing());
   current_access_mode_ = 0;
 }
diff --git a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.h b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.h
index 40522c8..43db6c14 100644
--- a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.h
@@ -21,14 +21,14 @@
 
 namespace gpu {
 
-class SharedImageRepresentationGLOzoneShared {
+class GLOzoneImageRepresentationShared {
  public:
   static bool BeginAccess(GLenum mode,
-                          SharedImageBackingOzone* ozone_backing,
+                          OzoneImageBacking* ozone_backing,
                           bool& need_end_fence);
   static void EndAccess(bool need_end_fence,
                         GLenum mode,
-                        SharedImageBackingOzone* ozone_backing);
+                        OzoneImageBacking* ozone_backing);
   static std::unique_ptr<ui::NativePixmapGLBinding> GetBinding(
       SharedImageBacking* backing,
       scoped_refptr<gfx::NativePixmap> pixmap,
@@ -39,33 +39,32 @@
 
 // Representation of an Ozone-backed SharedImage that can be accessed as a
 // GL texture.
-class SharedImageRepresentationGLTextureOzone
-    : public SharedImageRepresentationGLTexture {
+class GLTextureOzoneImageRepresentation : public GLTextureImageRepresentation {
  public:
-  // Creates and initializes a SharedImageRepresentationGLTextureOzone. On
+  // Creates and initializes a GLTextureOzoneImageRepresentation. On
   // failure, returns nullptr.
-  static std::unique_ptr<SharedImageRepresentationGLTextureOzone> Create(
+  static std::unique_ptr<GLTextureOzoneImageRepresentation> Create(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<gfx::NativePixmap> pixmap,
       gfx::BufferPlane plane);
 
-  ~SharedImageRepresentationGLTextureOzone() override;
+  ~GLTextureOzoneImageRepresentation() override;
 
-  // SharedImageRepresentationGLTexture implementation.
+  // GLTextureImageRepresentation implementation.
   gles2::Texture* GetTexture() override;
   bool BeginAccess(GLenum mode) override;
   void EndAccess() override;
 
  private:
-  SharedImageRepresentationGLTextureOzone(SharedImageManager* manager,
-                                          SharedImageBacking* backing,
-                                          MemoryTypeTracker* tracker,
-                                          gles2::Texture* texture);
+  GLTextureOzoneImageRepresentation(SharedImageManager* manager,
+                                    SharedImageBacking* backing,
+                                    MemoryTypeTracker* tracker,
+                                    gles2::Texture* texture);
 
-  SharedImageBackingOzone* ozone_backing() {
-    return static_cast<SharedImageBackingOzone*>(backing());
+  OzoneImageBacking* ozone_backing() {
+    return static_cast<OzoneImageBacking*>(backing());
   }
 
   raw_ptr<gles2::Texture> texture_;
@@ -75,36 +74,36 @@
 
 // Representation of an Ozone-backed SharedImage that can be accessed as a
 // GL texture with passthrough.
-class SharedImageRepresentationGLTexturePassthroughOzone
-    : public SharedImageRepresentationGLTexturePassthrough {
+class GLTexturePassthroughOzoneImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
   // Creates and initializes a
-  // SharedImageRepresentationGLTexturePassthroughOzone. On failure, returns
+  // GLTexturePassthroughOzoneImageRepresentation. On failure, returns
   // nullptr.
-  static std::unique_ptr<SharedImageRepresentationGLTexturePassthroughOzone>
-  Create(SharedImageManager* manager,
-         SharedImageBacking* backing,
-         MemoryTypeTracker* tracker,
-         scoped_refptr<gfx::NativePixmap> pixmap,
-         gfx::BufferPlane plane);
+  static std::unique_ptr<GLTexturePassthroughOzoneImageRepresentation> Create(
+      SharedImageManager* manager,
+      SharedImageBacking* backing,
+      MemoryTypeTracker* tracker,
+      scoped_refptr<gfx::NativePixmap> pixmap,
+      gfx::BufferPlane plane);
 
-  ~SharedImageRepresentationGLTexturePassthroughOzone() override;
+  ~GLTexturePassthroughOzoneImageRepresentation() override;
 
-  // SharedImageRepresentationGLTexturePassthrough implementation.
+  // GLTexturePassthroughImageRepresentation implementation.
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override;
   bool BeginAccess(GLenum mode) override;
   void EndAccess() override;
 
  private:
-  SharedImageRepresentationGLTexturePassthroughOzone(
+  GLTexturePassthroughOzoneImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<gles2::TexturePassthrough> texture_passthrough);
 
-  SharedImageBackingOzone* ozone_backing() {
-    return static_cast<SharedImageBackingOzone*>(backing());
+  OzoneImageBacking* ozone_backing() {
+    return static_cast<OzoneImageBacking*>(backing());
   }
 
   scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.cc b/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.cc
index 7f0ff70..99e7d10 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.cc
@@ -9,28 +9,26 @@
 
 namespace gpu {
 
-SharedImageRepresentationGLTextureAndroid::
-    SharedImageRepresentationGLTextureAndroid(
-        SharedImageManager* manager,
-        SharedImageBackingAndroid* backing,
-        MemoryTypeTracker* tracker,
-        gles2::Texture* texture)
-    : SharedImageRepresentationGLTexture(manager, backing, tracker),
+GLTextureAndroidImageRepresentation::GLTextureAndroidImageRepresentation(
+    SharedImageManager* manager,
+    AndroidImageBacking* backing,
+    MemoryTypeTracker* tracker,
+    gles2::Texture* texture)
+    : GLTextureImageRepresentation(manager, backing, tracker),
       texture_(texture) {}
 
-SharedImageRepresentationGLTextureAndroid::
-    ~SharedImageRepresentationGLTextureAndroid() {
+GLTextureAndroidImageRepresentation::~GLTextureAndroidImageRepresentation() {
   EndAccess();
 
   if (texture_)
     texture_->RemoveLightweightRef(has_context());
 }
 
-gles2::Texture* SharedImageRepresentationGLTextureAndroid::GetTexture() {
+gles2::Texture* GLTextureAndroidImageRepresentation::GetTexture() {
   return texture_;
 }
 
-bool SharedImageRepresentationGLTextureAndroid::BeginAccess(GLenum mode) {
+bool GLTextureAndroidImageRepresentation::BeginAccess(GLenum mode) {
   bool read_only_mode = (mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) ||
                         (mode == GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM);
   bool read_write_mode =
@@ -60,7 +58,7 @@
   return true;
 }
 
-void SharedImageRepresentationGLTextureAndroid::EndAccess() {
+void GLTextureAndroidImageRepresentation::EndAccess() {
   if (mode_ == RepresentationAccessMode::kNone)
     return;
 
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.h b/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.h
index 51ba041..086182b 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_android_image_representation.h
@@ -10,18 +10,23 @@
 #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
 
 namespace gpu {
-class SharedImageBackingAndroid;
+class AndroidImageBacking;
 
 // A generic GL Texture representation which can be used by any backing on
 // Android.
-class SharedImageRepresentationGLTextureAndroid
-    : public SharedImageRepresentationGLTexture {
+class GLTextureAndroidImageRepresentation
+    : public GLTextureImageRepresentation {
  public:
-  SharedImageRepresentationGLTextureAndroid(SharedImageManager* manager,
-                                            SharedImageBackingAndroid* backing,
-                                            MemoryTypeTracker* tracker,
-                                            gles2::Texture* texture);
-  ~SharedImageRepresentationGLTextureAndroid() override;
+  GLTextureAndroidImageRepresentation(SharedImageManager* manager,
+                                      AndroidImageBacking* backing,
+                                      MemoryTypeTracker* tracker,
+                                      gles2::Texture* texture);
+  ~GLTextureAndroidImageRepresentation() override;
+
+  GLTextureAndroidImageRepresentation(
+      const GLTextureAndroidImageRepresentation&) = delete;
+  GLTextureAndroidImageRepresentation& operator=(
+      const GLTextureAndroidImageRepresentation&) = delete;
 
   gles2::Texture* GetTexture() override;
 
@@ -29,17 +34,12 @@
   void EndAccess() override;
 
  private:
-  SharedImageBackingAndroid* android_backing() {
-    return static_cast<SharedImageBackingAndroid*>(backing());
+  AndroidImageBacking* android_backing() {
+    return static_cast<AndroidImageBacking*>(backing());
   }
 
   const raw_ptr<gles2::Texture> texture_;
   RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
-
-  SharedImageRepresentationGLTextureAndroid(
-      const SharedImageRepresentationGLTextureAndroid&) = delete;
-  SharedImageRepresentationGLTextureAndroid& operator=(
-      const SharedImageRepresentationGLTextureAndroid&) = delete;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
index 8485b98..b7927e8 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
@@ -71,22 +71,21 @@
 }
 
 using InitializeGLTextureParams =
-    SharedImageBackingGLCommon::InitializeGLTextureParams;
+    GLTextureImageBackingHelper::InitializeGLTextureParams;
 
 }  // anonymous namespace
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingGLTexture
+// GLTextureImageBacking
 
-SharedImageBackingGLTexture::SharedImageBackingGLTexture(
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage,
-    bool is_passthrough)
+GLTextureImageBacking::GLTextureImageBacking(const Mailbox& mailbox,
+                                             viz::ResourceFormat format,
+                                             const gfx::Size& size,
+                                             const gfx::ColorSpace& color_space,
+                                             GrSurfaceOrigin surface_origin,
+                                             SkAlphaType alpha_type,
+                                             uint32_t usage,
+                                             bool is_passthrough)
     : ClearTrackingSharedImageBacking(mailbox,
                                       format,
                                       size,
@@ -98,7 +97,7 @@
                                       false /* is_thread_safe */),
       is_passthrough_(is_passthrough) {}
 
-SharedImageBackingGLTexture::~SharedImageBackingGLTexture() {
+GLTextureImageBacking::~GLTextureImageBacking() {
   if (IsPassthrough()) {
     if (passthrough_texture_) {
       if (!have_context())
@@ -113,15 +112,15 @@
   }
 }
 
-GLenum SharedImageBackingGLTexture::GetGLTarget() const {
+GLenum GLTextureImageBacking::GetGLTarget() const {
   return texture_ ? texture_->target() : passthrough_texture_->target();
 }
 
-GLuint SharedImageBackingGLTexture::GetGLServiceId() const {
+GLuint GLTextureImageBacking::GetGLServiceId() const {
   return texture_ ? texture_->service_id() : passthrough_texture_->service_id();
 }
 
-void SharedImageBackingGLTexture::OnMemoryDump(
+void GLTextureImageBacking::OnMemoryDump(
     const std::string& dump_name,
     base::trace_event::MemoryAllocatorDump* dump,
     base::trace_event::ProcessMemoryDump* pmd,
@@ -136,11 +135,11 @@
   }
 }
 
-SharedImageBackingType SharedImageBackingGLTexture::GetType() const {
+SharedImageBackingType GLTextureImageBacking::GetType() const {
   return SharedImageBackingType::kGLTexture;
 }
 
-gfx::Rect SharedImageBackingGLTexture::ClearedRect() const {
+gfx::Rect GLTextureImageBacking::ClearedRect() const {
   if (!IsPassthrough())
     return texture_->GetLevelClearedRect(texture_->target(), 0);
 
@@ -149,8 +148,7 @@
   return ClearTrackingSharedImageBacking::ClearedRect();
 }
 
-void SharedImageBackingGLTexture::SetClearedRect(
-    const gfx::Rect& cleared_rect) {
+void GLTextureImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   if (!IsPassthrough()) {
     texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
     return;
@@ -161,7 +159,7 @@
   ClearTrackingSharedImageBacking::SetClearedRect(cleared_rect);
 }
 
-bool SharedImageBackingGLTexture::ProduceLegacyMailbox(
+bool GLTextureImageBacking::ProduceLegacyMailbox(
     MailboxManager* mailbox_manager) {
   if (IsPassthrough())
     mailbox_manager->ProduceTexture(mailbox(), passthrough_texture_.get());
@@ -170,40 +168,39 @@
   return true;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingGLTexture::ProduceGLTexture(SharedImageManager* manager,
-                                              MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+GLTextureImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                        MemoryTypeTracker* tracker) {
   DCHECK(texture_);
-  return std::make_unique<SharedImageRepresentationGLTextureImpl>(
+  return std::make_unique<GLTextureGLCommonRepresentation>(
       manager, this, nullptr, tracker, texture_);
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingGLTexture::ProduceGLTexturePassthrough(
-    SharedImageManager* manager,
-    MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+GLTextureImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                                   MemoryTypeTracker* tracker) {
   DCHECK(passthrough_texture_);
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
+  return std::make_unique<GLTexturePassthroughGLCommonRepresentation>(
       manager, this, nullptr, tracker, passthrough_texture_);
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingGLTexture::ProduceDawn(SharedImageManager* manager,
-                                         MemoryTypeTracker* tracker,
-                                         WGPUDevice device,
-                                         WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> GLTextureImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
 #if BUILDFLAG(USE_DAWN) && BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES)
   if (backend_type == WGPUBackendType_OpenGLES) {
     if (!image_egl_) {
       CreateEGLImage();
     }
-    std::unique_ptr<SharedImageRepresentationGLTextureBase> texture;
+    std::unique_ptr<GLTextureImageRepresentationBase> texture;
     if (IsPassthrough()) {
       texture = ProduceGLTexturePassthrough(manager, tracker);
     } else {
       texture = ProduceGLTexture(manager, tracker);
     }
-    return std::make_unique<SharedImageRepresentationDawnEGLImage>(
+    return std::make_unique<DawnEGLImageRepresentation>(
         std::move(texture), manager, this, tracker, device);
   }
 #endif
@@ -213,12 +210,11 @@
     return nullptr;
   }
 
-  return SharedImageBackingGLCommon::ProduceDawnCommon(
+  return GLTextureImageBackingHelper::ProduceDawnCommon(
       factory(), manager, tracker, device, backend_type, this, IsPassthrough());
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingGLTexture::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> GLTextureImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -230,18 +226,17 @@
                         &backend_texture);
     cached_promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
   }
-  return std::make_unique<SharedImageRepresentationSkiaImpl>(
+  return std::make_unique<SkiaGLCommonRepresentation>(
       manager, this, nullptr, std::move(context_state), cached_promise_texture_,
       tracker);
 }
 
-void SharedImageBackingGLTexture::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {}
+void GLTextureImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {}
 
-void SharedImageBackingGLTexture::InitializeGLTexture(
+void GLTextureImageBacking::InitializeGLTexture(
     GLuint service_id,
     const InitializeGLTextureParams& params) {
-  SharedImageBackingGLCommon::MakeTextureAndSetParameters(
+  GLTextureImageBackingHelper::MakeTextureAndSetParameters(
       params.target, service_id, params.framebuffer_attachment_angle,
       IsPassthrough() ? &passthrough_texture_ : nullptr,
       IsPassthrough() ? nullptr : &texture_);
@@ -258,7 +253,7 @@
   }
 }
 
-void SharedImageBackingGLTexture::CreateEGLImage() {
+void GLTextureImageBacking::CreateEGLImage() {
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || defined(USE_OZONE)
   SharedContextState* shared_context_state = factory()->GetSharedContextState();
   ui::ScopedMakeCurrent smc(shared_context_state->context(),
@@ -277,7 +272,7 @@
 #endif
 }
 
-void SharedImageBackingGLTexture::SetCompatibilitySwizzle(
+void GLTextureImageBacking::SetCompatibilitySwizzle(
     const gles2::Texture::CompatibilitySwizzle* swizzle) {
   if (!IsPassthrough())
     texture_->SetCompatibilitySwizzle(swizzle);
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
index 88721aa..a1938fd 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.h
@@ -15,24 +15,23 @@
 
 // Implementation of SharedImageBacking that creates a GL Texture that is not
 // backed by a GLImage.
-class SharedImageBackingGLTexture : public ClearTrackingSharedImageBacking {
+class GLTextureImageBacking : public ClearTrackingSharedImageBacking {
  public:
-  SharedImageBackingGLTexture(const Mailbox& mailbox,
-                              viz::ResourceFormat format,
-                              const gfx::Size& size,
-                              const gfx::ColorSpace& color_space,
-                              GrSurfaceOrigin surface_origin,
-                              SkAlphaType alpha_type,
-                              uint32_t usage,
-                              bool is_passthrough);
-  SharedImageBackingGLTexture(const SharedImageBackingGLTexture&) = delete;
-  SharedImageBackingGLTexture& operator=(const SharedImageBackingGLTexture&) =
-      delete;
-  ~SharedImageBackingGLTexture() override;
+  GLTextureImageBacking(const Mailbox& mailbox,
+                        viz::ResourceFormat format,
+                        const gfx::Size& size,
+                        const gfx::ColorSpace& color_space,
+                        GrSurfaceOrigin surface_origin,
+                        SkAlphaType alpha_type,
+                        uint32_t usage,
+                        bool is_passthrough);
+  GLTextureImageBacking(const GLTextureImageBacking&) = delete;
+  GLTextureImageBacking& operator=(const GLTextureImageBacking&) = delete;
+  ~GLTextureImageBacking() override;
 
   void InitializeGLTexture(
       GLuint service_id,
-      const SharedImageBackingGLCommon::InitializeGLTextureParams& params);
+      const GLTextureImageBackingHelper::InitializeGLTextureParams& params);
   void SetCompatibilitySwizzle(
       const gles2::Texture::CompatibilitySwizzle* swizzle);
 
@@ -50,18 +49,18 @@
   gfx::Rect ClearedRect() const final;
   void SetClearedRect(const gfx::Rect& cleared_rect) final;
   bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) final;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) final;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) final;
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) final;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
index 5bb39f6..623232d 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
@@ -21,33 +21,32 @@
 namespace {
 
 using ScopedResetAndRestoreUnpackState =
-    SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState;
+    GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState;
 
-using ScopedRestoreTexture = SharedImageBackingGLCommon::ScopedRestoreTexture;
+using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture;
 
 using InitializeGLTextureParams =
-    SharedImageBackingGLCommon::InitializeGLTextureParams;
+    GLTextureImageBackingHelper::InitializeGLTextureParams;
 
 }  // anonymous namespace
 
 ///////////////////////////////////////////////////////////////////////////////
-// SharedImageBackingFactoryGLTexture
+// GLTextureImageBackingFactory
 
-SharedImageBackingFactoryGLTexture::SharedImageBackingFactoryGLTexture(
+GLTextureImageBackingFactory::GLTextureImageBackingFactory(
     const GpuPreferences& gpu_preferences,
     const GpuDriverBugWorkarounds& workarounds,
     const gles2::FeatureInfo* feature_info,
     gl::ProgressReporter* progress_reporter)
-    : SharedImageBackingFactoryGLCommon(gpu_preferences,
-                                        workarounds,
-                                        feature_info,
-                                        progress_reporter) {}
+    : GLCommonImageBackingFactory(gpu_preferences,
+                                  workarounds,
+                                  feature_info,
+                                  progress_reporter) {}
 
-SharedImageBackingFactoryGLTexture::~SharedImageBackingFactoryGLTexture() =
-    default;
+GLTextureImageBackingFactory::~GLTextureImageBackingFactory() = default;
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLTexture::CreateSharedImage(
+GLTextureImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -64,7 +63,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLTexture::CreateSharedImage(
+GLTextureImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -79,7 +78,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLTexture::CreateSharedImage(
+GLTextureImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -96,7 +95,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLTexture::CreateSharedImageForTest(
+GLTextureImageBackingFactory::CreateSharedImageForTest(
     const Mailbox& mailbox,
     GLenum target,
     GLuint service_id,
@@ -104,7 +103,7 @@
     viz::ResourceFormat format,
     const gfx::Size& size,
     uint32_t usage) {
-  auto result = std::make_unique<SharedImageBackingGLTexture>(
+  auto result = std::make_unique<GLTextureImageBacking>(
       mailbox, format, size, gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin,
       kPremul_SkAlphaType, usage, false /* is_passthrough */);
   InitializeGLTextureParams params;
@@ -117,7 +116,7 @@
   return std::move(result);
 }
 
-bool SharedImageBackingFactoryGLTexture::IsSupported(
+bool GLTextureImageBackingFactory::IsSupported(
     uint32_t usage,
     viz::ResourceFormat format,
     bool thread_safe,
@@ -167,7 +166,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryGLTexture::CreateSharedImageInternal(
+GLTextureImageBackingFactory::CreateSharedImageInternal(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -200,7 +199,7 @@
   params.framebuffer_attachment_angle =
       for_framebuffer_attachment && texture_usage_angle_;
 
-  auto result = std::make_unique<SharedImageBackingGLTexture>(
+  auto result = std::make_unique<GLTextureImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       use_passthrough_);
   result->InitializeGLTexture(0, params);
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.h b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.h
index 01d192d..7feeebd 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.h
@@ -28,14 +28,14 @@
 
 // Implementation of SharedImageBackingFactory that produces GL-texture backed
 // SharedImages.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture
-    : public SharedImageBackingFactoryGLCommon {
+class GPU_GLES2_EXPORT GLTextureImageBackingFactory
+    : public GLCommonImageBackingFactory {
  public:
-  SharedImageBackingFactoryGLTexture(const GpuPreferences& gpu_preferences,
-                                     const GpuDriverBugWorkarounds& workarounds,
-                                     const gles2::FeatureInfo* feature_info,
-                                     gl::ProgressReporter* progress_reporter);
-  ~SharedImageBackingFactoryGLTexture() override;
+  GLTextureImageBackingFactory(const GpuPreferences& gpu_preferences,
+                               const GpuDriverBugWorkarounds& workarounds,
+                               const gles2::FeatureInfo* feature_info,
+                               gl::ProgressReporter* progress_reporter);
+  ~GLTextureImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation.
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
index 7fea39d..cb0af15 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
@@ -77,13 +77,13 @@
   MOCK_METHOD0(ReportProgress, void());
 };
 
-class SharedImageBackingFactoryGLTextureTestBase
+class GLTextureImageBackingFactoryTestBase
     : public testing::TestWithParam<std::tuple<bool, viz::ResourceFormat>> {
  public:
-  explicit SharedImageBackingFactoryGLTextureTestBase(bool is_thread_safe)
+  explicit GLTextureImageBackingFactoryTestBase(bool is_thread_safe)
       : shared_image_manager_(
             std::make_unique<SharedImageManager>(is_thread_safe)) {}
-  ~SharedImageBackingFactoryGLTextureTestBase() override {
+  ~GLTextureImageBackingFactoryTestBase() override {
     // |context_state_| must be destroyed on its own context.
     context_state_->MakeCurrent(surface_.get(), true /* needs_gl */);
   }
@@ -101,7 +101,7 @@
 
     GpuPreferences preferences;
     preferences.use_passthrough_cmd_decoder = use_passthrough();
-    backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>(
+    backing_factory_ = std::make_unique<GLTextureImageBackingFactory>(
         preferences, workarounds, context_state_->feature_info(),
         &progress_reporter_);
 
@@ -133,7 +133,7 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<SharedContextState> context_state_;
-  std::unique_ptr<SharedImageBackingFactoryGLTexture> backing_factory_;
+  std::unique_ptr<GLTextureImageBackingFactory> backing_factory_;
   gles2::MailboxManagerImpl mailbox_manager_;
   std::unique_ptr<SharedImageManager> shared_image_manager_;
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
@@ -144,11 +144,11 @@
   bool supports_ab30_ = false;
 };
 
-class SharedImageBackingFactoryGLTextureTest
-    : public SharedImageBackingFactoryGLTextureTestBase {
+class GLTextureImageBackingFactoryTest
+    : public GLTextureImageBackingFactoryTestBase {
  public:
-  SharedImageBackingFactoryGLTextureTest()
-      : SharedImageBackingFactoryGLTextureTestBase(false) {}
+  GLTextureImageBackingFactoryTest()
+      : GLTextureImageBackingFactoryTestBase(false) {}
   void SetUp() override {
     GpuDriverBugWorkarounds workarounds;
     SetUpBase(workarounds, &image_factory_);
@@ -158,7 +158,7 @@
   TextureImageFactory image_factory_;
 };
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) {
+TEST_P(GLTextureImageBackingFactoryTest, Basic) {
   // TODO(jonahr): Test fails on Mac with ANGLE/passthrough
   // (crbug.com/1100975)
   gpu::GPUTestBotConfig bot_config;
@@ -211,7 +211,7 @@
     EXPECT_EQ(height, size.height());
   }
 
-  // Next, validate via a SharedImageRepresentationGLTexture.
+  // Next, validate via a GLTextureImageRepresentation.
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       shared_image_manager_->Register(std::move(backing),
                                       memory_type_tracker_.get());
@@ -229,7 +229,7 @@
     gl_representation.reset();
   }
 
-  // Next, validate a SharedImageRepresentationGLTexturePassthrough.
+  // Next, validate a GLTexturePassthroughImageRepresentation.
   if (use_passthrough()) {
     auto gl_representation =
         shared_image_representation_factory_->ProduceGLTexturePassthrough(
@@ -245,13 +245,13 @@
     gl_representation.reset();
   }
 
-  // Finally, validate a SharedImageRepresentationSkia.
+  // Finally, validate a SkiaImageRepresentation.
   auto skia_representation = shared_image_representation_factory_->ProduceSkia(
       mailbox, context_state_.get());
   EXPECT_TRUE(skia_representation);
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
       &begin_semaphores, &end_semaphores,
@@ -272,8 +272,7 @@
   EXPECT_TRUE(end_semaphores.empty());
   scoped_write_access.reset();
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   auto* promise_texture = scoped_read_access->promise_image_texture();
@@ -291,7 +290,7 @@
   EXPECT_FALSE(mailbox_manager_.ConsumeTexture(mailbox));
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, InitialData) {
+TEST_P(GLTextureImageBackingFactoryTest, InitialData) {
   // TODO(andrescj): these loop over the formats can be replaced by test
   // parameters.
   for (auto format :
@@ -319,7 +318,7 @@
     ASSERT_TRUE(backing);
     EXPECT_TRUE(backing->IsCleared());
 
-    // Validate via a SharedImageRepresentationGLTexture(Passthrough).
+    // Validate via a GLTextureImageRepresentation(Passthrough).
     std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
         shared_image_manager_->Register(std::move(backing),
                                         memory_type_tracker_.get());
@@ -356,7 +355,7 @@
   }
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataImage) {
+TEST_P(GLTextureImageBackingFactoryTest, InitialDataImage) {
   const bool should_succeed = can_create_non_scanout_shared_image(get_format());
   if (should_succeed)
     EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1));
@@ -377,7 +376,7 @@
   }
   ASSERT_TRUE(backing);
 
-  // Validate via a SharedImageRepresentationGLTexture(Passthrough).
+  // Validate via a GLTextureImageRepresentation(Passthrough).
   std::unique_ptr<SharedImageRepresentationFactoryRef> shared_image =
       shared_image_manager_->Register(std::move(backing),
                                       memory_type_tracker_.get());
@@ -406,7 +405,7 @@
   }
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataWrongSize) {
+TEST_P(GLTextureImageBackingFactoryTest, InitialDataWrongSize) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = get_format();
   gfx::Size size(256, 256);
@@ -426,7 +425,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, InvalidFormat) {
+TEST_P(GLTextureImageBackingFactoryTest, InvalidFormat) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = viz::ResourceFormat::YUV_420_BIPLANAR;
   gfx::Size size(256, 256);
@@ -441,7 +440,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, InvalidSize) {
+TEST_P(GLTextureImageBackingFactoryTest, InvalidSize) {
   auto mailbox = Mailbox::GenerateForSharedImage();
   auto format = get_format();
   gfx::Size size(0, 0);
@@ -462,7 +461,7 @@
   EXPECT_FALSE(backing);
 }
 
-TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) {
+TEST_P(GLTextureImageBackingFactoryTest, EstimatedSize) {
   const bool should_succeed = can_create_non_scanout_shared_image(get_format());
   if (should_succeed)
     EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1));
@@ -497,8 +496,8 @@
 
 // Ensures that the various conversion functions used w/ TexStorage2D match
 // their TexImage2D equivalents, allowing us to minimize the amount of parallel
-// data tracked in the SharedImageFactoryGLTexture.
-TEST_P(SharedImageBackingFactoryGLTextureTest, TexImageTexStorageEquivalence) {
+// data tracked in the GLTextureImageBackingFactory.
+TEST_P(GLTextureImageBackingFactoryTest, TexImageTexStorageEquivalence) {
   scoped_refptr<gles2::FeatureInfo> feature_info =
       new gles2::FeatureInfo(GpuDriverBugWorkarounds(), GpuFeatureInfo());
   feature_info->Initialize(ContextType::CONTEXT_TYPE_OPENGLES2,
@@ -564,7 +563,7 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(Service,
-                         SharedImageBackingFactoryGLTextureTest,
+                         GLTextureImageBackingFactoryTest,
                          ::testing::Combine(::testing::Bool(),
                                             kResourceFormats),
                          TestParamToString);
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc
index e955324..e3746c5 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc
@@ -14,7 +14,7 @@
 
 namespace gpu {
 
-SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState::
+GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState::
     ScopedResetAndRestoreUnpackState(gl::GLApi* api,
                                      const UnpackStateAttribs& attribs,
                                      bool uploading_data)
@@ -64,7 +64,7 @@
   }
 }
 
-SharedImageBackingGLCommon::ScopedResetAndRestoreUnpackState::
+GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState::
     ~ScopedResetAndRestoreUnpackState() {
   if (unpack_buffer_)
     api_->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, unpack_buffer_);
@@ -86,7 +86,7 @@
     api_->glPixelStoreiFn(GL_UNPACK_LSB_FIRST, unpack_lsb_first_);
 }
 
-SharedImageBackingGLCommon::ScopedRestoreTexture::ScopedRestoreTexture(
+GLTextureImageBackingHelper::ScopedRestoreTexture::ScopedRestoreTexture(
     gl::GLApi* api,
     GLenum target)
     : api_(api), target_(target) {
@@ -110,18 +110,18 @@
   old_binding_ = old_texture_binding;
 }
 
-SharedImageBackingGLCommon::ScopedRestoreTexture::~ScopedRestoreTexture() {
+GLTextureImageBackingHelper::ScopedRestoreTexture::~ScopedRestoreTexture() {
   api_->glBindTextureFn(target_, old_binding_);
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingGLCommon::ProduceDawnCommon(SharedImageFactory* factory,
-                                              SharedImageManager* manager,
-                                              MemoryTypeTracker* tracker,
-                                              WGPUDevice device,
-                                              WGPUBackendType backend_type,
-                                              SharedImageBacking* backing,
-                                              bool use_passthrough) {
+std::unique_ptr<DawnImageRepresentation>
+GLTextureImageBackingHelper::ProduceDawnCommon(SharedImageFactory* factory,
+                                               SharedImageManager* manager,
+                                               MemoryTypeTracker* tracker,
+                                               WGPUDevice device,
+                                               WGPUBackendType backend_type,
+                                               SharedImageBacking* backing,
+                                               bool use_passthrough) {
   DCHECK(factory);
   // Make SharedContextState from factory the current context
   SharedContextState* shared_context_state = factory->GetSharedContextState();
@@ -143,8 +143,8 @@
 
   // Create a representation for current backing to avoid non-expected release
   // and using scope access methods.
-  std::unique_ptr<SharedImageRepresentationGLTextureBase> src_image;
-  std::unique_ptr<SharedImageRepresentationGLTextureBase> dst_image;
+  std::unique_ptr<GLTextureImageRepresentationBase> src_image;
+  std::unique_ptr<GLTextureImageRepresentationBase> dst_image;
   if (use_passthrough) {
     src_image =
         manager->ProduceGLTexturePassthrough(backing->mailbox(), tracker);
@@ -159,7 +159,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<SharedImageRepresentationGLTextureBase::ScopedAccess>
+  std::unique_ptr<GLTextureImageRepresentationBase::ScopedAccess>
       source_access = src_image->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kNo);
@@ -168,8 +168,8 @@
     return nullptr;
   }
 
-  std::unique_ptr<SharedImageRepresentationGLTextureBase::ScopedAccess>
-      dest_access = dst_image->BeginScopedAccess(
+  std::unique_ptr<GLTextureImageRepresentationBase::ScopedAccess> dest_access =
+      dst_image->BeginScopedAccess(
           GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM,
           SharedImageRepresentation::AllowUnclearedAccess::kYes);
   if (!dest_access) {
@@ -212,7 +212,7 @@
 }
 
 // static
-void SharedImageBackingGLCommon::MakeTextureAndSetParameters(
+void GLTextureImageBackingHelper::MakeTextureAndSetParameters(
     GLenum target,
     GLuint service_id,
     bool framebuffer_attachment_angle,
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h
index 1b5e8078..4498aec 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h
@@ -12,9 +12,8 @@
 
 namespace gpu {
 
-// Common helper functions for SharedImageBackingGLTexture and
-// SharedImageBackingPassthroughGLImage.
-class GPU_GLES2_EXPORT SharedImageBackingGLCommon {
+// Common helper functions for GLTextureImageBacking and GLImageBacking.
+class GPU_GLES2_EXPORT GLTextureImageBackingHelper {
  public:
   // These parameters are used to explicitly initialize a GL texture.
   struct InitializeGLTextureParams {
@@ -100,7 +99,7 @@
   // Create a Dawn backing. This will use |backing|'s ProduceGLTexture or
   // ProduceGLTexturePassthrough method, and populate the dawn backing via
   // CopyTextureCHROMIUM.
-  static std::unique_ptr<SharedImageRepresentationDawn> ProduceDawnCommon(
+  static std::unique_ptr<DawnImageRepresentation> ProduceDawnCommon(
       SharedImageFactory* factory,
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.cc b/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.cc
index 9ae077f..46f396e 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.cc
@@ -9,32 +9,31 @@
 
 namespace gpu {
 
-SharedImageRepresentationGLTexturePassthroughAndroid::
-    SharedImageRepresentationGLTexturePassthroughAndroid(
+GLTexturePassthroughAndroidImageRepresentation::
+    GLTexturePassthroughAndroidImageRepresentation(
         SharedImageManager* manager,
-        SharedImageBackingAndroid* backing,
+        AndroidImageBacking* backing,
         MemoryTypeTracker* tracker,
         scoped_refptr<gles2::TexturePassthrough> texture)
-    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+    : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
       texture_(std::move(texture)) {
   // TODO(https://crbug.com/1172769): Remove this CHECK.
   CHECK(texture_);
 }
 
-SharedImageRepresentationGLTexturePassthroughAndroid::
-    ~SharedImageRepresentationGLTexturePassthroughAndroid() {
+GLTexturePassthroughAndroidImageRepresentation::
+    ~GLTexturePassthroughAndroidImageRepresentation() {
   EndAccess();
   if (!has_context())
     texture_->MarkContextLost();
 }
 
 const scoped_refptr<gles2::TexturePassthrough>&
-SharedImageRepresentationGLTexturePassthroughAndroid::GetTexturePassthrough() {
+GLTexturePassthroughAndroidImageRepresentation::GetTexturePassthrough() {
   return texture_;
 }
 
-bool SharedImageRepresentationGLTexturePassthroughAndroid::BeginAccess(
-    GLenum mode) {
+bool GLTexturePassthroughAndroidImageRepresentation::BeginAccess(GLenum mode) {
   bool read_only_mode = (mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) ||
                         (mode == GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM);
   bool read_write_mode =
@@ -64,7 +63,7 @@
   return true;
 }
 
-void SharedImageRepresentationGLTexturePassthroughAndroid::EndAccess() {
+void GLTexturePassthroughAndroidImageRepresentation::EndAccess() {
   if (mode_ == RepresentationAccessMode::kNone)
     return;
 
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.h b/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.h
index 6278baf..957ff99f 100644
--- a/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/gl_texture_passthrough_android_image_representation.h
@@ -9,17 +9,22 @@
 #include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
 
 namespace gpu {
-class SharedImageBackingAndroid;
+class AndroidImageBacking;
 
-class SharedImageRepresentationGLTexturePassthroughAndroid
-    : public SharedImageRepresentationGLTexturePassthrough {
+class GLTexturePassthroughAndroidImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  SharedImageRepresentationGLTexturePassthroughAndroid(
+  GLTexturePassthroughAndroidImageRepresentation(
       SharedImageManager* manager,
-      SharedImageBackingAndroid* backing,
+      AndroidImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<gles2::TexturePassthrough> texture);
-  ~SharedImageRepresentationGLTexturePassthroughAndroid() override;
+  ~GLTexturePassthroughAndroidImageRepresentation() override;
+
+  GLTexturePassthroughAndroidImageRepresentation(
+      const GLTexturePassthroughAndroidImageRepresentation&) = delete;
+  GLTexturePassthroughAndroidImageRepresentation& operator=(
+      const GLTexturePassthroughAndroidImageRepresentation&) = delete;
 
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override;
@@ -28,17 +33,12 @@
   void EndAccess() override;
 
  private:
-  SharedImageBackingAndroid* android_backing() {
-    return static_cast<SharedImageBackingAndroid*>(backing());
+  AndroidImageBacking* android_backing() {
+    return static_cast<AndroidImageBacking*>(backing());
   }
 
   scoped_refptr<gles2::TexturePassthrough> texture_;
   RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
-
-  SharedImageRepresentationGLTexturePassthroughAndroid(
-      const SharedImageRepresentationGLTexturePassthroughAndroid&) = delete;
-  SharedImageRepresentationGLTexturePassthroughAndroid& operator=(
-      const SharedImageRepresentationGLTexturePassthroughAndroid&) = delete;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
index 660c1ba..103ac1a9 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.h
@@ -16,13 +16,13 @@
 
 // Helper functions used used by SharedImageRepresentationGLImage to do
 // IOSurface-specific sharing.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryIOSurface {
+class GPU_GLES2_EXPORT IOSurfaceImageBackingFactory {
  public:
   static sk_sp<SkPromiseImageTexture> ProduceSkiaPromiseTextureMetal(
       SharedImageBacking* backing,
       scoped_refptr<SharedContextState> context_state,
       scoped_refptr<gl::GLImage> image);
-  static std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  static std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
index 6320344..b3b7659 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -41,7 +41,7 @@
     IOSurfaceRef io_surface,
     const gfx::Size& size,
     viz::ResourceFormat format) {
-  TRACE_EVENT0("gpu", "SharedImageBackingFactoryIOSurface::CreateMetalTexture");
+  TRACE_EVENT0("gpu", "IOSurfaceImageBackingFactory::CreateMetalTexture");
   base::scoped_nsprotocol<id<MTLTexture>> mtl_texture;
   MTLPixelFormat mtl_pixel_format =
       static_cast<MTLPixelFormat>(viz::ToMTLPixelFormat(format));
@@ -83,17 +83,15 @@
 
 // Representation of a SharedImageBackingIOSurface as a Dawn Texture.
 #if BUILDFLAG(USE_DAWN)
-class SharedImageRepresentationDawnIOSurface
-    : public SharedImageRepresentationDawn {
+class DawnIOSurfaceRepresentation : public DawnImageRepresentation {
  public:
-  SharedImageRepresentationDawnIOSurface(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      MemoryTypeTracker* tracker,
-      WGPUDevice device,
-      base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
-      WGPUTextureFormat wgpu_format)
-      : SharedImageRepresentationDawn(manager, backing, tracker),
+  DawnIOSurfaceRepresentation(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker,
+                              WGPUDevice device,
+                              base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+                              WGPUTextureFormat wgpu_format)
+      : DawnImageRepresentation(manager, backing, tracker),
         io_surface_(std::move(io_surface)),
         device_(device),
         wgpu_format_(wgpu_format),
@@ -106,7 +104,7 @@
     dawn_procs_.deviceReference(device_);
   }
 
-  ~SharedImageRepresentationDawnIOSurface() override {
+  ~DawnIOSurfaceRepresentation() override {
     EndAccess();
     dawn_procs_.deviceRelease(device_);
   }
@@ -165,7 +163,7 @@
     // Wait for all the previous submitted commands to be scheduled to have
     // scheduling races between commands using the IOSurface on different APIs.
     // This is a blocking call but should be almost instant.
-    TRACE_EVENT0("gpu", "SharedImageRepresentationDawnIOSurface::EndAccess");
+    TRACE_EVENT0("gpu", "DawnIOSurfaceRepresentation::EndAccess");
     dawn::native::metal::WaitForCommandsToBeScheduled(device_);
 
     dawn_procs_.textureRelease(texture_);
@@ -186,7 +184,7 @@
 
 // static
 sk_sp<SkPromiseImageTexture>
-SharedImageBackingFactoryIOSurface::ProduceSkiaPromiseTextureMetal(
+IOSurfaceImageBackingFactory::ProduceSkiaPromiseTextureMetal(
     SharedImageBacking* backing,
     scoped_refptr<SharedContextState> context_state,
     scoped_refptr<gl::GLImage> image) {
@@ -210,15 +208,14 @@
 }
 
 // static
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingFactoryIOSurface::ProduceDawn(
-    SharedImageManager* manager,
-    SharedImageBacking* backing,
-    MemoryTypeTracker* tracker,
-    WGPUDevice device,
-    scoped_refptr<gl::GLImage> image) {
+std::unique_ptr<DawnImageRepresentation>
+IOSurfaceImageBackingFactory::ProduceDawn(SharedImageManager* manager,
+                                          SharedImageBacking* backing,
+                                          MemoryTypeTracker* tracker,
+                                          WGPUDevice device,
+                                          scoped_refptr<gl::GLImage> image) {
 #if BUILDFLAG(USE_DAWN)
-  // See comments in SharedImageBackingFactoryIOSurface::CreateSharedImage
+  // See comments in IOSurfaceImageBackingFactory::CreateSharedImage
   // regarding RGBA versus BGRA.
   viz::ResourceFormat actual_format = backing->format();
   if (actual_format == viz::RGBA_8888)
@@ -239,7 +236,7 @@
   if (wgpu_format.value() == WGPUTextureFormat_Undefined)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationDawnIOSurface>(
+  return std::make_unique<DawnIOSurfaceRepresentation>(
       manager, backing, tracker, device, io_surface, wgpu_format.value());
 #else   // BUILDFLAG(USE_DAWN)
   return nullptr;
@@ -247,7 +244,7 @@
 }
 
 // static
-bool SharedImageBackingFactoryIOSurface::InitializePixels(
+bool IOSurfaceImageBackingFactory::InitializePixels(
     SharedImageBacking* backing,
     scoped_refptr<gl::GLImage> image,
     const uint8_t* src_data) {
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
index c929fb0..681eba7 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory_unittest.cc
@@ -40,7 +40,7 @@
 namespace gpu {
 namespace {
 
-class SharedImageBackingFactoryIOSurfaceTest : public testing::Test {
+class IOSurfaceImageBackingFactoryTest : public testing::Test {
  public:
   void SetUp() override {
     surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
@@ -66,7 +66,7 @@
         base::MakeRefCounted<gles2::FeatureInfo>(workarounds, GpuFeatureInfo());
     context_state_->InitializeGL(preferences, std::move(feature_info));
 
-    backing_factory_ = std::make_unique<SharedImageBackingFactoryGLImage>(
+    backing_factory_ = std::make_unique<GLImageBackingFactory>(
         preferences, workarounds, context_state_->feature_info(),
         &image_factory_,
         /*progress_reporter=*/nullptr, /*for_shared_memory_gmbs=*/false);
@@ -83,7 +83,7 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<SharedContextState> context_state_;
-  std::unique_ptr<SharedImageBackingFactoryGLImage> backing_factory_;
+  std::unique_ptr<GLImageBackingFactory> backing_factory_;
   gles2::MailboxManagerImpl mailbox_manager_;
   SharedImageManager shared_image_manager_;
   std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
@@ -99,7 +99,7 @@
                                                           context_state_);
     ASSERT_NE(skia_representation, nullptr);
 
-    std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+    std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
         scoped_read_access =
             skia_representation->BeginScopedReadAccess(nullptr, nullptr);
     EXPECT_TRUE(scoped_read_access);
@@ -139,7 +139,7 @@
 };
 
 // Basic test to check creation and deletion of IOSurface backed shared image.
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, Basic) {
+TEST_F(IOSurfaceImageBackingFactoryTest, Basic) {
   // TODO(jonahr): Test crashes on Mac with ANGLE/passthrough
   // (crbug.com/1100980)
   gpu::GPUTestBotConfig bot_config;
@@ -187,7 +187,7 @@
   EXPECT_EQ(width, size.width());
   EXPECT_EQ(height, size.height());
 
-  // Next validate via a SharedImageRepresentationGLTexture.
+  // Next validate via a GLTextureImageRepresentation.
   std::unique_ptr<SharedImageRepresentationFactoryRef> factory_ref =
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
@@ -202,13 +202,13 @@
   EXPECT_EQ(usage, gl_representation->usage());
   gl_representation.reset();
 
-  // Finally, validate a SharedImageRepresentationSkia.
+  // Finally, validate a SkiaImageRepresentation.
   auto skia_representation = shared_image_representation_factory_->ProduceSkia(
       mailbox, context_state_);
   EXPECT_TRUE(skia_representation);
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
       scoped_write_access;
 
   scoped_write_access = skia_representation->BeginScopedWriteAccess(
@@ -222,8 +222,7 @@
   EXPECT_TRUE(end_semaphores.empty());
   scoped_write_access.reset();
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access =
       skia_representation->BeginScopedReadAccess(nullptr, nullptr);
   auto* promise_texture = scoped_read_access->promise_image_texture();
@@ -242,7 +241,7 @@
 // Test to check interaction between Gl and skia GL representations.
 // We write to a GL texture using gl representation and then read from skia
 // representation.
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, GL_SkiaGL) {
+TEST_F(IOSurfaceImageBackingFactoryTest, GL_SkiaGL) {
   // TODO(jonahr): Test crashes on Mac with ANGLE/passthrough
   // (crbug.com/1100980)
   gpu::GPUTestBotConfig bot_config;
@@ -270,7 +269,7 @@
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
 
-  // Create a SharedImageRepresentationGLTexture.
+  // Create a GLTextureImageRepresentation.
   {
     auto gl_representation =
         shared_image_representation_factory_->ProduceGLTexture(mailbox);
@@ -309,7 +308,7 @@
 
 // Test which ensures that legacy texture clear status is kept in sync with the
 // SharedImageBacking.
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, LegacyClearing) {
+TEST_F(IOSurfaceImageBackingFactoryTest, LegacyClearing) {
   Mailbox mailbox = Mailbox::GenerateForSharedImage();
   viz::ResourceFormat format = viz::ResourceFormat::RGBA_8888;
   gfx::Size size(256, 256);
@@ -372,7 +371,7 @@
 
 #if BUILDFLAG(USE_DAWN)
 // Test to check interaction between Dawn and skia GL representations.
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, Dawn_SkiaGL) {
+TEST_F(IOSurfaceImageBackingFactoryTest, Dawn_SkiaGL) {
   // Create a Dawn Metal device
   dawn::native::Instance instance;
   instance.DiscoverDefaultAdapters();
@@ -414,7 +413,7 @@
       shared_image_manager_.Register(std::move(backing),
                                      memory_type_tracker_.get());
 
-  // Create a SharedImageRepresentationDawn.
+  // Create a DawnImageRepresentation.
   auto dawn_representation = shared_image_representation_factory_->ProduceDawn(
       mailbox, device.Get(), WGPUBackendType_Metal);
   EXPECT_TRUE(dawn_representation);
@@ -462,7 +461,7 @@
 // 2. Do not call SetCleared so we can test Dawn Lazy clear
 // 3. Begin render pass in Dawn, but do not do anything
 // 4. Verify through CheckSkiaPixel that GL drawn color not seen
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, GL_Dawn_Skia_UnclearTexture) {
+TEST_F(IOSurfaceImageBackingFactoryTest, GL_Dawn_Skia_UnclearTexture) {
   // TODO(jonahr): Test crashes on Mac with ANGLE/passthrough
   // (crbug.com/1100980)
   gpu::GPUTestBotConfig bot_config;
@@ -492,13 +491,13 @@
                                      memory_type_tracker_.get());
 
   {
-    // Create a SharedImageRepresentationGLTexture.
+    // Create a GLTextureImageRepresentation.
     auto gl_representation =
         shared_image_representation_factory_->ProduceGLTexture(mailbox);
     EXPECT_TRUE(gl_representation);
     EXPECT_EQ(expected_target, gl_representation->GetTexture()->target());
 
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough::ScopedAccess>
+    std::unique_ptr<GLTexturePassthroughImageRepresentation::ScopedAccess>
         gl_scoped_access = gl_representation->BeginScopedAccess(
             GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM,
             SharedImageRepresentation::AllowUnclearedAccess::kYes);
@@ -594,7 +593,7 @@
 // 3. Texture in Dawn will stay as uninitialized
 // 3. Expect skia to fail to access the texture because texture is not
 // initialized
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, UnclearDawn_SkiaFails) {
+TEST_F(IOSurfaceImageBackingFactoryTest, UnclearDawn_SkiaFails) {
   // Create a backing using mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
   const auto format = viz::ResourceFormat::RGBA_8888;
@@ -681,7 +680,7 @@
   ASSERT_NE(skia_representation, nullptr);
 
   // Expect BeginScopedReadAccess to fail because sharedImage is uninitialized
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       scoped_read_access =
           skia_representation->BeginScopedReadAccess(nullptr, nullptr);
   EXPECT_EQ(scoped_read_access, nullptr);
@@ -689,7 +688,7 @@
 #endif  // BUILDFLAG(USE_DAWN)
 
 // Test that Skia trying to access uninitialized SharedImage will fail
-TEST_F(SharedImageBackingFactoryIOSurfaceTest, SkiaAccessFirstFails) {
+TEST_F(IOSurfaceImageBackingFactoryTest, SkiaAccessFirstFails) {
   // Create a mailbox.
   auto mailbox = Mailbox::GenerateForSharedImage();
   const auto format = viz::ResourceFormat::RGBA_8888;
@@ -713,7 +712,7 @@
   ASSERT_NE(skia_representation, nullptr);
   EXPECT_FALSE(skia_representation->IsCleared());
 
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
       scoped_read_access =
           skia_representation->BeginScopedReadAccess(nullptr, nullptr);
   // Expect BeginScopedReadAccess to fail because sharedImage is uninitialized
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
index f43723f..7340da8c 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
@@ -57,21 +57,18 @@
 
 }  // namespace
 
-class SharedImageBackingOzone::SharedImageRepresentationVaapiOzone
-    : public SharedImageRepresentationVaapi {
+class OzoneImageBacking::VaapiOzoneImageRepresentation
+    : public VaapiImageRepresentation {
  public:
-  SharedImageRepresentationVaapiOzone(SharedImageManager* manager,
-                                      SharedImageBacking* backing,
-                                      MemoryTypeTracker* tracker,
-                                      VaapiDependencies* vaapi_dependency)
-      : SharedImageRepresentationVaapi(manager,
-                                       backing,
-                                       tracker,
-                                       vaapi_dependency) {}
+  VaapiOzoneImageRepresentation(SharedImageManager* manager,
+                                SharedImageBacking* backing,
+                                MemoryTypeTracker* tracker,
+                                VaapiDependencies* vaapi_dependency)
+      : VaapiImageRepresentation(manager, backing, tracker, vaapi_dependency) {}
 
  private:
-  SharedImageBackingOzone* ozone_backing() {
-    return static_cast<SharedImageBackingOzone*>(backing());
+  OzoneImageBacking* ozone_backing() {
+    return static_cast<OzoneImageBacking*>(backing());
   }
   void EndAccess() override { ozone_backing()->has_pending_va_writes_ = true; }
   void BeginAccess() override {
@@ -81,18 +78,18 @@
   }
 };
 
-class SharedImageBackingOzone::SharedImageRepresentationOverlayOzone
-    : public SharedImageRepresentationOverlay {
+class OzoneImageBacking::OverlayOzoneImageRepresentation
+    : public OverlayImageRepresentation {
  public:
-  SharedImageRepresentationOverlayOzone(SharedImageManager* manager,
-                                        SharedImageBacking* backing,
-                                        MemoryTypeTracker* tracker)
-      : SharedImageRepresentationOverlay(manager, backing, tracker) {}
-  ~SharedImageRepresentationOverlayOzone() override = default;
+  OverlayOzoneImageRepresentation(SharedImageManager* manager,
+                                  SharedImageBacking* backing,
+                                  MemoryTypeTracker* tracker)
+      : OverlayImageRepresentation(manager, backing, tracker) {}
+  ~OverlayOzoneImageRepresentation() override = default;
 
  private:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override {
-    auto* ozone_backing = static_cast<SharedImageBackingOzone*>(backing());
+    auto* ozone_backing = static_cast<OzoneImageBacking*>(backing());
     std::vector<gfx::GpuFenceHandle> fences;
     bool need_end_fence;
     ozone_backing->BeginAccess(/*readonly=*/true, AccessStream::kOverlay,
@@ -106,7 +103,7 @@
     return true;
   }
   void EndReadAccess(gfx::GpuFenceHandle release_fence) override {
-    auto* ozone_backing = static_cast<SharedImageBackingOzone*>(backing());
+    auto* ozone_backing = static_cast<OzoneImageBacking*>(backing());
     ozone_backing->EndAccess(/*readonly=*/true, AccessStream::kOverlay,
                              std::move(release_fence));
   }
@@ -115,7 +112,7 @@
     if (!gl_image_) {
       gfx::BufferFormat buffer_format = viz::BufferFormat(format());
       auto pixmap =
-          static_cast<SharedImageBackingOzone*>(backing())->GetNativePixmap();
+          static_cast<OzoneImageBacking*>(backing())->GetNativePixmap();
       gl_image_ = base::MakeRefCounted<gl::GLImageNativePixmap>(
           pixmap->GetBufferSize(), buffer_format);
       if (backing()->color_space().IsValid())
@@ -129,78 +126,75 @@
   scoped_refptr<gl::GLImageNativePixmap> gl_image_;
 };
 
-SharedImageBackingOzone::~SharedImageBackingOzone() = default;
+OzoneImageBacking::~OzoneImageBacking() = default;
 
-SharedImageBackingType SharedImageBackingOzone::GetType() const {
+SharedImageBackingType OzoneImageBacking::GetType() const {
   return SharedImageBackingType::kOzone;
 }
 
-void SharedImageBackingOzone::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
+void OzoneImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   if (in_fence) {
     external_write_fence_ = in_fence->GetGpuFenceHandle().Clone();
   }
 }
 
-bool SharedImageBackingOzone::ProduceLegacyMailbox(
-    MailboxManager* mailbox_manager) {
+bool OzoneImageBacking::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
   NOTREACHED();
   return false;
 }
 
-scoped_refptr<gfx::NativePixmap> SharedImageBackingOzone::GetNativePixmap() {
+scoped_refptr<gfx::NativePixmap> OzoneImageBacking::GetNativePixmap() {
   return pixmap_;
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingOzone::ProduceDawn(SharedImageManager* manager,
-                                     MemoryTypeTracker* tracker,
-                                     WGPUDevice device,
-                                     WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> OzoneImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
 #if BUILDFLAG(USE_DAWN)
   DCHECK(dawn_procs_);
   WGPUTextureFormat webgpu_format = viz::ToWGPUFormat(format());
   if (webgpu_format == WGPUTextureFormat_Undefined) {
     return nullptr;
   }
-  return std::make_unique<SharedImageRepresentationDawnOzone>(
+  return std::make_unique<DawnOzoneImageRepresentation>(
       manager, this, tracker, device, webgpu_format, pixmap_, dawn_procs_);
 #else  // !BUILDFLAG(USE_DAWN)
   return nullptr;
 #endif
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingOzone::ProduceGLTexture(SharedImageManager* manager,
-                                          MemoryTypeTracker* tracker) {
-  return SharedImageRepresentationGLTextureOzone::Create(manager, this, tracker,
-                                                         pixmap_, plane_);
+std::unique_ptr<GLTextureImageRepresentation>
+OzoneImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                    MemoryTypeTracker* tracker) {
+  return GLTextureOzoneImageRepresentation::Create(manager, this, tracker,
+                                                   pixmap_, plane_);
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingOzone::ProduceGLTexturePassthrough(
-    SharedImageManager* manager,
-    MemoryTypeTracker* tracker) {
-  return SharedImageRepresentationGLTexturePassthroughOzone::Create(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+OzoneImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                               MemoryTypeTracker* tracker) {
+  return GLTexturePassthroughOzoneImageRepresentation::Create(
       manager, this, tracker, pixmap_, plane_);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingOzone::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> OzoneImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
   if (context_state->GrContextIsGL()) {
     auto gl_representation = ProduceGLTexture(manager, tracker);
     if (!gl_representation) {
-      LOG(ERROR) << "SharedImageBackingOzone::ProduceSkia failed to create GL "
+      LOG(ERROR) << "OzoneImageBacking::ProduceSkia failed to create GL "
                     "representation";
       return nullptr;
     }
-    auto skia_representation = SharedImageRepresentationSkiaGL::Create(
+    auto skia_representation = SkiaGLImageRepresentation::Create(
         std::move(gl_representation), std::move(context_state), manager, this,
         tracker);
     if (!skia_representation) {
-      LOG(ERROR) << "SharedImageBackingOzone::ProduceSkia failed to create "
+      LOG(ERROR) << "OzoneImageBacking::ProduceSkia failed to create "
                     "Skia representation";
       return nullptr;
     }
@@ -219,7 +213,7 @@
     if (!vulkan_image)
       return nullptr;
 
-    return std::make_unique<SharedImageRepresentationSkiaVkOzone>(
+    return std::make_unique<SkiaVkOzoneImageRepresentation>(
         manager, this, std::move(context_state), std::move(vulkan_image),
         tracker);
   }
@@ -227,14 +221,14 @@
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingOzone::ProduceOverlay(SharedImageManager* manager,
-                                        MemoryTypeTracker* tracker) {
-  return std::make_unique<SharedImageRepresentationOverlayOzone>(manager, this,
-                                                                 tracker);
+std::unique_ptr<OverlayImageRepresentation> OzoneImageBacking::ProduceOverlay(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  return std::make_unique<OverlayOzoneImageRepresentation>(manager, this,
+                                                           tracker);
 }
 
-SharedImageBackingOzone::SharedImageBackingOzone(
+OzoneImageBacking::OzoneImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     gfx::BufferPlane plane,
@@ -286,8 +280,7 @@
   }
 }
 
-std::unique_ptr<SharedImageRepresentationVaapi>
-SharedImageBackingOzone::ProduceVASurface(
+std::unique_ptr<VaapiImageRepresentation> OzoneImageBacking::ProduceVASurface(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     VaapiDependenciesFactory* dep_factory) {
@@ -296,22 +289,21 @@
     vaapi_deps_ = dep_factory->CreateVaapiDependencies(pixmap_);
 
   if (!vaapi_deps_) {
-    LOG(ERROR) << "SharedImageBackingOzone::ProduceVASurface failed to create "
+    LOG(ERROR) << "OzoneImageBacking::ProduceVASurface failed to create "
                   "VaapiDependencies";
     return nullptr;
   }
-  return std::make_unique<
-      SharedImageBackingOzone::SharedImageRepresentationVaapiOzone>(
+  return std::make_unique<OzoneImageBacking::VaapiOzoneImageRepresentation>(
       manager, this, tracker, vaapi_deps_.get());
 }
 
-bool SharedImageBackingOzone::VaSync() {
+bool OzoneImageBacking::VaSync() {
   if (has_pending_va_writes_)
     has_pending_va_writes_ = !vaapi_deps_->SyncSurface();
   return !has_pending_va_writes_;
 }
 
-bool SharedImageBackingOzone::UploadFromMemory(const SkPixmap& pixmap) {
+bool OzoneImageBacking::UploadFromMemory(const SkPixmap& pixmap) {
   DCHECK(!pixmap.info().isEmpty());
 
   if (context_state_->context_lost())
@@ -352,7 +344,7 @@
   return written;
 }
 
-void SharedImageBackingOzone::FlushAndSubmitIfNecessary(
+void OzoneImageBacking::FlushAndSubmitIfNecessary(
     std::vector<GrBackendSemaphore> signal_semaphores,
     SharedContextState* const shared_context_state) {
   bool sync_cpu = gpu::ShouldVulkanSyncCpuForSkiaSubmit(
@@ -373,11 +365,10 @@
   }
 }
 
-bool SharedImageBackingOzone::BeginAccess(
-    bool readonly,
-    AccessStream access_stream,
-    std::vector<gfx::GpuFenceHandle>* fences,
-    bool& need_end_fence) {
+bool OzoneImageBacking::BeginAccess(bool readonly,
+                                    AccessStream access_stream,
+                                    std::vector<gfx::GpuFenceHandle>* fences,
+                                    bool& need_end_fence) {
   // Track reads and writes if not being used for concurrent read/writes.
   if (!(usage() & SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE)) {
     if (is_write_in_progress_) {
@@ -471,9 +462,9 @@
   return true;
 }
 
-void SharedImageBackingOzone::EndAccess(bool readonly,
-                                        AccessStream access_stream,
-                                        gfx::GpuFenceHandle fence) {
+void OzoneImageBacking::EndAccess(bool readonly,
+                                  AccessStream access_stream,
+                                  gfx::GpuFenceHandle fence) {
   // Track reads and writes if not being used for concurrent read/writes.
   if (!(usage() & SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE)) {
     if (readonly) {
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing.h b/gpu/command_buffer/service/shared_image/ozone_image_backing.h
index 38bdbbf..edf9d24 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing.h
@@ -35,9 +35,9 @@
 // Implementation of SharedImageBacking that uses a NativePixmap created via
 // an Ozone surface factory. The memory associated with the pixmap can be
 // aliased by both GL and Vulkan for use in rendering or compositing.
-class SharedImageBackingOzone final : public ClearTrackingSharedImageBacking {
+class OzoneImageBacking final : public ClearTrackingSharedImageBacking {
  public:
-  SharedImageBackingOzone(
+  OzoneImageBacking(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       gfx::BufferPlane plane,
@@ -51,10 +51,10 @@
       scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs,
       const GpuDriverBugWorkarounds& workarounds);
 
-  SharedImageBackingOzone(const SharedImageBackingOzone&) = delete;
-  SharedImageBackingOzone& operator=(const SharedImageBackingOzone&) = delete;
+  OzoneImageBacking(const OzoneImageBacking&) = delete;
+  OzoneImageBacking& operator=(const OzoneImageBacking&) = delete;
 
-  ~SharedImageBackingOzone() override;
+  ~OzoneImageBacking() override;
 
   // gpu::SharedImageBacking:
   SharedImageBackingType GetType() const override;
@@ -66,35 +66,35 @@
   enum class AccessStream { kGL, kVulkan, kWebGPU, kOverlay, kLast };
 
  protected:
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) override;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
+  std::unique_ptr<VaapiImageRepresentation> ProduceVASurface(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       VaapiDependenciesFactory* dep_factory) override;
 
  private:
-  friend class SharedImageRepresentationGLOzoneShared;
-  friend class SharedImageRepresentationDawnOzone;
-  friend class SharedImageRepresentationSkiaVkOzone;
-  class SharedImageRepresentationVaapiOzone;
-  class SharedImageRepresentationOverlayOzone;
+  friend class GLOzoneImageRepresentationShared;
+  friend class DawnOzoneImageRepresentation;
+  friend class SkiaVkOzoneImageRepresentation;
+  class VaapiOzoneImageRepresentation;
+  class OverlayOzoneImageRepresentation;
 
   bool VaSync();
 
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
index 3d0b6d5..2181049 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
@@ -43,7 +43,7 @@
 
 }  // namespace
 
-SharedImageBackingFactoryOzone::SharedImageBackingFactoryOzone(
+OzoneImageBackingFactory::OzoneImageBackingFactory(
     SharedContextState* shared_context_state,
     const GpuDriverBugWorkarounds& workarounds)
     : shared_context_state_(shared_context_state), workarounds_(workarounds) {
@@ -53,10 +53,10 @@
 #endif  // BUILDFLAG(USE_DAWN)
 }
 
-SharedImageBackingFactoryOzone::~SharedImageBackingFactoryOzone() = default;
+OzoneImageBackingFactory::~OzoneImageBackingFactory() = default;
 
-std::unique_ptr<SharedImageBackingOzone>
-SharedImageBackingFactoryOzone::CreateSharedImageInternal(
+std::unique_ptr<OzoneImageBacking>
+OzoneImageBackingFactory::CreateSharedImageInternal(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -87,14 +87,13 @@
     DLOG(ERROR) << "Failed to create native pixmap";
     return nullptr;
   }
-  return std::make_unique<SharedImageBackingOzone>(
+  return std::make_unique<OzoneImageBacking>(
       mailbox, format, gfx::BufferPlane::DEFAULT, size, color_space,
       surface_origin, alpha_type, usage, shared_context_state_.get(),
       std::move(pixmap), dawn_procs_, workarounds_);
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryOzone::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> OzoneImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -110,8 +109,7 @@
                                    usage);
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryOzone::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> OzoneImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -139,8 +137,7 @@
   return backing;
 }
 
-std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryOzone::CreateSharedImage(
+std::unique_ptr<SharedImageBacking> OzoneImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -167,7 +164,7 @@
   const gfx::Size plane_size = gpu::GetPlaneSize(plane, size);
   const viz::ResourceFormat plane_format =
       viz::GetResourceFormat(GetPlaneBufferFormat(plane, buffer_format));
-  auto backing = std::make_unique<SharedImageBackingOzone>(
+  auto backing = std::make_unique<OzoneImageBacking>(
       mailbox, plane_format, plane, plane_size, color_space, surface_origin,
       alpha_type, usage, shared_context_state_.get(), std::move(pixmap),
       dawn_procs_, workarounds_);
@@ -176,14 +173,13 @@
   return backing;
 }
 
-bool SharedImageBackingFactoryOzone::IsSupported(
-    uint32_t usage,
-    viz::ResourceFormat format,
-    bool thread_safe,
-    gfx::GpuMemoryBufferType gmb_type,
-    GrContextType gr_context_type,
-    bool* allow_legacy_mailbox,
-    bool is_pixel_used) {
+bool OzoneImageBackingFactory::IsSupported(uint32_t usage,
+                                           viz::ResourceFormat format,
+                                           bool thread_safe,
+                                           gfx::GpuMemoryBufferType gmb_type,
+                                           GrContextType gr_context_type,
+                                           bool* allow_legacy_mailbox,
+                                           bool is_pixel_used) {
   if (gmb_type != gfx::EMPTY_BUFFER && gmb_type != gfx::NATIVE_PIXMAP) {
     return false;
   }
@@ -211,9 +207,9 @@
 #if BUILDFLAG(IS_FUCHSIA)
   DCHECK_EQ(gr_context_type, GrContextType::kVulkan);
 
-  // For now just use SharedImageBackingOzone for primary plane buffers.
+  // For now just use OzoneImageBacking for primary plane buffers.
   // TODO(crbug.com/1310026): When Vulkan/GL interop is supported on Fuchsia
-  // SharedImageBackingOzone should be used for all scanout buffers.
+  // OzoneImageBacking should be used for all scanout buffers.
   constexpr uint32_t kPrimaryPlaneUsageFlags = SHARED_IMAGE_USAGE_DISPLAY |
                                                SHARED_IMAGE_USAGE_SCANOUT |
                                                SHARED_IMAGE_USAGE_RASTER;
@@ -226,7 +222,7 @@
   return true;
 }
 
-bool SharedImageBackingFactoryOzone::CanImportNativePixmapToVulkan() {
+bool OzoneImageBackingFactory::CanImportNativePixmapToVulkan() {
   if (!shared_context_state_->vk_context_provider()) {
     return false;
   }
@@ -237,7 +233,7 @@
       ->CanImportGpuMemoryBuffer(vk_device, gfx::NATIVE_PIXMAP);
 }
 
-bool SharedImageBackingFactoryOzone::CanImportNativePixmapToWebGPU() {
+bool OzoneImageBackingFactory::CanImportNativePixmapToWebGPU() {
   // Assume that if skia/vulkan vkDevice supports the Vulkan extensions
   // (external_memory_dma_buf, image_drm_format_modifier), then Dawn/WebGPU also
   // support the extensions until there is capability to check the extensions
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
index 630e00a..dd40a6c 100644
--- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h
@@ -20,14 +20,13 @@
 
 // Implementation of SharedImageBackingFactory that produces NativePixmap
 // backed SharedImages.
-class GPU_GLES2_EXPORT SharedImageBackingFactoryOzone
+class GPU_GLES2_EXPORT OzoneImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  explicit SharedImageBackingFactoryOzone(
-      SharedContextState* shared_context_state,
-      const GpuDriverBugWorkarounds& workarounds);
+  explicit OzoneImageBackingFactory(SharedContextState* shared_context_state,
+                                    const GpuDriverBugWorkarounds& workarounds);
 
-  ~SharedImageBackingFactoryOzone() override;
+  ~OzoneImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
@@ -80,7 +79,7 @@
   scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_;
   const GpuDriverBugWorkarounds workarounds_;
 
-  std::unique_ptr<SharedImageBackingOzone> CreateSharedImageInternal(
+  std::unique_ptr<OzoneImageBacking> CreateSharedImageInternal(
       const Mailbox& mailbox,
       viz::ResourceFormat format,
       SurfaceHandle surface_handle,
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
index fcb8bb7..640f1f0 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.cc
@@ -29,14 +29,14 @@
 
 }  // namespace
 
-class SharedImageBackingRawDraw::RepresentationRaster
-    : public SharedImageRepresentationRaster {
+class RawDrawImageBacking::RasterRawDrawImageRepresentation
+    : public RasterImageRepresentation {
  public:
-  RepresentationRaster(SharedImageManager* manager,
-                       SharedImageBacking* backing,
-                       MemoryTypeTracker* tracker)
-      : SharedImageRepresentationRaster(manager, backing, tracker) {}
-  ~RepresentationRaster() override = default;
+  RasterRawDrawImageRepresentation(SharedImageManager* manager,
+                                   SharedImageBacking* backing,
+                                   MemoryTypeTracker* tracker)
+      : RasterImageRepresentation(manager, backing, tracker) {}
+  ~RasterRawDrawImageRepresentation() override = default;
 
   cc::PaintOpBuffer* BeginWriteAccess(
       scoped_refptr<SharedContextState> context_state,
@@ -61,18 +61,18 @@
   void EndReadAccess() override { raw_draw_backing()->EndReadAccess(); }
 
  private:
-  SharedImageBackingRawDraw* raw_draw_backing() {
-    return static_cast<SharedImageBackingRawDraw*>(backing());
+  RawDrawImageBacking* raw_draw_backing() {
+    return static_cast<RawDrawImageBacking*>(backing());
   }
 };
 
-class SharedImageBackingRawDraw::RepresentationSkia
-    : public SharedImageRepresentationSkia {
+class RawDrawImageBacking::SkiaRawDrawImageRepresentation
+    : public SkiaImageRepresentation {
  public:
-  RepresentationSkia(SharedImageManager* manager,
-                     SharedImageBacking* backing,
-                     MemoryTypeTracker* tracker)
-      : SharedImageRepresentationSkia(manager, backing, tracker) {}
+  SkiaRawDrawImageRepresentation(SharedImageManager* manager,
+                                 SharedImageBacking* backing,
+                                 MemoryTypeTracker* tracker)
+      : SkiaImageRepresentation(manager, backing, tracker) {}
 
   bool SupportsMultipleConcurrentReadAccess() override { return true; }
 
@@ -96,19 +96,18 @@
   void EndReadAccess() override { raw_draw_backing()->EndReadAccess(); }
 
  private:
-  SharedImageBackingRawDraw* raw_draw_backing() {
-    return static_cast<SharedImageBackingRawDraw*>(backing());
+  RawDrawImageBacking* raw_draw_backing() {
+    return static_cast<RawDrawImageBacking*>(backing());
   }
 };
 
-SharedImageBackingRawDraw::SharedImageBackingRawDraw(
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage)
+RawDrawImageBacking::RawDrawImageBacking(const Mailbox& mailbox,
+                                         viz::ResourceFormat format,
+                                         const gfx::Size& size,
+                                         const gfx::ColorSpace& color_space,
+                                         GrSurfaceOrigin surface_origin,
+                                         SkAlphaType alpha_type,
+                                         uint32_t usage)
     : ClearTrackingSharedImageBacking(mailbox,
                                       format,
                                       size,
@@ -119,7 +118,7 @@
                                       /*estimated_size=*/0,
                                       /*is_thread_safe=*/true) {}
 
-SharedImageBackingRawDraw::~SharedImageBackingRawDraw() {
+RawDrawImageBacking::~RawDrawImageBacking() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
   DCHECK_EQ(read_count_, 0);
@@ -128,22 +127,21 @@
   DestroyBackendTexture();
 }
 
-SharedImageBackingType SharedImageBackingRawDraw::GetType() const {
+SharedImageBackingType RawDrawImageBacking::GetType() const {
   return SharedImageBackingType::kRawDraw;
 }
 
-bool SharedImageBackingRawDraw::ProduceLegacyMailbox(
+bool RawDrawImageBacking::ProduceLegacyMailbox(
     MailboxManager* mailbox_manager) {
   NOTIMPLEMENTED();
   return false;
 }
 
-void SharedImageBackingRawDraw::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {
+void RawDrawImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   NOTIMPLEMENTED();
 }
 
-void SharedImageBackingRawDraw::OnMemoryDump(
+void RawDrawImageBacking::OnMemoryDump(
     const std::string& dump_name,
     base::trace_event::MemoryAllocatorDump* dump,
     base::trace_event::ProcessMemoryDump* pmd,
@@ -171,14 +169,14 @@
   }
 }
 
-std::unique_ptr<SharedImageRepresentationRaster>
-SharedImageBackingRawDraw::ProduceRaster(SharedImageManager* manager,
-                                         MemoryTypeTracker* tracker) {
-  return std::make_unique<RepresentationRaster>(manager, this, tracker);
+std::unique_ptr<RasterImageRepresentation> RawDrawImageBacking::ProduceRaster(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  return std::make_unique<RasterRawDrawImageRepresentation>(manager, this,
+                                                            tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingRawDraw::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> RawDrawImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -186,10 +184,11 @@
   if (!context_state_)
     context_state_ = context_state;
   DCHECK(context_state_ == context_state);
-  return std::make_unique<RepresentationSkia>(manager, this, tracker);
+  return std::make_unique<SkiaRawDrawImageRepresentation>(manager, this,
+                                                          tracker);
 }
 
-void SharedImageBackingRawDraw::ResetPaintOpBuffer() {
+void RawDrawImageBacking::ResetPaintOpBuffer() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (!paint_op_buffer_) {
     DCHECK(!clear_color_);
@@ -206,8 +205,7 @@
     std::move(paint_op_release_callback_).Run();
 }
 
-bool SharedImageBackingRawDraw::CreateBackendTextureAndFlushPaintOps(
-    bool flush) {
+bool RawDrawImageBacking::CreateBackendTextureAndFlushPaintOps(bool flush) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!backend_texture_.isValid());
   DCHECK(!promise_texture_);
@@ -262,7 +260,7 @@
   return true;
 }
 
-void SharedImageBackingRawDraw::DestroyBackendTexture() {
+void RawDrawImageBacking::DestroyBackendTexture() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (backend_texture_.isValid()) {
     DCHECK(context_state_);
@@ -272,7 +270,7 @@
   }
 }
 
-cc::PaintOpBuffer* SharedImageBackingRawDraw::BeginRasterWriteAccess(
+cc::PaintOpBuffer* RawDrawImageBacking::BeginRasterWriteAccess(
     scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
@@ -310,8 +308,7 @@
   return paint_op_buffer_.get();
 }
 
-void SharedImageBackingRawDraw::EndRasterWriteAccess(
-    base::OnceClosure callback) {
+void RawDrawImageBacking::EndRasterWriteAccess(base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
   DCHECK_EQ(read_count_, 0);
@@ -340,7 +337,7 @@
   }
 }
 
-cc::PaintOpBuffer* SharedImageBackingRawDraw::BeginRasterReadAccess(
+cc::PaintOpBuffer* RawDrawImageBacking::BeginRasterReadAccess(
     absl::optional<SkColor4f>& clear_color) {
   // paint ops will be read on compositor thread, so do not check thread with
   // DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -377,7 +374,7 @@
   return paint_op_buffer_.get();
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageBackingRawDraw::BeginSkiaReadAccess() {
+sk_sp<SkPromiseImageTexture> RawDrawImageBacking::BeginSkiaReadAccess() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
   if (!backend_texture_.isValid() &&
@@ -389,7 +386,7 @@
   return promise_texture_;
 }
 
-void SharedImageBackingRawDraw::EndReadAccess() {
+void RawDrawImageBacking::EndReadAccess() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   AutoLock auto_lock(this);
   DCHECK_GE(read_count_, 0);
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
index 06ebbdc..1cb6998a 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing.h
@@ -21,16 +21,16 @@
 
 namespace gpu {
 
-class SharedImageBackingRawDraw : public ClearTrackingSharedImageBacking {
+class RawDrawImageBacking : public ClearTrackingSharedImageBacking {
  public:
-  SharedImageBackingRawDraw(const Mailbox& mailbox,
-                            viz::ResourceFormat format,
-                            const gfx::Size& size,
-                            const gfx::ColorSpace& color_space,
-                            GrSurfaceOrigin surface_origin,
-                            SkAlphaType alpha_type,
-                            uint32_t usage);
-  ~SharedImageBackingRawDraw() override;
+  RawDrawImageBacking(const Mailbox& mailbox,
+                      viz::ResourceFormat format,
+                      const gfx::Size& size,
+                      const gfx::ColorSpace& color_space,
+                      GrSurfaceOrigin surface_origin,
+                      SkAlphaType alpha_type,
+                      uint32_t usage);
+  ~RawDrawImageBacking() override;
 
   // SharedImageBacking implementation.
   SharedImageBackingType GetType() const override;
@@ -42,17 +42,17 @@
                     uint64_t client_tracing_id) override;
 
  protected:
-  std::unique_ptr<SharedImageRepresentationRaster> ProduceRaster(
+  std::unique_ptr<RasterImageRepresentation> ProduceRaster(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
  private:
-  class RepresentationRaster;
-  class RepresentationSkia;
+  class RasterRawDrawImageRepresentation;
+  class SkiaRawDrawImageRepresentation;
 
   void ResetPaintOpBuffer() EXCLUSIVE_LOCKS_REQUIRED(lock_);
   bool CreateBackendTextureAndFlushPaintOps(bool flush)
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.cc
index fef4e2c..17fb0f9 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.cc
@@ -10,12 +10,12 @@
 
 namespace gpu {
 
-SharedImageBackingFactoryRawDraw::SharedImageBackingFactoryRawDraw() = default;
+RawDrawImageBackingFactory::RawDrawImageBackingFactory() = default;
 
-SharedImageBackingFactoryRawDraw::~SharedImageBackingFactoryRawDraw() = default;
+RawDrawImageBackingFactory::~RawDrawImageBackingFactory() = default;
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryRawDraw::CreateSharedImage(
+RawDrawImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -26,13 +26,13 @@
     uint32_t usage,
     bool is_thread_safe) {
   DCHECK(is_thread_safe);
-  auto texture = std::make_unique<SharedImageBackingRawDraw>(
+  auto texture = std::make_unique<RawDrawImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage);
   return texture;
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryRawDraw::CreateSharedImage(
+RawDrawImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -46,7 +46,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactoryRawDraw::CreateSharedImage(
+RawDrawImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -62,27 +62,26 @@
   return nullptr;
 }
 
-bool SharedImageBackingFactoryRawDraw::CanUseRawDrawBacking(
+bool RawDrawImageBackingFactory::CanUseRawDrawImageBacking(
     uint32_t usage,
     GrContextType gr_context_type) const {
   // Ignore for mipmap usage.
   usage &= ~SHARED_IMAGE_USAGE_MIPMAP;
 
-  auto kRawDrawBackingUsage =
+  auto kRawDrawImageBackingUsage =
       SHARED_IMAGE_USAGE_DISPLAY | SHARED_IMAGE_USAGE_RASTER |
       SHARED_IMAGE_USAGE_OOP_RASTERIZATION | SHARED_IMAGE_USAGE_RAW_DRAW;
-  return usage == kRawDrawBackingUsage;
+  return usage == kRawDrawImageBackingUsage;
 }
 
-bool SharedImageBackingFactoryRawDraw::IsSupported(
-    uint32_t usage,
-    viz::ResourceFormat format,
-    bool thread_safe,
-    gfx::GpuMemoryBufferType gmb_type,
-    GrContextType gr_context_type,
-    bool* allow_legacy_mailbox,
-    bool is_pixel_used) {
-  if (!CanUseRawDrawBacking(usage, gr_context_type)) {
+bool RawDrawImageBackingFactory::IsSupported(uint32_t usage,
+                                             viz::ResourceFormat format,
+                                             bool thread_safe,
+                                             gfx::GpuMemoryBufferType gmb_type,
+                                             GrContextType gr_context_type,
+                                             bool* allow_legacy_mailbox,
+                                             bool is_pixel_used) {
+  if (!CanUseRawDrawImageBacking(usage, gr_context_type)) {
     return false;
   }
 
diff --git a/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.h b/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.h
index 5b85f1e..40f95bf 100644
--- a/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/raw_draw_image_backing_factory.h
@@ -11,10 +11,10 @@
 
 namespace gpu {
 
-class SharedImageBackingFactoryRawDraw : public SharedImageBackingFactory {
+class RawDrawImageBackingFactory : public SharedImageBackingFactory {
  public:
-  SharedImageBackingFactoryRawDraw();
-  ~SharedImageBackingFactoryRawDraw() override;
+  RawDrawImageBackingFactory();
+  ~RawDrawImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation:
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
@@ -57,8 +57,8 @@
                    bool is_pixel_used) override;
 
  private:
-  bool CanUseRawDrawBacking(uint32_t usage,
-                            GrContextType gr_context_type) const;
+  bool CanUseRawDrawImageBacking(uint32_t usage,
+                                 GrContextType gr_context_type) const;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
index 18fffc2..db0f6d51 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
@@ -19,33 +19,33 @@
 const char* BackingTypeToString(SharedImageBackingType type) {
   switch (type) {
     case SharedImageBackingType::kTest:
-      return "TestBacking";
+      return "TestImageBacking";
     case SharedImageBackingType::kExternalVkImage:
       return "ExternalVkImageBacking";
     case SharedImageBackingType::kD3D:
-      return "SharedImageBackingD3D";
-    case SharedImageBackingType::kEglImage:
-      return "SharedImageBackingEglImage";
-    case SharedImageBackingType::kAHB:
-      return "SharedImageBackingAHB";
+      return "D3DImageBacking";
+    case SharedImageBackingType::kEGLImage:
+      return "EGLImageBacking";
+    case SharedImageBackingType::kAHardwareBuffer:
+      return "AHardwareBufferImageBacking";
     case SharedImageBackingType::kAngleVulkan:
-      return "AngleVulkanBacking";
+      return "AngleVulkanImageBacking";
     case SharedImageBackingType::kGLImage:
-      return "SharedImageBackingGLImage";
+      return "GLImageBacking";
     case SharedImageBackingType::kGLTexture:
-      return "SharedImageBackingGLTexture";
+      return "GLTextureImageBacking";
     case SharedImageBackingType::kOzone:
-      return "SharedImageBackingOzone";
+      return "OzoneImageBacking";
     case SharedImageBackingType::kRawDraw:
-      return "SharedImageBackingRawDraw";
+      return "RawDrawImageBacking";
     case SharedImageBackingType::kSharedMemory:
-      return "SharedImageBackingSharedMemory";
+      return "SharedMemoryImageBacking";
     case SharedImageBackingType::kVideo:
       return "SharedImageVideo";
     case SharedImageBackingType::kWrappedSkImage:
       return "WrappedSkImage";
     case SharedImageBackingType::kCompound:
-      return "SharedImageBackingCompound";
+      return "CompoundImageBacking";
   }
   NOTREACHED();
 };
@@ -111,32 +111,32 @@
   NOTIMPLEMENTED();
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageBacking::ProduceGLTexture(SharedImageManager* manager,
                                      MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageBacking::ProduceRGBEmulationGLTexture(SharedImageManager* manager,
                                                  MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
 SharedImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
                                                 MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationSkia> SharedImageBacking::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> SharedImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationDawn> SharedImageBacking::ProduceDawn(
+std::unique_ptr<DawnImageRepresentation> SharedImageBacking::ProduceDawn(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     WGPUDevice device,
@@ -144,33 +144,33 @@
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBacking::ProduceOverlay(SharedImageManager* manager,
-                                   MemoryTypeTracker* tracker) {
+std::unique_ptr<OverlayImageRepresentation> SharedImageBacking::ProduceOverlay(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationVaapi>
-SharedImageBacking::ProduceVASurface(SharedImageManager* manager,
-                                     MemoryTypeTracker* tracker,
-                                     VaapiDependenciesFactory* dep_factory) {
+std::unique_ptr<VaapiImageRepresentation> SharedImageBacking::ProduceVASurface(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    VaapiDependenciesFactory* dep_factory) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationMemory>
-SharedImageBacking::ProduceMemory(SharedImageManager* manager,
-                                  MemoryTypeTracker* tracker) {
+std::unique_ptr<MemoryImageRepresentation> SharedImageBacking::ProduceMemory(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationRaster>
-SharedImageBacking::ProduceRaster(SharedImageManager* manager,
-                                  MemoryTypeTracker* tracker) {
+std::unique_ptr<RasterImageRepresentation> SharedImageBacking::ProduceRaster(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
   return nullptr;
 }
 
 #if BUILDFLAG(IS_ANDROID)
-std::unique_ptr<SharedImageRepresentationLegacyOverlay>
+std::unique_ptr<LegacyOverlayImageRepresentation>
 SharedImageBacking::ProduceLegacyOverlay(SharedImageManager* manager,
                                          MemoryTypeTracker* tracker) {
   return nullptr;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.h b/gpu/command_buffer/service/shared_image/shared_image_backing.h
index 91e567c1..ce81623 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_backing.h
@@ -43,15 +43,15 @@
 class SharedContextState;
 class SharedImageManager;
 class SharedImageRepresentation;
-class SharedImageRepresentationGLTexture;
-class SharedImageRepresentationGLTexturePassthrough;
-class SharedImageRepresentationSkia;
-class SharedImageRepresentationDawn;
-class SharedImageRepresentationLegacyOverlay;
-class SharedImageRepresentationOverlay;
-class SharedImageRepresentationMemory;
-class SharedImageRepresentationVaapi;
-class SharedImageRepresentationRaster;
+class GLTextureImageRepresentation;
+class GLTexturePassthroughImageRepresentation;
+class SkiaImageRepresentation;
+class DawnImageRepresentation;
+class LegacyOverlayImageRepresentation;
+class OverlayImageRepresentation;
+class MemoryImageRepresentation;
+class VaapiImageRepresentation;
+class RasterImageRepresentation;
 class MemoryTypeTracker;
 class SharedImageFactory;
 class VaapiDependenciesFactory;
@@ -60,8 +60,8 @@
   kTest = 0,
   kExternalVkImage = 1,
   kD3D = 2,
-  kEglImage = 3,
-  kAHB = 4,
+  kEGLImage = 3,
+  kAHardwareBuffer = 4,
   kAngleVulkan = 5,
   kGLImage = 6,
   kGLTexture = 7,
@@ -179,48 +179,48 @@
  protected:
   // Used by SharedImageManager.
   friend class SharedImageManager;
-  friend class SharedImageBackingCompound;
+  friend class CompoundImageBacking;
 
-  virtual std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  virtual std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker);
-  virtual std::unique_ptr<SharedImageRepresentationGLTexture>
+  virtual std::unique_ptr<GLTextureImageRepresentation>
   ProduceRGBEmulationGLTexture(SharedImageManager* manager,
                                MemoryTypeTracker* tracker);
-  virtual std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  virtual std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker);
-  virtual std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  virtual std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state);
-  virtual std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  virtual std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type);
-  virtual std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  virtual std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker);
-  virtual std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
+  virtual std::unique_ptr<VaapiImageRepresentation> ProduceVASurface(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       VaapiDependenciesFactory* dep_factory);
-  virtual std::unique_ptr<SharedImageRepresentationMemory> ProduceMemory(
+  virtual std::unique_ptr<MemoryImageRepresentation> ProduceMemory(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker);
-  virtual std::unique_ptr<SharedImageRepresentationRaster> ProduceRaster(
+  virtual std::unique_ptr<RasterImageRepresentation> ProduceRaster(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker);
 #if BUILDFLAG(IS_ANDROID)
-  virtual std::unique_ptr<SharedImageRepresentationLegacyOverlay>
+  virtual std::unique_ptr<LegacyOverlayImageRepresentation>
   ProduceLegacyOverlay(SharedImageManager* manager, MemoryTypeTracker* tracker);
 #endif
 
   // Used by subclasses during destruction.
   bool have_context() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
-  // Used by SharedImageBackingFactoryGLTexture to get register factory.
+  // Used by GLTextureImageBackingFactory to get register factory.
   SharedImageFactory* factory() {
     DCHECK_CALLED_ON_VALID_THREAD(factory_thread_checker_);
     return factory_;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
index 2a5a337..01473b3 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -102,7 +102,7 @@
 
 #endif  // defined(USE_OZONE) && BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)
 
-bool ShouldUseOzoneFactory() {
+bool ShouldUseOzoneImageBackingFactory() {
 #if defined(USE_OZONE)
   return ui::OzonePlatform::GetInstance()
       ->GetPlatformRuntimeProperties()
@@ -262,7 +262,7 @@
   }
 
   if (!set_dmabuf_supported_metric_) {
-    bool pixmap_supported = ShouldUseOzoneFactory();
+    bool pixmap_supported = ShouldUseOzoneImageBackingFactory();
     bool vulkan_ext_supported = false;
     GLExtType gl_ext_type = GLExtType::kNone;
 
@@ -303,17 +303,17 @@
   }
 
   auto shared_memory_backing_factory =
-      std::make_unique<SharedImageBackingFactorySharedMemory>();
+      std::make_unique<SharedMemoryImageBackingFactory>();
   factories_.push_back(std::move(shared_memory_backing_factory));
 
   if (context_state) {
     auto wrapped_sk_image_factory =
-        std::make_unique<raster::WrappedSkImageFactory>(context_state);
+        std::make_unique<WrappedSkImageBackingFactory>(context_state);
     factories_.push_back(std::move(wrapped_sk_image_factory));
   }
 
   if (features::IsUsingRawDraw() && context_state) {
-    auto factory = std::make_unique<SharedImageBackingFactoryRawDraw>();
+    auto factory = std::make_unique<RawDrawImageBackingFactory>();
     factories_.push_back(std::move(factory));
   }
 
@@ -322,7 +322,7 @@
       (!is_for_display_compositor_ || gr_context_type_ == GrContextType::kGL);
   if (use_gl) {
     auto gl_texture_backing_factory =
-        std::make_unique<SharedImageBackingFactoryGLTexture>(
+        std::make_unique<GLTextureImageBackingFactory>(
             gpu_preferences, workarounds, feature_info.get(),
             shared_context_state_ ? shared_context_state_->progress_reporter()
                                   : nullptr);
@@ -330,10 +330,9 @@
   }
 
 #if BUILDFLAG(IS_WIN)
-  if (SharedImageBackingFactoryD3D::IsD3DSharedImageSupported(
-          gpu_preferences)) {
+  if (D3DImageBackingFactory::IsD3DSharedImageSupported(gpu_preferences)) {
     // TODO(sunnyps): Should we get the device from SharedContextState instead?
-    auto d3d_factory = std::make_unique<SharedImageBackingFactoryD3D>(
+    auto d3d_factory = std::make_unique<D3DImageBackingFactory>(
         gl::QueryD3D11DeviceObjectFromANGLE(),
         shared_image_manager_->dxgi_shared_handle_manager());
     d3d_backing_factory_ = d3d_factory.get();
@@ -343,12 +342,11 @@
 
 #if !BUILDFLAG(IS_ANDROID)
   if (use_gl) {
-    auto gl_image_backing_factory =
-        std::make_unique<SharedImageBackingFactoryGLImage>(
-            gpu_preferences, workarounds, feature_info.get(), image_factory,
-            shared_context_state_ ? shared_context_state_->progress_reporter()
-                                  : nullptr,
-            /*for_shared_memory_gmbs=*/true);
+    auto gl_image_backing_factory = std::make_unique<GLImageBackingFactory>(
+        gpu_preferences, workarounds, feature_info.get(), image_factory,
+        shared_context_state_ ? shared_context_state_->progress_reporter()
+                              : nullptr,
+        /*for_shared_memory_gmbs=*/true);
     factories_.push_back(std::move(gl_image_backing_factory));
   }
 #endif
@@ -358,7 +356,7 @@
   // backing will be used for interop.
   if ((gr_context_type_ == GrContextType::kVulkan) &&
       (base::FeatureList::IsEnabled(features::kVulkanFromANGLE))) {
-    auto factory = std::make_unique<SharedImageBackingFactoryAngleVulkan>(
+    auto factory = std::make_unique<AngleVulkanImageBackingFactory>(
         gpu_preferences, workarounds, context_state);
     factories_.push_back(std::move(factory));
   }
@@ -367,12 +365,12 @@
 #if BUILDFLAG(IS_WIN)
   if (gr_context_type_ == GrContextType::kVulkan) {
     auto external_vk_image_factory =
-        std::make_unique<ExternalVkImageFactory>(context_state);
+        std::make_unique<ExternalVkImageBackingFactory>(context_state);
     factories_.push_back(std::move(external_vk_image_factory));
   }
 #elif BUILDFLAG(IS_ANDROID)
   if (use_gl) {
-    auto egl_backing_factory = std::make_unique<SharedImageBackingFactoryEGL>(
+    auto egl_backing_factory = std::make_unique<EGLImageBackingFactory>(
         gpu_preferences, workarounds, feature_info.get());
     factories_.push_back(std::move(egl_backing_factory));
   }
@@ -389,43 +387,44 @@
             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
   }
   if (is_ahb_supported) {
-    auto ahb_factory =
-        std::make_unique<SharedImageBackingFactoryAHB>(feature_info.get());
+    auto ahb_factory = std::make_unique<AHardwareBufferImageBackingFactory>(
+        feature_info.get());
     factories_.push_back(std::move(ahb_factory));
   }
   if (gr_context_type_ == GrContextType::kVulkan &&
       !base::FeatureList::IsEnabled(features::kVulkanFromANGLE)) {
     auto external_vk_image_factory =
-        std::make_unique<ExternalVkImageFactory>(context_state);
+        std::make_unique<ExternalVkImageBackingFactory>(context_state);
     factories_.push_back(std::move(external_vk_image_factory));
   }
 #elif defined(USE_OZONE)
 #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)
   // Desktop Linux, not ChromeOS.
-  if (ShouldUseOzoneFactory()) {
-    auto ozone_factory = std::make_unique<SharedImageBackingFactoryOzone>(
-        context_state, workarounds);
+  if (ShouldUseOzoneImageBackingFactory()) {
+    auto ozone_factory =
+        std::make_unique<OzoneImageBackingFactory>(context_state, workarounds);
     factories_.push_back(std::move(ozone_factory));
   }
   if (gr_context_type_ == GrContextType::kVulkan &&
-      (!ShouldUseOzoneFactory() || ShouldUseExternalVulkanImageFactory())) {
+      (!ShouldUseOzoneImageBackingFactory() ||
+       ShouldUseExternalVulkanImageFactory())) {
     auto external_vk_image_factory =
-        std::make_unique<ExternalVkImageFactory>(context_state);
+        std::make_unique<ExternalVkImageBackingFactory>(context_state);
     factories_.push_back(std::move(external_vk_image_factory));
   }
 #elif BUILDFLAG(IS_FUCHSIA)
   if (gr_context_type_ == GrContextType::kVulkan) {
-    auto ozone_factory = std::make_unique<SharedImageBackingFactoryOzone>(
-        context_state, workarounds);
+    auto ozone_factory =
+        std::make_unique<OzoneImageBackingFactory>(context_state, workarounds);
     factories_.push_back(std::move(ozone_factory));
     auto external_vk_image_factory =
-        std::make_unique<ExternalVkImageFactory>(context_state);
+        std::make_unique<ExternalVkImageBackingFactory>(context_state);
     factories_.push_back(std::move(external_vk_image_factory));
   }
   vulkan_context_provider_ = context_state->vk_context_provider();
 #elif BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
-  auto ozone_factory = std::make_unique<SharedImageBackingFactoryOzone>(
-      context_state, workarounds);
+  auto ozone_factory =
+      std::make_unique<OzoneImageBackingFactory>(context_state, workarounds);
   factories_.push_back(std::move(ozone_factory));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #endif  // defined(USE_OZONE)
@@ -434,12 +433,11 @@
   // TODO(hitawala): Temporary factory that will be replaced with Ozone and
   // other backings
   if (use_gl) {
-    auto gl_image_backing_factory =
-        std::make_unique<SharedImageBackingFactoryGLImage>(
-            gpu_preferences, workarounds, feature_info.get(), image_factory,
-            shared_context_state_ ? shared_context_state_->progress_reporter()
-                                  : nullptr,
-            /*for_shared_memory_gmbs=*/false);
+    auto gl_image_backing_factory = std::make_unique<GLImageBackingFactory>(
+        gpu_preferences, workarounds, feature_info.get(), image_factory,
+        shared_context_state_ ? shared_context_state_->progress_reporter()
+                              : nullptr,
+        /*for_shared_memory_gmbs=*/false);
     factories_.push_back(std::move(gl_image_backing_factory));
   }
 #endif
@@ -541,7 +539,7 @@
 
   std::unique_ptr<SharedImageBacking> backing;
   if (use_compound) {
-    backing = SharedImageBackingCompound::CreateSharedMemory(
+    backing = CompoundImageBacking::CreateSharedMemory(
         factory, mailbox, std::move(handle), format, plane, surface_handle,
         size, color_space, surface_origin, alpha_type, usage);
   } else {
@@ -605,7 +603,7 @@
                                          GrSurfaceOrigin surface_origin,
                                          SkAlphaType alpha_type,
                                          uint32_t usage) {
-  if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+  if (!D3DImageBackingFactory::IsSwapChainSupported())
     return false;
 
   bool allow_legacy_mailbox = true;
@@ -618,7 +616,7 @@
 }
 
 bool SharedImageFactory::PresentSwapChain(const Mailbox& mailbox) {
-  if (!SharedImageBackingFactoryD3D::IsSwapChainSupported())
+  if (!D3DImageBackingFactory::IsSwapChainSupported())
     return false;
   auto it = shared_images_.find(mailbox);
   if (it == shared_images_.end()) {
@@ -831,54 +829,54 @@
   DCHECK_EQ(0u, tracker_->GetMemRepresented());
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageRepresentationFactory::ProduceGLTexture(const Mailbox& mailbox) {
   return manager_->ProduceGLTexture(mailbox, tracker_.get());
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageRepresentationFactory::ProduceRGBEmulationGLTexture(
     const Mailbox& mailbox) {
   return manager_->ProduceRGBEmulationGLTexture(mailbox, tracker_.get());
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
 SharedImageRepresentationFactory::ProduceGLTexturePassthrough(
     const Mailbox& mailbox) {
   return manager_->ProduceGLTexturePassthrough(mailbox, tracker_.get());
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
+std::unique_ptr<SkiaImageRepresentation>
 SharedImageRepresentationFactory::ProduceSkia(
     const Mailbox& mailbox,
     scoped_refptr<SharedContextState> context_state) {
   return manager_->ProduceSkia(mailbox, tracker_.get(), context_state);
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
+std::unique_ptr<DawnImageRepresentation>
 SharedImageRepresentationFactory::ProduceDawn(const Mailbox& mailbox,
                                               WGPUDevice device,
                                               WGPUBackendType backend_type) {
   return manager_->ProduceDawn(mailbox, tracker_.get(), device, backend_type);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
+std::unique_ptr<OverlayImageRepresentation>
 SharedImageRepresentationFactory::ProduceOverlay(const gpu::Mailbox& mailbox) {
   return manager_->ProduceOverlay(mailbox, tracker_.get());
 }
 
-std::unique_ptr<SharedImageRepresentationMemory>
+std::unique_ptr<MemoryImageRepresentation>
 SharedImageRepresentationFactory::ProduceMemory(const gpu::Mailbox& mailbox) {
   return manager_->ProduceMemory(mailbox, tracker_.get());
 }
 
-std::unique_ptr<SharedImageRepresentationRaster>
+std::unique_ptr<RasterImageRepresentation>
 SharedImageRepresentationFactory::ProduceRaster(const Mailbox& mailbox) {
   return manager_->ProduceRaster(mailbox, tracker_.get());
 }
 
 #if BUILDFLAG(IS_ANDROID)
-std::unique_ptr<SharedImageRepresentationLegacyOverlay>
+std::unique_ptr<LegacyOverlayImageRepresentation>
 SharedImageRepresentationFactory::ProduceLegacyOverlay(
     const gpu::Mailbox& mailbox) {
   return manager_->ProduceLegacyOverlay(mailbox, tracker_.get());
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.h b/gpu/command_buffer/service/shared_image/shared_image_factory.h
index 190b0d0..5e02995 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_factory.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_factory.h
@@ -34,7 +34,7 @@
 class MemoryTracker;
 class SharedContextState;
 class SharedImageBackingFactory;
-class SharedImageBackingFactoryD3D;
+class D3DImageBackingFactory;
 struct GpuFeatureInfo;
 struct GpuPreferences;
 
@@ -181,7 +181,7 @@
 
 #if BUILDFLAG(IS_WIN)
   // Used for creating swap chains
-  raw_ptr<SharedImageBackingFactoryD3D> d3d_backing_factory_ = nullptr;
+  raw_ptr<D3DImageBackingFactory> d3d_backing_factory_ = nullptr;
 #endif
 
 #if BUILDFLAG(IS_FUCHSIA)
@@ -202,28 +202,28 @@
 
   // Helpers which call similar classes on SharedImageManager, providing a
   // MemoryTypeTracker.
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       const Mailbox& mailbox);
-  std::unique_ptr<SharedImageRepresentationGLTexture>
-  ProduceRGBEmulationGLTexture(const Mailbox& mailbox);
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTextureImageRepresentation> ProduceRGBEmulationGLTexture(
+      const Mailbox& mailbox);
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(const Mailbox& mailbox);
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       const Mailbox& mailbox,
       scoped_refptr<SharedContextState> context_State);
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       const Mailbox& mailbox,
       WGPUDevice device,
       WGPUBackendType backend_type);
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       const Mailbox& mailbox);
-  std::unique_ptr<SharedImageRepresentationMemory> ProduceMemory(
+  std::unique_ptr<MemoryImageRepresentation> ProduceMemory(
       const Mailbox& mailbox);
-  std::unique_ptr<SharedImageRepresentationRaster> ProduceRaster(
+  std::unique_ptr<RasterImageRepresentation> ProduceRaster(
       const Mailbox& mailbox);
 
 #if BUILDFLAG(IS_ANDROID)
-  std::unique_ptr<SharedImageRepresentationLegacyOverlay> ProduceLegacyOverlay(
+  std::unique_ptr<LegacyOverlayImageRepresentation> ProduceLegacyOverlay(
       const Mailbox& mailbox);
 #endif
 
diff --git a/gpu/command_buffer/service/shared_image/shared_image_manager.cc b/gpu/command_buffer/service/shared_image/shared_image_manager.cc
index 8b1be45..b944f0b 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_manager.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_manager.cc
@@ -130,7 +130,7 @@
   (*found)->OnContextLost();
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageManager::ProduceGLTexture(const Mailbox& mailbox,
                                      MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
@@ -154,7 +154,7 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
+std::unique_ptr<GLTextureImageRepresentation>
 SharedImageManager::ProduceRGBEmulationGLTexture(const Mailbox& mailbox,
                                                  MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
@@ -177,7 +177,7 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
 SharedImageManager::ProduceGLTexturePassthrough(const Mailbox& mailbox,
                                                 MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
@@ -200,7 +200,7 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationSkia> SharedImageManager::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> SharedImageManager::ProduceSkia(
     const Mailbox& mailbox,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -224,7 +224,7 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationDawn> SharedImageManager::ProduceDawn(
+std::unique_ptr<DawnImageRepresentation> SharedImageManager::ProduceDawn(
     const Mailbox& mailbox,
     MemoryTypeTracker* tracker,
     WGPUDevice device,
@@ -250,9 +250,9 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageManager::ProduceOverlay(const gpu::Mailbox& mailbox,
-                                   gpu::MemoryTypeTracker* tracker) {
+std::unique_ptr<OverlayImageRepresentation> SharedImageManager::ProduceOverlay(
+    const gpu::Mailbox& mailbox,
+    gpu::MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
 
   AutoLock autolock(this);
@@ -273,10 +273,10 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationVaapi>
-SharedImageManager::ProduceVASurface(const Mailbox& mailbox,
-                                     MemoryTypeTracker* tracker,
-                                     VaapiDependenciesFactory* dep_factory) {
+std::unique_ptr<VaapiImageRepresentation> SharedImageManager::ProduceVASurface(
+    const Mailbox& mailbox,
+    MemoryTypeTracker* tracker,
+    VaapiDependenciesFactory* dep_factory) {
   CALLED_ON_VALID_THREAD();
 
   AutoLock autolock(this);
@@ -297,9 +297,9 @@
   return representation;
 }
 
-std::unique_ptr<SharedImageRepresentationMemory>
-SharedImageManager::ProduceMemory(const Mailbox& mailbox,
-                                  MemoryTypeTracker* tracker) {
+std::unique_ptr<MemoryImageRepresentation> SharedImageManager::ProduceMemory(
+    const Mailbox& mailbox,
+    MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
 
   AutoLock autolock(this);
@@ -315,9 +315,9 @@
   return (*found)->ProduceMemory(this, tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationRaster>
-SharedImageManager::ProduceRaster(const Mailbox& mailbox,
-                                  MemoryTypeTracker* tracker) {
+std::unique_ptr<RasterImageRepresentation> SharedImageManager::ProduceRaster(
+    const Mailbox& mailbox,
+    MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
 
   AutoLock autolock(this);
@@ -334,7 +334,7 @@
 }
 
 #if BUILDFLAG(IS_ANDROID)
-std::unique_ptr<SharedImageRepresentationLegacyOverlay>
+std::unique_ptr<LegacyOverlayImageRepresentation>
 SharedImageManager::ProduceLegacyOverlay(const Mailbox& mailbox,
                                          MemoryTypeTracker* tracker) {
   CALLED_ON_VALID_THREAD();
diff --git a/gpu/command_buffer/service/shared_image/shared_image_manager.h b/gpu/command_buffer/service/shared_image/shared_image_manager.h
index 3d3134fa..5b4a42c 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_manager.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_manager.h
@@ -50,14 +50,15 @@
   // Accessors which return a SharedImageRepresentation. Representations also
   // take a ref on the mailbox, releasing it when the representation is
   // destroyed.
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref);
-  std::unique_ptr<SharedImageRepresentationGLTexture>
-  ProduceRGBEmulationGLTexture(const Mailbox& mailbox, MemoryTypeTracker* ref);
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTextureImageRepresentation> ProduceRGBEmulationGLTexture(
+      const Mailbox& mailbox,
+      MemoryTypeTracker* ref);
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(const Mailbox& mailbox, MemoryTypeTracker* ref);
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref,
       scoped_refptr<SharedContextState> context_state);
@@ -68,27 +69,27 @@
   // associate with the representation.
   // TODO(crbug.com/1147184): Revisit this in the future for WebGPU
   // multi-adapter support.
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref,
       WGPUDevice device,
       WGPUBackendType backend_type);
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref);
-  std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
+  std::unique_ptr<VaapiImageRepresentation> ProduceVASurface(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref,
       VaapiDependenciesFactory* dep_factory);
-  std::unique_ptr<SharedImageRepresentationMemory> ProduceMemory(
+  std::unique_ptr<MemoryImageRepresentation> ProduceMemory(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref);
-  std::unique_ptr<SharedImageRepresentationRaster> ProduceRaster(
+  std::unique_ptr<RasterImageRepresentation> ProduceRaster(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref);
 
 #if BUILDFLAG(IS_ANDROID)
-  std::unique_ptr<SharedImageRepresentationLegacyOverlay> ProduceLegacyOverlay(
+  std::unique_ptr<LegacyOverlayImageRepresentation> ProduceLegacyOverlay(
       const Mailbox& mailbox,
       MemoryTypeTracker* ref);
 #endif
diff --git a/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc b/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
index 8f1ae7d..6e3c8364 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_manager_unittest.cc
@@ -44,7 +44,7 @@
   auto alpha_type = kPremul_SkAlphaType;
   uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
 
-  auto backing = std::make_unique<TestSharedImageBacking>(
+  auto backing = std::make_unique<TestImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       kSizeBytes);
 
@@ -84,7 +84,7 @@
   auto alpha_type = kPremul_SkAlphaType;
   uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
 
-  auto backing = std::make_unique<TestSharedImageBacking>(
+  auto backing = std::make_unique<TestImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       kSizeBytes);
 
@@ -116,7 +116,7 @@
   auto alpha_type = kPremul_SkAlphaType;
   uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
 
-  auto backing = std::make_unique<TestSharedImageBacking>(
+  auto backing = std::make_unique<TestImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       kSizeBytes);
 
@@ -186,7 +186,7 @@
   auto alpha_type = kPremul_SkAlphaType;
   uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
 
-  auto backing = std::make_unique<TestSharedImageBacking>(
+  auto backing = std::make_unique<TestImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       kSizeBytes);
 
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.cc b/gpu/command_buffer/service/shared_image/shared_image_representation.cc
index 4dbc40d..5e55999 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation.cc
@@ -46,8 +46,8 @@
   }
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture::ScopedAccess>
-SharedImageRepresentationGLTextureBase::BeginScopedAccess(
+std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>
+GLTextureImageRepresentationBase::BeginScopedAccess(
     GLenum mode,
     AllowUnclearedAccess allow_uncleared) {
   if (allow_uncleared != AllowUnclearedAccess::kYes && !IsCleared()) {
@@ -66,23 +66,22 @@
     backing()->OnWriteSucceeded();
 
   return std::make_unique<ScopedAccess>(
-      base::PassKey<SharedImageRepresentationGLTextureBase>(), this);
+      base::PassKey<GLTextureImageRepresentationBase>(), this);
 }
 
-bool SharedImageRepresentationGLTextureBase::BeginAccess(GLenum mode) {
+bool GLTextureImageRepresentationBase::BeginAccess(GLenum mode) {
   return true;
 }
 
-bool SharedImageRepresentationGLTextureBase::
-    SupportsMultipleConcurrentReadAccess() {
+bool GLTextureImageRepresentationBase::SupportsMultipleConcurrentReadAccess() {
   return false;
 }
 
-gpu::TextureBase* SharedImageRepresentationGLTexture::GetTextureBase() {
+gpu::TextureBase* GLTextureImageRepresentation::GetTextureBase() {
   return GetTexture();
 }
 
-void SharedImageRepresentationGLTexture::UpdateClearedStateOnEndAccess() {
+void GLTextureImageRepresentation::UpdateClearedStateOnEndAccess() {
   auto* texture = GetTexture();
   // Operations on the gles2::Texture may have cleared or uncleared it. Make
   // sure this state is reflected back in the SharedImage.
@@ -91,7 +90,7 @@
     SetClearedRect(cleared_rect);
 }
 
-void SharedImageRepresentationGLTexture::UpdateClearedStateOnBeginAccess() {
+void GLTextureImageRepresentation::UpdateClearedStateOnBeginAccess() {
   auto* texture = GetTexture();
   // Operations outside of the gles2::Texture may have cleared or uncleared it.
   // Make sure this state is reflected back in gles2::Texture.
@@ -100,34 +99,33 @@
     texture->SetLevelClearedRect(texture->target(), 0, cleared_rect);
 }
 
-gpu::TextureBase*
-SharedImageRepresentationGLTexturePassthrough::GetTextureBase() {
+gpu::TextureBase* GLTexturePassthroughImageRepresentation::GetTextureBase() {
   return GetTexturePassthrough().get();
 }
 
-bool SharedImageRepresentationSkia::SupportsMultipleConcurrentReadAccess() {
+bool SkiaImageRepresentation::SupportsMultipleConcurrentReadAccess() {
   return false;
 }
 
-SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
-    base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
-    SharedImageRepresentationSkia* representation,
+SkiaImageRepresentation::ScopedWriteAccess::ScopedWriteAccess(
+    base::PassKey<SkiaImageRepresentation> /* pass_key */,
+    SkiaImageRepresentation* representation,
     sk_sp<SkSurface> surface,
     std::unique_ptr<GrBackendSurfaceMutableState> end_state)
     : ScopedAccessBase(representation),
       surface_(std::move(surface)),
       end_state_(std::move(end_state)) {}
 
-SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
-    base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
-    SharedImageRepresentationSkia* representation,
+SkiaImageRepresentation::ScopedWriteAccess::ScopedWriteAccess(
+    base::PassKey<SkiaImageRepresentation> /* pass_key */,
+    SkiaImageRepresentation* representation,
     sk_sp<SkPromiseImageTexture> promise_image_texture,
     std::unique_ptr<GrBackendSurfaceMutableState> end_state)
     : ScopedAccessBase(representation),
       promise_image_texture_(std::move(promise_image_texture)),
       end_state_(std::move(end_state)) {}
 
-SharedImageRepresentationSkia::ScopedWriteAccess::~ScopedWriteAccess() {
+SkiaImageRepresentation::ScopedWriteAccess::~ScopedWriteAccess() {
   if (end_state_) {
     NOTREACHED() << "Before ending write access TakeEndState() must be called "
                     "and the result passed to skia to make sure all layout and "
@@ -142,12 +140,12 @@
 }
 
 std::unique_ptr<GrBackendSurfaceMutableState>
-SharedImageRepresentationSkia::ScopedWriteAccess::TakeEndState() {
+SkiaImageRepresentation::ScopedWriteAccess::TakeEndState() {
   return std::move(end_state_);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
-SharedImageRepresentationSkia::BeginScopedWriteAccess(
+std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
+SkiaImageRepresentation::BeginScopedWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -172,8 +170,8 @@
     backing()->OnWriteSucceeded();
 
     return std::make_unique<ScopedWriteAccess>(
-        base::PassKey<SharedImageRepresentationSkia>(), this,
-        std::move(surface), std::move(end_state));
+        base::PassKey<SkiaImageRepresentation>(), this, std::move(surface),
+        std::move(end_state));
   }
   sk_sp<SkPromiseImageTexture> promise_image_texture =
       BeginWriteAccess(begin_semaphores, end_semaphores, &end_state);
@@ -185,12 +183,12 @@
   backing()->OnWriteSucceeded();
 
   return std::make_unique<ScopedWriteAccess>(
-      base::PassKey<SharedImageRepresentationSkia>(), this,
+      base::PassKey<SkiaImageRepresentation>(), this,
       std::move(promise_image_texture), std::move(end_state));
 }
 
-std::unique_ptr<SharedImageRepresentationSkia::ScopedWriteAccess>
-SharedImageRepresentationSkia::BeginScopedWriteAccess(
+std::unique_ptr<SkiaImageRepresentation::ScopedWriteAccess>
+SkiaImageRepresentation::BeginScopedWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     AllowUnclearedAccess allow_uncleared,
@@ -201,16 +199,16 @@
       end_semaphores, allow_uncleared, use_sk_surface);
 }
 
-SharedImageRepresentationSkia::ScopedReadAccess::ScopedReadAccess(
-    base::PassKey<SharedImageRepresentationSkia> /* pass_key */,
-    SharedImageRepresentationSkia* representation,
+SkiaImageRepresentation::ScopedReadAccess::ScopedReadAccess(
+    base::PassKey<SkiaImageRepresentation> /* pass_key */,
+    SkiaImageRepresentation* representation,
     sk_sp<SkPromiseImageTexture> promise_image_texture,
     std::unique_ptr<GrBackendSurfaceMutableState> end_state)
     : ScopedAccessBase(representation),
       promise_image_texture_(std::move(promise_image_texture)),
       end_state_(std::move(end_state)) {}
 
-SharedImageRepresentationSkia::ScopedReadAccess::~ScopedReadAccess() {
+SkiaImageRepresentation::ScopedReadAccess::~ScopedReadAccess() {
   if (end_state_) {
     NOTREACHED() << "Before ending read access TakeEndState() must be called "
                     "and the result passed to skia to make sure all layout and "
@@ -223,7 +221,7 @@
   representation()->EndReadAccess();
 }
 
-sk_sp<SkImage> SharedImageRepresentationSkia::ScopedReadAccess::CreateSkImage(
+sk_sp<SkImage> SkiaImageRepresentation::ScopedReadAccess::CreateSkImage(
     GrDirectContext* context) const {
   auto surface_origin = representation()->surface_origin();
   auto color_type =
@@ -236,12 +234,12 @@
 }
 
 std::unique_ptr<GrBackendSurfaceMutableState>
-SharedImageRepresentationSkia::ScopedReadAccess::TakeEndState() {
+SkiaImageRepresentation::ScopedReadAccess::TakeEndState() {
   return std::move(end_state_);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-SharedImageRepresentationSkia::BeginScopedReadAccess(
+std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess>
+SkiaImageRepresentation::BeginScopedReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
   if (!IsCleared()) {
@@ -263,11 +261,11 @@
   backing()->OnReadSucceeded();
 
   return std::make_unique<ScopedReadAccess>(
-      base::PassKey<SharedImageRepresentationSkia>(), this,
+      base::PassKey<SkiaImageRepresentation>(), this,
       std::move(promise_image_texture), std::move(end_state));
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
+sk_sp<SkSurface> SkiaImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -277,7 +275,7 @@
                           end_semaphores);
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkia::BeginWriteAccess(
+sk_sp<SkSurface> SkiaImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -285,46 +283,45 @@
   return nullptr;
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
   return BeginReadAccess(begin_semaphores, end_semaphores);
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
   return nullptr;
 }
 
 #if BUILDFLAG(IS_ANDROID)
-AHardwareBuffer* SharedImageRepresentationOverlay::GetAHardwareBuffer() {
+AHardwareBuffer* OverlayImageRepresentation::GetAHardwareBuffer() {
   NOTREACHED();
   return nullptr;
 }
 #elif defined(USE_OZONE)
-scoped_refptr<gfx::NativePixmap>
-SharedImageRepresentationOverlay::GetNativePixmap() {
+scoped_refptr<gfx::NativePixmap> OverlayImageRepresentation::GetNativePixmap() {
   return backing()->GetNativePixmap();
 }
 #endif
 
-SharedImageRepresentationOverlay::ScopedReadAccess::ScopedReadAccess(
-    base::PassKey<SharedImageRepresentationOverlay> pass_key,
-    SharedImageRepresentationOverlay* representation,
+OverlayImageRepresentation::ScopedReadAccess::ScopedReadAccess(
+    base::PassKey<OverlayImageRepresentation> pass_key,
+    OverlayImageRepresentation* representation,
     gl::GLImage* gl_image,
     gfx::GpuFenceHandle acquire_fence)
     : ScopedAccessBase(representation),
       gl_image_(gl_image),
       acquire_fence_(std::move(acquire_fence)) {}
 
-SharedImageRepresentationOverlay::ScopedReadAccess::~ScopedReadAccess() {
+OverlayImageRepresentation::ScopedReadAccess::~ScopedReadAccess() {
   representation()->EndReadAccess(std::move(release_fence_));
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay::ScopedReadAccess>
-SharedImageRepresentationOverlay::BeginScopedReadAccess(bool needs_gl_image) {
+std::unique_ptr<OverlayImageRepresentation::ScopedReadAccess>
+OverlayImageRepresentation::BeginScopedReadAccess(bool needs_gl_image) {
   if (!IsCleared()) {
     LOG(ERROR) << "Attempt to read from an uninitialized SharedImage";
     return nullptr;
@@ -337,22 +334,22 @@
   backing()->OnReadSucceeded();
 
   return std::make_unique<ScopedReadAccess>(
-      base::PassKey<SharedImageRepresentationOverlay>(), this,
+      base::PassKey<OverlayImageRepresentation>(), this,
       needs_gl_image ? GetGLImage() : nullptr, std::move(acquire_fence));
 }
 
-SharedImageRepresentationDawn::ScopedAccess::ScopedAccess(
-    base::PassKey<SharedImageRepresentationDawn> /* pass_key */,
-    SharedImageRepresentationDawn* representation,
+DawnImageRepresentation::ScopedAccess::ScopedAccess(
+    base::PassKey<DawnImageRepresentation> /* pass_key */,
+    DawnImageRepresentation* representation,
     WGPUTexture texture)
     : ScopedAccessBase(representation), texture_(texture) {}
 
-SharedImageRepresentationDawn::ScopedAccess::~ScopedAccess() {
+DawnImageRepresentation::ScopedAccess::~ScopedAccess() {
   representation()->EndAccess();
 }
 
-std::unique_ptr<SharedImageRepresentationDawn::ScopedAccess>
-SharedImageRepresentationDawn::BeginScopedAccess(
+std::unique_ptr<DawnImageRepresentation::ScopedAccess>
+DawnImageRepresentation::BeginScopedAccess(
     WGPUTextureUsage usage,
     AllowUnclearedAccess allow_uncleared) {
   if (allow_uncleared != AllowUnclearedAccess::kYes && !IsCleared()) {
@@ -371,7 +368,7 @@
   }
 
   return std::make_unique<ScopedAccess>(
-      base::PassKey<SharedImageRepresentationDawn>(), this, texture);
+      base::PassKey<DawnImageRepresentation>(), this, texture);
 }
 
 SharedImageRepresentationFactoryRef::~SharedImageRepresentationFactoryRef() {
@@ -379,7 +376,7 @@
   backing()->MarkForDestruction();
 }
 
-SharedImageRepresentationVaapi::SharedImageRepresentationVaapi(
+VaapiImageRepresentation::VaapiImageRepresentation(
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
@@ -387,87 +384,85 @@
     : SharedImageRepresentation(manager, backing, tracker),
       vaapi_deps_(vaapi_deps) {}
 
-SharedImageRepresentationVaapi::~SharedImageRepresentationVaapi() = default;
+VaapiImageRepresentation::~VaapiImageRepresentation() = default;
 
-SharedImageRepresentationVaapi::ScopedWriteAccess::ScopedWriteAccess(
-    base::PassKey<SharedImageRepresentationVaapi> /* pass_key */,
-    SharedImageRepresentationVaapi* representation)
+VaapiImageRepresentation::ScopedWriteAccess::ScopedWriteAccess(
+    base::PassKey<VaapiImageRepresentation> /* pass_key */,
+    VaapiImageRepresentation* representation)
     : ScopedAccessBase(representation) {}
 
-SharedImageRepresentationVaapi::ScopedWriteAccess::~ScopedWriteAccess() {
+VaapiImageRepresentation::ScopedWriteAccess::~ScopedWriteAccess() {
   representation()->EndAccess();
 }
 
 const media::VASurface*
-SharedImageRepresentationVaapi::ScopedWriteAccess::va_surface() {
+VaapiImageRepresentation::ScopedWriteAccess::va_surface() {
   return representation()->vaapi_deps_->GetVaSurface();
 }
 
-std::unique_ptr<SharedImageRepresentationVaapi::ScopedWriteAccess>
-SharedImageRepresentationVaapi::BeginScopedWriteAccess() {
+std::unique_ptr<VaapiImageRepresentation::ScopedWriteAccess>
+VaapiImageRepresentation::BeginScopedWriteAccess() {
   return std::make_unique<ScopedWriteAccess>(
-      base::PassKey<SharedImageRepresentationVaapi>(), this);
+      base::PassKey<VaapiImageRepresentation>(), this);
 }
 
-SharedImageRepresentationMemory::ScopedReadAccess::ScopedReadAccess(
-    base::PassKey<SharedImageRepresentationMemory> pass_key,
-    SharedImageRepresentationMemory* representation,
+MemoryImageRepresentation::ScopedReadAccess::ScopedReadAccess(
+    base::PassKey<MemoryImageRepresentation> pass_key,
+    MemoryImageRepresentation* representation,
     SkPixmap pixmap)
     : ScopedAccessBase(representation), pixmap_(pixmap) {}
 
-SharedImageRepresentationMemory::ScopedReadAccess::~ScopedReadAccess() =
-    default;
+MemoryImageRepresentation::ScopedReadAccess::~ScopedReadAccess() = default;
 
-std::unique_ptr<SharedImageRepresentationMemory::ScopedReadAccess>
-SharedImageRepresentationMemory::BeginScopedReadAccess() {
+std::unique_ptr<MemoryImageRepresentation::ScopedReadAccess>
+MemoryImageRepresentation::BeginScopedReadAccess() {
   return std::make_unique<ScopedReadAccess>(
-      base::PassKey<SharedImageRepresentationMemory>(), this,
-      BeginReadAccess());
+      base::PassKey<MemoryImageRepresentation>(), this, BeginReadAccess());
 }
 
-SharedImageRepresentationRaster::ScopedReadAccess::ScopedReadAccess(
-    base::PassKey<SharedImageRepresentationRaster> pass_key,
-    SharedImageRepresentationRaster* representation,
+RasterImageRepresentation::ScopedReadAccess::ScopedReadAccess(
+    base::PassKey<RasterImageRepresentation> pass_key,
+    RasterImageRepresentation* representation,
     const cc::PaintOpBuffer* paint_op_buffer,
     const absl::optional<SkColor4f>& clear_color)
     : ScopedAccessBase(representation),
       paint_op_buffer_(paint_op_buffer),
       clear_color_(clear_color) {}
 
-SharedImageRepresentationRaster::ScopedReadAccess::~ScopedReadAccess() {
+RasterImageRepresentation::ScopedReadAccess::~ScopedReadAccess() {
   representation()->EndReadAccess();
 }
 
-SharedImageRepresentationRaster::ScopedWriteAccess::ScopedWriteAccess(
-    base::PassKey<SharedImageRepresentationRaster> pass_key,
-    SharedImageRepresentationRaster* representation,
+RasterImageRepresentation::ScopedWriteAccess::ScopedWriteAccess(
+    base::PassKey<RasterImageRepresentation> pass_key,
+    RasterImageRepresentation* representation,
     cc::PaintOpBuffer* paint_op_buffer)
     : ScopedAccessBase(representation), paint_op_buffer_(paint_op_buffer) {}
 
-SharedImageRepresentationRaster::ScopedWriteAccess::~ScopedWriteAccess() {
+RasterImageRepresentation::ScopedWriteAccess::~ScopedWriteAccess() {
   representation()->EndWriteAccess(std::move(callback_));
 }
 
-std::unique_ptr<SharedImageRepresentationRaster::ScopedReadAccess>
-SharedImageRepresentationRaster::BeginScopedReadAccess() {
+std::unique_ptr<RasterImageRepresentation::ScopedReadAccess>
+RasterImageRepresentation::BeginScopedReadAccess() {
   absl::optional<SkColor4f> clear_color;
   auto* paint_op_buffer = BeginReadAccess(clear_color);
   if (!paint_op_buffer)
     return nullptr;
   return std::make_unique<ScopedReadAccess>(
-      base::PassKey<SharedImageRepresentationRaster>(), this, paint_op_buffer,
+      base::PassKey<RasterImageRepresentation>(), this, paint_op_buffer,
       clear_color);
 }
 
-std::unique_ptr<SharedImageRepresentationRaster::ScopedWriteAccess>
-SharedImageRepresentationRaster::BeginScopedWriteAccess(
+std::unique_ptr<RasterImageRepresentation::ScopedWriteAccess>
+RasterImageRepresentation::BeginScopedWriteAccess(
     scoped_refptr<SharedContextState> context_state,
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     const absl::optional<SkColor4f>& clear_color,
     bool visible) {
   return std::make_unique<ScopedWriteAccess>(
-      base::PassKey<SharedImageRepresentationRaster>(), this,
+      base::PassKey<RasterImageRepresentation>(), this,
       BeginWriteAccess(std::move(context_state), final_msaa_count,
                        surface_props, clear_color, visible));
 }
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.h b/gpu/command_buffer/service/shared_image/shared_image_representation.h
index c09e5558..8ef5937 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation.h
@@ -164,16 +164,16 @@
   }
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationGLTextureBase
+class GPU_GLES2_EXPORT GLTextureImageRepresentationBase
     : public SharedImageRepresentation {
  public:
   static constexpr GLenum kReadAccessMode = 0x8AF6;
 
   class ScopedAccess
-      : public ScopedAccessBase<SharedImageRepresentationGLTextureBase> {
+      : public ScopedAccessBase<GLTextureImageRepresentationBase> {
    public:
-    ScopedAccess(base::PassKey<SharedImageRepresentationGLTextureBase> pass_key,
-                 SharedImageRepresentationGLTextureBase* representation)
+    ScopedAccess(base::PassKey<GLTextureImageRepresentationBase> pass_key,
+                 GLTextureImageRepresentationBase* representation)
         : ScopedAccessBase(representation) {}
     ~ScopedAccess() {
       representation()->UpdateClearedStateOnEndAccess();
@@ -181,9 +181,9 @@
     }
   };
 
-  SharedImageRepresentationGLTextureBase(SharedImageManager* manager,
-                                         SharedImageBacking* backing,
-                                         MemoryTypeTracker* tracker)
+  GLTextureImageRepresentationBase(SharedImageManager* manager,
+                                   SharedImageBacking* backing,
+                                   MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   std::unique_ptr<ScopedAccess> BeginScopedAccess(
@@ -193,9 +193,9 @@
   virtual gpu::TextureBase* GetTextureBase() = 0;
 
  protected:
-  friend class SharedImageRepresentationSkiaGL;
-  friend class SharedImageRepresentationDawnEGLImage;
-  friend class SharedImageRepresentationGLTextureImpl;
+  friend class SkiaGLImageRepresentation;
+  friend class DawnEGLImageRepresentation;
+  friend class GLTextureGLCommonRepresentation;
 
   // Can be overridden to handle clear state tracking when GL access begins or
   // ends.
@@ -210,13 +210,13 @@
   virtual bool SupportsMultipleConcurrentReadAccess();
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationGLTexture
-    : public SharedImageRepresentationGLTextureBase {
+class GPU_GLES2_EXPORT GLTextureImageRepresentation
+    : public GLTextureImageRepresentationBase {
  public:
-  SharedImageRepresentationGLTexture(SharedImageManager* manager,
-                                     SharedImageBacking* backing,
-                                     MemoryTypeTracker* tracker)
-      : SharedImageRepresentationGLTextureBase(manager, backing, tracker) {}
+  GLTextureImageRepresentation(SharedImageManager* manager,
+                               SharedImageBacking* backing,
+                               MemoryTypeTracker* tracker)
+      : GLTextureImageRepresentationBase(manager, backing, tracker) {}
 
   // TODO(ericrk): Move this to the ScopedAccess object. crbug.com/1003686
   virtual gles2::Texture* GetTexture() = 0;
@@ -224,19 +224,19 @@
   gpu::TextureBase* GetTextureBase() override;
 
  protected:
-  friend class WrappedGLTextureRepresentation;
+  friend class WrappedGLTextureCompoundImageRepresentation;
 
   void UpdateClearedStateOnBeginAccess() override;
   void UpdateClearedStateOnEndAccess() override;
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationGLTexturePassthrough
-    : public SharedImageRepresentationGLTextureBase {
+class GPU_GLES2_EXPORT GLTexturePassthroughImageRepresentation
+    : public GLTextureImageRepresentationBase {
  public:
-  SharedImageRepresentationGLTexturePassthrough(SharedImageManager* manager,
-                                                SharedImageBacking* backing,
-                                                MemoryTypeTracker* tracker)
-      : SharedImageRepresentationGLTextureBase(manager, backing, tracker) {}
+  GLTexturePassthroughImageRepresentation(SharedImageManager* manager,
+                                          SharedImageBacking* backing,
+                                          MemoryTypeTracker* tracker)
+      : GLTextureImageRepresentationBase(manager, backing, tracker) {}
 
   // TODO(ericrk): Move this to the ScopedAccess object. crbug.com/1003686
   virtual const scoped_refptr<gles2::TexturePassthrough>&
@@ -245,21 +245,21 @@
   gpu::TextureBase* GetTextureBase() override;
 
  private:
-  friend class WrappedGLTexturePassthroughRepresentation;
+  friend class WrappedGLTexturePassthroughCompoundImageRepresentation;
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationSkia
+class GPU_GLES2_EXPORT SkiaImageRepresentation
     : public SharedImageRepresentation {
  public:
   class GPU_GLES2_EXPORT ScopedWriteAccess
-      : public ScopedAccessBase<SharedImageRepresentationSkia> {
+      : public ScopedAccessBase<SkiaImageRepresentation> {
    public:
-    ScopedWriteAccess(base::PassKey<SharedImageRepresentationSkia> pass_key,
-                      SharedImageRepresentationSkia* representation,
+    ScopedWriteAccess(base::PassKey<SkiaImageRepresentation> pass_key,
+                      SkiaImageRepresentation* representation,
                       sk_sp<SkSurface> surface,
                       std::unique_ptr<GrBackendSurfaceMutableState> end_state);
-    ScopedWriteAccess(base::PassKey<SharedImageRepresentationSkia> pass_key,
-                      SharedImageRepresentationSkia* representation,
+    ScopedWriteAccess(base::PassKey<SkiaImageRepresentation> pass_key,
+                      SkiaImageRepresentation* representation,
                       sk_sp<SkPromiseImageTexture> promise_image_texture,
                       std::unique_ptr<GrBackendSurfaceMutableState> end_state);
     ~ScopedWriteAccess();
@@ -277,10 +277,10 @@
   };
 
   class GPU_GLES2_EXPORT ScopedReadAccess
-      : public ScopedAccessBase<SharedImageRepresentationSkia> {
+      : public ScopedAccessBase<SkiaImageRepresentation> {
    public:
-    ScopedReadAccess(base::PassKey<SharedImageRepresentationSkia> pass_key,
-                     SharedImageRepresentationSkia* representation,
+    ScopedReadAccess(base::PassKey<SkiaImageRepresentation> pass_key,
+                     SkiaImageRepresentation* representation,
                      sk_sp<SkPromiseImageTexture> promise_image_texture,
                      std::unique_ptr<GrBackendSurfaceMutableState> end_state);
     ~ScopedReadAccess();
@@ -296,9 +296,9 @@
     std::unique_ptr<GrBackendSurfaceMutableState> end_state_;
   };
 
-  SharedImageRepresentationSkia(SharedImageManager* manager,
-                                SharedImageBacking* backing,
-                                MemoryTypeTracker* tracker)
+  SkiaImageRepresentation(SharedImageManager* manager,
+                          SharedImageBacking* backing,
+                          MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   // Note: See BeginWriteAccess below for a description of the semaphore
@@ -326,7 +326,7 @@
   virtual bool SupportsMultipleConcurrentReadAccess();
 
  protected:
-  friend class WrappedSkiaRepresentation;
+  friend class WrappedSkiaCompoundImageRepresentation;
 
   // Begin the write access. The implementations should insert semaphores into
   // begin_semaphores vector which client will wait on before writing the
@@ -376,22 +376,22 @@
   virtual void EndReadAccess() = 0;
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationDawn
+class GPU_GLES2_EXPORT DawnImageRepresentation
     : public SharedImageRepresentation {
  public:
   static constexpr uint32_t kWriteUsage =
       WGPUTextureUsage_CopyDst | WGPUTextureUsage_RenderAttachment;
 
-  SharedImageRepresentationDawn(SharedImageManager* manager,
-                                SharedImageBacking* backing,
-                                MemoryTypeTracker* tracker)
+  DawnImageRepresentation(SharedImageManager* manager,
+                          SharedImageBacking* backing,
+                          MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   class GPU_GLES2_EXPORT ScopedAccess
-      : public ScopedAccessBase<SharedImageRepresentationDawn> {
+      : public ScopedAccessBase<DawnImageRepresentation> {
    public:
-    ScopedAccess(base::PassKey<SharedImageRepresentationDawn> pass_key,
-                 SharedImageRepresentationDawn* representation,
+    ScopedAccess(base::PassKey<DawnImageRepresentation> pass_key,
+                 DawnImageRepresentation* representation,
                  WGPUTexture texture);
     ~ScopedAccess();
 
@@ -411,7 +411,7 @@
       AllowUnclearedAccess allow_uncleared);
 
  private:
-  friend class WrappedDawnRepresentation;
+  friend class WrappedDawnCompoundImageRepresentation;
 
   // This can return null in case of a Dawn validation error, for example if
   // usage is invalid.
@@ -419,19 +419,19 @@
   virtual void EndAccess() = 0;
 };
 
-class GPU_GLES2_EXPORT SharedImageRepresentationOverlay
+class GPU_GLES2_EXPORT OverlayImageRepresentation
     : public SharedImageRepresentation {
  public:
-  SharedImageRepresentationOverlay(SharedImageManager* manager,
-                                   SharedImageBacking* backing,
-                                   MemoryTypeTracker* tracker)
+  OverlayImageRepresentation(SharedImageManager* manager,
+                             SharedImageBacking* backing,
+                             MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   class GPU_GLES2_EXPORT ScopedReadAccess
-      : public ScopedAccessBase<SharedImageRepresentationOverlay> {
+      : public ScopedAccessBase<OverlayImageRepresentation> {
    public:
-    ScopedReadAccess(base::PassKey<SharedImageRepresentationOverlay> pass_key,
-                     SharedImageRepresentationOverlay* representation,
+    ScopedReadAccess(base::PassKey<OverlayImageRepresentation> pass_key,
+                     OverlayImageRepresentation* representation,
                      gl::GLImage* gl_image,
                      gfx::GpuFenceHandle acquire_fence);
     ~ScopedReadAccess();
@@ -466,7 +466,7 @@
   std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess(bool needs_gl_image);
 
  protected:
-  friend class WrappedOverlayRepresentation;
+  friend class WrappedOverlayCompoundImageRepresentation;
 
   // Notifies the backing that an access will start. Returns false if there is a
   // conflict. Otherwise, returns true and:
@@ -493,12 +493,12 @@
 };
 
 #if BUILDFLAG(IS_ANDROID)
-class GPU_GLES2_EXPORT SharedImageRepresentationLegacyOverlay
+class GPU_GLES2_EXPORT LegacyOverlayImageRepresentation
     : public SharedImageRepresentation {
  public:
-  SharedImageRepresentationLegacyOverlay(SharedImageManager* manager,
-                                         SharedImageBacking* backing,
-                                         MemoryTypeTracker* tracker)
+  LegacyOverlayImageRepresentation(SharedImageManager* manager,
+                                   SharedImageBacking* backing,
+                                   MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   // Renders shared image to SurfaceView/Dialog overlay. Should only be called
@@ -511,14 +511,14 @@
 };
 #endif
 
-class GPU_GLES2_EXPORT SharedImageRepresentationMemory
+class GPU_GLES2_EXPORT MemoryImageRepresentation
     : public SharedImageRepresentation {
  public:
   class GPU_GLES2_EXPORT ScopedReadAccess
-      : public ScopedAccessBase<SharedImageRepresentationMemory> {
+      : public ScopedAccessBase<MemoryImageRepresentation> {
    public:
-    ScopedReadAccess(base::PassKey<SharedImageRepresentationMemory> pass_key,
-                     SharedImageRepresentationMemory* representation,
+    ScopedReadAccess(base::PassKey<MemoryImageRepresentation> pass_key,
+                     MemoryImageRepresentation* representation,
                      SkPixmap pixmap);
     ~ScopedReadAccess();
 
@@ -528,9 +528,9 @@
     SkPixmap pixmap_;
   };
 
-  SharedImageRepresentationMemory(SharedImageManager* manager,
-                                  SharedImageBacking* backing,
-                                  MemoryTypeTracker* tracker)
+  MemoryImageRepresentation(SharedImageManager* manager,
+                            SharedImageBacking* backing,
+                            MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
@@ -559,7 +559,7 @@
 };
 
 // Representation of a SharedImageBacking as a VA-API surface.
-// This representation is currently only supported by SharedImageBackingOzone.
+// This representation is currently only supported by OzoneImageBacking.
 //
 // Synchronized access is currently not required in this representation because:
 //
@@ -572,24 +572,24 @@
 // decoding work until we're sure that the destination buffer is not being used
 // by the rest of the pipeline. However, we still need to keep track of write
 // accesses so that other representations can synchronize with the decoder.
-class GPU_GLES2_EXPORT SharedImageRepresentationVaapi
+class GPU_GLES2_EXPORT VaapiImageRepresentation
     : public SharedImageRepresentation {
  public:
   class GPU_GLES2_EXPORT ScopedWriteAccess
-      : public ScopedAccessBase<SharedImageRepresentationVaapi> {
+      : public ScopedAccessBase<VaapiImageRepresentation> {
    public:
-    ScopedWriteAccess(base::PassKey<SharedImageRepresentationVaapi> pass_key,
-                      SharedImageRepresentationVaapi* representation);
+    ScopedWriteAccess(base::PassKey<VaapiImageRepresentation> pass_key,
+                      VaapiImageRepresentation* representation);
 
     ~ScopedWriteAccess();
 
     const media::VASurface* va_surface();
   };
-  SharedImageRepresentationVaapi(SharedImageManager* manager,
-                                 SharedImageBacking* backing,
-                                 MemoryTypeTracker* tracker,
-                                 VaapiDependencies* vaapi_dependency);
-  ~SharedImageRepresentationVaapi() override;
+  VaapiImageRepresentation(SharedImageManager* manager,
+                           SharedImageBacking* backing,
+                           MemoryTypeTracker* tracker,
+                           VaapiDependencies* vaapi_dependency);
+  ~VaapiImageRepresentation() override;
 
   std::unique_ptr<ScopedWriteAccess> BeginScopedWriteAccess();
 
@@ -606,14 +606,14 @@
 // will be converted to a cc::PaintOpBuffer and stored in the
 // SharedImageBacking. And then the the compositor will access the stored
 // cc::PaintOpBuffer and execute paint ops in it.
-class GPU_GLES2_EXPORT SharedImageRepresentationRaster
+class GPU_GLES2_EXPORT RasterImageRepresentation
     : public SharedImageRepresentation {
  public:
   class GPU_GLES2_EXPORT ScopedReadAccess
-      : public ScopedAccessBase<SharedImageRepresentationRaster> {
+      : public ScopedAccessBase<RasterImageRepresentation> {
    public:
-    ScopedReadAccess(base::PassKey<SharedImageRepresentationRaster> pass_key,
-                     SharedImageRepresentationRaster* representation,
+    ScopedReadAccess(base::PassKey<RasterImageRepresentation> pass_key,
+                     RasterImageRepresentation* representation,
                      const cc::PaintOpBuffer* paint_op_buffer,
                      const absl::optional<SkColor4f>& clear_color);
     ~ScopedReadAccess();
@@ -631,10 +631,10 @@
   };
 
   class GPU_GLES2_EXPORT ScopedWriteAccess
-      : public ScopedAccessBase<SharedImageRepresentationRaster> {
+      : public ScopedAccessBase<RasterImageRepresentation> {
    public:
-    ScopedWriteAccess(base::PassKey<SharedImageRepresentationRaster> pass_key,
-                      SharedImageRepresentationRaster* representation,
+    ScopedWriteAccess(base::PassKey<RasterImageRepresentation> pass_key,
+                      RasterImageRepresentation* representation,
                       cc::PaintOpBuffer* paint_op_buffer);
     ~ScopedWriteAccess();
 
@@ -652,9 +652,9 @@
     base::OnceClosure callback_;
   };
 
-  SharedImageRepresentationRaster(SharedImageManager* manager,
-                                  SharedImageBacking* backing,
-                                  MemoryTypeTracker* tracker)
+  RasterImageRepresentation(SharedImageManager* manager,
+                            SharedImageBacking* backing,
+                            MemoryTypeTracker* tracker)
       : SharedImageRepresentation(manager, backing, tracker) {}
 
   std::unique_ptr<ScopedReadAccess> BeginScopedReadAccess();
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc b/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
index 2f8dc52..d25ef608 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_representation_unittest.cc
@@ -31,7 +31,7 @@
     auto alpha_type = kPremul_SkAlphaType;
     uint32_t usage = SHARED_IMAGE_USAGE_GLES2;
 
-    auto backing = std::make_unique<TestSharedImageBacking>(
+    auto backing = std::make_unique<TestImageBacking>(
         mailbox_, format, size, color_space, surface_origin, alpha_type, usage,
         0 /* estimated_size */);
     factory_ref_ = manager_.Register(std::move(backing), tracker_.get());
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
index 6a67c81..809a4253 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.cc
@@ -36,13 +36,12 @@
   return estimated_size;
 }
 
-class SharedImageRepresentationMemorySharedMemory
-    : public SharedImageRepresentationMemory {
+class MemoryImageRepresentationImpl : public MemoryImageRepresentation {
  public:
-  SharedImageRepresentationMemorySharedMemory(SharedImageManager* manager,
-                                              SharedImageBacking* backing,
-                                              MemoryTypeTracker* tracker)
-      : SharedImageRepresentationMemory(manager, backing, tracker) {}
+  MemoryImageRepresentationImpl(SharedImageManager* manager,
+                                SharedImageBacking* backing,
+                                MemoryTypeTracker* tracker)
+      : MemoryImageRepresentation(manager, backing, tracker) {}
 
  protected:
   SkPixmap BeginReadAccess() override {
@@ -53,71 +52,68 @@
   }
 
  private:
-  SharedImageBackingSharedMemory* shared_image_shared_memory() {
-    return static_cast<SharedImageBackingSharedMemory*>(backing());
+  SharedMemoryImageBacking* shared_image_shared_memory() {
+    return static_cast<SharedMemoryImageBacking*>(backing());
   }
 };
 
 }  // namespace
 
-SharedImageBackingSharedMemory::~SharedImageBackingSharedMemory() = default;
+SharedMemoryImageBacking::~SharedMemoryImageBacking() = default;
 
-void SharedImageBackingSharedMemory::Update(
-    std::unique_ptr<gfx::GpuFence> in_fence) {
+void SharedMemoryImageBacking::Update(std::unique_ptr<gfx::GpuFence> in_fence) {
   // Intentionally no-op for now. Will be called by clients later
 }
 
 const SharedMemoryRegionWrapper&
-SharedImageBackingSharedMemory::shared_memory_wrapper() {
+SharedMemoryImageBacking::shared_memory_wrapper() {
   return shared_memory_wrapper_;
 }
 
-bool SharedImageBackingSharedMemory::ProduceLegacyMailbox(
+bool SharedMemoryImageBacking::ProduceLegacyMailbox(
     MailboxManager* mailbox_manager) {
   NOTREACHED();
   return false;
 }
 
-SharedImageBackingType SharedImageBackingSharedMemory::GetType() const {
+SharedImageBackingType SharedMemoryImageBacking::GetType() const {
   return SharedImageBackingType::kSharedMemory;
 }
 
-gfx::Rect SharedImageBackingSharedMemory::ClearedRect() const {
+gfx::Rect SharedMemoryImageBacking::ClearedRect() const {
   NOTREACHED();
   return gfx::Rect();
 }
 
-void SharedImageBackingSharedMemory::SetClearedRect(
-    const gfx::Rect& cleared_rect) {
+void SharedMemoryImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   NOTREACHED();
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-SharedImageBackingSharedMemory::ProduceDawn(SharedImageManager* manager,
-                                            MemoryTypeTracker* tracker,
-                                            WGPUDevice device,
-                                            WGPUBackendType backend_type) {
+std::unique_ptr<DawnImageRepresentation> SharedMemoryImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
   NOTIMPLEMENTED_LOG_ONCE();
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageBackingSharedMemory::ProduceGLTexture(SharedImageManager* manager,
-                                                 MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+SharedMemoryImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                           MemoryTypeTracker* tracker) {
   NOTIMPLEMENTED_LOG_ONCE();
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageBackingSharedMemory::ProduceGLTexturePassthrough(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+SharedMemoryImageBacking::ProduceGLTexturePassthrough(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   NOTIMPLEMENTED_LOG_ONCE();
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageBackingSharedMemory::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> SharedMemoryImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -125,15 +121,15 @@
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-SharedImageBackingSharedMemory::ProduceOverlay(SharedImageManager* manager,
-                                               MemoryTypeTracker* tracker) {
+std::unique_ptr<OverlayImageRepresentation>
+SharedMemoryImageBacking::ProduceOverlay(SharedImageManager* manager,
+                                         MemoryTypeTracker* tracker) {
   NOTIMPLEMENTED_LOG_ONCE();
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationVaapi>
-SharedImageBackingSharedMemory::ProduceVASurface(
+std::unique_ptr<VaapiImageRepresentation>
+SharedMemoryImageBacking::ProduceVASurface(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     VaapiDependenciesFactory* dep_factory) {
@@ -141,17 +137,17 @@
   return nullptr;
 }
 
-std::unique_ptr<SharedImageRepresentationMemory>
-SharedImageBackingSharedMemory::ProduceMemory(SharedImageManager* manager,
-                                              MemoryTypeTracker* tracker) {
+std::unique_ptr<MemoryImageRepresentation>
+SharedMemoryImageBacking::ProduceMemory(SharedImageManager* manager,
+                                        MemoryTypeTracker* tracker) {
   if (!shared_memory_wrapper_.IsValid())
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationMemorySharedMemory>(
-      manager, this, tracker);
+  return std::make_unique<MemoryImageRepresentationImpl>(manager, this,
+                                                         tracker);
 }
 
-void SharedImageBackingSharedMemory::OnMemoryDump(
+void SharedMemoryImageBacking::OnMemoryDump(
     const std::string& dump_name,
     base::trace_event::MemoryAllocatorDump* dump,
     base::trace_event::ProcessMemoryDump* pmd,
@@ -166,7 +162,7 @@
   }
 }
 
-SharedImageBackingSharedMemory::SharedImageBackingSharedMemory(
+SharedMemoryImageBacking::SharedMemoryImageBacking(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
index ec786e0..48e52063 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing.h
@@ -20,18 +20,18 @@
 namespace gpu {
 
 // Implementation of SharedImageBacking that uses Shared Memory GMB.
-class SharedImageBackingSharedMemory : public SharedImageBacking {
+class SharedMemoryImageBacking : public SharedImageBacking {
  public:
-  SharedImageBackingSharedMemory(const Mailbox& mailbox,
-                                 viz::ResourceFormat format,
-                                 const gfx::Size& size,
-                                 const gfx::ColorSpace& color_space,
-                                 GrSurfaceOrigin surface_origin,
-                                 SkAlphaType alpha_type,
-                                 uint32_t usage,
-                                 SharedMemoryRegionWrapper wrapper);
+  SharedMemoryImageBacking(const Mailbox& mailbox,
+                           viz::ResourceFormat format,
+                           const gfx::Size& size,
+                           const gfx::ColorSpace& color_space,
+                           GrSurfaceOrigin surface_origin,
+                           SkAlphaType alpha_type,
+                           uint32_t usage,
+                           SharedMemoryRegionWrapper wrapper);
 
-  ~SharedImageBackingSharedMemory() override;
+  ~SharedMemoryImageBacking() override;
 
   // gpu::SharedImageBacking:
   void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
@@ -43,35 +43,33 @@
   const SharedMemoryRegionWrapper& shared_memory_wrapper();
 
  protected:
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) override;
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationVaapi> ProduceVASurface(
+  std::unique_ptr<VaapiImageRepresentation> ProduceVASurface(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       VaapiDependenciesFactory* dep_factory) override;
-  std::unique_ptr<SharedImageRepresentationMemory> ProduceMemory(
+  std::unique_ptr<MemoryImageRepresentation> ProduceMemory(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
  private:
-  class SharedImageRepresentationSharedMemory;
-
   void OnMemoryDump(const std::string& dump_name,
                     base::trace_event::MemoryAllocatorDump* dump,
                     base::trace_event::ProcessMemoryDump* pmd,
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc
index 09d9b21e..bfed573 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.cc
@@ -14,14 +14,12 @@
 
 namespace gpu {
 
-SharedImageBackingFactorySharedMemory::SharedImageBackingFactorySharedMemory() =
-    default;
+SharedMemoryImageBackingFactory::SharedMemoryImageBackingFactory() = default;
 
-SharedImageBackingFactorySharedMemory::
-    ~SharedImageBackingFactorySharedMemory() = default;
+SharedMemoryImageBackingFactory::~SharedMemoryImageBackingFactory() = default;
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactorySharedMemory::CreateSharedImage(
+SharedMemoryImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -36,7 +34,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactorySharedMemory::CreateSharedImage(
+SharedMemoryImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -50,7 +48,7 @@
 }
 
 std::unique_ptr<SharedImageBacking>
-SharedImageBackingFactorySharedMemory::CreateSharedImage(
+SharedMemoryImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -69,13 +67,13 @@
     return nullptr;
   }
 
-  auto backing = std::make_unique<SharedImageBackingSharedMemory>(
+  auto backing = std::make_unique<SharedMemoryImageBacking>(
       mailbox, format, size, color_space, surface_origin, alpha_type, usage,
       std::move(shm_wrapper));
   return backing;
 }
 
-bool SharedImageBackingFactorySharedMemory::IsSupported(
+bool SharedMemoryImageBackingFactory::IsSupported(
     uint32_t usage,
     viz::ResourceFormat format,
     bool thread_safe,
diff --git a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.h b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.h
index beb9486..1e838787 100644
--- a/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/shared_memory_image_backing_factory.h
@@ -12,12 +12,12 @@
 
 // Implementation of SharedImageBackingFactory that produces
 // SharedMemory GMB backed SharedImages.
-class GPU_GLES2_EXPORT SharedImageBackingFactorySharedMemory
+class GPU_GLES2_EXPORT SharedMemoryImageBackingFactory
     : public SharedImageBackingFactory {
  public:
-  explicit SharedImageBackingFactorySharedMemory();
+  explicit SharedMemoryImageBackingFactory();
 
-  ~SharedImageBackingFactorySharedMemory() override;
+  ~SharedMemoryImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/skia_gl_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_gl_image_representation.cc
index 6c497c7..d4f08ca 100644
--- a/gpu/command_buffer/service/shared_image/skia_gl_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/skia_gl_image_representation.cc
@@ -33,9 +33,8 @@
 }
 
 // static method.
-std::unique_ptr<SharedImageRepresentationSkiaGL>
-SharedImageRepresentationSkiaGL::Create(
-    std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+std::unique_ptr<SkiaGLImageRepresentation> SkiaGLImageRepresentation::Create(
+    std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
     scoped_refptr<SharedContextState> context_state,
     SharedImageManager* manager,
     SharedImageBacking* backing,
@@ -51,19 +50,19 @@
   auto promise_texture = SkPromiseImageTexture::Make(backend_texture);
   if (!promise_texture)
     return nullptr;
-  return base::WrapUnique(new SharedImageRepresentationSkiaGL(
+  return base::WrapUnique(new SkiaGLImageRepresentation(
       std::move(gl_representation), std::move(promise_texture),
       std::move(context_state), manager, backing, tracker));
 }
 
-SharedImageRepresentationSkiaGL::SharedImageRepresentationSkiaGL(
-    std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+SkiaGLImageRepresentation::SkiaGLImageRepresentation(
+    std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
     sk_sp<SkPromiseImageTexture> promise_texture,
     scoped_refptr<SharedContextState> context_state,
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker)
-    : SharedImageRepresentationSkia(manager, backing, tracker),
+    : SkiaImageRepresentation(manager, backing, tracker),
       gl_representation_(std::move(gl_representation)),
       promise_texture_(std::move(promise_texture)),
       context_state_(std::move(context_state)) {
@@ -73,14 +72,14 @@
 #endif
 }
 
-SharedImageRepresentationSkiaGL::~SharedImageRepresentationSkiaGL() {
+SkiaGLImageRepresentation::~SkiaGLImageRepresentation() {
   DCHECK_EQ(RepresentationAccessMode::kNone, mode_);
   surface_.reset();
   if (!has_context())
     gl_representation_->OnContextLost();
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkiaGL::BeginWriteAccess(
+sk_sp<SkSurface> SkiaGLImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -108,7 +107,7 @@
   return surface;
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaGL::BeginWriteAccess(
+sk_sp<SkPromiseImageTexture> SkiaGLImageRepresentation::BeginWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -123,7 +122,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaGL::EndWriteAccess(sk_sp<SkSurface> surface) {
+void SkiaGLImageRepresentation::EndWriteAccess(sk_sp<SkSurface> surface) {
   DCHECK_EQ(mode_, RepresentationAccessMode::kWrite);
   if (surface) {
     DCHECK(surface_);
@@ -136,7 +135,7 @@
   mode_ = RepresentationAccessMode::kNone;
 }
 
-sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaGL::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaGLImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
   DCHECK_EQ(mode_, RepresentationAccessMode::kNone);
@@ -150,7 +149,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaGL::EndReadAccess() {
+void SkiaGLImageRepresentation::EndReadAccess() {
   DCHECK_EQ(mode_, RepresentationAccessMode::kRead);
   CheckContext();
 
@@ -158,13 +157,13 @@
   mode_ = RepresentationAccessMode::kNone;
 }
 
-void SharedImageRepresentationSkiaGL::CheckContext() {
+void SkiaGLImageRepresentation::CheckContext() {
 #if DCHECK_IS_ON()
   DCHECK(gl::GLContext::GetCurrent() == context_);
 #endif
 }
 
-bool SharedImageRepresentationSkiaGL::SupportsMultipleConcurrentReadAccess() {
+bool SkiaGLImageRepresentation::SupportsMultipleConcurrentReadAccess() {
   return gl_representation_->SupportsMultipleConcurrentReadAccess();
 }
 
diff --git a/gpu/command_buffer/service/shared_image/skia_gl_image_representation.h b/gpu/command_buffer/service/shared_image/skia_gl_image_representation.h
index 62952d9..b4c2a121 100644
--- a/gpu/command_buffer/service/shared_image/skia_gl_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/skia_gl_image_representation.h
@@ -10,23 +10,23 @@
 #include "ui/gl/gl_context.h"
 
 namespace gpu {
-// This is a wrapper class for SharedImageRepresentationSkia to be used in GL
-// mode. For most of the SharedImageBackings, SharedImageRepresentationGLTexture
-// and SharedImageRepresentationSkia implementations do the same work which
+// This is a wrapper class for SkiaImageRepresentation to be used in GL
+// mode. For most of the SharedImageBackings, GLTextureImageRepresentation
+// and SkiaImageRepresentation implementations do the same work which
 // results in duplicate code. Hence instead of implementing
-// SharedImageRepresentationSkia, this wrapper can be directly used or
+// SkiaImageRepresentation, this wrapper can be directly used or
 // implemented by the backings.
-class GPU_GLES2_EXPORT SharedImageRepresentationSkiaGL
-    : public SharedImageRepresentationSkia {
+class GPU_GLES2_EXPORT SkiaGLImageRepresentation
+    : public SkiaImageRepresentation {
  public:
-  static std::unique_ptr<SharedImageRepresentationSkiaGL> Create(
-      std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+  static std::unique_ptr<SkiaGLImageRepresentation> Create(
+      std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
       scoped_refptr<SharedContextState> context_state,
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker);
 
-  ~SharedImageRepresentationSkiaGL() override;
+  ~SkiaGLImageRepresentation() override;
 
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
@@ -46,8 +46,8 @@
   bool SupportsMultipleConcurrentReadAccess() override;
 
  private:
-  SharedImageRepresentationSkiaGL(
-      std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
+  SkiaGLImageRepresentation(
+      std::unique_ptr<GLTextureImageRepresentationBase> gl_representation,
       sk_sp<SkPromiseImageTexture> promise_texture,
       scoped_refptr<SharedContextState> context_state,
       SharedImageManager* manager,
@@ -56,7 +56,7 @@
 
   void CheckContext();
 
-  std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation_;
+  std::unique_ptr<GLTextureImageRepresentationBase> gl_representation_;
   sk_sp<SkPromiseImageTexture> promise_texture_;
   scoped_refptr<SharedContextState> context_state_;
   sk_sp<SkSurface> surface_;
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc
index 5fc75f0..25fc9ef 100644
--- a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc
@@ -31,20 +31,19 @@
 
 namespace gpu {
 
-SharedImageRepresentationSkiaVkAndroid::SharedImageRepresentationSkiaVkAndroid(
+SkiaVkAndroidImageRepresentation::SkiaVkAndroidImageRepresentation(
     SharedImageManager* manager,
-    SharedImageBackingAndroid* backing,
+    AndroidImageBacking* backing,
     scoped_refptr<SharedContextState> context_state,
     MemoryTypeTracker* tracker)
-    : SharedImageRepresentationSkia(manager, backing, tracker),
+    : SkiaImageRepresentation(manager, backing, tracker),
       context_state_(std::move(context_state)) {
   DCHECK(backing);
   DCHECK(context_state_);
   DCHECK(context_state_->vk_context_provider());
 }
 
-SharedImageRepresentationSkiaVkAndroid::
-    ~SharedImageRepresentationSkiaVkAndroid() {
+SkiaVkAndroidImageRepresentation::~SkiaVkAndroidImageRepresentation() {
   DCHECK_EQ(mode_, RepresentationAccessMode::kNone);
   surface_.reset();
   if (vulkan_image_) {
@@ -56,7 +55,7 @@
   }
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkiaVkAndroid::BeginWriteAccess(
+sk_sp<SkSurface> SkiaVkAndroidImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -94,8 +93,7 @@
   return surface_;
 }
 
-sk_sp<SkPromiseImageTexture>
-SharedImageRepresentationSkiaVkAndroid::BeginWriteAccess(
+sk_sp<SkPromiseImageTexture> SkiaVkAndroidImageRepresentation::BeginWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -110,7 +108,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaVkAndroid::EndWriteAccess(
+void SkiaVkAndroidImageRepresentation::EndWriteAccess(
     sk_sp<SkSurface> surface) {
   DCHECK_EQ(mode_, RepresentationAccessMode::kWrite);
   if (surface) {
@@ -128,8 +126,7 @@
   EndAccess(false /* readonly */);
 }
 
-sk_sp<SkPromiseImageTexture>
-SharedImageRepresentationSkiaVkAndroid::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaVkAndroidImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -145,7 +142,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaVkAndroid::EndReadAccess() {
+void SkiaVkAndroidImageRepresentation::EndReadAccess() {
   DCHECK_EQ(mode_, RepresentationAccessMode::kRead);
   DCHECK(!surface_);
 
@@ -153,29 +150,29 @@
 }
 
 gpu::VulkanImplementation*
-SharedImageRepresentationSkiaVkAndroid::vk_implementation() {
+SkiaVkAndroidImageRepresentation::vk_implementation() {
   return context_state_->vk_context_provider()->GetVulkanImplementation();
 }
 
-VkDevice SharedImageRepresentationSkiaVkAndroid::vk_device() {
+VkDevice SkiaVkAndroidImageRepresentation::vk_device() {
   return context_state_->vk_context_provider()
       ->GetDeviceQueue()
       ->GetVulkanDevice();
 }
 
-VkPhysicalDevice SharedImageRepresentationSkiaVkAndroid::vk_phy_device() {
+VkPhysicalDevice SkiaVkAndroidImageRepresentation::vk_phy_device() {
   return context_state_->vk_context_provider()
       ->GetDeviceQueue()
       ->GetVulkanPhysicalDevice();
 }
 
-VkQueue SharedImageRepresentationSkiaVkAndroid::vk_queue() {
+VkQueue SkiaVkAndroidImageRepresentation::vk_queue() {
   return context_state_->vk_context_provider()
       ->GetDeviceQueue()
       ->GetVulkanQueue();
 }
 
-bool SharedImageRepresentationSkiaVkAndroid::BeginAccess(
+bool SkiaVkAndroidImageRepresentation::BeginAccess(
     bool readonly,
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
@@ -235,7 +232,7 @@
   return true;
 }
 
-void SharedImageRepresentationSkiaVkAndroid::EndAccess(bool readonly) {
+void SkiaVkAndroidImageRepresentation::EndAccess(bool readonly) {
   base::ScopedFD sync_fd;
   if (end_access_semaphore_ != VK_NULL_HANDLE) {
     SemaphoreHandle semaphore_handle = vk_implementation()->GetSemaphoreHandle(
@@ -272,7 +269,7 @@
 }
 
 std::unique_ptr<GrBackendSurfaceMutableState>
-SharedImageRepresentationSkiaVkAndroid::GetEndAccessState() {
+SkiaVkAndroidImageRepresentation::GetEndAccessState() {
   // There is no layout to change if there is no image.
   if (!vulkan_image_)
     return nullptr;
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.h b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.h
index 83043ba..e76157e 100644
--- a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.h
@@ -14,22 +14,21 @@
 
 namespace gpu {
 class SharedContextState;
-class SharedImageBackingAndroid;
+class AndroidImageBacking;
 class VulkanImage;
 class VulkanImplementation;
 
 // A generic Skia vulkan representation which can be used by any backing on
 // Android.
-class SharedImageRepresentationSkiaVkAndroid
-    : public SharedImageRepresentationSkia {
+class SkiaVkAndroidImageRepresentation : public SkiaImageRepresentation {
  public:
-  SharedImageRepresentationSkiaVkAndroid(
+  SkiaVkAndroidImageRepresentation(
       SharedImageManager* manager,
-      SharedImageBackingAndroid* backing,
+      AndroidImageBacking* backing,
       scoped_refptr<SharedContextState> context_state,
       MemoryTypeTracker* tracker);
 
-  ~SharedImageRepresentationSkiaVkAndroid() override;
+  ~SkiaVkAndroidImageRepresentation() override;
 
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
@@ -49,8 +48,8 @@
   void EndReadAccess() override;
 
  protected:
-  SharedImageBackingAndroid* android_backing() const {
-    return static_cast<SharedImageBackingAndroid*>(backing());
+  AndroidImageBacking* android_backing() const {
+    return static_cast<AndroidImageBacking*>(backing());
   }
 
   SharedContextState* context_state() const { return context_state_.get(); }
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc
index d6d47d8..2ed518b 100644
--- a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc
@@ -27,14 +27,14 @@
 
 namespace gpu {
 
-// Vk backed Skia representation of SharedImageBackingOzone.
-SharedImageRepresentationSkiaVkOzone::SharedImageRepresentationSkiaVkOzone(
+// Vk backed Skia representation of OzoneImageBacking.
+SkiaVkOzoneImageRepresentation::SkiaVkOzoneImageRepresentation(
     SharedImageManager* manager,
-    SharedImageBackingOzone* backing,
+    OzoneImageBacking* backing,
     scoped_refptr<SharedContextState> context_state,
     std::unique_ptr<VulkanImage> vulkan_image,
     MemoryTypeTracker* tracker)
-    : SharedImageRepresentationSkia(manager, backing, tracker),
+    : SkiaImageRepresentation(manager, backing, tracker),
       vulkan_image_(std::move(vulkan_image)),
       context_state_(std::move(context_state)) {
   DCHECK(backing);
@@ -48,7 +48,7 @@
   DCHECK(promise_texture_);
 }
 
-SharedImageRepresentationSkiaVkOzone::~SharedImageRepresentationSkiaVkOzone() {
+SkiaVkOzoneImageRepresentation::~SkiaVkOzoneImageRepresentation() {
   DCHECK_EQ(mode_, RepresentationAccessMode::kNone);
   surface_.reset();
   if (vulkan_image_) {
@@ -60,7 +60,7 @@
   }
 }
 
-sk_sp<SkSurface> SharedImageRepresentationSkiaVkOzone::BeginWriteAccess(
+sk_sp<SkSurface> SkiaVkOzoneImageRepresentation::BeginWriteAccess(
     int final_msaa_count,
     const SkSurfaceProps& surface_props,
     std::vector<GrBackendSemaphore>* begin_semaphores,
@@ -76,7 +76,7 @@
   if (gr_context->abandoned()) {
     LOG(ERROR) << "GrContext is abandoned.";
     ozone_backing()->EndAccess(/*readonly=*/false,
-                               SharedImageBackingOzone::AccessStream::kVulkan,
+                               OzoneImageBacking::AccessStream::kVulkan,
                                gfx::GpuFenceHandle());
     return nullptr;
   }
@@ -92,7 +92,7 @@
     if (!surface_) {
       LOG(ERROR) << "MakeFromBackendTexture() failed.";
       ozone_backing()->EndAccess(/*readonly=*/false,
-                                 SharedImageBackingOzone::AccessStream::kVulkan,
+                                 OzoneImageBacking::AccessStream::kVulkan,
                                  gfx::GpuFenceHandle());
       return nullptr;
     }
@@ -103,8 +103,7 @@
   return surface_;
 }
 
-sk_sp<SkPromiseImageTexture>
-SharedImageRepresentationSkiaVkOzone::BeginWriteAccess(
+sk_sp<SkPromiseImageTexture> SkiaVkOzoneImageRepresentation::BeginWriteAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -118,8 +117,7 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaVkOzone::EndWriteAccess(
-    sk_sp<SkSurface> surface) {
+void SkiaVkOzoneImageRepresentation::EndWriteAccess(sk_sp<SkSurface> surface) {
   DCHECK_EQ(mode_, RepresentationAccessMode::kWrite);
   if (surface) {
     DCHECK_EQ(surface.get(), surface_.get());
@@ -130,8 +128,7 @@
   EndAccess(false /* readonly */);
 }
 
-sk_sp<SkPromiseImageTexture>
-SharedImageRepresentationSkiaVkOzone::BeginReadAccess(
+sk_sp<SkPromiseImageTexture> SkiaVkOzoneImageRepresentation::BeginReadAccess(
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores,
     std::unique_ptr<GrBackendSurfaceMutableState>* end_state) {
@@ -146,25 +143,24 @@
   return promise_texture_;
 }
 
-void SharedImageRepresentationSkiaVkOzone::EndReadAccess() {
+void SkiaVkOzoneImageRepresentation::EndReadAccess() {
   DCHECK_EQ(mode_, RepresentationAccessMode::kRead);
   DCHECK(!surface_);
 
   EndAccess(true /* readonly */);
 }
 
-gpu::VulkanImplementation*
-SharedImageRepresentationSkiaVkOzone::vk_implementation() {
+gpu::VulkanImplementation* SkiaVkOzoneImageRepresentation::vk_implementation() {
   return context_state_->vk_context_provider()->GetVulkanImplementation();
 }
 
-VkDevice SharedImageRepresentationSkiaVkOzone::vk_device() {
+VkDevice SkiaVkOzoneImageRepresentation::vk_device() {
   return context_state_->vk_context_provider()
       ->GetDeviceQueue()
       ->GetVulkanDevice();
 }
 
-bool SharedImageRepresentationSkiaVkOzone::BeginAccess(
+bool SkiaVkOzoneImageRepresentation::BeginAccess(
     bool readonly,
     std::vector<GrBackendSemaphore>* begin_semaphores,
     std::vector<GrBackendSemaphore>* end_semaphores) {
@@ -172,9 +168,9 @@
   DCHECK(end_access_semaphore_ == VK_NULL_HANDLE);
 
   std::vector<gfx::GpuFenceHandle> fences;
-  if (!ozone_backing()->BeginAccess(
-          readonly, SharedImageBackingOzone::AccessStream::kVulkan, &fences,
-          need_end_fence_))
+  if (!ozone_backing()->BeginAccess(readonly,
+                                    OzoneImageBacking::AccessStream::kVulkan,
+                                    &fences, need_end_fence_))
     return false;
 
   VkDevice device = vk_device();
@@ -196,7 +192,7 @@
     if (end_access_semaphore_ == VK_NULL_HANDLE) {
       DLOG(ERROR) << "Failed to create the external semaphore.";
       ozone_backing()->EndAccess(readonly,
-                                 SharedImageBackingOzone::AccessStream::kVulkan,
+                                 OzoneImageBacking::AccessStream::kVulkan,
                                  gfx::GpuFenceHandle());
       return false;
     }
@@ -210,7 +206,7 @@
   return true;
 }
 
-void SharedImageRepresentationSkiaVkOzone::EndAccess(bool readonly) {
+void SkiaVkOzoneImageRepresentation::EndAccess(bool readonly) {
   gfx::GpuFenceHandle fence;
   if (end_access_semaphore_ != VK_NULL_HANDLE) {
     SemaphoreHandle semaphore_handle = vk_implementation()->GetSemaphoreHandle(
@@ -219,8 +215,7 @@
     DCHECK(!fence.is_null());
   }
 
-  ozone_backing()->EndAccess(readonly,
-                             SharedImageBackingOzone::AccessStream::kVulkan,
+  ozone_backing()->EndAccess(readonly, OzoneImageBacking::AccessStream::kVulkan,
                              std::move(fence));
 
   std::vector<VkSemaphore> semaphores = std::move(begin_access_semaphores_);
@@ -241,7 +236,7 @@
 }
 
 std::unique_ptr<GrBackendSurfaceMutableState>
-SharedImageRepresentationSkiaVkOzone::GetEndAccessState() {
+SkiaVkOzoneImageRepresentation::GetEndAccessState() {
   // There is no layout to change if there is no image.
   if (!vulkan_image_)
     return nullptr;
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.h b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.h
index a30938f..8409c36a 100644
--- a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.h
@@ -14,22 +14,21 @@
 
 namespace gpu {
 class SharedContextState;
-class SharedImageBackingOzone;
+class OzoneImageBacking;
 class VulkanImage;
 class VulkanImplementation;
 
 // A generic Skia vulkan representation which can be used by Ozone backing.
-class SharedImageRepresentationSkiaVkOzone
-    : public SharedImageRepresentationSkia {
+class SkiaVkOzoneImageRepresentation : public SkiaImageRepresentation {
  public:
-  SharedImageRepresentationSkiaVkOzone(
+  SkiaVkOzoneImageRepresentation(
       SharedImageManager* manager,
-      SharedImageBackingOzone* backing,
+      OzoneImageBacking* backing,
       scoped_refptr<SharedContextState> context_state,
       std::unique_ptr<VulkanImage> vulkan_image,
       MemoryTypeTracker* tracker);
 
-  ~SharedImageRepresentationSkiaVkOzone() override;
+  ~SkiaVkOzoneImageRepresentation() override;
 
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
@@ -49,8 +48,8 @@
   void EndReadAccess() override;
 
  protected:
-  SharedImageBackingOzone* ozone_backing() const {
-    return static_cast<SharedImageBackingOzone*>(backing());
+  OzoneImageBacking* ozone_backing() const {
+    return static_cast<OzoneImageBacking*>(backing());
   }
 
   SharedContextState* context_state() const { return context_state_.get(); }
diff --git a/gpu/command_buffer/service/shared_image/test_image_backing.cc b/gpu/command_buffer/service/shared_image/test_image_backing.cc
index 08fd7c19..6da9a3a0 100644
--- a/gpu/command_buffer/service/shared_image/test_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/test_image_backing.cc
@@ -14,36 +14,33 @@
 
 namespace gpu {
 namespace {
-class TestSharedImageRepresentationGLTexture
-    : public SharedImageRepresentationGLTexture {
+class TestGLTextureImageRepresentation : public GLTextureImageRepresentation {
  public:
-  TestSharedImageRepresentationGLTexture(SharedImageManager* manager,
-                                         SharedImageBacking* backing,
-                                         MemoryTypeTracker* tracker,
-                                         gles2::Texture* texture)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
+  TestGLTextureImageRepresentation(SharedImageManager* manager,
+                                   SharedImageBacking* backing,
+                                   MemoryTypeTracker* tracker,
+                                   gles2::Texture* texture)
+      : GLTextureImageRepresentation(manager, backing, tracker),
         texture_(texture) {}
 
   gles2::Texture* GetTexture() override { return texture_; }
   bool BeginAccess(GLenum mode) override {
-    return static_cast<TestSharedImageBacking*>(backing())->can_access();
+    return static_cast<TestImageBacking*>(backing())->can_access();
   }
 
  private:
   const raw_ptr<gles2::Texture> texture_;
 };
 
-class TestSharedImageRepresentationGLTexturePassthrough
-    : public SharedImageRepresentationGLTexturePassthrough {
+class TestGLTexturePassthroughImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  TestSharedImageRepresentationGLTexturePassthrough(
+  TestGLTexturePassthroughImageRepresentation(
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
       scoped_refptr<gles2::TexturePassthrough> texture)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
+      : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
         texture_(std::move(texture)) {}
 
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
@@ -51,19 +48,19 @@
     return texture_;
   }
   bool BeginAccess(GLenum mode) override {
-    return static_cast<TestSharedImageBacking*>(backing())->can_access();
+    return static_cast<TestImageBacking*>(backing())->can_access();
   }
 
  private:
   const scoped_refptr<gles2::TexturePassthrough> texture_;
 };
 
-class TestSharedImageRepresentationSkia : public SharedImageRepresentationSkia {
+class TestSkiaImageRepresentation : public SkiaImageRepresentation {
  public:
-  TestSharedImageRepresentationSkia(SharedImageManager* manager,
-                                    SharedImageBacking* backing,
-                                    MemoryTypeTracker* tracker)
-      : SharedImageRepresentationSkia(manager, backing, tracker) {}
+  TestSkiaImageRepresentation(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker)
+      : SkiaImageRepresentation(manager, backing, tracker) {}
 
  protected:
   sk_sp<SkSurface> BeginWriteAccess(
@@ -71,7 +68,7 @@
       const SkSurfaceProps& surface_props,
       std::vector<GrBackendSemaphore>* begin_semaphores,
       std::vector<GrBackendSemaphore>* end_semaphores) override {
-    if (!static_cast<TestSharedImageBacking*>(backing())->can_access()) {
+    if (!static_cast<TestImageBacking*>(backing())->can_access()) {
       return nullptr;
     }
     SkSurfaceProps props = skia::LegacyDisplayGlobals::GetSkSurfaceProps();
@@ -82,7 +79,7 @@
       std::vector<GrBackendSemaphore>* begin_semaphores,
       std::vector<GrBackendSemaphore>* end_semaphores,
       std::unique_ptr<GrBackendSurfaceMutableState>* end_state) override {
-    if (!static_cast<TestSharedImageBacking*>(backing())->can_access()) {
+    if (!static_cast<TestImageBacking*>(backing())->can_access()) {
       return nullptr;
     }
     GrBackendTexture backend_tex(size().width(), size().height(),
@@ -93,7 +90,7 @@
   sk_sp<SkPromiseImageTexture> BeginReadAccess(
       std::vector<GrBackendSemaphore>* begin_semaphores,
       std::vector<GrBackendSemaphore>* end_semaphores) override {
-    if (!static_cast<TestSharedImageBacking*>(backing())->can_access()) {
+    if (!static_cast<TestImageBacking*>(backing())->can_access()) {
       return nullptr;
     }
     GrBackendTexture backend_tex(size().width(), size().height(),
@@ -103,15 +100,15 @@
   void EndReadAccess() override {}
 };
 
-class TestSharedImageRepresentationDawn : public SharedImageRepresentationDawn {
+class TestDawnImageRepresentation : public DawnImageRepresentation {
  public:
-  TestSharedImageRepresentationDawn(SharedImageManager* manager,
-                                    SharedImageBacking* backing,
-                                    MemoryTypeTracker* tracker)
-      : SharedImageRepresentationDawn(manager, backing, tracker) {}
+  TestDawnImageRepresentation(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker)
+      : DawnImageRepresentation(manager, backing, tracker) {}
 
   WGPUTexture BeginAccess(WGPUTextureUsage usage) override {
-    if (!static_cast<TestSharedImageBacking*>(backing())->can_access()) {
+    if (!static_cast<TestImageBacking*>(backing())->can_access()) {
       return nullptr;
     }
 
@@ -122,13 +119,12 @@
   void EndAccess() override {}
 };
 
-class TestSharedImageRepresentationOverlay
-    : public SharedImageRepresentationOverlay {
+class TestOverlayImageRepresentation : public OverlayImageRepresentation {
  public:
-  TestSharedImageRepresentationOverlay(SharedImageManager* manager,
-                                       SharedImageBacking* backing,
-                                       MemoryTypeTracker* tracker)
-      : SharedImageRepresentationOverlay(manager, backing, tracker) {}
+  TestOverlayImageRepresentation(SharedImageManager* manager,
+                                 SharedImageBacking* backing,
+                                 MemoryTypeTracker* tracker)
+      : OverlayImageRepresentation(manager, backing, tracker) {}
 
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override {
     return true;
@@ -139,16 +135,15 @@
 
 }  // namespace
 
-TestSharedImageBacking::TestSharedImageBacking(
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage,
-    size_t estimated_size,
-    GLuint texture_id)
+TestImageBacking::TestImageBacking(const Mailbox& mailbox,
+                                   viz::ResourceFormat format,
+                                   const gfx::Size& size,
+                                   const gfx::ColorSpace& color_space,
+                                   GrSurfaceOrigin surface_origin,
+                                   SkAlphaType alpha_type,
+                                   uint32_t usage,
+                                   size_t estimated_size,
+                                   GLuint texture_id)
     : SharedImageBacking(mailbox,
                          format,
                          size,
@@ -174,30 +169,29 @@
       service_id_, GL_TEXTURE_2D);
 }
 
-TestSharedImageBacking::TestSharedImageBacking(
-    const Mailbox& mailbox,
-    viz::ResourceFormat format,
-    const gfx::Size& size,
-    const gfx::ColorSpace& color_space,
-    GrSurfaceOrigin surface_origin,
-    SkAlphaType alpha_type,
-    uint32_t usage,
-    size_t estimated_size)
-    : TestSharedImageBacking(mailbox,
-                             format,
-                             size,
-                             color_space,
-                             surface_origin,
-                             alpha_type,
-                             usage,
-                             estimated_size,
-                             203 /* texture_id */) {
+TestImageBacking::TestImageBacking(const Mailbox& mailbox,
+                                   viz::ResourceFormat format,
+                                   const gfx::Size& size,
+                                   const gfx::ColorSpace& color_space,
+                                   GrSurfaceOrigin surface_origin,
+                                   SkAlphaType alpha_type,
+                                   uint32_t usage,
+                                   size_t estimated_size)
+    : TestImageBacking(mailbox,
+                       format,
+                       size,
+                       color_space,
+                       surface_origin,
+                       alpha_type,
+                       usage,
+                       estimated_size,
+                       203 /* texture_id */) {
   // Using a dummy |texture_id|, so lose our context so we don't do anything
   // real with it.
   OnContextLost();
 }
 
-TestSharedImageBacking::~TestSharedImageBacking() {
+TestImageBacking::~TestImageBacking() {
   // Pretend our context is lost to avoid actual cleanup in |texture_| or
   // |passthrough_texture_|.
   texture_->RemoveLightweightRef(false /* have_context */);
@@ -208,70 +202,65 @@
     glDeleteTextures(1, &service_id_);
 }
 
-bool TestSharedImageBacking::GetUploadFromMemoryCalledAndReset() {
+bool TestImageBacking::GetUploadFromMemoryCalledAndReset() {
   return std::exchange(upload_from_memory_called_, false);
 }
 
-SharedImageBackingType TestSharedImageBacking::GetType() const {
+SharedImageBackingType TestImageBacking::GetType() const {
   return SharedImageBackingType::kTest;
 }
 
-gfx::Rect TestSharedImageBacking::ClearedRect() const {
+gfx::Rect TestImageBacking::ClearedRect() const {
   return texture_->GetLevelClearedRect(texture_->target(), 0);
 }
 
-void TestSharedImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
+void TestImageBacking::SetClearedRect(const gfx::Rect& cleared_rect) {
   texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
 }
 
-bool TestSharedImageBacking::UploadFromMemory(const SkPixmap& pixmap) {
+bool TestImageBacking::UploadFromMemory(const SkPixmap& pixmap) {
   upload_from_memory_called_ = true;
   return true;
 }
 
-bool TestSharedImageBacking::ProduceLegacyMailbox(
-    MailboxManager* mailbox_manager) {
+bool TestImageBacking::ProduceLegacyMailbox(MailboxManager* mailbox_manager) {
   return false;
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-TestSharedImageBacking::ProduceGLTexture(SharedImageManager* manager,
-                                         MemoryTypeTracker* tracker) {
-  return std::make_unique<TestSharedImageRepresentationGLTexture>(
-      manager, this, tracker, texture_);
+std::unique_ptr<GLTextureImageRepresentation>
+TestImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                   MemoryTypeTracker* tracker) {
+  return std::make_unique<TestGLTextureImageRepresentation>(manager, this,
+                                                            tracker, texture_);
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-TestSharedImageBacking::ProduceGLTexturePassthrough(
-    SharedImageManager* manager,
-    MemoryTypeTracker* tracker) {
-  return std::make_unique<TestSharedImageRepresentationGLTexturePassthrough>(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+TestImageBacking::ProduceGLTexturePassthrough(SharedImageManager* manager,
+                                              MemoryTypeTracker* tracker) {
+  return std::make_unique<TestGLTexturePassthroughImageRepresentation>(
       manager, this, tracker, texture_passthrough_);
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-TestSharedImageBacking::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> TestImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
-  return std::make_unique<TestSharedImageRepresentationSkia>(manager, this,
-                                                             tracker);
+  return std::make_unique<TestSkiaImageRepresentation>(manager, this, tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationDawn>
-TestSharedImageBacking::ProduceDawn(SharedImageManager* manager,
-                                    MemoryTypeTracker* tracker,
-                                    WGPUDevice device,
-                                    WGPUBackendType backend_type) {
-  return std::make_unique<TestSharedImageRepresentationDawn>(manager, this,
-                                                             tracker);
+std::unique_ptr<DawnImageRepresentation> TestImageBacking::ProduceDawn(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    WGPUDevice device,
+    WGPUBackendType backend_type) {
+  return std::make_unique<TestDawnImageRepresentation>(manager, this, tracker);
 }
 
-std::unique_ptr<SharedImageRepresentationOverlay>
-TestSharedImageBacking::ProduceOverlay(SharedImageManager* manager,
-                                       MemoryTypeTracker* tracker) {
-  return std::make_unique<TestSharedImageRepresentationOverlay>(manager, this,
-                                                                tracker);
+std::unique_ptr<OverlayImageRepresentation> TestImageBacking::ProduceOverlay(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  return std::make_unique<TestOverlayImageRepresentation>(manager, this,
+                                                          tracker);
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/test_image_backing.h b/gpu/command_buffer/service/shared_image/test_image_backing.h
index 310b072..a9db0e859 100644
--- a/gpu/command_buffer/service/shared_image/test_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/test_image_backing.h
@@ -12,28 +12,28 @@
 namespace gpu {
 
 // Test implementation of a gles2::Texture backed backing.
-class TestSharedImageBacking : public SharedImageBacking {
+class TestImageBacking : public SharedImageBacking {
  public:
   // Constructor which uses a dummy GL texture ID for the backing.
-  TestSharedImageBacking(const Mailbox& mailbox,
-                         viz::ResourceFormat format,
-                         const gfx::Size& size,
-                         const gfx::ColorSpace& color_space,
-                         GrSurfaceOrigin surface_origin,
-                         SkAlphaType alpha_type,
-                         uint32_t usage,
-                         size_t estimated_size);
+  TestImageBacking(const Mailbox& mailbox,
+                   viz::ResourceFormat format,
+                   const gfx::Size& size,
+                   const gfx::ColorSpace& color_space,
+                   GrSurfaceOrigin surface_origin,
+                   SkAlphaType alpha_type,
+                   uint32_t usage,
+                   size_t estimated_size);
   // Constructor which uses a provided GL texture ID for the backing.
-  TestSharedImageBacking(const Mailbox& mailbox,
-                         viz::ResourceFormat format,
-                         const gfx::Size& size,
-                         const gfx::ColorSpace& color_space,
-                         GrSurfaceOrigin surface_origin,
-                         SkAlphaType alpha_type,
-                         uint32_t usage,
-                         size_t estimated_size,
-                         GLuint texture_id);
-  ~TestSharedImageBacking() override;
+  TestImageBacking(const Mailbox& mailbox,
+                   viz::ResourceFormat format,
+                   const gfx::Size& size,
+                   const gfx::ColorSpace& color_space,
+                   GrSurfaceOrigin surface_origin,
+                   SkAlphaType alpha_type,
+                   uint32_t usage,
+                   size_t estimated_size,
+                   GLuint texture_id);
+  ~TestImageBacking() override;
 
   bool GetUploadFromMemoryCalledAndReset();
 
@@ -55,25 +55,25 @@
   bool can_access() const { return can_access_; }
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
   // ProduceSkia/Dawn/Overlay all create dummy representations that
   // don't link up to a real texture.
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+  std::unique_ptr<DawnImageRepresentation> ProduceDawn(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       WGPUDevice device,
       WGPUBackendType backend_type) override;
-  std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<OverlayImageRepresentation> ProduceOverlay(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
diff --git a/gpu/command_buffer/service/shared_image/test_utils.cc b/gpu/command_buffer/service/shared_image/test_utils.cc
index ed101c8..7636018 100644
--- a/gpu/command_buffer/service/shared_image/test_utils.cc
+++ b/gpu/command_buffer/service/shared_image/test_utils.cc
@@ -28,8 +28,7 @@
   EXPECT_TRUE(skia_representation);
   std::vector<GrBackendSemaphore> begin_semaphores;
   std::vector<GrBackendSemaphore> end_semaphores;
-  std::unique_ptr<SharedImageRepresentationSkia::ScopedReadAccess>
-      scoped_read_access;
+  std::unique_ptr<SkiaImageRepresentation::ScopedReadAccess> scoped_read_access;
   scoped_read_access = skia_representation->BeginScopedReadAccess(
       &begin_semaphores, &end_semaphores);
   auto* promise_texture = scoped_read_access->promise_image_texture();
diff --git a/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.cc b/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.cc
index 809ae224..4576274 100644
--- a/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.cc
@@ -111,7 +111,7 @@
 
 }  // namespace
 
-SharedImageVideoImageReader::SharedImageVideoImageReader(
+VideoImageReaderImageBacking::VideoImageReaderImageBacking(
     const Mailbox& mailbox,
     const gfx::Size& size,
     const gfx::ColorSpace color_space,
@@ -120,12 +120,12 @@
     scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
     scoped_refptr<SharedContextState> context_state,
     scoped_refptr<RefCountedLock> drdc_lock)
-    : SharedImageVideo(mailbox,
-                       size,
-                       color_space,
-                       surface_origin,
-                       alpha_type,
-                       !!drdc_lock),
+    : AndroidVideoImageBacking(mailbox,
+                               size,
+                               color_space,
+                               surface_origin,
+                               alpha_type,
+                               !!drdc_lock),
       RefCountedLockHelperDrDc(std::move(drdc_lock)),
       stream_texture_sii_(std::move(stream_texture_sii)),
       gpu_main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
@@ -136,7 +136,7 @@
       GetDrDcLock());
 }
 
-SharedImageVideoImageReader::~SharedImageVideoImageReader() {
+VideoImageReaderImageBacking::~VideoImageReaderImageBacking() {
   // This backing is created on gpu main thread but can be destroyed on DrDc
   // thread if the last representation was on DrDc thread.
   // |context_lost_helper_| is destroyed here by posting task to the
@@ -159,7 +159,7 @@
   }
 }
 
-size_t SharedImageVideoImageReader::EstimatedSizeForMemTracking() const {
+size_t VideoImageReaderImageBacking::EstimatedSizeForMemTracking() const {
   base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
 
   // This backing contributes to gpu memory only if its bound to the texture
@@ -167,26 +167,26 @@
   return stream_texture_sii_->IsUsingGpuMemory() ? estimated_size() : 0;
 }
 
-// Representation of SharedImageVideoImageReader as a GL Texture.
-class SharedImageVideoImageReader::SharedImageRepresentationGLTextureVideo
-    : public SharedImageRepresentationGLTexture,
+// Representation of VideoImageReaderImageBacking as a GL Texture.
+class VideoImageReaderImageBacking::GLTextureVideoImageRepresentation
+    : public GLTextureImageRepresentation,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageRepresentationGLTextureVideo(
+  GLTextureVideoImageRepresentation(
       SharedImageManager* manager,
-      SharedImageVideoImageReader* backing,
+      VideoImageReaderImageBacking* backing,
       MemoryTypeTracker* tracker,
       std::unique_ptr<gles2::AbstractTexture> texture,
       scoped_refptr<RefCountedLock> drdc_lock)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
+      : GLTextureImageRepresentation(manager, backing, tracker),
         RefCountedLockHelperDrDc(std::move(drdc_lock)),
         texture_(std::move(texture)) {}
 
   // Disallow copy and assign.
-  SharedImageRepresentationGLTextureVideo(
-      const SharedImageRepresentationGLTextureVideo&) = delete;
-  SharedImageRepresentationGLTextureVideo& operator=(
-      const SharedImageRepresentationGLTextureVideo&) = delete;
+  GLTextureVideoImageRepresentation(const GLTextureVideoImageRepresentation&) =
+      delete;
+  GLTextureVideoImageRepresentation& operator=(
+      const GLTextureVideoImageRepresentation&) = delete;
 
   gles2::Texture* GetTexture() override {
     auto* texture = gles2::Texture::CheckedCast(texture_->GetTextureBase());
@@ -199,7 +199,7 @@
     // This representation should only be called for read.
     DCHECK(mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
 
-    auto* video_backing = static_cast<SharedImageVideoImageReader*>(backing());
+    auto* video_backing = static_cast<VideoImageReaderImageBacking*>(backing());
     {
       base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
       scoped_hardware_buffer_ =
@@ -231,21 +231,18 @@
       scoped_hardware_buffer_;
 };
 
-// Representation of SharedImageVideoImageReader as a GL Texture.
-class SharedImageVideoImageReader::
-    SharedImageRepresentationGLTexturePassthroughVideo
-    : public SharedImageRepresentationGLTexturePassthrough,
+// Representation of VideoImageReaderImageBacking as a GL Texture.
+class VideoImageReaderImageBacking::GLTexturePassthroughVideoImageRepresentation
+    : public GLTexturePassthroughImageRepresentation,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageRepresentationGLTexturePassthroughVideo(
+  GLTexturePassthroughVideoImageRepresentation(
       SharedImageManager* manager,
-      SharedImageVideoImageReader* backing,
+      VideoImageReaderImageBacking* backing,
       MemoryTypeTracker* tracker,
       std::unique_ptr<gles2::AbstractTexture> abstract_texture,
       scoped_refptr<RefCountedLock> drdc_lock)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
+      : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
         RefCountedLockHelperDrDc(std::move(drdc_lock)),
         abstract_texture_(std::move(abstract_texture)),
         passthrough_texture_(gles2::TexturePassthrough::CheckedCast(
@@ -255,10 +252,10 @@
   }
 
   // Disallow copy and assign.
-  SharedImageRepresentationGLTexturePassthroughVideo(
-      const SharedImageRepresentationGLTexturePassthroughVideo&) = delete;
-  SharedImageRepresentationGLTexturePassthroughVideo& operator=(
-      const SharedImageRepresentationGLTexturePassthroughVideo&) = delete;
+  GLTexturePassthroughVideoImageRepresentation(
+      const GLTexturePassthroughVideoImageRepresentation&) = delete;
+  GLTexturePassthroughVideoImageRepresentation& operator=(
+      const GLTexturePassthroughVideoImageRepresentation&) = delete;
 
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override {
@@ -269,7 +266,7 @@
     // This representation should only be called for read.
     DCHECK(mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
 
-    auto* video_backing = static_cast<SharedImageVideoImageReader*>(backing());
+    auto* video_backing = static_cast<VideoImageReaderImageBacking*>(backing());
 
     {
       base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
@@ -303,20 +300,20 @@
       scoped_hardware_buffer_;
 };
 
-class SharedImageVideoImageReader::SharedImageRepresentationVideoSkiaVk
-    : public SharedImageRepresentationSkiaVkAndroid,
+class VideoImageReaderImageBacking::SkiaVkVideoImageRepresentation
+    : public SkiaVkAndroidImageRepresentation,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageRepresentationVideoSkiaVk(
+  SkiaVkVideoImageRepresentation(
       SharedImageManager* manager,
-      SharedImageBackingAndroid* backing,
+      AndroidImageBacking* backing,
       scoped_refptr<SharedContextState> context_state,
       MemoryTypeTracker* tracker,
       scoped_refptr<RefCountedLock> drdc_lock)
-      : SharedImageRepresentationSkiaVkAndroid(manager,
-                                               backing,
-                                               std::move(context_state),
-                                               tracker),
+      : SkiaVkAndroidImageRepresentation(manager,
+                                         backing,
+                                         std::move(context_state),
+                                         tracker),
         RefCountedLockHelperDrDc(std::move(drdc_lock)) {}
 
   sk_sp<SkSurface> BeginWriteAccess(
@@ -339,7 +336,7 @@
     base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
 
     DCHECK(!scoped_hardware_buffer_);
-    auto* video_backing = static_cast<SharedImageVideoImageReader*>(backing());
+    auto* video_backing = static_cast<VideoImageReaderImageBacking*>(backing());
     DCHECK(video_backing);
     auto* stream_texture_sii = video_backing->stream_texture_sii_.get();
 
@@ -391,7 +388,7 @@
       DCHECK(promise_texture_);
     }
 
-    auto result = SharedImageRepresentationSkiaVkAndroid::BeginReadAccess(
+    auto result = SkiaVkAndroidImageRepresentation::BeginReadAccess(
         begin_semaphores, end_semaphores, end_state);
     if (!result) {
       Bug1307307Tracker::SetLastAccessError(
@@ -405,7 +402,7 @@
     base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
     DCHECK(scoped_hardware_buffer_);
 
-    SharedImageRepresentationSkiaVkAndroid::EndReadAccess();
+    SkiaVkAndroidImageRepresentation::EndReadAccess();
 
     // Pass the end read access sync fd to the scoped hardware buffer. This
     // will make sure that the AImage associated with the hardware buffer will
@@ -420,9 +417,9 @@
       scoped_hardware_buffer_;
 };
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageVideoImageReader::ProduceGLTexture(SharedImageManager* manager,
-                                              MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+VideoImageReaderImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                               MemoryTypeTracker* tracker) {
   base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
 
   // For (old) overlays, we don't have a texture owner, but overlay promotion
@@ -436,12 +433,12 @@
   if (!texture)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationGLTextureVideo>(
+  return std::make_unique<GLTextureVideoImageRepresentation>(
       manager, this, tracker, std::move(texture), GetDrDcLock());
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageVideoImageReader::ProduceGLTexturePassthrough(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+VideoImageReaderImageBacking::ProduceGLTexturePassthrough(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
@@ -457,12 +454,12 @@
   if (!texture)
     return nullptr;
 
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughVideo>(
+  return std::make_unique<GLTexturePassthroughVideoImageRepresentation>(
       manager, this, tracker, std::move(texture), GetDrDcLock());
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageVideoImageReader::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation>
+VideoImageReaderImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -479,7 +476,7 @@
     return nullptr;
   }
   if (context_state->GrContextIsVulkan()) {
-    return std::make_unique<SharedImageRepresentationVideoSkiaVk>(
+    return std::make_unique<SkiaVkVideoImageRepresentation>(
         manager, this, std::move(context_state), tracker, GetDrDcLock());
   }
 
@@ -496,18 +493,16 @@
     return nullptr;
   }
 
-  std::unique_ptr<gpu::SharedImageRepresentationGLTextureBase>
-      gl_representation;
+  std::unique_ptr<gpu::GLTextureImageRepresentationBase> gl_representation;
   if (passthrough) {
     gl_representation =
-        std::make_unique<SharedImageRepresentationGLTexturePassthroughVideo>(
+        std::make_unique<GLTexturePassthroughVideoImageRepresentation>(
             manager, this, tracker, std::move(texture), GetDrDcLock());
   } else {
-    gl_representation =
-        std::make_unique<SharedImageRepresentationGLTextureVideo>(
-            manager, this, tracker, std::move(texture), GetDrDcLock());
+    gl_representation = std::make_unique<GLTextureVideoImageRepresentation>(
+        manager, this, tracker, std::move(texture), GetDrDcLock());
   }
-  auto skia_representation = SharedImageRepresentationSkiaGL::Create(
+  auto skia_representation = SkiaGLImageRepresentation::Create(
       std::move(gl_representation), std::move(context_state), manager, this,
       tracker);
 
@@ -519,29 +514,29 @@
   return skia_representation;
 }
 
-// Representation of SharedImageVideoImageReader as an overlay plane.
-class SharedImageVideoImageReader::SharedImageRepresentationOverlayVideo
-    : public gpu::SharedImageRepresentationOverlay,
+// Representation of VideoImageReaderImageBacking as an overlay plane.
+class VideoImageReaderImageBacking::OverlayVideoImageRepresentation
+    : public gpu::OverlayImageRepresentation,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageRepresentationOverlayVideo(gpu::SharedImageManager* manager,
-                                        SharedImageVideoImageReader* backing,
-                                        gpu::MemoryTypeTracker* tracker,
-                                        scoped_refptr<RefCountedLock> drdc_lock)
-      : gpu::SharedImageRepresentationOverlay(manager, backing, tracker),
+  OverlayVideoImageRepresentation(gpu::SharedImageManager* manager,
+                                  VideoImageReaderImageBacking* backing,
+                                  gpu::MemoryTypeTracker* tracker,
+                                  scoped_refptr<RefCountedLock> drdc_lock)
+      : gpu::OverlayImageRepresentation(manager, backing, tracker),
         RefCountedLockHelperDrDc(std::move(drdc_lock)) {}
 
   // Disallow copy and assign.
-  SharedImageRepresentationOverlayVideo(
-      const SharedImageRepresentationOverlayVideo&) = delete;
-  SharedImageRepresentationOverlayVideo& operator=(
-      const SharedImageRepresentationOverlayVideo&) = delete;
+  OverlayVideoImageRepresentation(const OverlayVideoImageRepresentation&) =
+      delete;
+  OverlayVideoImageRepresentation& operator=(
+      const OverlayVideoImageRepresentation&) = delete;
 
  protected:
   bool BeginReadAccess(gfx::GpuFenceHandle& acquire_fence) override {
     base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
     // A |CodecImage| must have TextureOwner() for SurfaceControl overlays.
-    // Legacy overlays are handled by SharedImageRepresentationLegacyOverlay.
+    // Legacy overlays are handled by LegacyOverlayImageRepresentation.
     DCHECK(stream_image()->HasTextureOwner());
     scoped_hardware_buffer_ = stream_image()->GetAHardwareBuffer();
 
@@ -601,30 +596,28 @@
   scoped_refptr<VideoImage> gl_image_;
 
   StreamTextureSharedImageInterface* stream_image() {
-    auto* video_backing = static_cast<SharedImageVideoImageReader*>(backing());
+    auto* video_backing = static_cast<VideoImageReaderImageBacking*>(backing());
     DCHECK(video_backing);
     return video_backing->stream_texture_sii_.get();
   }
 };
 
-// Representation of SharedImageVideoImageReader as an SurfaceView overlay
+// Representation of VideoImageReaderImageBacking as an SurfaceView overlay
 // plane.
-class SharedImageVideoImageReader::SharedImageRepresentationLegacyOverlayVideo
-    : public gpu::SharedImageRepresentationLegacyOverlay,
+class VideoImageReaderImageBacking::LegacyOverlayVideoImageRepresentation
+    : public gpu::LegacyOverlayImageRepresentation,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageRepresentationLegacyOverlayVideo(
-      gpu::SharedImageManager* manager,
-      SharedImageVideoImageReader* backing,
-      gpu::MemoryTypeTracker* tracker,
-      scoped_refptr<RefCountedLock> drdc_lock)
-      : gpu::SharedImageRepresentationLegacyOverlay(manager, backing, tracker),
+  LegacyOverlayVideoImageRepresentation(gpu::SharedImageManager* manager,
+                                        VideoImageReaderImageBacking* backing,
+                                        gpu::MemoryTypeTracker* tracker,
+                                        scoped_refptr<RefCountedLock> drdc_lock)
+      : gpu::LegacyOverlayImageRepresentation(manager, backing, tracker),
         RefCountedLockHelperDrDc(std::move(drdc_lock)) {}
 
   void RenderToOverlay() override {
-    TRACE_EVENT0(
-        "media",
-        "SharedImageRepresentationLegacyOverlayVideo::RenderToOverlay");
+    TRACE_EVENT0("media",
+                 "LegacyOverlayVideoImageRepresentation::RenderToOverlay");
 
     base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
     auto* stream_texture_sii = stream_image();
@@ -640,28 +633,28 @@
   }
 
   StreamTextureSharedImageInterface* stream_image() {
-    auto* video_backing = static_cast<SharedImageVideoImageReader*>(backing());
+    auto* video_backing = static_cast<VideoImageReaderImageBacking*>(backing());
     DCHECK(video_backing);
     return video_backing->stream_texture_sii_.get();
   }
 };
 
-std::unique_ptr<gpu::SharedImageRepresentationOverlay>
-SharedImageVideoImageReader::ProduceOverlay(gpu::SharedImageManager* manager,
-                                            gpu::MemoryTypeTracker* tracker) {
-  return std::make_unique<SharedImageRepresentationOverlayVideo>(
+std::unique_ptr<gpu::OverlayImageRepresentation>
+VideoImageReaderImageBacking::ProduceOverlay(gpu::SharedImageManager* manager,
+                                             gpu::MemoryTypeTracker* tracker) {
+  return std::make_unique<OverlayVideoImageRepresentation>(
       manager, this, tracker, GetDrDcLock());
 }
 
-std::unique_ptr<gpu::SharedImageRepresentationLegacyOverlay>
-SharedImageVideoImageReader::ProduceLegacyOverlay(
+std::unique_ptr<gpu::LegacyOverlayImageRepresentation>
+VideoImageReaderImageBacking::ProduceLegacyOverlay(
     gpu::SharedImageManager* manager,
     gpu::MemoryTypeTracker* tracker) {
-  return std::make_unique<SharedImageRepresentationLegacyOverlayVideo>(
+  return std::make_unique<LegacyOverlayVideoImageRepresentation>(
       manager, this, tracker, GetDrDcLock());
 }
 
-SharedImageVideoImageReader::ContextLostObserverHelper::
+VideoImageReaderImageBacking::ContextLostObserverHelper::
     ContextLostObserverHelper(
         scoped_refptr<SharedContextState> context_state,
         scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
@@ -677,7 +670,7 @@
   context_state_->AddContextLostObserver(this);
 }
 
-SharedImageVideoImageReader::ContextLostObserverHelper::
+VideoImageReaderImageBacking::ContextLostObserverHelper::
     ~ContextLostObserverHelper() {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
 
@@ -691,7 +684,7 @@
 }
 
 // SharedContextState::ContextLostObserver implementation.
-void SharedImageVideoImageReader::ContextLostObserverHelper::OnContextLost() {
+void VideoImageReaderImageBacking::ContextLostObserverHelper::OnContextLost() {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
   base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
 
diff --git a/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.h b/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.h
index 20f0ba13..ca99c71b 100644
--- a/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/video_image_reader_image_backing.h
@@ -17,17 +17,17 @@
 #include "gpu/gpu_gles2_export.h"
 
 namespace gpu {
-class SharedImageRepresentationGLTexture;
-class SharedImageRepresentationSkia;
+class GLTextureImageRepresentation;
+class SkiaImageRepresentation;
 struct Mailbox;
 
 // Implementation of SharedImageBacking that renders MediaCodec buffers to a
 // TextureOwner or overlay as needed in order to draw them.
-class GPU_GLES2_EXPORT SharedImageVideoImageReader
-    : public SharedImageVideo,
+class GPU_GLES2_EXPORT VideoImageReaderImageBacking
+    : public AndroidVideoImageBacking,
       public RefCountedLockHelperDrDc {
  public:
-  SharedImageVideoImageReader(
+  VideoImageReaderImageBacking(
       const Mailbox& mailbox,
       const gfx::Size& size,
       const gfx::ColorSpace color_space,
@@ -37,37 +37,37 @@
       scoped_refptr<SharedContextState> shared_context_state,
       scoped_refptr<RefCountedLock> drdc_lock);
 
-  ~SharedImageVideoImageReader() override;
+  ~VideoImageReaderImageBacking() override;
 
   // Disallow copy and assign.
-  SharedImageVideoImageReader(const SharedImageVideoImageReader&) = delete;
-  SharedImageVideoImageReader& operator=(const SharedImageVideoImageReader&) =
+  VideoImageReaderImageBacking(const VideoImageReaderImageBacking&) = delete;
+  VideoImageReaderImageBacking& operator=(const VideoImageReaderImageBacking&) =
       delete;
 
   // SharedImageBacking implementation.
   size_t EstimatedSizeForMemTracking() const override;
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
-  std::unique_ptr<gpu::SharedImageRepresentationOverlay> ProduceOverlay(
+  std::unique_ptr<gpu::OverlayImageRepresentation> ProduceOverlay(
       gpu::SharedImageManager* manager,
       gpu::MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<gpu::SharedImageRepresentationLegacyOverlay>
-  ProduceLegacyOverlay(gpu::SharedImageManager* manager,
-                       gpu::MemoryTypeTracker* tracker) override;
+  std::unique_ptr<gpu::LegacyOverlayImageRepresentation> ProduceLegacyOverlay(
+      gpu::SharedImageManager* manager,
+      gpu::MemoryTypeTracker* tracker) override;
 
  private:
   // Helper class for observing SharedContext loss on gpu main thread and
@@ -92,11 +92,11 @@
     scoped_refptr<base::SingleThreadTaskRunner> gpu_main_task_runner_;
   };
 
-  class SharedImageRepresentationGLTextureVideo;
-  class SharedImageRepresentationGLTexturePassthroughVideo;
-  class SharedImageRepresentationVideoSkiaVk;
-  class SharedImageRepresentationOverlayVideo;
-  class SharedImageRepresentationLegacyOverlayVideo;
+  class GLTextureVideoImageRepresentation;
+  class GLTexturePassthroughVideoImageRepresentation;
+  class SkiaVkVideoImageRepresentation;
+  class OverlayVideoImageRepresentation;
+  class LegacyOverlayVideoImageRepresentation;
 
   std::unique_ptr<ContextLostObserverHelper> context_lost_helper_;
   scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii_;
diff --git a/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.cc b/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.cc
index 15f27b50..d54262c 100644
--- a/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.cc
@@ -26,7 +26,7 @@
 
 namespace gpu {
 
-SharedImageVideoSurfaceTexture::SharedImageVideoSurfaceTexture(
+VideoSurfaceTextureImageBacking::VideoSurfaceTextureImageBacking(
     const Mailbox& mailbox,
     const gfx::Size& size,
     const gfx::ColorSpace color_space,
@@ -34,12 +34,12 @@
     SkAlphaType alpha_type,
     scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
     scoped_refptr<SharedContextState> context_state)
-    : SharedImageVideo(mailbox,
-                       size,
-                       color_space,
-                       surface_origin,
-                       alpha_type,
-                       /*is_thread_safe=*/false),
+    : AndroidVideoImageBacking(mailbox,
+                               size,
+                               color_space,
+                               surface_origin,
+                               alpha_type,
+                               /*is_thread_safe=*/false),
       stream_texture_sii_(std::move(stream_texture_sii)),
       context_state_(std::move(context_state)),
       gpu_main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
@@ -49,7 +49,7 @@
   context_state_->AddContextLostObserver(this);
 }
 
-SharedImageVideoSurfaceTexture::~SharedImageVideoSurfaceTexture() {
+VideoSurfaceTextureImageBacking::~VideoSurfaceTextureImageBacking() {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
 
   if (context_state_)
@@ -59,7 +59,7 @@
   stream_texture_sii_.reset();
 }
 
-size_t SharedImageVideoSurfaceTexture::EstimatedSizeForMemTracking() const {
+size_t VideoSurfaceTextureImageBacking::EstimatedSizeForMemTracking() const {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
 
   // This backing contributes to gpu memory only if its bound to the texture
@@ -67,7 +67,7 @@
   return stream_texture_sii_->IsUsingGpuMemory() ? estimated_size() : 0;
 }
 
-void SharedImageVideoSurfaceTexture::OnContextLost() {
+void VideoSurfaceTextureImageBacking::OnContextLost() {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
 
   // We release codec buffers when shared image context is lost. This is
@@ -78,23 +78,23 @@
   context_state_ = nullptr;
 }
 
-// Representation of SharedImageVideoSurfaceTexture as a GL Texture.
-class SharedImageVideoSurfaceTexture::SharedImageRepresentationGLTextureVideo
-    : public SharedImageRepresentationGLTexture {
+// Representation of VideoSurfaceTextureImageBacking as a GL Texture.
+class VideoSurfaceTextureImageBacking::GLTextureVideoImageRepresentation
+    : public GLTextureImageRepresentation {
  public:
-  SharedImageRepresentationGLTextureVideo(
+  GLTextureVideoImageRepresentation(
       SharedImageManager* manager,
-      SharedImageVideoSurfaceTexture* backing,
+      VideoSurfaceTextureImageBacking* backing,
       MemoryTypeTracker* tracker,
       std::unique_ptr<gles2::AbstractTexture> texture)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
+      : GLTextureImageRepresentation(manager, backing, tracker),
         texture_(std::move(texture)) {}
 
   // Disallow copy and assign.
-  SharedImageRepresentationGLTextureVideo(
-      const SharedImageRepresentationGLTextureVideo&) = delete;
-  SharedImageRepresentationGLTextureVideo& operator=(
-      const SharedImageRepresentationGLTextureVideo&) = delete;
+  GLTextureVideoImageRepresentation(const GLTextureVideoImageRepresentation&) =
+      delete;
+  GLTextureVideoImageRepresentation& operator=(
+      const GLTextureVideoImageRepresentation&) = delete;
 
   gles2::Texture* GetTexture() override {
     auto* texture = gles2::Texture::CheckedCast(texture_->GetTextureBase());
@@ -108,7 +108,7 @@
     DCHECK(mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
 
     auto* video_backing =
-        static_cast<SharedImageVideoSurfaceTexture*>(backing());
+        static_cast<VideoSurfaceTextureImageBacking*>(backing());
     video_backing->BeginGLReadAccess(texture_->service_id());
     return true;
   }
@@ -119,19 +119,17 @@
   std::unique_ptr<gles2::AbstractTexture> texture_;
 };
 
-// Representation of SharedImageVideoSurfaceTexture as a GL Texture.
-class SharedImageVideoSurfaceTexture::
-    SharedImageRepresentationGLTexturePassthroughVideo
-    : public SharedImageRepresentationGLTexturePassthrough {
+// Representation of VideoSurfaceTextureImageBacking as a GL Texture.
+class VideoSurfaceTextureImageBacking::
+    GLTexturePassthroughVideoImageRepresentation
+    : public GLTexturePassthroughImageRepresentation {
  public:
-  SharedImageRepresentationGLTexturePassthroughVideo(
+  GLTexturePassthroughVideoImageRepresentation(
       SharedImageManager* manager,
-      SharedImageVideoSurfaceTexture* backing,
+      VideoSurfaceTextureImageBacking* backing,
       MemoryTypeTracker* tracker,
       std::unique_ptr<gles2::AbstractTexture> abstract_texture)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
+      : GLTexturePassthroughImageRepresentation(manager, backing, tracker),
         abstract_texture_(std::move(abstract_texture)),
         passthrough_texture_(gles2::TexturePassthrough::CheckedCast(
             abstract_texture_->GetTextureBase())) {
@@ -140,10 +138,10 @@
   }
 
   // Disallow copy and assign.
-  SharedImageRepresentationGLTexturePassthroughVideo(
-      const SharedImageRepresentationGLTexturePassthroughVideo&) = delete;
-  SharedImageRepresentationGLTexturePassthroughVideo& operator=(
-      const SharedImageRepresentationGLTexturePassthroughVideo&) = delete;
+  GLTexturePassthroughVideoImageRepresentation(
+      const GLTexturePassthroughVideoImageRepresentation&) = delete;
+  GLTexturePassthroughVideoImageRepresentation& operator=(
+      const GLTexturePassthroughVideoImageRepresentation&) = delete;
 
   const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
       override {
@@ -155,7 +153,7 @@
     DCHECK(mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
 
     auto* video_backing =
-        static_cast<SharedImageVideoSurfaceTexture*>(backing());
+        static_cast<VideoSurfaceTextureImageBacking*>(backing());
     video_backing->BeginGLReadAccess(passthrough_texture_->service_id());
     return true;
   }
@@ -167,9 +165,9 @@
   scoped_refptr<gles2::TexturePassthrough> passthrough_texture_;
 };
 
-std::unique_ptr<SharedImageRepresentationGLTexture>
-SharedImageVideoSurfaceTexture::ProduceGLTexture(SharedImageManager* manager,
-                                                 MemoryTypeTracker* tracker) {
+std::unique_ptr<GLTextureImageRepresentation>
+VideoSurfaceTextureImageBacking::ProduceGLTexture(SharedImageManager* manager,
+                                                  MemoryTypeTracker* tracker) {
   // Note that for DrDc this method will never be called for
   // this(SurfaceTexture) implementation and for Webview, this method is called
   // only on gpu main thread.
@@ -194,12 +192,12 @@
       stream_texture_sii_.get(),
       stream_texture_sii_->GetTextureBase()->service_id());
 
-  return std::make_unique<SharedImageRepresentationGLTextureVideo>(
+  return std::make_unique<GLTextureVideoImageRepresentation>(
       manager, this, tracker, std::move(texture));
 }
 
-std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-SharedImageVideoSurfaceTexture::ProduceGLTexturePassthrough(
+std::unique_ptr<GLTexturePassthroughImageRepresentation>
+VideoSurfaceTextureImageBacking::ProduceGLTexturePassthrough(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
@@ -223,12 +221,12 @@
       stream_texture_sii_.get(),
       stream_texture_sii_->GetTextureBase()->service_id());
 
-  return std::make_unique<SharedImageRepresentationGLTexturePassthroughVideo>(
+  return std::make_unique<GLTexturePassthroughVideoImageRepresentation>(
       manager, this, tracker, std::move(texture));
 }
 
-std::unique_ptr<SharedImageRepresentationSkia>
-SharedImageVideoSurfaceTexture::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation>
+VideoSurfaceTextureImageBacking::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
@@ -272,18 +270,16 @@
       stream_texture_sii_.get(),
       stream_texture_sii_->GetTextureBase()->service_id());
 
-  std::unique_ptr<gpu::SharedImageRepresentationGLTextureBase>
-      gl_representation;
+  std::unique_ptr<gpu::GLTextureImageRepresentationBase> gl_representation;
   if (passthrough) {
     gl_representation =
-        std::make_unique<SharedImageRepresentationGLTexturePassthroughVideo>(
+        std::make_unique<GLTexturePassthroughVideoImageRepresentation>(
             manager, this, tracker, std::move(texture));
   } else {
-    gl_representation =
-        std::make_unique<SharedImageRepresentationGLTextureVideo>(
-            manager, this, tracker, std::move(texture));
+    gl_representation = std::make_unique<GLTextureVideoImageRepresentation>(
+        manager, this, tracker, std::move(texture));
   }
-  auto skia_representation = SharedImageRepresentationSkiaGL::Create(
+  auto skia_representation = SkiaGLImageRepresentation::Create(
       std::move(gl_representation), std::move(context_state), manager, this,
       tracker);
   if (!skia_representation) {
@@ -294,33 +290,31 @@
   return skia_representation;
 }
 
-void SharedImageVideoSurfaceTexture::BeginGLReadAccess(
+void VideoSurfaceTextureImageBacking::BeginGLReadAccess(
     const GLuint service_id) {
   stream_texture_sii_->UpdateAndBindTexImage(service_id);
 }
 
-// Representation of SharedImageVideoSurfaceTexture as an overlay plane.
-class SharedImageVideoSurfaceTexture::SharedImageRepresentationOverlayVideo
-    : public gpu::SharedImageRepresentationLegacyOverlay {
+// Representation of VideoSurfaceTextureImageBacking as an overlay plane.
+class VideoSurfaceTextureImageBacking::OverlayVideoImageRepresentation
+    : public gpu::LegacyOverlayImageRepresentation {
  public:
-  SharedImageRepresentationOverlayVideo(gpu::SharedImageManager* manager,
-                                        SharedImageVideoSurfaceTexture* backing,
-                                        gpu::MemoryTypeTracker* tracker)
-      : gpu::SharedImageRepresentationLegacyOverlay(manager, backing, tracker) {
-  }
+  OverlayVideoImageRepresentation(gpu::SharedImageManager* manager,
+                                  VideoSurfaceTextureImageBacking* backing,
+                                  gpu::MemoryTypeTracker* tracker)
+      : gpu::LegacyOverlayImageRepresentation(manager, backing, tracker) {}
 
   // Disallow copy and assign.
-  SharedImageRepresentationOverlayVideo(
-      const SharedImageRepresentationOverlayVideo&) = delete;
-  SharedImageRepresentationOverlayVideo& operator=(
-      const SharedImageRepresentationOverlayVideo&) = delete;
+  OverlayVideoImageRepresentation(const OverlayVideoImageRepresentation&) =
+      delete;
+  OverlayVideoImageRepresentation& operator=(
+      const OverlayVideoImageRepresentation&) = delete;
 
  protected:
   void RenderToOverlay() override {
     DCHECK(!stream_image()->HasTextureOwner())
         << "CodecImage must be already in overlay";
-    TRACE_EVENT0("media",
-                 "SharedImageRepresentationOverlayVideo::RenderToOverlay");
+    TRACE_EVENT0("media", "OverlayVideoImageRepresentation::RenderToOverlay");
     stream_image()->RenderToOverlay();
   }
 
@@ -332,20 +326,20 @@
  private:
   StreamTextureSharedImageInterface* stream_image() {
     auto* video_backing =
-        static_cast<SharedImageVideoSurfaceTexture*>(backing());
+        static_cast<VideoSurfaceTextureImageBacking*>(backing());
     DCHECK(video_backing);
     return video_backing->stream_texture_sii_.get();
   }
 };
 
-std::unique_ptr<gpu::SharedImageRepresentationLegacyOverlay>
-SharedImageVideoSurfaceTexture::ProduceLegacyOverlay(
+std::unique_ptr<gpu::LegacyOverlayImageRepresentation>
+VideoSurfaceTextureImageBacking::ProduceLegacyOverlay(
     gpu::SharedImageManager* manager,
     gpu::MemoryTypeTracker* tracker) {
   DCHECK(gpu_main_task_runner_->RunsTasksInCurrentSequence());
 
-  return std::make_unique<SharedImageRepresentationOverlayVideo>(manager, this,
-                                                                 tracker);
+  return std::make_unique<OverlayVideoImageRepresentation>(manager, this,
+                                                           tracker);
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.h b/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.h
index e357a30..a3eb1f4d 100644
--- a/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.h
+++ b/gpu/command_buffer/service/shared_image/video_surface_texture_image_backing.h
@@ -18,17 +18,17 @@
 #include "gpu/gpu_gles2_export.h"
 
 namespace gpu {
-class SharedImageRepresentationGLTexture;
-class SharedImageRepresentationSkia;
+class GLTextureImageRepresentation;
+class SkiaImageRepresentation;
 struct Mailbox;
 
 // Implementation of SharedImageBacking that renders MediaCodec buffers to a
 // TextureOwner or overlay as needed in order to draw them.
-class GPU_GLES2_EXPORT SharedImageVideoSurfaceTexture
-    : public SharedImageVideo,
+class GPU_GLES2_EXPORT VideoSurfaceTextureImageBacking
+    : public AndroidVideoImageBacking,
       public SharedContextState::ContextLostObserver {
  public:
-  SharedImageVideoSurfaceTexture(
+  VideoSurfaceTextureImageBacking(
       const Mailbox& mailbox,
       const gfx::Size& size,
       const gfx::ColorSpace color_space,
@@ -37,13 +37,13 @@
       scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
       scoped_refptr<SharedContextState> shared_context_state);
 
-  ~SharedImageVideoSurfaceTexture() override;
+  ~VideoSurfaceTextureImageBacking() override;
 
   // Disallow copy and assign.
-  SharedImageVideoSurfaceTexture(const SharedImageVideoSurfaceTexture&) =
+  VideoSurfaceTextureImageBacking(const VideoSurfaceTextureImageBacking&) =
       delete;
-  SharedImageVideoSurfaceTexture& operator=(
-      const SharedImageVideoSurfaceTexture&) = delete;
+  VideoSurfaceTextureImageBacking& operator=(
+      const VideoSurfaceTextureImageBacking&) = delete;
 
   // SharedImageBacking implementation.
   size_t EstimatedSizeForMemTracking() const override;
@@ -52,27 +52,27 @@
   void OnContextLost() override;
 
  protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+  std::unique_ptr<GLTextureImageRepresentation> ProduceGLTexture(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  std::unique_ptr<GLTexturePassthroughImageRepresentation>
   ProduceGLTexturePassthrough(SharedImageManager* manager,
                               MemoryTypeTracker* tracker) override;
 
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
-  std::unique_ptr<gpu::SharedImageRepresentationLegacyOverlay>
-  ProduceLegacyOverlay(gpu::SharedImageManager* manager,
-                       gpu::MemoryTypeTracker* tracker) override;
+  std::unique_ptr<gpu::LegacyOverlayImageRepresentation> ProduceLegacyOverlay(
+      gpu::SharedImageManager* manager,
+      gpu::MemoryTypeTracker* tracker) override;
 
  private:
-  class SharedImageRepresentationGLTextureVideo;
-  class SharedImageRepresentationGLTexturePassthroughVideo;
-  class SharedImageRepresentationOverlayVideo;
+  class GLTextureVideoImageRepresentation;
+  class GLTexturePassthroughVideoImageRepresentation;
+  class OverlayVideoImageRepresentation;
 
   void BeginGLReadAccess(const GLuint service_id);
 
diff --git a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc
index 81e3a6e7..f695bb87 100644
--- a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc
@@ -48,9 +48,8 @@
 #endif
 
 namespace gpu {
-namespace raster {
 
-class WrappedSkImageFactory;
+class WrappedSkImageBackingFactory;
 
 namespace {
 
@@ -62,7 +61,7 @@
 
 class WrappedSkImage : public ClearTrackingSharedImageBacking {
  public:
-  WrappedSkImage(base::PassKey<WrappedSkImageFactory>,
+  WrappedSkImage(base::PassKey<WrappedSkImageBackingFactory>,
                  const Mailbox& mailbox,
                  viz::ResourceFormat format,
                  const gfx::Size& size,
@@ -239,15 +238,14 @@
   sk_sp<SkPromiseImageTexture> promise_texture() { return promise_texture_; }
 
  protected:
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+  std::unique_ptr<SkiaImageRepresentation> ProduceSkia(
       SharedImageManager* manager,
       MemoryTypeTracker* tracker,
       scoped_refptr<SharedContextState> context_state) override;
 
  private:
-  friend class gpu::raster::WrappedSkImageFactory;
-  class RepresentationSkia;
-  class RepresentationMemory;
+  friend class gpu::WrappedSkImageBackingFactory;
+  class SkiaImageRepresentationImpl;
 
   bool Initialize() {
     // MakeCurrent to avoid destroying another client's state because Skia may
@@ -352,17 +350,17 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 };
 
-class WrappedSkImage::RepresentationSkia
-    : public SharedImageRepresentationSkia {
+class WrappedSkImage::SkiaImageRepresentationImpl
+    : public SkiaImageRepresentation {
  public:
-  RepresentationSkia(SharedImageManager* manager,
-                     SharedImageBacking* backing,
-                     MemoryTypeTracker* tracker,
-                     scoped_refptr<SharedContextState> context_state)
-      : SharedImageRepresentationSkia(manager, backing, tracker),
+  SkiaImageRepresentationImpl(SharedImageManager* manager,
+                              SharedImageBacking* backing,
+                              MemoryTypeTracker* tracker,
+                              scoped_refptr<SharedContextState> context_state)
+      : SkiaImageRepresentation(manager, backing, tracker),
         context_state_(std::move(context_state)) {}
 
-  ~RepresentationSkia() override { DCHECK(!write_surface_); }
+  ~SkiaImageRepresentationImpl() override { DCHECK(!write_surface_); }
 
   sk_sp<SkSurface> BeginWriteAccess(
       int final_msaa_count,
@@ -422,14 +420,15 @@
 
 }  // namespace
 
-WrappedSkImageFactory::WrappedSkImageFactory(
+WrappedSkImageBackingFactory::WrappedSkImageBackingFactory(
     scoped_refptr<SharedContextState> context_state)
     : context_state_(std::move(context_state)),
       is_drdc_enabled_(features::IsDrDcEnabled()) {}
 
-WrappedSkImageFactory::~WrappedSkImageFactory() = default;
+WrappedSkImageBackingFactory::~WrappedSkImageBackingFactory() = default;
 
-std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+WrappedSkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     SurfaceHandle surface_handle,
@@ -450,7 +449,7 @@
          (context_state_->GrContextIsVulkan() && is_drdc_enabled_));
   size_t estimated_size = EstimatedSize(format, size);
   auto texture = std::make_unique<WrappedSkImage>(
-      base::PassKey<WrappedSkImageFactory>(), mailbox, format, size,
+      base::PassKey<WrappedSkImageBackingFactory>(), mailbox, format, size,
       color_space, surface_origin, alpha_type, usage, estimated_size,
       context_state_,
       /*is_thread_safe=*/is_thread_safe &&
@@ -460,7 +459,8 @@
   return texture;
 }
 
-std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+WrappedSkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     viz::ResourceFormat format,
     const gfx::Size& size,
@@ -471,7 +471,7 @@
     base::span<const uint8_t> data) {
   size_t estimated_size = EstimatedSize(format, size);
   auto texture = std::make_unique<WrappedSkImage>(
-      base::PassKey<WrappedSkImageFactory>(), mailbox, format, size,
+      base::PassKey<WrappedSkImageBackingFactory>(), mailbox, format, size,
       color_space, surface_origin, alpha_type, usage, estimated_size,
       context_state_, /*is_thread_safe=*/context_state_->GrContextIsVulkan() &&
                           is_drdc_enabled_);
@@ -480,7 +480,8 @@
   return texture;
 }
 
-std::unique_ptr<SharedImageBacking> WrappedSkImageFactory::CreateSharedImage(
+std::unique_ptr<SharedImageBacking>
+WrappedSkImageBackingFactory::CreateSharedImage(
     const Mailbox& mailbox,
     int client_id,
     gfx::GpuMemoryBufferHandle handle,
@@ -496,7 +497,7 @@
   return nullptr;
 }
 
-bool WrappedSkImageFactory::CanUseWrappedSkImage(
+bool WrappedSkImageBackingFactory::CanUseWrappedSkImage(
     uint32_t usage,
     GrContextType gr_context_type) const {
   // Ignore for mipmap usage.
@@ -507,13 +508,14 @@
   return (usage & kWrappedSkImageUsage) && !(usage & ~kWrappedSkImageUsage);
 }
 
-bool WrappedSkImageFactory::IsSupported(uint32_t usage,
-                                        viz::ResourceFormat format,
-                                        bool thread_safe,
-                                        gfx::GpuMemoryBufferType gmb_type,
-                                        GrContextType gr_context_type,
-                                        bool* allow_legacy_mailbox,
-                                        bool is_pixel_used) {
+bool WrappedSkImageBackingFactory::IsSupported(
+    uint32_t usage,
+    viz::ResourceFormat format,
+    bool thread_safe,
+    gfx::GpuMemoryBufferType gmb_type,
+    GrContextType gr_context_type,
+    bool* allow_legacy_mailbox,
+    bool is_pixel_used) {
   // Note that this backing support thread safety only for vulkan mode because
   // the underlying vulkan resources like vulkan images can be shared across
   // multiple vulkan queues. Also note that this backing currently only supports
@@ -545,16 +547,15 @@
   return true;
 }
 
-std::unique_ptr<SharedImageRepresentationSkia> WrappedSkImage::ProduceSkia(
+std::unique_ptr<SkiaImageRepresentation> WrappedSkImage::ProduceSkia(
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     scoped_refptr<SharedContextState> context_state) {
   if (context_state_->context_lost())
     return nullptr;
 
-  return std::make_unique<RepresentationSkia>(manager, this, tracker,
-                                              std::move(context_state));
+  return std::make_unique<SkiaImageRepresentationImpl>(
+      manager, this, tracker, std::move(context_state));
 }
 
-}  // namespace raster
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.h b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.h
index 52d930a..a2575d54 100644
--- a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.h
@@ -18,18 +18,17 @@
 
 class SharedContextState;
 
-namespace raster {
-
-class GPU_GLES2_EXPORT WrappedSkImageFactory
+class GPU_GLES2_EXPORT WrappedSkImageBackingFactory
     : public gpu::SharedImageBackingFactory {
  public:
-  explicit WrappedSkImageFactory(
+  explicit WrappedSkImageBackingFactory(
       scoped_refptr<SharedContextState> context_state);
 
-  WrappedSkImageFactory(const WrappedSkImageFactory&) = delete;
-  WrappedSkImageFactory& operator=(const WrappedSkImageFactory&) = delete;
+  WrappedSkImageBackingFactory(const WrappedSkImageBackingFactory&) = delete;
+  WrappedSkImageBackingFactory& operator=(const WrappedSkImageBackingFactory&) =
+      delete;
 
-  ~WrappedSkImageFactory() override;
+  ~WrappedSkImageBackingFactory() override;
 
   // SharedImageBackingFactory implementation:
   std::unique_ptr<SharedImageBacking> CreateSharedImage(
@@ -79,7 +78,6 @@
   const bool is_drdc_enabled_;
 };
 
-}  // namespace raster
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_WRAPPED_SK_IMAGE_BACKING_FACTORY_H_
diff --git a/gpu/command_buffer/service/skia_utils.cc b/gpu/command_buffer/service/skia_utils.cc
index 2d2529c..310aa75 100644
--- a/gpu/command_buffer/service/skia_utils.cc
+++ b/gpu/command_buffer/service/skia_utils.cc
@@ -270,9 +270,10 @@
   image_info.fAlloc = alloc;
   // TODO(hitawala, https://crbug.com/1310028): Skia assumes that all VkImages
   // with DRM modifier extensions are only for reads. When using Vulkan with
-  // OzoneBackings on Skia, when importing buffer we create SkSurface and write
-  // to it which fails. To fix this, we add checks for tiling with DRM modifiers
-  // and set it to optimal. This will be removed once skia adds write support.
+  // OzoneImageBackings on Skia, when importing buffer we create SkSurface and
+  // write to it which fails. To fix this, we add checks for tiling with DRM
+  // modifiers and set it to optimal. This will be removed once skia adds write
+  // support.
   if (image->image_tiling() == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
       (image->format() == VK_FORMAT_R8G8B8A8_UNORM ||
        image->format() == VK_FORMAT_R8G8B8_UNORM ||
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index f9869c4..44d94a60 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2134,7 +2134,7 @@
 }
 
 void TextureRef::SetSharedImageRepresentation(
-    std::unique_ptr<SharedImageRepresentationGLTexture> shared_image) {
+    std::unique_ptr<GLTextureImageRepresentation> shared_image) {
   shared_image_ = std::move(shared_image);
 }
 
@@ -2402,7 +2402,7 @@
 
 TextureRef* TextureManager::ConsumeSharedImage(
     GLuint client_id,
-    std::unique_ptr<SharedImageRepresentationGLTexture> shared_image) {
+    std::unique_ptr<GLTextureImageRepresentation> shared_image) {
   DCHECK(client_id);
   Texture* texture = shared_image->GetTexture();
   TextureRef* ref = Consume(client_id, texture);
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 450735ab..501b457 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -759,16 +759,16 @@
   // TODO(ericrk): Remove this once the Texture itself is generated from and
   // owns the SharedImageRepresentation.
   void SetSharedImageRepresentation(
-      std::unique_ptr<SharedImageRepresentationGLTexture> shared_image);
+      std::unique_ptr<GLTextureImageRepresentation> shared_image);
   const Texture* texture() const { return texture_; }
   Texture* texture() { return texture_; }
   GLuint client_id() const { return client_id_; }
   GLuint service_id() const { return texture_->service_id(); }
   GLint num_observers() const { return num_observers_; }
-  SharedImageRepresentationGLTexture* shared_image() const {
+  GLTextureImageRepresentation* shared_image() const {
     return shared_image_.get();
   }
-  const std::unique_ptr<SharedImageRepresentationGLTexture::ScopedAccess>&
+  const std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>&
   shared_image_scoped_access() const {
     return shared_image_scoped_access_;
   }
@@ -796,8 +796,8 @@
   GLint num_observers_;
   bool force_context_lost_;
 
-  std::unique_ptr<SharedImageRepresentationGLTexture> shared_image_;
-  std::unique_ptr<SharedImageRepresentationGLTexture::ScopedAccess>
+  std::unique_ptr<GLTextureImageRepresentation> shared_image_;
+  std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>
       shared_image_scoped_access_;
 };
 
@@ -979,7 +979,7 @@
   // ID.
   TextureRef* ConsumeSharedImage(
       GLuint client_id,
-      std::unique_ptr<SharedImageRepresentationGLTexture> shared_image);
+      std::unique_ptr<GLTextureImageRepresentation> shared_image);
 
   // Sets |rect| of mip as cleared.
   void SetLevelClearedRect(TextureRef* ref,
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 7535c25..67fc9c5a 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -411,31 +411,31 @@
     virtual WGPUTexture texture() const = 0;
   };
 
-  // Wraps a |SharedImageRepresentationDawn| as a WGPUTexture.
+  // Wraps a |DawnImageRepresentation| as a WGPUTexture.
   class SharedImageRepresentationAndAccessDawn
       : public SharedImageRepresentationAndAccess {
    public:
     SharedImageRepresentationAndAccessDawn(
-        std::unique_ptr<SharedImageRepresentationDawn> representation,
-        std::unique_ptr<SharedImageRepresentationDawn::ScopedAccess> access)
+        std::unique_ptr<DawnImageRepresentation> representation,
+        std::unique_ptr<DawnImageRepresentation::ScopedAccess> access)
         : representation_(std::move(representation)),
           access_(std::move(access)) {}
 
     WGPUTexture texture() const override { return access_->texture(); }
 
    private:
-    std::unique_ptr<SharedImageRepresentationDawn> representation_;
-    std::unique_ptr<SharedImageRepresentationDawn::ScopedAccess> access_;
+    std::unique_ptr<DawnImageRepresentation> representation_;
+    std::unique_ptr<DawnImageRepresentation::ScopedAccess> access_;
   };
 
-  // Wraps a |SharedImageRepresentationSkia| and exposes
+  // Wraps a |SkiaImageRepresentation| and exposes
   // it as a WGPUTexture by performing CPU readbacks/uploads.
   class SharedImageRepresentationAndAccessSkiaFallback
       : public SharedImageRepresentationAndAccess {
    public:
     static std::unique_ptr<SharedImageRepresentationAndAccessSkiaFallback>
     Create(scoped_refptr<SharedContextState> shared_context_state,
-           std::unique_ptr<SharedImageRepresentationSkia> representation,
+           std::unique_ptr<SkiaImageRepresentation> representation,
            const DawnProcTable& procs,
            WGPUDevice device,
            WGPUTextureUsage usage) {
@@ -492,7 +492,7 @@
    private:
     SharedImageRepresentationAndAccessSkiaFallback(
         scoped_refptr<SharedContextState> shared_context_state,
-        std::unique_ptr<SharedImageRepresentationSkia> representation,
+        std::unique_ptr<SkiaImageRepresentation> representation,
         const DawnProcTable& procs,
         WGPUDevice device,
         WGPUTextureUsage usage)
@@ -806,7 +806,7 @@
     }
 
     scoped_refptr<SharedContextState> shared_context_state_;
-    std::unique_ptr<SharedImageRepresentationSkia> representation_;
+    std::unique_ptr<SkiaImageRepresentation> representation_;
     const DawnProcTable& procs_;
     WGPUDevice device_;
     WGPUTexture texture_;
@@ -1482,7 +1482,7 @@
                                         WGPUDevice device,
                                         WGPUBackendType backendType,
                                         WGPUTextureUsage usage) {
-  std::unique_ptr<SharedImageRepresentationDawn> shared_image =
+  std::unique_ptr<DawnImageRepresentation> shared_image =
       shared_image_representation_factory_->ProduceDawn(mailbox, device,
                                                         backendType);
 
@@ -1504,7 +1504,7 @@
     shared_image->SetClearedRect(gfx::Rect());
   }
 
-  std::unique_ptr<SharedImageRepresentationDawn::ScopedAccess> scoped_access =
+  std::unique_ptr<DawnImageRepresentation::ScopedAccess> scoped_access =
       shared_image->BeginScopedAccess(
           usage, SharedImageRepresentation::AllowUnclearedAccess::kYes);
   if (!scoped_access) {
@@ -1522,7 +1522,7 @@
                                                      WGPUDevice device,
                                                      WGPUTextureUsage usage) {
   // Produce a Skia image from the mailbox.
-  std::unique_ptr<SharedImageRepresentationSkia> shared_image =
+  std::unique_ptr<SkiaImageRepresentation> shared_image =
       shared_image_representation_factory_->ProduceSkia(
           mailbox, shared_context_state_.get());
 
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index f5f3360..79ebb7c6 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -4036,7 +4036,7 @@
     {
       "id": 396,
       "cr_bugs": [1327044],
-      "description": "Add fence to SharedImageBackingOzone::BeginAccess when on same GL context",
+      "description": "Add fence to OzoneImageBacking::BeginAccess when on same GL context",
       "os": {
         "type": "chromeos"
       },
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index c38a0215..4a157111 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -75,6 +75,7 @@
       return format == gfx::BufferFormat::BGRA_8888 ||
              format == gfx::BufferFormat::RGBA_8888 ||
              format == gfx::BufferFormat::BGRX_8888 ||
+             format == gfx::BufferFormat::RGBX_8888 ||
              format == gfx::BufferFormat::R_8 ||
              format == gfx::BufferFormat::RGBA_F16 ||
              format == gfx::BufferFormat::BGRA_1010102 ||
diff --git a/gpu/ipc/service/dcomp_texture_win.cc b/gpu/ipc/service/dcomp_texture_win.cc
index c5a589c4..cbe350c 100644
--- a/gpu/ipc/service/dcomp_texture_win.cc
+++ b/gpu/ipc/service/dcomp_texture_win.cc
@@ -44,8 +44,8 @@
 }
 
 using InitializeGLTextureParams =
-    SharedImageBackingGLCommon::InitializeGLTextureParams;
-using UnpackStateAttribs = SharedImageBackingGLCommon::UnpackStateAttribs;
+    GLTextureImageBackingHelper::InitializeGLTextureParams;
+using UnpackStateAttribs = GLTextureImageBackingHelper::UnpackStateAttribs;
 
 }  // namespace
 
@@ -158,9 +158,9 @@
   auto scoped_make_current = MakeCurrent(context_state_.get());
   auto mailbox = gpu::Mailbox::GenerateForSharedImage();
 
-  // Use SharedImageBackingGLImage as the backing to hold GLImageDCOMPSurface
+  // Use GLImageBacking as the backing to hold GLImageDCOMPSurface
   // and be able to retrieve it later via ProduceOverlay.
-  // Use some reasonable defaults for params to create SharedImageBackingGLImage
+  // Use some reasonable defaults for params to create GLImageBacking
   // since params are only used when the backing is accessed for GL.
   // Note: this backing shouldn't be accessed via GL at all.
   InitializeGLTextureParams params;
@@ -171,7 +171,7 @@
   params.is_rgb_emulation = false;
   params.framebuffer_attachment_angle = false;
   UnpackStateAttribs attribs;
-  auto shared_image = std::make_unique<SharedImageBackingGLImage>(
+  auto shared_image = std::make_unique<GLImageBacking>(
       this, mailbox, viz::BGRA_8888, GetSize(), gfx::ColorSpace::CreateSRGB(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
       /*usage=*/SHARED_IMAGE_USAGE_DISPLAY, params, attribs,
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc
index 11c5b0c..8056447 100644
--- a/gpu/ipc/service/stream_texture_android.cc
+++ b/gpu/ipc/service/stream_texture_android.cc
@@ -228,8 +228,8 @@
     if (context_state_->GrContextIsVulkan()) {
       vulkan_context_provider = context_state_->vk_context_provider();
     }
-    auto ycbcr_info = SharedImageVideo::GetYcbcrInfo(texture_owner_.get(),
-                                                     vulkan_context_provider);
+    auto ycbcr_info = AndroidVideoImageBacking::GetYcbcrInfo(
+        texture_owner_.get(), vulkan_context_provider);
 
     client_->OnFrameWithInfoAvailable(mailbox, coded_size, visible_rect,
                                       ycbcr_info);
@@ -279,7 +279,7 @@
 
   // TODO(vikassoni): Hardcoding colorspace to SRGB. Figure how if we have a
   // colorspace and wire it here.
-  auto shared_image = SharedImageVideo::Create(
+  auto shared_image = AndroidVideoImageBacking::Create(
       mailbox, coded_size, gfx::ColorSpace::CreateSRGB(),
       kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, this, context_state_,
       /*lock=*/nullptr);
diff --git a/ios/build/bots/scripts/wpr_runner.py b/ios/build/bots/scripts/wpr_runner.py
index 7b98682..c06faf4 100644
--- a/ios/build/bots/scripts/wpr_runner.py
+++ b/ios/build/bots/scripts/wpr_runner.py
@@ -235,11 +235,15 @@
 
     return test_matched_filter != invert
 
-  def copy_trusted_certificate(self):
-    """Copies a TrustStore file with a trusted HTTPS certificate into all sims.
+  def copy_trusted_certificate(self, udid):
+    """Copies a root HTTPS cert into a simulator.
 
     This allows the simulators to access HTTPS webpages served through WprGo.
 
+    Args:
+      udid: String of UDID of the simulator to install the trusted certificate
+        into.
+
     Raises:
       WprToolsNotFoundError: If wpr_tools_path is not specified.
 
@@ -247,24 +251,16 @@
 
     if not os.path.exists(self.wpr_tools_path):
       raise WprToolsNotFoundError(self.wpr_tools_path)
-    cert_path = "{}/TrustStore_trust.sqlite3".format(self.wpr_tools_path)
+    cert_path = "{}/web_page_replay_go/wpr_cert.pem".format(self.wpr_tools_path)
 
     if not os.path.exists(cert_path):
       raise CertPathNotFoundError(cert_path)
 
-    trust_stores = glob.glob(
-        '{}/Library/Developer/CoreSimulator/Devices/*/data/Library'.format(
-            os.path.expanduser('~')))
-    for trust_store in trust_stores:
-      LOGGER.info('Copying TrustStore to %s', trust_store)
-      trust_store_file_path = os.path.join(trust_store,
-                                           'Keychains/TrustStore.sqlite3')
-      if os.path.isfile(trust_store_file_path):
-        os.remove(trust_store_file_path)
-      trust_store_dir_path = os.path.join(trust_store, 'Keychains')
-      if not os.path.exists(trust_store_dir_path):
-        os.makedirs(trust_store_dir_path)
-      shutil.copy(cert_path, trust_store_file_path)
+    LOGGER.info('Copying root cert into %s', udid)
+    subprocess.check_call(['xcrun', 'simctl', 'boot', udid])
+    subprocess.check_call(
+        ['xcrun', 'simctl', 'keychain', udid, 'add-root-cert', cert_path])
+    subprocess.check_call(['xcrun', 'simctl', 'shutdown', udid])
 
   def _run(self, cmd, shards=1):
     """Runs the specified command, parsing GTest output.
@@ -295,7 +291,7 @@
     # certificate needed for HTTPS proxying.
     udid = self.getSimulator()
 
-    self.copy_trusted_certificate()
+    self.copy_trusted_certificate(udid)
 
     for recipe_path in glob.glob('{}/*.test'.format(self.replay_path)):
       base_name = os.path.basename(recipe_path)
diff --git a/ios/build/bots/scripts/wpr_runner_test.py b/ios/build/bots/scripts/wpr_runner_test.py
index 2218ad8..db972ef 100755
--- a/ios/build/bots/scripts/wpr_runner_test.py
+++ b/ios/build/bots/scripts/wpr_runner_test.py
@@ -35,7 +35,7 @@
     self.mock(test_runner.SimulatorTestRunner, 'deleteSimulator',
               lambda a, b: True)
     self.mock(wpr_runner.WprProxySimulatorTestRunner,
-              'copy_trusted_certificate', lambda a: True)
+              'copy_trusted_certificate', lambda a, b: True)
     self.mock(iossim_util, 'get_simulator',
               lambda a, b: 'E4E66320-177A-450A-9BA1-488D85B7278E')
 
diff --git a/ios/chrome/app/feed_app_agent.h b/ios/chrome/app/feed_app_agent.h
index e9eebbe..2f51de8f 100644
--- a/ios/chrome/app/feed_app_agent.h
+++ b/ios/chrome/app/feed_app_agent.h
@@ -12,12 +12,6 @@
 // a Website, etc. This also manages feed background refresh.
 // TODO(crbug.com/1344866): Coordinate background tasks when more are added.
 @interface FeedAppAgent : SceneObservingAppAgent
-// Registers handler for the background refresh task. According to
-// documentation, this must complete before the end of
-// `applicationDidFinishLaunching`.
-// TODO(crbug.com/1343695): Do not call this until it is protected by a build
-// flag.
-- (void)registerBackgroundRefreshTask;
 @end
 
 #endif  // IOS_CHROME_APP_FEED_APP_AGENT_H_
diff --git a/ios/chrome/app/feed_app_agent.mm b/ios/chrome/app/feed_app_agent.mm
index 56b720b..57c6b36b 100644
--- a/ios/chrome/app/feed_app_agent.mm
+++ b/ios/chrome/app/feed_app_agent.mm
@@ -18,16 +18,6 @@
 
 @implementation FeedAppAgent
 
-- (void)registerBackgroundRefreshTask {
-  __weak FeedAppAgent* weakSelf = self;
-  [BGTaskScheduler.sharedScheduler
-      registerForTaskWithIdentifier:kFeedBackgroundRefreshTaskIdentifier
-                         usingQueue:nil
-                      launchHandler:^(BGTask* task) {
-                        [weakSelf handleBackgroundRefreshTask:task];
-                      }];
-}
-
 #pragma mark - AppStateObserver
 
 - (void)appState:(AppState*)appState
@@ -72,6 +62,21 @@
   return nil;
 }
 
+// Registers handler for the background refresh task. According to
+// documentation, this must complete before the end of
+// `applicationDidFinishLaunching`.
+- (void)registerBackgroundRefreshTask {
+  // TODO(crbug.com/1343695): Do not call this until Info.plist is modified.
+  DCHECK(TRUE);
+  __weak FeedAppAgent* weakSelf = self;
+  [BGTaskScheduler.sharedScheduler
+      registerForTaskWithIdentifier:kFeedBackgroundRefreshTaskIdentifier
+                         usingQueue:nil
+                      launchHandler:^(BGTask* task) {
+                        [weakSelf handleBackgroundRefreshTask:task];
+                      }];
+}
+
 // Schedules a background refresh task with an earliest begin date in the
 // future. The OS limits to 1 refresh task at any time, and a new request will
 // replace a previous request. Tasks are only executed in the background.
@@ -80,29 +85,42 @@
 // including other files. The OS only allows one fetch task at a time.
 // Eventually, background fetches should be managed by a central manager.
 - (void)scheduleBackgroundRefresh {
-  DCHECK(IsFeedBackgroundRefreshEnabled());
-  if (![self feedServiceIfAvailable]) {
+  // Do not DCHECK IsFeedBackgroundRefreshEnabled() because it is also called
+  // from the background task handler, and the value could have changed during a
+  // cold start.
+  if (!IsFeedBackgroundRefreshEnabled() || ![self feedServiceIfAvailable]) {
     return;
   }
   BGAppRefreshTaskRequest* request = [[BGAppRefreshTaskRequest alloc]
       initWithIdentifier:kFeedBackgroundRefreshTaskIdentifier];
-  // TODO(crbug.com/1343695): Use DiscoverFeedService to set the earliest begin
-  // date on the request. This ensures that any task scheduling from anywhere
-  // sets the correct earliest begin date. Error in scheduling is intentionally
-  // not handled since the fallback is that the user will just refresh in the
-  // foreground.
+  request.earliestBeginDate =
+      [self feedServiceIfAvailable]->GetEarliestBackgroundRefreshBeginDate();
+  // Error in scheduling is intentionally not handled since the fallback is that
+  // the user will just refresh in the foreground.
+  // TODO(crbug.com/1343695): Consider logging error in histogram.
   [BGTaskScheduler.sharedScheduler submitTaskRequest:request error:nil];
 }
 
 // This method is called when the app is in the background.
 - (void)handleBackgroundRefreshTask:(BGTask*)task {
-  DCHECK(IsFeedBackgroundRefreshEnabled());
-  if (![self feedServiceIfAvailable]) {
+  // Do not DCHECK IsFeedBackgroundRefreshEnabled() because the value could have
+  // changed during a cold start.
+  if (!IsFeedBackgroundRefreshEnabled() || ![self feedServiceIfAvailable]) {
     return;
   }
-  // TODO(crbug.com/1343695): Use DiscoverFeedService to refresh the feed. Then
-  // mark the task completed or failed. Also set a task expiration handler.
-  [task setTaskCompletedWithSuccess:NO];
+  if (IsRecurringBackgroundRefreshScheduleEnabled()) {
+    [self scheduleBackgroundRefresh];
+  }
+  task.expirationHandler = ^{
+    if ([self feedServiceIfAvailable]) {
+      // There would be no refresh task to stop if there is no feed service
+      // available.
+      [self feedServiceIfAvailable]->HandleBackgroundRefreshTaskExpiration();
+    }
+  };
+  [self feedServiceIfAvailable]->PerformBackgroundRefreshes(^(BOOL success) {
+    [task setTaskCompletedWithSuccess:success];
+  });
 }
 
 @end
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index b7bcba5b..c7c4983 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2430,7 +2430,7 @@
         Stay protected from dangerous websites
       </message>
       <message name="IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_TITLE" desc="Title for HTTPS-Only Mode toggle in settings">
-        Try to use secure connections
+        Always use secure connections
       </message>
       <message name="IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_DESCRIPTION" desc="Description text of HTTPS-Only Mode in  settings">
         Upgrade to HTTPS, when possible. Secure sites might embed content that isn't secure.
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_TITLE.png.sha1
index 51eb0b2..2d9fd86 100644
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_TITLE.png.sha1
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SETTINGS_HTTPS_ONLY_MODE_TITLE.png.sha1
@@ -1 +1 @@
-c7b42beb78d273c3a1939c7e468885cddad2b5a9
\ No newline at end of file
+691101cce715fac7a9e71d1c4fc7b38f608d1025
\ No newline at end of file
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.h b/ios/chrome/browser/discover_feed/discover_feed_service.h
index 2cb746f..e26db81 100644
--- a/ios/chrome/browser/discover_feed/discover_feed_service.h
+++ b/ios/chrome/browser/discover_feed/discover_feed_service.h
@@ -73,18 +73,16 @@
   // Performs a background refresh for the feed. `completion` is called
   // after success, failure, or timeout. The BOOL argument indicates whether the
   // refresh was successful or a failure.
-  // TODO(crbug.com/1343695): Make this a pure virtual function.
-  virtual void PerformBackgroundRefreshes(ProceduralBlockWithBool completion);
+  virtual void PerformBackgroundRefreshes(
+      ProceduralBlockWithBool completion) = 0;
 
   // Stops the background refresh task and cleans up any temporary objects. This
   // is called by the OS when the task is taking too long.
-  // TODO(crbug.com/1343695): Make this a pure virtual function.
-  virtual void HandleBackgroundRefreshTaskExpiration();
+  virtual void HandleBackgroundRefreshTaskExpiration() = 0;
 
   // The earliest datetime at which the next background refresh should be
   // scheduled.
-  // TODO(crbug.com/1343695): Make this a pure virtual function.
-  virtual NSDate* GetEarliestBackgroundRefreshBeginDate();
+  virtual NSDate* GetEarliestBackgroundRefreshBeginDate() = 0;
 
   // Returns whether the Following feed model has unseen content.
   virtual BOOL GetFollowingFeedHasUnseenContent() = 0;
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.mm b/ios/chrome/browser/discover_feed/discover_feed_service.mm
index 73c5b95..29da5a2 100644
--- a/ios/chrome/browser/discover_feed/discover_feed_service.mm
+++ b/ios/chrome/browser/discover_feed/discover_feed_service.mm
@@ -30,15 +30,3 @@
     observer.OnDiscoverFeedModelRecreated();
   }
 }
-
-// TODO(crbug.com/1343695): Make this a pure virtual function.
-void DiscoverFeedService::PerformBackgroundRefreshes(
-    ProceduralBlockWithBool completion) {}
-
-// TODO(crbug.com/1343695): Make this a pure virtual function.
-void DiscoverFeedService::HandleBackgroundRefreshTaskExpiration() {}
-
-// TODO(crbug.com/1343695): Make this a pure virtual function.
-NSDate* DiscoverFeedService::GetEarliestBackgroundRefreshBeginDate() {
-  return nil;
-}
diff --git a/ios/chrome/browser/follow/follow_tab_helper.h b/ios/chrome/browser/follow/follow_tab_helper.h
index d9aca78..97353b4 100644
--- a/ios/chrome/browser/follow/follow_tab_helper.h
+++ b/ios/chrome/browser/follow/follow_tab_helper.h
@@ -35,27 +35,27 @@
 
   ~FollowTabHelper() override;
 
-  // Creates the TabHelper and attaches to |web_state|. |web_state| must not be
+  // Creates the TabHelper and attaches to `web_state`. `web_state` must not be
   // null.
   static void CreateForWebState(web::WebState* web_state);
 
-  // Sets the presenter for follow in-product help (IPH). |presenter| is not
+  // Sets the presenter for follow in-product help (IPH). `presenter` is not
   // retained by this tab helper.
   void set_follow_iph_presenter(id<FollowIPHPresenter> presenter) {
     follow_iph_presenter_ = presenter;
   }
 
-  // Sets the value of shoud_update_follow_item_.
+  // Sets the value of `shoud_update_follow_item_`.
   void set_should_update_follow_item(bool shoud_update_follow_item) {
     should_update_follow_item_ = shoud_update_follow_item;
   }
 
-  // Sets the follow meue updater. |follow_menu_updater| is not retained by this
+  // Sets the follow menu updater. `follow_menu_updater` is not retained by this
   // tab helper.
-  void set_follow_menu_updater(id<FollowMenuUpdater> follow_menu_updater);
+  void SetFollowMenuUpdater(id<FollowMenuUpdater> follow_menu_updater);
 
-  // Removes the follow meue updater.
-  void remove_follow_menu_updater();
+  // Removes the follow menu updater.
+  void RemoveFollowMenuUpdater();
 
  private:
   friend class web::WebStateUserData<FollowTabHelper>;
@@ -99,7 +99,7 @@
   // Presenter for follow in-product help (IPH).
   __weak id<FollowIPHPresenter> follow_iph_presenter_ = nil;
 
-  // Manages this object as an observer of |web_state_|.
+  // Manages this object as an observer of `web_state_`.
   base::ScopedObservation<web::WebState, web::WebStateObserver>
       web_state_observation_{this};
 
@@ -111,6 +111,10 @@
   // Used to update the follow menu item.
   __weak id<FollowMenuUpdater> follow_menu_updater_ = nil;
 
+  // The recommended rss url of the current website. Nil if
+  // the site is not recommended.
+  NSURL* recommended_rss_url_ = nil;
+
   base::CancelableTaskTracker history_task_tracker_;
   base::WeakPtrFactory<FollowTabHelper> weak_ptr_factory_{this};
 
diff --git a/ios/chrome/browser/follow/follow_tab_helper.mm b/ios/chrome/browser/follow/follow_tab_helper.mm
index 78e3353..d55544c 100644
--- a/ios/chrome/browser/follow/follow_tab_helper.mm
+++ b/ios/chrome/browser/follow/follow_tab_helper.mm
@@ -76,7 +76,7 @@
   web_state_observation_.Observe(web_state_);
 }
 
-void FollowTabHelper::set_follow_menu_updater(
+void FollowTabHelper::SetFollowMenuUpdater(
     id<FollowMenuUpdater> follow_menu_updater) {
   DCHECK(web_state_);
   follow_menu_updater_ = follow_menu_updater;
@@ -84,13 +84,12 @@
     // If the page has finished loading check if the Follow menu item should be
     // updated, if not it will be updated once the page finishes loading.
     FollowJavaScriptFeature::GetInstance()->GetFollowWebPageURLs(
-        web_state_, base::BindOnce(^(FollowWebPageURLs* web_page_urls) {
-          UpdateFollowMenuItem(web_page_urls);
-        }));
+        web_state_, base::BindOnce(&FollowTabHelper::UpdateFollowMenuItem,
+                                   weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
-void FollowTabHelper::remove_follow_menu_updater() {
+void FollowTabHelper::RemoveFollowMenuUpdater() {
   follow_menu_updater_ = nil;
   should_update_follow_item_ = true;
 }
@@ -109,7 +108,7 @@
 void FollowTabHelper::PageLoaded(
     web::WebState* web_state,
     web::PageLoadCompletionStatus load_completion_status) {
-  // TODO(crbug.com/1340154): move the checking to follow_iph_presenter_
+  // TODO(crbug.com/1340154): move the checking to `follow_iph_presenter_`
   // (FollowIPHCoordinator), so this class won't need to access browser_state
   // anymore, which brings convinience to testing.
 
@@ -159,24 +158,27 @@
   }
 
   // Show follow in-product help (IPH) if eligible.
-
-  // Do not show follow IPH if:
-  // 1. The site is not recommended;
-  // 2. The IPH was shown too recently.
-  if (!ios::GetChromeBrowserProvider()
-           .GetFollowProvider()
-           ->GetRecommendedStatus(web_page_urls) ||
-      !IsFollowIPHShownFrequencyEligible())
-    return;
-
   feature_engagement::Tracker* feature_engagement_tracker =
       feature_engagement::TrackerFactory::GetForBrowserState(
           ChromeBrowserState::FromBrowserState(web_state_->GetBrowserState()));
   // Do not show follow IPH if the feature engagement conditions are
-  // not fulfilled. Ex. Don not show more than 5 Follow IPHs per week.
+  // not fulfilled. Ex. Do not show more than 5 Follow IPHs per week.
   if (!feature_engagement_tracker->WouldTriggerHelpUI(
-          feature_engagement::kIPHFollowWhileBrowsingFeature))
+          feature_engagement::kIPHFollowWhileBrowsingFeature)) {
     return;
+  }
+
+  recommended_rss_url_ = ios::GetChromeBrowserProvider()
+                             .GetFollowProvider()
+                             ->GetRecommendedSiteURL(web_page_urls);
+
+  // Do not show follow IPH if:
+  // 1. The site is not recommended;
+  // 2. The IPH was shown too recently.
+  if (!recommended_rss_url_ ||
+      !IsFollowIPHShownFrequencyEligible(recommended_rss_url_)) {
+    return;
+  }
 
   // Check if the site has enough visit count.
   history::HistoryService* history_service =
@@ -202,8 +204,9 @@
     history::DailyVisitsResult result) {
   // Do not display the IPH if there are not enough visits.
   if (result.total_visits < kDefaultNumVisitMin ||
-      result.days_with_visits < kDefaultDailyVisitMin)
+      result.days_with_visits < kDefaultDailyVisitMin) {
     return;
+  }
 
   // Check how much time remains before the IPH needs to be displayed.
   const base::TimeDelta elapsed_time = base::Time::Now() - page_load_time;
@@ -250,6 +253,7 @@
 void FollowTabHelper::PresentFollowIPH() {
   DCHECK(follow_iph_presenter_);
   [follow_iph_presenter_ presentFollowWhileBrowsingIPH];
+  StoreFollowIPHPresentingTime(recommended_rss_url_);
 }
 
 WEB_STATE_USER_DATA_KEY_IMPL(FollowTabHelper)
diff --git a/ios/chrome/browser/follow/follow_util.h b/ios/chrome/browser/follow/follow_util.h
index 6cc4c53..5c382a8a 100644
--- a/ios/chrome/browser/follow/follow_util.h
+++ b/ios/chrome/browser/follow/follow_util.h
@@ -20,6 +20,8 @@
 #pragma mark - For Follow IPH
 // Returns true if the time between the last time a Follow IPH was shown and now
 // is long enough for another Follow IPH appearance.
-bool IsFollowIPHShownFrequencyEligible();
+bool IsFollowIPHShownFrequencyEligible(NSURL* RSSLink);
+// Stores the Follow IPH presenting time for website with `RSSLink`.
+void StoreFollowIPHPresentingTime(NSURL* RSSLink);
 
 #endif  // IOS_CHROME_BROWSER_FOLLOW_FOLLOW_UTIL_H_
diff --git a/ios/chrome/browser/follow/follow_util.mm b/ios/chrome/browser/follow/follow_util.mm
index 0640e54..8005a48 100644
--- a/ios/chrome/browser/follow/follow_util.mm
+++ b/ios/chrome/browser/follow/follow_util.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/follow/follow_util.h"
 
+#import <UIKit/UIKit.h>
+
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/ntp/features.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
@@ -19,9 +21,14 @@
 namespace {
 // Set the Follow IPH apperance threshold to 15 minutes.
 NSTimeInterval const kFollowIPHAppearanceThresholdInSeconds = 15 * 60;
+// Set the Follow IPH apperance threshold for site to 1 day.
+NSTimeInterval const kFollowIPHAppearanceThresholdForSiteInSeconds =
+    24 * 60 * 60;
 }  // namespace
 
 NSString* const kFollowIPHLastShownTime = @"FollowIPHLastShownTime";
+NSString* const kFollowIPHLastShownTimeForSite =
+    @"FollowIPHLastShownTimeForSite";
 
 FollowActionState GetFollowActionState(web::WebState* webState) {
   // This method should be called only if the feature flag has been enabled.
@@ -55,12 +62,62 @@
 }
 
 #pragma mark - For Follow IPH
-bool IsFollowIPHShownFrequencyEligible() {
+bool IsFollowIPHShownFrequencyEligible(NSURL* RSSLink) {
   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
   NSDate* lastFollowIPHShownTime =
       [defaults objectForKey:kFollowIPHLastShownTime];
-  return (
-      [[NSDate
+  // Return false if its too soon to show another IPH.
+  if ([[NSDate
           dateWithTimeIntervalSinceNow:-kFollowIPHAppearanceThresholdInSeconds]
-          compare:lastFollowIPHShownTime] != NSOrderedAscending);
+          compare:lastFollowIPHShownTime] == NSOrderedAscending)
+    return false;
+
+  NSDictionary<NSURL*, NSDate*>* lastFollowIPHShownTimeForSite =
+      [defaults objectForKey:kFollowIPHLastShownTimeForSite];
+  NSDate* lastIPHForSite = [lastFollowIPHShownTimeForSite objectForKey:RSSLink];
+  // Return true if it is long enough to show another IPH for this specific
+  // site.
+  if (!lastIPHForSite ||
+      [[NSDate dateWithTimeIntervalSinceNow:
+                   -kFollowIPHAppearanceThresholdForSiteInSeconds]
+          compare:lastIPHForSite] != NSOrderedAscending)
+    return true;
+
+  return false;
+}
+
+void StoreFollowIPHPresentingTime(NSURL* RSSLink) {
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+  NSDictionary<NSURL*, NSDate*>* lastFollowIPHShownTimeForSite =
+      [defaults objectForKey:kFollowIPHLastShownTimeForSite];
+
+  // Convert the dictionary to a mutable dictionary.
+  // If the dictionary value hasn't been set in user default, then create a
+  // mutable dictionary.
+  NSMutableDictionary<NSURL*, NSDate*>* mutablelLastFollowIPHShownTimeForSite =
+      lastFollowIPHShownTimeForSite
+          ? [lastFollowIPHShownTimeForSite mutableCopy]
+          : [[NSMutableDictionary<NSURL*, NSDate*> alloc] init];
+
+  // Update the last follow IPH show time for `RSSLink`.
+  [mutablelLastFollowIPHShownTimeForSite setObject:[NSDate date]
+                                            forKey:RSSLink];
+
+  NSDate* uselessDate =
+      [NSDate dateWithTimeIntervalSinceNow:
+                  -kFollowIPHAppearanceThresholdForSiteInSeconds];
+  // Clean up object that has a date older than 1 day ago. Since the follow iph
+  // will show less than 5 times a week, this clean up logic won't execute
+  // every time when page loaded.
+  // TODO(crbug.com/1340154): move the clean up logic to a more fitable place.
+  for (NSURL* key in mutablelLastFollowIPHShownTimeForSite) {
+    if ([[mutablelLastFollowIPHShownTimeForSite objectForKey:key]
+            compare:uselessDate] == NSOrderedAscending) {
+      [mutablelLastFollowIPHShownTimeForSite removeObjectForKey:key];
+    }
+  }
+
+  [defaults setObject:mutablelLastFollowIPHShownTimeForSite
+               forKey:kFollowIPHLastShownTimeForSite];
+  [defaults synchronize];
 }
diff --git a/ios/chrome/browser/ntp/BUILD.gn b/ios/chrome/browser/ntp/BUILD.gn
index 8ddd533..e651780f 100644
--- a/ios/chrome/browser/ntp/BUILD.gn
+++ b/ios/chrome/browser/ntp/BUILD.gn
@@ -34,7 +34,10 @@
     "features.mm",
   ]
   configs += [ "//build/config/compiler:enable_arc" ]
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser:utils",
+  ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/ntp/features.h b/ios/chrome/browser/ntp/features.h
index e6b0089c..f303c8b3 100644
--- a/ios/chrome/browser/ntp/features.h
+++ b/ios/chrome/browser/ntp/features.h
@@ -18,6 +18,10 @@
 // Use IsWebChannelsEnabled() instead of this constant directly.
 extern const base::Feature kEnableWebChannels;
 
+// Feature param under `kEnableFeedBackgroundRefresh` to also enable background
+// refresh for the Following feed.
+extern const char kEnableFollowingFeedBackgroundRefresh[];
+
 // Feature param under `kEnableFeedBackgroundRefresh` to enable server driven
 // background refresh schedule.
 extern const char kEnableServerDrivenBackgroundRefreshSchedule[];
@@ -30,6 +34,11 @@
 // interval in seconds.
 extern const char kBackgroundRefreshIntervalInSeconds[];
 
+// Feature param under `kEnableFeedBackgroundRefresh` for the background refresh
+// max age in seconds. This value is compared against the age of the feed when
+// performing a background refresh. A zero value means the age check is ignored.
+extern const char kBackgroundRefreshMaxAgeInSeconds[];
+
 // Whether the Following Feed is enabled on NTP.
 bool IsWebChannelsEnabled();
 
@@ -41,6 +50,9 @@
 // DCHECKs on the availability of `base::FeatureList`.
 void SaveFeedBackgroundRefreshEnabledForNextColdStart();
 
+// Whether the Following feed should also be refreshed in the background.
+bool IsFollowingFeedBackgroundRefreshEnabled();
+
 // Whether the background refresh schedule should be driven by server values.
 bool IsServerDrivenBackgroundRefreshScheduleEnabled();
 
@@ -51,4 +63,7 @@
 // The earliest interval to refresh if server value is not used.
 double GetBackgroundRefreshIntervalInSeconds();
 
+// Returns the background refresh max age in seconds.
+double GetBackgroundRefreshMaxAgeInSeconds();
+
 #endif  // IOS_CHROME_BROWSER_NTP_FEATURES_H_
diff --git a/ios/chrome/browser/ntp/features.mm b/ios/chrome/browser/ntp/features.mm
index a3ea1e0a..f18e55d 100644
--- a/ios/chrome/browser/ntp/features.mm
+++ b/ios/chrome/browser/ntp/features.mm
@@ -7,6 +7,7 @@
 #import <Foundation/Foundation.h>
 
 #import "base/metrics/field_trial_params.h"
+#import "ios/chrome/browser/system_flags.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -31,12 +32,17 @@
 NSString* const kEnableFeedBackgroundRefreshForNextColdStart =
     @"EnableFeedBackgroundRefreshForNextColdStart";
 
+const char kEnableFollowingFeedBackgroundRefresh[] =
+    "EnableFollowingFeedBackgroundRefresh";
+
 const char kEnableServerDrivenBackgroundRefreshSchedule[] =
-    "server_driven_schedule";
+    "EnableServerDrivenBackgroundRefreshSchedule";
 const char kEnableRecurringBackgroundRefreshSchedule[] =
-    "recurring_refresh_schedule";
+    "EnableRecurringBackgroundRefreshSchedule";
 const char kBackgroundRefreshIntervalInSeconds[] =
-    "refresh_interval_in_seconds";
+    "BackgroundRefreshIntervalInSeconds";
+const char kBackgroundRefreshMaxAgeInSeconds[] =
+    "BackgroundRefreshMaxAgeInSeconds";
 
 bool IsWebChannelsEnabled() {
   return base::FeatureList::IsEnabled(kEnableWebChannels);
@@ -56,6 +62,15 @@
        forKey:kEnableFeedBackgroundRefreshForNextColdStart];
 }
 
+bool IsFollowingFeedBackgroundRefreshEnabled() {
+  if (experimental_flags::IsForceBackgroundRefreshForFollowingFeedEnabled()) {
+    return YES;
+  }
+  return base::GetFieldTrialParamByFeatureAsBool(
+      kEnableFeedBackgroundRefresh, kEnableFollowingFeedBackgroundRefresh,
+      /*default=*/false);
+}
+
 bool IsServerDrivenBackgroundRefreshScheduleEnabled() {
   return base::GetFieldTrialParamByFeatureAsBool(
       kEnableFeedBackgroundRefresh,
@@ -73,3 +88,12 @@
       kEnableFeedBackgroundRefresh, kBackgroundRefreshIntervalInSeconds,
       /*default=*/60 * 60);
 }
+
+double GetBackgroundRefreshMaxAgeInSeconds() {
+  if (experimental_flags::GetBackgroundRefreshMaxAgeInSeconds() > 0) {
+    return experimental_flags::GetBackgroundRefreshMaxAgeInSeconds();
+  }
+  return base::GetFieldTrialParamByFeatureAsDouble(
+      kEnableFeedBackgroundRefresh, kBackgroundRefreshMaxAgeInSeconds,
+      /*default=*/0);
+}
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index 759e861..a7060ba 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -53,7 +53,6 @@
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils",
     "//ios/chrome/browser/ui/authentication/signin:signin_headers",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/infobars/resources:infobar_warning",
     "//ios/chrome/browser/ui/settings:settings_root",
@@ -145,7 +144,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/authentication/unified_consent:unified_consent_ui",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/unified_consent",
diff --git a/ios/chrome/browser/ui/authentication/cells/BUILD.gn b/ios/chrome/browser/ui/authentication/cells/BUILD.gn
index 5f2041e..c615966 100644
--- a/ios/chrome/browser/ui/authentication/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/cells/BUILD.gn
@@ -32,7 +32,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/authentication/views",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/settings/cells:public",
     "//ios/chrome/browser/ui/table_view:styler",
@@ -78,7 +77,6 @@
     "//ios/chrome/browser/signin:test_support",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/ui/table_view/cells",
diff --git a/ios/chrome/browser/ui/authentication/cells/signin_promo_view.mm b/ios/chrome/browser/ui/authentication/cells/signin_promo_view.mm
index 583c16f..fee1b8f2 100644
--- a/ios/chrome/browser/ui/authentication/cells/signin_promo_view.mm
+++ b/ios/chrome/browser/ui/authentication/cells/signin_promo_view.mm
@@ -11,7 +11,6 @@
 #include "components/signin/public/base/signin_metrics.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_delegate.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
index f009a29..7ae8a6f7 100644
--- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
@@ -20,7 +20,6 @@
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/BUILD.gn b/ios/chrome/browser/ui/authentication/unified_consent/BUILD.gn
index 35e10c4..14bb592 100644
--- a/ios/chrome/browser/ui/authentication/unified_consent/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/unified_consent/BUILD.gn
@@ -46,7 +46,6 @@
     "//ios/chrome/browser/ui/authentication:authentication_constants",
     "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser:identity_chooser_ui",
     "//ios/chrome/browser/ui/authentication/views",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common:string_util",
     "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/BUILD.gn b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/BUILD.gn
index ba7edc7..37a59d0 100644
--- a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/BUILD.gn
@@ -55,7 +55,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/authentication/views",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/resources:menu_shadow",
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
index d8b1855e..6a4bee61 100644
--- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
@@ -16,7 +16,6 @@
 #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/authentication/views/identity_button_control.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "ios/chrome/common/string_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn
index 4555d39b4a..6f364bba 100644
--- a/ios/chrome/browser/ui/autofill/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -47,7 +47,6 @@
     "//ios/chrome/browser/ui/autofill/manual_fill:manual_fill",
     "//ios/chrome/browser/ui/autofill/manual_fill:manual_fill_ui",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/web_state_list:web_state_list",
     "//ios/chrome/browser/webdata_services",
@@ -85,8 +84,8 @@
     "//components/strings",
     "//ios/chrome/browser/ui/autofill/cells",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/list_model",
+    "//ios/chrome/browser/ui/table_view:utils",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/colors",
@@ -118,7 +117,6 @@
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:public",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
index 5e420c0..e00d4273 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h
@@ -5,12 +5,21 @@
 #ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_VIEW_BRIDGE_H_
 #define IOS_CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_VIEW_BRIDGE_H_
 
+#import "base/memory/weak_ptr.h"
 #import "components/autofill/core/browser/ui/payments/card_unmask_prompt_view.h"
 
+@class CardUnmaskPromptViewController;
+@class UIViewController;
+
 namespace autofill {
+
+class CardUnmaskPromptController;
+
 // iOS implementation of the unmask prompt UI.
 class CardUnmaskPromptViewBridge : public CardUnmaskPromptView {
  public:
+  CardUnmaskPromptViewBridge(CardUnmaskPromptController* controller,
+                             UIViewController* base_view_controller);
   CardUnmaskPromptViewBridge(const CardUnmaskPromptViewBridge&) = delete;
   CardUnmaskPromptViewBridge& operator=(const CardUnmaskPromptViewBridge&) =
       delete;
@@ -23,6 +32,28 @@
   void DisableAndWaitForVerification() override;
   void GotVerificationResult(const std::u16string& error_message,
                              bool allow_retry) override;
+
+  CardUnmaskPromptController* GetController();
+
+  // Closes the view.
+  void PerformClose();
+
+ protected:
+  // Created on `Show` and destroyed when 'this' is destroyed.
+  CardUnmaskPromptViewController* view_controller_;
+
+ private:
+  // Deletes self. This should only be called by CardUnmaskPromptViewController
+  // after it finishes dismissing its own UI elements.
+  void DeleteSelf();
+
+  // The controller `this` queries for logic and state.
+  CardUnmaskPromptController* controller_;  // weak
+
+  // Weak reference to the view controller used to present UI.
+  __weak UIViewController* base_view_controller_;
+
+  base::WeakPtrFactory<CardUnmaskPromptViewBridge> weak_ptr_factory_;
 };
 
 }  // namespace autofill
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
index 359236e..1ac25dce 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
@@ -5,6 +5,8 @@
 #import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h"
 
 #import "base/notreached.h"
+#import "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h"
+#import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -14,16 +16,45 @@
 
 #pragma mark CardUnmaskPromptViewBridge
 
+CardUnmaskPromptViewBridge::CardUnmaskPromptViewBridge(
+    CardUnmaskPromptController* controller,
+    UIViewController* base_view_controller)
+    : controller_(controller),
+      base_view_controller_(base_view_controller),
+      weak_ptr_factory_(this) {
+  DCHECK(controller_);
+}
+
 CardUnmaskPromptViewBridge::~CardUnmaskPromptViewBridge() {
-  NOTIMPLEMENTED();
+  if (controller_) {
+    controller_->OnUnmaskDialogClosed();
+  }
 }
 
 void CardUnmaskPromptViewBridge::Show() {
-  NOTIMPLEMENTED();
+  view_controller_ =
+      [[CardUnmaskPromptViewController alloc] initWithBridge:this];
+
+  UINavigationController* navigation_controller =
+      [[UINavigationController alloc]
+          initWithRootViewController:view_controller_];
+  [navigation_controller
+      setModalPresentationStyle:UIModalPresentationFormSheet];
+  [navigation_controller
+      setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
+  // If this prompt is swiped away, it cannot be opened again. Work
+  // around this bug by preventing swipe-to-dismiss.
+  // TODO(crbug.com/1346060)
+  [navigation_controller setModalInPresentation:YES];
+
+  [base_view_controller_ presentViewController:navigation_controller
+                                      animated:YES
+                                    completion:nil];
 }
 
 void CardUnmaskPromptViewBridge::ControllerGone() {
-  NOTIMPLEMENTED();
+  controller_ = nullptr;
+  PerformClose();
 }
 
 void CardUnmaskPromptViewBridge::DisableAndWaitForVerification() {
@@ -36,4 +67,24 @@
   NOTIMPLEMENTED();
 }
 
+CardUnmaskPromptController* CardUnmaskPromptViewBridge::GetController() {
+  return controller_;
+}
+
+void CardUnmaskPromptViewBridge::PerformClose() {
+  base::WeakPtr<CardUnmaskPromptViewBridge> weak_this =
+      weak_ptr_factory_.GetWeakPtr();
+  [view_controller_.navigationController
+      dismissViewControllerAnimated:YES
+                         completion:^{
+                           if (weak_this) {
+                             weak_this->DeleteSelf();
+                           }
+                         }];
+}
+
+void CardUnmaskPromptViewBridge::DeleteSelf() {
+  delete this;
+}
+
 }  // namespace autofill
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h
index dd62fb0..0443362 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h
@@ -7,6 +7,10 @@
 
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
 
+namespace autofill {
+class CardUnmaskPromptViewBridge;
+}
+
 // IOS UI for the Autofill Card Unmask Prompt.
 //
 // This view controller is presented when the user needs to verify a saved
@@ -17,6 +21,10 @@
 // dismissed and the operation requiring the card verification is continued
 // (e.g: the card is autofilled in a payment form).
 @interface CardUnmaskPromptViewController : ChromeTableViewController
+// Designated initializer. `bridge` must not be null.
+- (instancetype)initWithBridge:(autofill::CardUnmaskPromptViewBridge*)bridge
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithStyle:(UITableViewStyle*)style NS_UNAVAILABLE;
 
 @end
 #endif  // IOS_CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
index 4941eea0..73584bf 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.mm
@@ -4,10 +4,31 @@
 
 #import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_controller.h"
 
+#import "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h"
+#import "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h"
+#import "ios/chrome/browser/ui/table_view/table_view_utils.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+@interface CardUnmaskPromptViewController () {
+  // Owns `self`.
+  autofill::CardUnmaskPromptViewBridge* _bridge;  // weak
+}
+
+@end
+
 @implementation CardUnmaskPromptViewController
 
+- (instancetype)initWithBridge:(autofill::CardUnmaskPromptViewBridge*)bridge {
+  self = [super initWithStyle:ChromeTableViewStyle()];
+
+  if (self) {
+    _bridge = bridge;
+  }
+
+  return self;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/autofill/cells/BUILD.gn b/ios/chrome/browser/ui/autofill/cells/BUILD.gn
index 7d86894..1848ca6 100644
--- a/ios/chrome/browser/ui/autofill/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/cells/BUILD.gn
@@ -28,7 +28,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/autofill:autofill_ui_type",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/ntp:logo",
     "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/ui/table_view/cells",
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index 02259033..9e78b1c 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -123,9 +123,7 @@
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/main:public",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/default_promo:utils",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/util:url_with_title",
     "//ios/chrome/browser/undo",
@@ -165,7 +163,6 @@
     "//ios/chrome/browser/ui/icons",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/keyboard",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:presentation",
     "//ios/chrome/browser/ui/table_view:styler",
diff --git a/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn b/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn
index f20db4d..9e3bbe9 100644
--- a/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/cells/BUILD.gn
@@ -27,7 +27,6 @@
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/bookmarks:constants",
     "//ios/chrome/browser/ui/bookmarks:core",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/icons",
     "//ios/chrome/browser/ui/ntp:logo",
     "//ios/chrome/browser/ui/table_view:styler",
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index d16ec41..2da92c0 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -93,7 +93,6 @@
     "//ios/chrome/browser/ui/browser_container",
     "//ios/chrome/browser/ui/browser_container:ui",
     "//ios/chrome/browser/ui/bubble",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
diff --git a/ios/chrome/browser/ui/bubble/BUILD.gn b/ios/chrome/browser/ui/bubble/BUILD.gn
index 6320a54..bc2c340 100644
--- a/ios/chrome/browser/ui/bubble/BUILD.gn
+++ b/ios/chrome/browser/ui/bubble/BUILD.gn
@@ -26,7 +26,6 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/follow:utils",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/icons:symbols",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm
index d888c46..f5b3397 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -9,7 +9,6 @@
 #include "base/check.h"
 #include "base/notreached.h"
 #import "ios/chrome/browser/ui/bubble/bubble_util.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/icons/chrome_symbol.h"
 #include "ios/chrome/browser/ui/util/rtl_geometry.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
diff --git a/ios/chrome/browser/ui/collection_view/cells/BUILD.gn b/ios/chrome/browser/ui/collection_view/cells/BUILD.gn
index 4fcdc47..2846030 100644
--- a/ios/chrome/browser/ui/collection_view/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/collection_view/cells/BUILD.gn
@@ -21,9 +21,7 @@
     "//base",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/list_model",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common",
diff --git a/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.mm b/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.mm
index 19c90caf..41c35e38 100644
--- a/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.mm
+++ b/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.mm
@@ -10,7 +10,6 @@
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
 #include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
index b05c6e6..c8cebc8 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
@@ -56,7 +56,6 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/collection_view",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/content_suggestions:constants",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_ui_util",
@@ -64,7 +63,6 @@
     "//ios/chrome/browser/ui/content_suggestions:public",
     "//ios/chrome/browser/ui/content_suggestions/identifier",
     "//ios/chrome/browser/ui/icons:symbols",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common:string_util",
     "//ios/chrome/common:timing",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h
index 8895e71f..bf9ba75 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h
@@ -33,6 +33,8 @@
 extern const CGFloat kMostVisitedBottomMargin;
 
 // Maximum number of Trending Queries shown.
-extern const NSUInteger kMaxTrendingQueries;
+// If the value of this constant is updated, please also update the
+// TrendingQueryIndex enum so it can capture a higher max value.
+const int kMaxTrendingQueries = 4;
 
 #endif  // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm
index 1c21c97e..720af1b 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm
@@ -20,5 +20,3 @@
     @"contentSuggestionsShortcutsAccessibilityIdentifierPrefix";
 
 const CGFloat kMostVisitedBottomMargin = 13;
-
-const NSUInteger kMaxTrendingQueries = 4;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
index 6d015cf..be8e55c5 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -9,6 +9,7 @@
 #import "base/bind.h"
 #import "base/callback.h"
 #import "base/mac/foundation_util.h"
+#import "base/metrics/histogram_macros.h"
 #import "base/metrics/user_metrics.h"
 #import "base/metrics/user_metrics_action.h"
 #import "base/strings/sys_string_conversions.h"
@@ -487,6 +488,10 @@
 }
 
 - (void)loadSuggestedQuery:(QuerySuggestionConfig*)config {
+  UMA_HISTOGRAM_ENUMERATION("IOS.TrendingQueries", config.index,
+                            kMaxTrendingQueries);
+  [self.NTPMetrics recordContentSuggestionsActionForType:
+                       IOSContentSuggestionsActionType::kTrendingQuery];
   UrlLoadParams params = UrlLoadParams::InCurrentTab(config.URL);
   params.web_params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK;
   UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
@@ -555,7 +560,7 @@
 
 - (void)suggestionsReceived:(std::vector<QuerySuggestion>)suggestions {
   self.trendingQueries = [NSMutableArray array];
-  NSUInteger index = 0;
+  int index = 0;
   for (QuerySuggestion query : suggestions) {
     if (index == kMaxTrendingQueries) {
       break;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm
index 72ce5f0..4f279ea 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm
@@ -281,15 +281,25 @@
   OCMExpect([consumer_ setTrendingQueriesWithConfigs:@[]]);
   [mediator_ suggestionsReceived:std::vector<QuerySuggestion>()];
 
+  int index = 1;
+  histogram_tester_->ExpectUniqueSample(
+      "IOS.ContentSuggestions.ActionOnNTP",
+      IOSContentSuggestionsActionType::kTrendingQuery, 0);
+  histogram_tester_->ExpectUniqueSample("IOS.TrendingQueries", index, 0);
+
   // Test that the mediator loads the URL in the config passed into
   // loadSuggestedQuery:.
   GURL url = GURL("http://chromium.org");
   QuerySuggestionConfig* config = [[QuerySuggestionConfig alloc] init];
-  config.index = 1;
+  config.index = index;
   config.URL = url;
   [mediator_ loadSuggestedQuery:config];
   EXPECT_EQ(url, url_loader_->last_params.web_params.url);
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       ui::PAGE_TRANSITION_AUTO_BOOKMARK,
       url_loader_->last_params.web_params.transition_type));
+  histogram_tester_->ExpectUniqueSample(
+      "IOS.ContentSuggestions.ActionOnNTP",
+      IOSContentSuggestionsActionType::kTrendingQuery, 1);
+  histogram_tester_->ExpectUniqueSample("IOS.TrendingQueries", index, 1);
 }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index 4f6aedb4..c8e8401 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -542,7 +542,7 @@
     self.trendingQueryViews = [NSMutableArray array];
   }
 
-  if ([configs count] < kMaxTrendingQueries) {
+  if ((int)[configs count] < kMaxTrendingQueries) {
     // No Trending Queries to show. Remove module.
     [self.trendingQueriesContainingView removeFromSuperview];
     [self.trendingQueriesModuleContainer removeFromSuperview];
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_metrics.h b/ios/chrome/browser/ui/content_suggestions/ntp_home_metrics.h
index 2f7523b..b91fc182 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_metrics.h
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_metrics.h
@@ -30,7 +30,8 @@
   kReturnToRecentTab = 2,
   kFeedCard = 3,
   kFakebox = 4,
-  kMaxValue = kFakebox,
+  kTrendingQuery = 5,
+  kMaxValue = kTrendingQuery,
 };
 
 // Metrics recorder for the action used to potentially leave the NTP.
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn
index 76cccf0..3fafa7ab 100644
--- a/ios/chrome/browser/ui/download/BUILD.gn
+++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -49,7 +49,6 @@
     "//ios/chrome/browser/store_kit",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/download/activities",
diff --git a/ios/chrome/browser/ui/elements/BUILD.gn b/ios/chrome/browser/ui/elements/BUILD.gn
index ebfe77d..c77089f 100644
--- a/ios/chrome/browser/ui/elements/BUILD.gn
+++ b/ios/chrome/browser/ui/elements/BUILD.gn
@@ -29,8 +29,6 @@
   deps = [
     "//base",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common:string_util",
     "//ios/chrome/common/ui/colors",
@@ -81,7 +79,6 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/main:scene_state_header",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/scoped_ui_blocker:scoped_ui_blocker",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/elements/home_waiting_view.mm b/ios/chrome/browser/ui/elements/home_waiting_view.mm
index b6038d27..7893881 100644
--- a/ios/chrome/browser/ui/elements/home_waiting_view.mm
+++ b/ios/chrome/browser/ui/elements/home_waiting_view.mm
@@ -5,11 +5,9 @@
 #import "ios/chrome/browser/ui/elements/home_waiting_view.h"
 
 #import <MaterialComponents/MaterialActivityIndicator.h>
-#import <MaterialComponents/MaterialPalettes.h>
 
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
-#import "ios/chrome/browser/ui/material_components/activity_indicator.h"
 #import "ios/chrome/browser/ui/util/rtl_geometry.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -50,8 +48,7 @@
         UIViewAutoresizingFlexibleBottomMargin;
     self.activityIndicator.center = CGPointMake(
         CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2);
-    self.activityIndicator.cycleColors =
-        @[ [[MDCPalette cr_bluePalette] tint500] ];
+    self.activityIndicator.cycleColors = @[ [UIColor colorNamed:kBlueColor] ];
     [self addSubview:self.activityIndicator];
     [self.activityIndicator startAnimating];
   });
diff --git a/ios/chrome/browser/ui/fancy_ui/BUILD.gn b/ios/chrome/browser/ui/fancy_ui/BUILD.gn
index 4da42bf7..9249ab6 100644
--- a/ios/chrome/browser/ui/fancy_ui/BUILD.gn
+++ b/ios/chrome/browser/ui/fancy_ui/BUILD.gn
@@ -12,7 +12,6 @@
     "//base",
     "//base:i18n",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/util",
   ]
diff --git a/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm b/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm
index fd39d859..816ef60f 100644
--- a/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm
+++ b/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm
@@ -4,7 +4,6 @@
 
 #import "ios/chrome/browser/ui/fancy_ui/primary_action_button.h"
 
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/pointer_interaction_util.h"
 
diff --git a/ios/chrome/browser/ui/material_components/BUILD.gn b/ios/chrome/browser/ui/material_components/BUILD.gn
deleted file mode 100644
index 862662b..0000000
--- a/ios/chrome/browser/ui/material_components/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("material_components") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "activity_indicator.h",
-    "activity_indicator.mm",
-  ]
-  deps = [
-    "//base",
-    "//build:branding_buildflags",
-    "//ios/chrome/browser/ui/colors",
-    "//ios/chrome/common/ui/colors",
-    "//ios/third_party/material_components_ios",
-  ]
-  frameworks = [ "UIKit.framework" ]
-}
diff --git a/ios/chrome/browser/ui/material_components/activity_indicator.h b/ios/chrome/browser/ui/material_components/activity_indicator.h
deleted file mode 100644
index b6436ec..0000000
--- a/ios/chrome/browser/ui/material_components/activity_indicator.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_ACTIVITY_INDICATOR_H_
-#define IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_ACTIVITY_INDICATOR_H_
-
-#import <Foundation/Foundation.h>
-
-// Returns an array of UIColor objects that matches the current product
-// branding. These colors are suitable for use in an MDCActivityIndicator.
-NSArray* ActivityIndicatorBrandedCycleColors();
-
-#endif  // IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_ACTIVITY_INDICATOR_H_
diff --git a/ios/chrome/browser/ui/material_components/activity_indicator.mm b/ios/chrome/browser/ui/material_components/activity_indicator.mm
deleted file mode 100644
index b099585d..0000000
--- a/ios/chrome/browser/ui/material_components/activity_indicator.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/material_components/activity_indicator.h"
-
-#import <MaterialComponents/MaterialPalettes.h>
-
-#include "build/branding_buildflags.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-NSArray* ActivityIndicatorBrandedCycleColors() {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  return @[
-    [[MDCPalette cr_bluePalette] tint500], [[MDCPalette cr_redPalette] tint500],
-    [[MDCPalette cr_yellowPalette] tint500],
-    [[MDCPalette cr_greenPalette] tint500]
-  ];
-#else
-  return @[
-    [MDCPalette bluePalette].tint800,
-    [MDCPalette bluePalette].tint500,
-    [MDCPalette bluePalette].tint200,
-  ];
-#endif
-}
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
index 2579eab..85f942c 100644
--- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -152,7 +152,6 @@
     "//ios/chrome/app/theme",
     "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions/cells",
     "//ios/chrome/browser/ui/elements",
@@ -189,7 +188,6 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/omnibox:features",
     "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
index 893eb0d..a940e8d 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_formatter.mm
@@ -7,7 +7,6 @@
 #include "base/notreached.h"
 #import "components/omnibox/browser/autocomplete_match.h"
 #import "ios/chrome/browser/net/crurl.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "url/gurl.h"
 
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
index d6b1f29..8d805c2a 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
@@ -6,7 +6,6 @@
 
 #include "base/check.h"
 #include "components/omnibox/common/omnibox_features.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/elements/extended_touch_target_button.h"
 #import "ios/chrome/browser/ui/elements/fade_truncating_label.h"
 #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/simple_omnibox_icon.mm b/ios/chrome/browser/ui/omnibox/popup/simple_omnibox_icon.mm
index b3c0521d..a75ab9eb 100644
--- a/ios/chrome/browser/ui/omnibox/popup/simple_omnibox_icon.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/simple_omnibox_icon.mm
@@ -6,7 +6,6 @@
 
 #import "base/notreached.h"
 #import "ios/chrome/browser/net/crurl.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_suggestion_icon_util.h"
 #import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
diff --git a/ios/chrome/browser/ui/open_in/BUILD.gn b/ios/chrome/browser/ui/open_in/BUILD.gn
index 4786240..30b8305 100644
--- a/ios/chrome/browser/ui/open_in/BUILD.gn
+++ b/ios/chrome/browser/ui/open_in/BUILD.gn
@@ -18,7 +18,6 @@
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/open_in",
     "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/util",
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
index c0aaac1..6845663 100644
--- a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
+++ b/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm
@@ -134,6 +134,10 @@
 
 // Tests that open in button do not appears when opening a MOV file.
 - (void)testOpenInMOV {
+  // TODO(crbug.com/1346136): Opening this mov is crashing WebContent on iOS16.
+  if (@available(iOS 16, *)) {
+    EARL_GREY_TEST_DISABLED(@"testOpenInMOV crashing WebContent on iOS16");
+  }
   [ChromeEarlGrey loadURL:self.testServer->GetURL(kMOVPath)];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()]
       assertWithMatcher:grey_nil()];
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
index 72572e5b..7f4e8dc 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -255,7 +255,7 @@
   }
 
   if (self.webState && self.followAction) {
-    FollowTabHelper::FromWebState(self.webState)->remove_follow_menu_updater();
+    FollowTabHelper::FromWebState(self.webState)->RemoveFollowMenuUpdater();
   }
 
   self.destinationUsageHistory = nil;
@@ -313,7 +313,7 @@
   self.webState = (_webStateList) ? _webStateList->GetActiveWebState() : nil;
 
   if (self.webState && !self.isIncognito && IsWebChannelsEnabled()) {
-    FollowTabHelper::FromWebState(self.webState)->set_follow_menu_updater(self);
+    FollowTabHelper::FromWebState(self.webState)->SetFollowMenuUpdater(self);
   }
 
   if (_webStateList) {
@@ -1167,7 +1167,7 @@
                      reason:(ActiveWebStateChangeReason)reason {
   self.webState = newWebState;
   if (self.webState && self.followAction) {
-    FollowTabHelper::FromWebState(self.webState)->set_follow_menu_updater(self);
+    FollowTabHelper::FromWebState(self.webState)->SetFollowMenuUpdater(self);
   }
 }
 
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index c540b4a..e3d826de 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -259,7 +259,7 @@
     _webState->RemoveObserver(_webStateObserver.get());
     _webStateObserver.reset();
     if (self.followItem) {
-      FollowTabHelper::FromWebState(_webState)->remove_follow_menu_updater();
+      FollowTabHelper::FromWebState(_webState)->RemoveFollowMenuUpdater();
       self.webPageURLs = nil;
     }
     _webState = nullptr;
@@ -521,7 +521,7 @@
         [self createToolsMenuItems];
         if (self.webState && self.followItem) {
           FollowTabHelper::FromWebState(self.webState)
-              ->set_follow_menu_updater(self);
+              ->SetFollowMenuUpdater(self);
         }
         break;
       case PopupMenuTypeNavigationForward:
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index d46b938..0dcf43ff 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -147,7 +147,6 @@
     "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/list_model",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/settings/cells",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:utils",
diff --git a/ios/chrome/browser/ui/sad_tab/BUILD.gn b/ios/chrome/browser/ui/sad_tab/BUILD.gn
index 930a9928..c6fa4d6 100644
--- a/ios/chrome/browser/ui/sad_tab/BUILD.gn
+++ b/ios/chrome/browser/ui/sad_tab/BUILD.gn
@@ -17,7 +17,6 @@
     "//components/ui_metrics",
     "//ios/chrome/browser",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm b/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
index cbbf91e..5e4eb36 100644
--- a/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
+++ b/ios/chrome/browser/ui/sad_tab/sad_tab_view.mm
@@ -13,7 +13,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/ui_metrics/sadtab_metrics_types.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #include "ios/chrome/browser/ui/util/rtl_geometry.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 810b9f7c..1959d96f 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -146,7 +146,6 @@
     "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils",
     "//ios/chrome/browser/ui/authentication/signin:signin_headers",
     "//ios/chrome/browser/ui/autofill/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions:feature_flags",
     "//ios/chrome/browser/ui/content_suggestions/cells",
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn
index 8690b2e..afb694a9 100644
--- a/ios/chrome/browser/ui/settings/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -40,7 +40,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/authentication:authentication_constants",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/icons",
     "//ios/chrome/browser/ui/settings:constants",
     "//ios/chrome/browser/ui/table_view:styler",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
index ec9cb0a..7be091c 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -48,7 +48,6 @@
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/collection_view",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/elements:elements_internal",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
index a1fe9403..d5f51f7 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -45,7 +45,6 @@
 #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/icons/chrome_symbol.h"
 #import "ios/chrome/browser/ui/list_model/list_model.h"
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn
index e6715633..0685f455 100644
--- a/ios/chrome/browser/ui/settings/password/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -257,6 +257,7 @@
     "//components/strings:components_strings_grit",
     "//components/sync/driver",
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/metrics:eg_test_support+eg2",
     "//ios/chrome/browser/ui/authentication:eg_test_support+eg2",
     "//ios/chrome/browser/ui/settings:settings_root_constants",
     "//ios/chrome/browser/ui/settings/google_services:constants",
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
index 3192b6b..5b3912c 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/password_manager_view_controller.mm
@@ -316,6 +316,11 @@
 // Return YES if the search bar should be enabled.
 @property(nonatomic, assign) BOOL shouldEnableSearchBar;
 
+// Keep track of how many passwords have been loaded for the logs and how many
+// of them are favicons with an image (not monogram string).
+@property(nonatomic, strong)
+    NSMutableDictionary<NSString*, NSNumber*>* passwordsLoadedWithFavicons;
+
 @end
 
 @implementation PasswordManagerViewController
@@ -439,6 +444,10 @@
   if (!_didReceiveSavedForms) {
     [self showLoadingSpinnerBackground];
   }
+
+  if (!self.passwordsLoadedWithFavicons) {
+    self.passwordsLoadedWithFavicons = [[NSMutableDictionary alloc] init];
+  }
 }
 
 - (void)viewWillAppear:(BOOL)animated {
@@ -459,6 +468,8 @@
 - (void)viewWillDisappear:(BOOL)animated {
   [super viewWillDisappear:animated];
 
+  [self logMetricsForFavicons];
+
   // Restore to default origin offset for cancel button proxy style.
   UIBarButtonItem* cancelButton = [UIBarButtonItem
       appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]];
@@ -1797,6 +1808,31 @@
   }
 }
 
+// Logs metrics related to favicons for the Password Manager.
+- (void)logMetricsForFavicons {
+  // Log the number of passwords with a favicon loaded.
+  base::UmaHistogramCounts10000(
+      "IOS.PasswordManager.PasswordsWithFavicons.Count",
+      self.passwordsLoadedWithFavicons.count);
+
+  if (self.passwordsLoadedWithFavicons.count == 0)
+    return;
+
+  int count = 0;
+  NSNumber* yesAsNSNumber = [NSNumber numberWithBool:YES];
+  for (NSNumber* value in self.passwordsLoadedWithFavicons.allValues) {
+    if (value == yesAsNSNumber)
+      count++;
+  }
+  // Log the number of favicons loaded (image, not monogram string).
+  base::UmaHistogramCounts10000("IOS.PasswordManager.Favicons.Count", count);
+  // Log % of passwords that have a favicon that is an image.
+  float percentage =
+      ((float)count / (float)self.passwordsLoadedWithFavicons.count) * 100.0f;
+  base::UmaHistogramPercentage("IOS.PasswordManager.Favicons.Percentage",
+                               percentage);
+}
+
 #pragma mark - UITableViewDelegate
 
 - (void)tableView:(UITableView*)tableView
@@ -2018,6 +2054,13 @@
            if ([URLCell.cellUniqueIdentifier isEqualToString:itemIdentifier]) {
              DCHECK(attributes);
              [URLCell.faviconView configureWithAttributes:attributes];
+
+             // Value is YES if the favicon is an image not a monogram string.
+             // Storing as the value as an NSNumber object because values in an
+             // NSDictionary must be objects.
+             [self.passwordsLoadedWithFavicons
+                 setValue:(attributes.faviconImage != nil ? @YES : @NO)
+                   forKey:itemIdentifier];
            }
          }];
 }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
index e1e67be..6abc7504 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
@@ -6,22 +6,23 @@
 
 #include <utility>
 
-#include "base/callback.h"
-#include "base/ios/ios_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/time/time.h"
-#include "components/password_manager/core/common/password_manager_features.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/sync/base/features.h"
+#import "base/callback.h"
+#import "base/ios/ios_util.h"
+#import "base/strings/sys_string_conversions.h"
+#import "base/test/scoped_feature_list.h"
+#import "base/time/time.h"
+#import "components/password_manager/core/common/password_manager_features.h"
+#import "components/strings/grit/components_strings.h"
+#import "components/sync/base/features.h"
+#import "ios/chrome/browser/metrics/metrics_app_interface.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h"
-#include "ios/chrome/browser/ui/settings/password/password_settings_app_interface.h"
+#import "ios/chrome/browser/ui/settings/password/password_settings_app_interface.h"
 #import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h"
 #import "ios/chrome/browser/ui/settings/settings_root_table_constants.h"
 #import "ios/chrome/common/ui/reauthentication/reauthentication_protocol.h"
 #import "ios/chrome/common/ui/table_view/table_view_cells_constants.h"
-#include "ios/chrome/grit/ios_strings.h"
+#import "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h"
@@ -31,8 +32,8 @@
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/testing/earl_grey/app_launch_manager.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
-#include "ios/web/public/test/element_selector.h"
-#include "ui/base/l10n/l10n_util.h"
+#import "ios/web/public/test/element_selector.h"
+#import "ui/base/l10n/l10n_util.h"
 
 #include "ios/third_party/earl_grey2/src/CommonLib/Matcher/GREYLayoutConstraint.h"  // nogncheck
 
@@ -387,6 +388,12 @@
 
 @implementation PasswordsSettingsTestCase
 
+- (void)setUp {
+  [super setUp];
+  GREYAssertNil([MetricsAppInterface setupHistogramTester],
+                @"Cannot setup histogram tester.");
+}
+
 - (void)tearDown {
   // Snackbars triggered by tests stay up for a limited time even if the
   // settings get closed. Ensure that they are closed to avoid interference with
@@ -395,6 +402,9 @@
   GREYAssert([PasswordSettingsAppInterface clearPasswordStore],
              @"PasswordStore was not cleared.");
 
+  GREYAssertNil([MetricsAppInterface releaseHistogramTester],
+                @"Cannot reset histogram tester.");
+
   [super tearDown];
 }
 
@@ -2107,4 +2117,110 @@
       performAction:grey_tap()];
 }
 
+// Tests that the favicons for the password managers metrics are logged
+// properly when there are passwords with a favicon.
+- (void)testLogFaviconsForPasswordsMetrics {
+  // Sign-in and synced user.
+  FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1];
+  [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
+
+  // Add passwords for the user.
+  SaveExamplePasswordForms();
+
+  OpenPasswordSettings();
+
+  [GetInteractionForPasswordEntry(@"example11.com, user1")
+      performAction:grey_tap()];
+
+  // Metric: Passwords in the password manager.
+  // Verify that histogram is called.
+  NSError* error = [MetricsAppInterface
+      expectTotalCount:1
+          forHistogram:@"IOS.PasswordManager.PasswordsWithFavicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+  // Verify the logged value of the histogram.
+  error = [MetricsAppInterface
+         expectSum:2
+      forHistogram:@"IOS.PasswordManager.PasswordsWithFavicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+
+  // Metric: Passwords with a favicon (image) in the password manager.
+  // Verify that histogram is called.
+  error = [MetricsAppInterface
+      expectTotalCount:1
+          forHistogram:@"IOS.PasswordManager.Favicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+  // Verify the logged value of the histogram.
+  error = [MetricsAppInterface expectSum:0
+                            forHistogram:@"IOS.PasswordManager.Favicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+
+  // Metric: Percentage of favicons with image.
+  // Verify that histogram is called.
+  error = [MetricsAppInterface
+      expectTotalCount:1
+          forHistogram:@"IOS.PasswordManager.Favicons.Percentage"];
+  if (error) {
+    GREYFail([error description]);
+  }
+  // Verify the logged value of the histogram.
+  error = [MetricsAppInterface
+         expectSum:0
+      forHistogram:@"IOS.PasswordManager.Favicons.Percentage"];
+  if (error) {
+    GREYFail([error description]);
+  }
+}
+
+// Tests that the favicons for the password managers metrics are logged
+// properly when there are no password.
+- (void)testLogFaviconsForPasswordsMetricsNoPassword {
+  OpenPasswordSettings();
+
+  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
+      performAction:grey_tap()];
+
+  // Metric: Passwords in the password manager.
+  // Verify that histogram is called.
+  NSError* error = [MetricsAppInterface
+      expectTotalCount:1
+          forHistogram:@"IOS.PasswordManager.PasswordsWithFavicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+  // Verify the logged value of the histogram.
+  error = [MetricsAppInterface
+         expectSum:0
+      forHistogram:@"IOS.PasswordManager.PasswordsWithFavicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+
+  // Metric: Percentage of favicons with image.
+  // This histogram is not logged.
+  error = [MetricsAppInterface
+      expectTotalCount:0
+          forHistogram:@"IOS.PasswordManager.Favicons.Count"];
+  if (error) {
+    GREYFail([error description]);
+  }
+
+  // Metric: Percentage of favicons with image.
+  // This histogram is not logged.
+  error = [MetricsAppInterface
+      expectTotalCount:0
+          forHistogram:@"IOS.PasswordManager.Favicons.Percentage"];
+  if (error) {
+    GREYFail([error description]);
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/privacy/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
index 5abdf54..79f737a6 100644
--- a/ios/chrome/browser/ui/settings/privacy/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
@@ -43,7 +43,6 @@
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/icons:symbols",
diff --git a/ios/chrome/browser/ui/settings/sync/BUILD.gn b/ios/chrome/browser/ui/settings/sync/BUILD.gn
index c164fcf..123057c8 100644
--- a/ios/chrome/browser/ui/settings/sync/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/sync/BUILD.gn
@@ -36,7 +36,6 @@
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/collection_view",
     "//ios/chrome/browser/ui/collection_view/cells",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/main:scene_state_header",
     "//ios/chrome/browser/ui/scoped_ui_blocker",
diff --git a/ios/chrome/browser/ui/table_view/BUILD.gn b/ios/chrome/browser/ui/table_view/BUILD.gn
index 2e55229..19dfd16 100644
--- a/ios/chrome/browser/ui/table_view/BUILD.gn
+++ b/ios/chrome/browser/ui/table_view/BUILD.gn
@@ -21,7 +21,6 @@
     "//base",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/list_model",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/common/ui/colors",
     "//ios/third_party/material_components_ios",
   ]
@@ -86,8 +85,6 @@
   deps = [
     ":constants",
     "//base",
-    "//ios/chrome/browser/ui/colors",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/colors",
     "//ios/third_party/material_components_ios",
diff --git a/ios/chrome/browser/ui/table_view/cells/BUILD.gn b/ios/chrome/browser/ui/table_view/cells/BUILD.gn
index e41db572..be6c8215 100644
--- a/ios/chrome/browser/ui/table_view/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/table_view/cells/BUILD.gn
@@ -66,7 +66,6 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/net:crurl",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/colors:colors",
     "//ios/chrome/browser/ui/elements",
     "//ios/chrome/browser/ui/icons:item_icons",
     "//ios/chrome/browser/ui/icons:symbols",
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
index 3c7ffe4e..0c726d1 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_activity_indicator_header_footer_item.mm
@@ -7,7 +7,6 @@
 #import <MaterialComponents/MaterialActivityIndicator.h>
 
 #include "base/mac/foundation_util.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
@@ -78,7 +77,7 @@
     // Activity Indicator.
     MDCActivityIndicator* activityIndicator =
         [[MDCActivityIndicator alloc] init];
-    activityIndicator.cycleColors = @[ [[MDCPalette cr_bluePalette] tint500] ];
+    activityIndicator.cycleColors = @[ [UIColor colorNamed:kBlueColor] ];
     [activityIndicator startAnimating];
     [activityIndicator
         setContentHuggingPriority:UILayoutPriorityDefaultHigh
diff --git a/ios/chrome/browser/ui/table_view/table_view_loading_view.mm b/ios/chrome/browser/ui/table_view/table_view_loading_view.mm
index 07aed76b..be21898 100644
--- a/ios/chrome/browser/ui/table_view/table_view_loading_view.mm
+++ b/ios/chrome/browser/ui/table_view/table_view_loading_view.mm
@@ -6,9 +6,8 @@
 
 #import <MaterialComponents/MaterialActivityIndicator.h>
 
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
-#import "ios/chrome/browser/ui/material_components/activity_indicator.h"
 #import "ios/chrome/browser/ui/util/rtl_geometry.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -56,8 +55,7 @@
       [[MDCActivityIndicator alloc] initWithFrame:CGRectZero];
   self.activityIndicator.radius = kLoadingIndicatorRadius;
   self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
-  self.activityIndicator.cycleColors =
-      @[ [[MDCPalette cr_bluePalette] tint500] ];
+  self.activityIndicator.cycleColors = @[ [UIColor colorNamed:kBlueColor] ];
   self.activityIndicator.delegate = self;
 
   UILabel* messageLabel = [[UILabel alloc] init];
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index 21ad0538..9b5ab40 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -47,7 +47,6 @@
     "//ios/chrome/browser/snapshots",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/bubble",
-    "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/elements",
     "//ios/chrome/browser/ui/fullscreen",
diff --git a/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc b/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
index 83c39c7d..2742d3c8 100644
--- a/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
+++ b/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
@@ -70,8 +70,8 @@
     PrefService* prefs,
     gcm::GCMProfileService* profile_service,
     const gcm::GCMClient::GCMStatistics* stats) const {
-  base::DictionaryValue results;
-  gcm_driver::SetGCMInternalsInfo(stats, profile_service, prefs, &results);
+  base::Value results =
+      gcm_driver::SetGCMInternalsInfo(stats, profile_service, prefs);
 
   base::Value event_name(gcm_driver::kSetGcmInternalsInfo);
   std::vector<const base::Value*> args{&event_name, &results};
diff --git a/ios/chrome/browser/ui/webui/policy/policy_ui.mm b/ios/chrome/browser/ui/webui/policy/policy_ui.mm
index 6e096bc..9000e619d 100644
--- a/ios/chrome/browser/ui/webui/policy/policy_ui.mm
+++ b/ios/chrome/browser/ui/webui/policy/policy_ui.mm
@@ -90,11 +90,19 @@
   source->AddResourcePath("policy.css", IDR_POLICY_CSS);
   source->AddResourcePath("policy_base.js", IDR_POLICY_BASE_JS);
   source->AddResourcePath("policy.js", IDR_POLICY_JS);
+  source->AddResourcePath("policy_conflict.html.js",
+                          IDR_POLICY_POLICY_CONFLICT_HTML_JS);
   source->AddResourcePath("policy_conflict.js", IDR_POLICY_POLICY_CONFLICT_JS);
+  source->AddResourcePath("policy_row.html.js", IDR_POLICY_POLICY_ROW_HTML_JS);
   source->AddResourcePath("policy_row.js", IDR_POLICY_POLICY_ROW_JS);
+  source->AddResourcePath("policy_precedence_row.html.js",
+                          IDR_POLICY_POLICY_PRECEDENCE_ROW_HTML_JS);
   source->AddResourcePath("policy_precedence_row.js",
                           IDR_POLICY_POLICY_PRECEDENCE_ROW_JS);
+  source->AddResourcePath("policy_table.html.js",
+                          IDR_POLICY_POLICY_TABLE_HTML_JS);
   source->AddResourcePath("policy_table.js", IDR_POLICY_POLICY_TABLE_JS);
+  source->AddResourcePath("status_box.html.js", IDR_POLICY_STATUS_BOX_HTML_JS);
   source->AddResourcePath("status_box.js", IDR_POLICY_STATUS_BOX_JS);
   source->SetDefaultResource(IDR_POLICY_HTML);
   source->EnableReplaceI18nInJS();
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 40a789b..9927688 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -120,7 +120,6 @@
     "//ios/chrome/browser/ui/location_bar:constants",
     "//ios/chrome/browser/ui/location_bar:location_bar",
     "//ios/chrome/browser/ui/main:scene_state_header",
-    "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/omnibox:eg_app_support+eg2",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
diff --git a/ios/chrome/test/providers/discover_feed/test_discover_feed.mm b/ios/chrome/test/providers/discover_feed/test_discover_feed.mm
index e59701fb..6bdb36c 100644
--- a/ios/chrome/test/providers/discover_feed/test_discover_feed.mm
+++ b/ios/chrome/test/providers/discover_feed/test_discover_feed.mm
@@ -34,6 +34,9 @@
   void UpdateTheme() final {}
   void RefreshFeedIfNeeded() final {}
   void RefreshFeed() final {}
+  void PerformBackgroundRefreshes(ProceduralBlockWithBool completion) final {}
+  void HandleBackgroundRefreshTaskExpiration() final {}
+  NSDate* GetEarliestBackgroundRefreshBeginDate() final { return nil; }
   BOOL GetFollowingFeedHasUnseenContent() final { return NO; }
   void SetFollowingFeedContentSeen() final {}
 };
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 41f4747..8017c96 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e3782fce44e098d2d74a35ba3c3eedf2c6c65035
\ No newline at end of file
+b07d2b9566a0050390852297ba7fecda22089f0d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index a58355c5..bc28881 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-4a12eb2a39e1c13d596dcc6c8e65ca0c498b641a
\ No newline at end of file
+5d1e92db4ba3ca470f3d4c31e329d93bd53bd200
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index b4e6289..d7e72d39 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ca64430aa7cf21bcb0fb017464ace70ec926ae97
\ No newline at end of file
+9464b31ec843875e3b4599123d06d8e8349ed1a3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 0c6f4b4..109327e4 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-b09840ef2f87faaa90ad572ad41bea54e5c22f76
\ No newline at end of file
+0a83ca8e3eb9e3bb2b30e3de4c1e002caccbf5bf
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 4fa5e0c1..fcb56d2 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-3b1ba1e23a5e66197ebe9f783312e61228af3c41
\ No newline at end of file
+1458fe4ab2252e0f63ffa12e1cc89807d81fb6cf
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 1b53f5b..5720c5b 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-1fe93d98224c4adf2bbbb8bb88e3bbfb5d0f52c0
\ No newline at end of file
+e4fa971975d87e42d94cbc76296c9435b9d2c72f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 724ee2c..583f5e4 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-0d79de6a6ae300138122277dab7a99240634bf08
\ No newline at end of file
+0bdf4f80e9d681b16107785a05da214b94c1635a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index f4fb60da..4743c805 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-f5269b0071b1007f6cddd8ba296052462ab72f11
\ No newline at end of file
+49dc98eada7227acdfb036f129e33e3bbfaf19d5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 1b4ba982..c388c84 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-4d41f91863212cb5572e00c75e09edd557968667
\ No newline at end of file
+ea1b320a0658a4f71fe63e0de8869b36a81bab77
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index a8f3c19c..5efd279 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-3120ed39b73023834f47a90838e0bfec2967e030
\ No newline at end of file
+55f21bbc2135dfa33a9388bb3335e1e73f2af2bf
\ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/follow/follow_provider.h b/ios/public/provider/chrome/browser/follow/follow_provider.h
index ae6f91c..87c0c1c00c 100644
--- a/ios/public/provider/chrome/browser/follow/follow_provider.h
+++ b/ios/public/provider/chrome/browser/follow/follow_provider.h
@@ -31,6 +31,10 @@
   // recommended.
   virtual bool GetRecommendedStatus(FollowWebPageURLs* follow_web_page_urls);
 
+  // Returns the URL identifier if the web channel with |follow_web_page_urls|
+  // has been recommended.
+  virtual NSURL* GetRecommendedSiteURL(FollowWebPageURLs* follow_web_page_urls);
+
   // Returns a list of followed web channels.
   virtual NSArray<FollowedWebChannel*>* GetFollowedWebChannels();
 
diff --git a/ios/public/provider/chrome/browser/follow/follow_provider.mm b/ios/public/provider/chrome/browser/follow/follow_provider.mm
index 4ee9511..834d848 100644
--- a/ios/public/provider/chrome/browser/follow/follow_provider.mm
+++ b/ios/public/provider/chrome/browser/follow/follow_provider.mm
@@ -17,6 +17,11 @@
   return false;
 }
 
+NSURL* FollowProvider::GetRecommendedSiteURL(
+    FollowWebPageURLs* follow_web_page_urls) {
+  return nil;
+}
+
 NSArray<FollowedWebChannel*>* FollowProvider::GetFollowedWebChannels() {
   return nil;
 }
diff --git a/media/formats/hls/media_playlist.cc b/media/formats/hls/media_playlist.cc
index 28eee298..b493b116 100644
--- a/media/formats/hls/media_playlist.cc
+++ b/media/formats/hls/media_playlist.cc
@@ -8,8 +8,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/check.h"
-#include "base/notreached.h"
 #include "base/numerics/clamped_math.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
@@ -87,6 +85,7 @@
   absl::optional<XMediaSequenceTag> media_sequence_tag;
   absl::optional<XDiscontinuitySequenceTag> discontinuity_sequence_tag;
   std::vector<MediaSegment> segments;
+  scoped_refptr<MediaSegment::InitializationSegment> initialization_segment;
 
   types::DecimalInteger discontinuity_sequence_number = 0;
 
@@ -142,13 +141,27 @@
           }
           break;
         }
-        case MediaPlaylistTagName::kXTargetDuration: {
-          auto error = ParseUniqueTag(*tag, target_duration_tag);
+        case MediaPlaylistTagName::kXBitrate: {
+          auto result = XBitrateTag::Parse(*tag);
+          if (result.has_error()) {
+            return std::move(result).error();
+          }
+          bitrate_tag = std::move(result).value();
+          break;
+        }
+        case MediaPlaylistTagName::kXByteRange: {
+          // TODO(https://crbug.com/1328528): Investigate supporting aspects of
+          // this tag not described by the spec
+          auto error = ParseUniqueTag(*tag, byterange_tag);
           if (error.has_value()) {
             return std::move(error).value();
           }
           break;
         }
+        case MediaPlaylistTagName::kXDateRange: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-DATERANGE tag.
+          break;
+        }
         case MediaPlaylistTagName::kXDiscontinuity: {
           // Multiple occurrences of `EXT-X-DISCONTINUITY` per media segment are
           // allowed, and each increments the segment's discontinuity sequence
@@ -165,64 +178,6 @@
           discontinuity_sequence_number += 1;
           break;
         }
-        case MediaPlaylistTagName::kXGap: {
-          auto error = ParseUniqueTag(*tag, gap_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXEndList: {
-          auto error = ParseUniqueTag(*tag, end_list_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXIFramesOnly: {
-          auto error = ParseUniqueTag(*tag, i_frames_only_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXPlaylistType: {
-          auto error = ParseUniqueTag(*tag, playlist_type_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXPartInf: {
-          auto error = ParseUniqueTag(*tag, part_inf_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXPart: {
-          // TODO(crbug.com/1266991): Integrate the EXT-X-PART tag
-          break;
-        }
-        case MediaPlaylistTagName::kXServerControl: {
-          auto error = ParseUniqueTag(*tag, server_control_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
-        case MediaPlaylistTagName::kXMediaSequence: {
-          // This tag must appear before any media segment
-          if (!segments.empty()) {
-            return ParseStatusCode::kMediaSegmentBeforeMediaSequenceTag;
-          }
-
-          auto error = ParseUniqueTag(*tag, media_sequence_tag);
-          if (error.has_value()) {
-            return std::move(error).value();
-          }
-          break;
-        }
         case MediaPlaylistTagName::kXDiscontinuitySequence: {
           auto error = ParseUniqueTag(*tag, discontinuity_sequence_tag);
           if (error.has_value()) {
@@ -242,21 +197,121 @@
           discontinuity_sequence_number = discontinuity_sequence_tag->number;
           break;
         }
-        case MediaPlaylistTagName::kXByteRange: {
-          // TODO(https://crbug.com/1328528): Investigate supporting aspects of
-          // this tag not described by the spec
-          auto error = ParseUniqueTag(*tag, byterange_tag);
+        case MediaPlaylistTagName::kXEndList: {
+          auto error = ParseUniqueTag(*tag, end_list_tag);
           if (error.has_value()) {
             return std::move(error).value();
           }
           break;
         }
-        case MediaPlaylistTagName::kXBitrate: {
-          auto result = XBitrateTag::Parse(*tag);
+        case MediaPlaylistTagName::kXGap: {
+          auto error = ParseUniqueTag(*tag, gap_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXIFramesOnly: {
+          auto error = ParseUniqueTag(*tag, i_frames_only_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXKey: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-KEY tag.
+          break;
+        }
+        case MediaPlaylistTagName::kXMap: {
+          auto result =
+              XMapTag::Parse(*tag, common_state.variable_dict, sub_buffer);
           if (result.has_error()) {
             return std::move(result).error();
           }
-          bitrate_tag = std::move(result).value();
+          auto value = std::move(result).value();
+
+          // Resolve the URI against the playlist URI
+          auto resource_uri = uri.Resolve(value.uri.Str());
+          if (!resource_uri.is_valid()) {
+            return ParseStatusCode::kInvalidUri;
+          }
+
+          // Extract the byte range
+          absl::optional<types::ByteRange> byte_range;
+          if (value.byte_range.has_value()) {
+            // Safari defaults byte range offset to 0, do that here as well.
+            byte_range = types::ByteRange::Validate(
+                value.byte_range->length, value.byte_range->offset.value_or(0));
+            if (!byte_range.has_value()) {
+              return ParseStatusCode::kByteRangeInvalid;
+            }
+          }
+
+          initialization_segment =
+              base::MakeRefCounted<MediaSegment::InitializationSegment>(
+                  std::move(resource_uri), byte_range);
+          break;
+        }
+        case MediaPlaylistTagName::kXMediaSequence: {
+          // This tag must appear before any media segment
+          if (!segments.empty()) {
+            return ParseStatusCode::kMediaSegmentBeforeMediaSequenceTag;
+          }
+
+          auto error = ParseUniqueTag(*tag, media_sequence_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXPart: {
+          // TODO(crbug.com/1266991): Integrate the EXT-X-PART tag.
+          break;
+        }
+        case MediaPlaylistTagName::kXPartInf: {
+          auto error = ParseUniqueTag(*tag, part_inf_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXPlaylistType: {
+          auto error = ParseUniqueTag(*tag, playlist_type_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXPreloadHint: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-PRELOAD-HINT tag.
+          break;
+        }
+        case MediaPlaylistTagName::kXProgramDateTime: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-PROGRAM-DATE-TIME tag.
+          break;
+        }
+        case MediaPlaylistTagName::kXRenditionReport: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-RENDITION-REPORT tag.
+          break;
+        }
+        case MediaPlaylistTagName::kXServerControl: {
+          auto error = ParseUniqueTag(*tag, server_control_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
+          break;
+        }
+        case MediaPlaylistTagName::kXSkip: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-SKIP tag.
+          // Since the appearance of the EXT-X-SKIP tag implies that this is a
+          // playlist delta update, we cannot parse this playlist.
+          return ParseStatusCode::kPlaylistHasUnexpectedDeltaUpdate;
+        }
+        case MediaPlaylistTagName::kXTargetDuration: {
+          auto error = ParseUniqueTag(*tag, target_duration_tag);
+          if (error.has_value()) {
+            return std::move(error).value();
+          }
           break;
         }
       }
@@ -330,8 +385,8 @@
 
     segments.emplace_back(inf_tag->duration, media_sequence_number,
                           discontinuity_sequence_number, std::move(segment_uri),
-                          byterange, bitrate, discontinuity_tag.has_value(),
-                          gap_tag.has_value());
+                          initialization_segment, byterange, bitrate,
+                          discontinuity_tag.has_value(), gap_tag.has_value());
 
     // Reset per-segment tags
     inf_tag.reset();
diff --git a/media/formats/hls/media_playlist.h b/media/formats/hls/media_playlist.h
index 7152786..06f86351 100644
--- a/media/formats/hls/media_playlist.h
+++ b/media/formats/hls/media_playlist.h
@@ -12,7 +12,6 @@
 #include "media/formats/hls/parse_status.h"
 #include "media/formats/hls/playlist.h"
 #include "media/formats/hls/tags.h"
-#include "media/formats/hls/types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
diff --git a/media/formats/hls/media_playlist_test_builder.h b/media/formats/hls/media_playlist_test_builder.h
index 2d49c26..9b20bb7 100644
--- a/media/formats/hls/media_playlist_test_builder.h
+++ b/media/formats/hls/media_playlist_test_builder.h
@@ -195,6 +195,35 @@
   EXPECT_EQ(segment.GetUri(), uri) << from.ToString();
 }
 
+// Checks that the latest media segment's media initialization segment is
+// equivalent to the given value.
+inline void HasInitializationSegment(
+    scoped_refptr<MediaSegment::InitializationSegment> expected,
+    const base::Location& from,
+    const MediaSegment& segment) {
+  auto actual = segment.GetInitializationSegment();
+  if (actual && expected) {
+    EXPECT_EQ(actual->GetUri(), expected->GetUri()) << from.ToString();
+
+    if (actual->GetByteRange() && expected->GetByteRange()) {
+      EXPECT_EQ(actual->GetByteRange()->GetOffset(),
+                expected->GetByteRange()->GetOffset())
+          << from.ToString();
+      EXPECT_EQ(actual->GetByteRange()->GetLength(),
+                expected->GetByteRange()->GetLength())
+          << from.ToString();
+      EXPECT_EQ(actual->GetByteRange()->GetEnd(),
+                expected->GetByteRange()->GetEnd())
+          << from.ToString();
+    } else {
+      EXPECT_FALSE(actual->GetByteRange() || expected->GetByteRange())
+          << from.ToString();
+    }
+  } else {
+    EXPECT_FALSE(actual || expected) << from.ToString();
+  }
+}
+
 // Checks that the latest media segment has the given byte range.
 inline void HasByteRange(absl::optional<types::ByteRange> range,
                          const base::Location& from,
diff --git a/media/formats/hls/media_playlist_unittest.cc b/media/formats/hls/media_playlist_unittest.cc
index dd82754..a9890af 100644
--- a/media/formats/hls/media_playlist_unittest.cc
+++ b/media/formats/hls/media_playlist_unittest.cc
@@ -41,86 +41,6 @@
 
 }  // namespace
 
-TEST(HlsMediaPlaylistTest, XDiscontinuityTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-  builder.ExpectPlaylist(HasVersion, 1);
-  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
-
-  // Default discontinuity state is false
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDiscontinuity, false);
-  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
-
-  builder.AppendLine("#EXT-X-DISCONTINUITY");
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDiscontinuity, true);
-  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
-
-  // The discontinuity tag does not apply to subsequent segments
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDiscontinuity, false);
-  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
-
-  // The discontinuity tag may appear multiple times per segment
-  builder.AppendLine("#EXT-X-DISCONTINUITY");
-  builder.AppendLine("#EXT-X-DISCONTINUITY");
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDiscontinuity, true);
-  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 3);
-
-  builder.ExpectOk();
-}
-
-TEST(HlsMediaPlaylistTest, XGapTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-  builder.ExpectPlaylist(HasVersion, 1);
-  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
-
-  // Default gap state is false
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(IsGap, false);
-
-  builder.AppendLine("#EXT-X-GAP");
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(IsGap, true);
-
-  // The gap tag does not apply to subsequent segments
-  builder.AppendLine("#EXTINF:9.9,\t");
-  builder.AppendLine("video.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(IsGap, false);
-
-  // The gap tag may only appear once per segment
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-GAP");
-    fork.AppendLine("#EXT-X-GAP");
-    fork.AppendLine("#EXTINF:9.9,\t");
-    fork.AppendLine("video.ts");
-    fork.ExpectAdditionalSegment();
-    fork.ExpectSegment(IsGap, true);
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-
-  builder.ExpectOk();
-}
-
 TEST(HlsMediaPlaylistTest, Segments) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
@@ -351,64 +271,6 @@
   builder.ExpectOk();
 }
 
-TEST(HlsMediaPlaylistTest, PlaylistType) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-
-  // Without the EXT-X-PLAYLIST-TYPE tag, the playlist has no type.
-  {
-    auto fork = builder;
-    fork.ExpectPlaylist(HasType, absl::nullopt);
-    fork.ExpectOk();
-  }
-
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-    fork.ExpectPlaylist(HasType, PlaylistType::kVOD);
-    fork.ExpectOk();
-  }
-
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:EVENT");
-    fork.ExpectPlaylist(HasType, PlaylistType::kEvent);
-    fork.ExpectOk();
-  }
-
-  // This tag may not be specified twice
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:EVENT");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-
-  // Unknown or invalid playlist types should trigger an error
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:FOOBAR");
-    fork.ExpectError(ParseStatusCode::kUnknownPlaylistType);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-PLAYLIST-TYPE");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-}
-
 TEST(HlsMediaPlaylistTest, MultivariantPlaylistTag) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
@@ -460,351 +322,108 @@
   EXPECT_FALSE(parent2.AreSegmentsIndependent());
 }
 
-TEST(HlsMediaPlaylistTest, XTargetDurationTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-
-  // The XTargetDurationTag tag is required
-  builder.ExpectError(ParseStatusCode::kMediaPlaylistMissingTargetDuration);
-
-  // The XTargetDurationTag must appear exactly once
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
-  builder.ExpectOk();
-
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-TARGETDURATION:10");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-TARGETDURATION:11");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-
-  // The XTargetDurationTag must be a valid DecimalInteger (unsigned)
-  for (base::StringPiece x : {"-1", "0.5", "-1.5", "999999999999999999999"}) {
-    MediaPlaylistTestBuilder builder2;
-    builder2.AppendLine("#EXTM3U");
-    builder2.AppendLine("#EXT-X-TARGETDURATION:", x);
-    builder2.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-
-  // The target duration value may not exceed this implementation's max
-  builder = MediaPlaylistTestBuilder();
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine(
-      "#EXT-X-TARGETDURATION:",
-      base::NumberToString(MediaPlaylist::kMaxTargetDuration.InSeconds()));
-  builder.ExpectPlaylist(
-      HasTargetDuration,
-      base::Seconds(MediaPlaylist::kMaxTargetDuration.InSeconds()));
-  builder.ExpectOk();
-
-  builder = MediaPlaylistTestBuilder();
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine(
-      "#EXT-X-TARGETDURATION:",
-      base::NumberToString(MediaPlaylist::kMaxTargetDuration.InSeconds() + 1));
-  builder.ExpectError(ParseStatusCode::kTargetDurationExceedsMax);
-}
-
-TEST(HlsMediaPlaylistTest, XEndListTag) {
+TEST(HlsMediaPlaylistTest, XBitrateTag) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
   builder.AppendLine("#EXT-X-TARGETDURATION:10");
 
-  // Without the 'EXT-X-ENDLIST' tag, the default value is false, regardless of
-  // the playlist type.
+  // The EXT-X-BITRATE tag must be a valid DecimalInteger
   {
-    for (const base::StringPiece type : {"", "EVENT", "VOD"}) {
+    for (base::StringPiece x : {"", ":", ": 1", ":1 ", ":-1", ":{$bitrate}"}) {
       auto fork = builder;
-      if (!type.empty()) {
-        fork.AppendLine("#EXT-X-PLAYLIST-TYPE:", type);
-      }
-      fork.ExpectPlaylist(IsEndList, false);
-      fork.ExpectOk();
-    }
-  }
-
-  // The 'EXT-X-ENDLIST' tag may not have any content
-  {
-    for (const base::StringPiece x : {"", "FOO=BAR", "1"}) {
-      auto fork = builder;
-      fork.AppendLine("#EXT-X-ENDLIST:", x);
+      fork.AppendLine("#EXT-X-BITRATE", x);
       fork.ExpectError(ParseStatusCode::kMalformedTag);
     }
   }
 
-  // The EXT-X-ENDLIST tag can appear anywhere in the playlist
-  builder.AppendLine("#EXTINF:9.2,\t");
+  // The EXT-X-BITRATE tag applies only to the segments that it appears after
+  builder.AppendLine("#EXTINF:9.2,");
   builder.AppendLine("segment0.ts");
   builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 0);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
+  builder.ExpectSegment(HasBitRate, absl::nullopt);
 
-  builder.AppendLine("#EXT-X-ENDLIST");
-  builder.ExpectPlaylist(IsEndList, true);
-
-  builder.AppendLine("#EXTINF:9.2,\n");
+  builder.AppendLine("#EXT-X-BITRATE:15");
+  builder.AppendLine("#EXTINF:9.2,");
   builder.AppendLine("segment1.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectOk();
+  builder.ExpectSegment(HasMediaSequenceNumber, 1);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment1.ts"));
+  builder.ExpectSegment(HasBitRate, 15000);
 
-  // The EXT-X-ENDLIST tag may not appear twice
-  builder.AppendLine("#EXT-X-ENDLIST");
-  builder.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-}
-
-TEST(HlsMediaPlaylistTest, XIFramesOnlyTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-
-  // Without the 'EXT-X-I-FRAMES-ONLY' tag, the default value is false.
-  {
-    auto fork = builder;
-    fork.ExpectPlaylist(IsIFramesOnly, false);
-    fork.ExpectOk();
-  }
-
-  // The 'EXT-X-I-FRAMES-ONLY' tag may not have any content
-  {
-    for (const base::StringPiece x : {"", "FOO=BAR", "1"}) {
-      auto fork = builder;
-      fork.AppendLine("#EXT-X-I-FRAMES-ONLY:", x);
-      fork.ExpectError(ParseStatusCode::kMalformedTag);
-    }
-  }
-
-  builder.AppendLine("#EXT-X-I-FRAMES-ONLY");
-  builder.ExpectPlaylist(IsIFramesOnly, true);
-
-  // This should not affect the calculation of the playlist's duration
-  builder.AppendLine("#EXTINF:10,\t");
-  builder.AppendLine("segment0.ts");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment2.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDuration, base::Seconds(10));
+  builder.ExpectSegment(HasMediaSequenceNumber, 2);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment2.ts"));
+  builder.ExpectSegment(HasBitRate, 15000);
 
-  builder.AppendLine("#EXTINF:10,\t");
-  builder.AppendLine("segment1.ts");
+  // The EXT-X-BITRATE tag does not apply to segments that are byteranges
+  builder.AppendLine("#EXT-X-BYTERANGE:1024@0");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment3.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasDuration, base::Seconds(10));
+  builder.ExpectSegment(HasMediaSequenceNumber, 3);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment3.ts"));
+  builder.ExpectSegment(HasByteRange, CreateByteRange(1024, 0));
+  builder.ExpectSegment(HasBitRate, absl::nullopt);
 
-  builder.ExpectPlaylist(HasComputedDuration, base::Seconds(20));
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment4.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 4);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment4.ts"));
+  builder.ExpectSegment(HasByteRange, absl::nullopt);
+  builder.ExpectSegment(HasBitRate, 15000);
+
+  // The EXT-X-BITRATE tag is allowed to appear twice
+  builder.AppendLine("#EXT-X-BITRATE:20");
+  builder.AppendLine("#EXT-X-BITRATE:21");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment5.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 5);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment5.ts"));
+  builder.ExpectSegment(HasBitRate, 21000);
+
+  // A value of 0 is tolerated
+  builder.AppendLine("#EXT-X-BITRATE:0");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment6.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 6);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment6.ts"));
+  builder.ExpectSegment(HasBitRate, 0);
+
+  // Large values should saturate to `DecimalInteger::max`
+  builder.AppendLine("#EXT-X-BITRATE:18446744073709551");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment7.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 7);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment7.ts"));
+  builder.ExpectSegment(HasBitRate, 18446744073709551000u);
+
+  builder.AppendLine("#EXT-X-BITRATE:18446744073709552");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment8.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 8);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment8.ts"));
+  builder.ExpectSegment(HasBitRate,
+                        std::numeric_limits<types::DecimalInteger>::max());
+
+  builder.AppendLine("#EXT-X-BITRATE:18446744073709551615");
+  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("segment9.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasMediaSequenceNumber, 9);
+  builder.ExpectSegment(HasUri, GURL("http://localhost/segment9.ts"));
+  builder.ExpectSegment(HasBitRate,
+                        std::numeric_limits<types::DecimalInteger>::max());
+
   builder.ExpectOk();
-
-  // The 'EXT-X-I-FRAMES-ONLY' tag should not appear twice
-  builder.AppendLine("#EXT-X-I-FRAMES-ONLY");
-  builder.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-}
-
-TEST(HlsMediaPlaylistTest, XMediaSequenceTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-
-  // The EXT-X-MEDIA-SEQUENCE tag's content must be a valid DecimalInteger
-  {
-    for (const base::StringPiece x : {"", ":-1", ":{$foo}", ":1.5", ":one"}) {
-      auto fork = builder;
-      fork.AppendLine("#EXT-X-MEDIA-SEQUENCE", x);
-      fork.ExpectError(ParseStatusCode::kMalformedTag);
-    }
-  }
-  // The EXT-X-MEDIA-SEQUENCE tag may not appear twice
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
-    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:1");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-  // The EXT-X-MEDIA-SEQUENCE tag must appear before any media segment
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXTINF:9.8,\t");
-    fork.AppendLine("segment0.ts");
-    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
-    fork.ExpectError(ParseStatusCode::kMediaSegmentBeforeMediaSequenceTag);
-  }
-
-  const auto fill_playlist = [](auto& builder, auto first_sequence_number) {
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment0.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
-    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
-
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment1.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 1);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
-
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment2.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 2);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
-  };
-
-  // If the playlist does not contain the EXT-X-MEDIA-SEQUENCE tag, the default
-  // starting segment number is 0.
-  auto fork = builder;
-  fill_playlist(fork, 0);
-  fork.ExpectPlaylist(HasMediaSequenceTag, false);
-  fork.ExpectOk();
-
-  // If the playlist has the EXT-X-MEDIA-SEQUENCE tag, it specifies the starting
-  // segment number.
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
-  fill_playlist(fork, 0);
-  fork.ExpectPlaylist(HasMediaSequenceTag, true);
-  fork.ExpectOk();
-
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:15");
-  fill_playlist(fork, 15);
-  fork.ExpectPlaylist(HasMediaSequenceTag, true);
-  fork.ExpectOk();
-
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:9999");
-  fill_playlist(fork, 9999);
-  fork.ExpectPlaylist(HasMediaSequenceTag, true);
-  fork.ExpectOk();
-}
-
-TEST(HlsMediaPlaylistTest, XDiscontinuitySequenceTag) {
-  MediaPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-TARGETDURATION:10");
-
-  // The EXT-X-DISCONTINUITY-SEQUENCE tag must be a valid DecimalInteger
-  {
-    for (const base::StringPiece x : {"", ":-1", ":{$foo}", ":1.5", ":one"}) {
-      auto fork = builder;
-      fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE", x);
-      fork.ExpectError(ParseStatusCode::kMalformedTag);
-    }
-  }
-  // The EXT-X-DISCONTINUITY-SEQUENCE tag may not appear twice
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
-    fork.AppendLine("#EXT-X-DISCONTINUITY");
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
-    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
-  }
-  // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any media segment
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXTINF:9.8,\t");
-    fork.AppendLine("segment0.ts");
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
-    fork.ExpectError(
-        ParseStatusCode::kMediaSegmentBeforeDiscontinuitySequenceTag);
-  }
-  // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any
-  // EXT-X-DISCONTINUITY tag
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-DISCONTINUITY");
-    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
-    fork.AppendLine("#EXTINF:9.8,\t");
-    fork.AppendLine("segment0.ts");
-    fork.ExpectError(
-        ParseStatusCode::kDiscontinuityTagBeforeDiscontinuitySequenceTag);
-  }
-
-  const auto fill_playlist = [](auto& builder, auto first_media_sequence_number,
-                                auto first_discontinuity_sequence_number) {
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment0.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
-    builder.ExpectSegment(HasDiscontinuity, false);
-    builder.ExpectSegment(HasMediaSequenceNumber, first_media_sequence_number);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
-                          first_discontinuity_sequence_number);
-
-    builder.AppendLine("#EXT-X-DISCONTINUITY");
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment1.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasDiscontinuity, true);
-    builder.ExpectSegment(HasMediaSequenceNumber,
-                          first_media_sequence_number + 1);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
-                          first_discontinuity_sequence_number + 1);
-
-    builder.AppendLine("#EXTINF:9.8,\t");
-    builder.AppendLine("segment2.ts");
-    builder.ExpectAdditionalSegment();
-    builder.ExpectSegment(HasDiscontinuity, false);
-    builder.ExpectSegment(HasMediaSequenceNumber,
-                          first_media_sequence_number + 2);
-    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
-                          first_discontinuity_sequence_number + 1);
-  };
-
-  // If the playlist does not contain the EXT-X-DISCONTINUITY-SEQUENCE tag, the
-  // default starting value is 0.
-  auto fork = builder;
-  fill_playlist(fork, 0, 0);
-  fork.ExpectOk();
-
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
-  fill_playlist(fork, 10, 0);
-  fork.ExpectOk();
-
-  // If the playlist has the EXT-X-DISCONTINUITY-SEQUENCE tag, it specifies the
-  // starting value.
-  fork = builder;
-  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
-  fill_playlist(fork, 0, 5);
-  fork.ExpectOk();
-
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
-  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
-  fill_playlist(fork, 10, 5);
-  fork.ExpectOk();
-
-  // If the very first segment is a discontinuity, it should still have a
-  // subsequent discontinuity sequence number.
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
-  fork.AppendLine("#EXT-X-DISCONTINUITY");
-  fork.AppendLine("#EXTINF:9.2,\t");
-  fork.AppendLine("segment.ts");
-  fork.ExpectAdditionalSegment();
-  fork.ExpectSegment(HasDiscontinuity, true);
-  fork.ExpectSegment(HasMediaSequenceNumber, 10);
-  fork.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
-  fill_playlist(fork, 11, 1);
-  fork.ExpectOk();
-
-  fork = builder;
-  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
-  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
-  fork.AppendLine("#EXT-X-DISCONTINUITY");
-  fork.AppendLine("#EXTINF:9.2,\t");
-  fork.AppendLine("segment.ts");
-  fork.ExpectAdditionalSegment();
-  fork.ExpectSegment(HasDiscontinuity, true);
-  fork.ExpectSegment(HasMediaSequenceNumber, 10);
-  fork.ExpectSegment(HasDiscontinuitySequenceNumber, 6);
-  fill_playlist(fork, 11, 6);
-  fork.ExpectOk();
 }
 
 TEST(HlsMediaPlaylistTest, XByteRangeTag) {
@@ -1010,110 +629,449 @@
   }
 }
 
-TEST(HlsMediaPlaylistTest, XBitrateTag) {
+TEST(HlsMediaPlaylistTest, XDiscontinuityTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+  builder.ExpectPlaylist(HasVersion, 1);
+  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
+
+  // Default discontinuity state is false
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDiscontinuity, false);
+  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
+
+  builder.AppendLine("#EXT-X-DISCONTINUITY");
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDiscontinuity, true);
+  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
+
+  // The discontinuity tag does not apply to subsequent segments
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDiscontinuity, false);
+  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
+
+  // The discontinuity tag may appear multiple times per segment
+  builder.AppendLine("#EXT-X-DISCONTINUITY");
+  builder.AppendLine("#EXT-X-DISCONTINUITY");
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDiscontinuity, true);
+  builder.ExpectSegment(HasDiscontinuitySequenceNumber, 3);
+
+  builder.ExpectOk();
+}
+
+TEST(HlsMediaPlaylistTest, XDiscontinuitySequenceTag) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
   builder.AppendLine("#EXT-X-TARGETDURATION:10");
 
-  // The EXT-X-BITRATE tag must be a valid DecimalInteger
+  // The EXT-X-DISCONTINUITY-SEQUENCE tag must be a valid DecimalInteger
   {
-    for (base::StringPiece x : {"", ":", ": 1", ":1 ", ":-1", ":{$bitrate}"}) {
+    for (const base::StringPiece x : {"", ":-1", ":{$foo}", ":1.5", ":one"}) {
       auto fork = builder;
-      fork.AppendLine("#EXT-X-BITRATE", x);
+      fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE", x);
+      fork.ExpectError(ParseStatusCode::kMalformedTag);
+    }
+  }
+  // The EXT-X-DISCONTINUITY-SEQUENCE tag may not appear twice
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
+    fork.AppendLine("#EXT-X-DISCONTINUITY");
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:1");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+  // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any media segment
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXTINF:9.8,\t");
+    fork.AppendLine("segment0.ts");
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
+    fork.ExpectError(
+        ParseStatusCode::kMediaSegmentBeforeDiscontinuitySequenceTag);
+  }
+  // The EXT-X-DISCONTINUITY-SEQUENCE tag must appear before any
+  // EXT-X-DISCONTINUITY tag
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-DISCONTINUITY");
+    fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:0");
+    fork.AppendLine("#EXTINF:9.8,\t");
+    fork.AppendLine("segment0.ts");
+    fork.ExpectError(
+        ParseStatusCode::kDiscontinuityTagBeforeDiscontinuitySequenceTag);
+  }
+
+  const auto fill_playlist = [](auto& builder, auto first_media_sequence_number,
+                                auto first_discontinuity_sequence_number) {
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment0.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
+    builder.ExpectSegment(HasDiscontinuity, false);
+    builder.ExpectSegment(HasMediaSequenceNumber, first_media_sequence_number);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
+                          first_discontinuity_sequence_number);
+
+    builder.AppendLine("#EXT-X-DISCONTINUITY");
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment1.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasDiscontinuity, true);
+    builder.ExpectSegment(HasMediaSequenceNumber,
+                          first_media_sequence_number + 1);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
+                          first_discontinuity_sequence_number + 1);
+
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment2.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasDiscontinuity, false);
+    builder.ExpectSegment(HasMediaSequenceNumber,
+                          first_media_sequence_number + 2);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber,
+                          first_discontinuity_sequence_number + 1);
+  };
+
+  // If the playlist does not contain the EXT-X-DISCONTINUITY-SEQUENCE tag, the
+  // default starting value is 0.
+  auto fork = builder;
+  fill_playlist(fork, 0, 0);
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
+  fill_playlist(fork, 10, 0);
+  fork.ExpectOk();
+
+  // If the playlist has the EXT-X-DISCONTINUITY-SEQUENCE tag, it specifies the
+  // starting value.
+  fork = builder;
+  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
+  fill_playlist(fork, 0, 5);
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
+  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
+  fill_playlist(fork, 10, 5);
+  fork.ExpectOk();
+
+  // If the very first segment is a discontinuity, it should still have a
+  // subsequent discontinuity sequence number.
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
+  fork.AppendLine("#EXT-X-DISCONTINUITY");
+  fork.AppendLine("#EXTINF:9.2,\t");
+  fork.AppendLine("segment.ts");
+  fork.ExpectAdditionalSegment();
+  fork.ExpectSegment(HasDiscontinuity, true);
+  fork.ExpectSegment(HasMediaSequenceNumber, 10);
+  fork.ExpectSegment(HasDiscontinuitySequenceNumber, 1);
+  fill_playlist(fork, 11, 1);
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:10");
+  fork.AppendLine("#EXT-X-DISCONTINUITY-SEQUENCE:5");
+  fork.AppendLine("#EXT-X-DISCONTINUITY");
+  fork.AppendLine("#EXTINF:9.2,\t");
+  fork.AppendLine("segment.ts");
+  fork.ExpectAdditionalSegment();
+  fork.ExpectSegment(HasDiscontinuity, true);
+  fork.ExpectSegment(HasMediaSequenceNumber, 10);
+  fork.ExpectSegment(HasDiscontinuitySequenceNumber, 6);
+  fill_playlist(fork, 11, 6);
+  fork.ExpectOk();
+}
+
+TEST(HlsMediaPlaylistTest, XEndListTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // Without the 'EXT-X-ENDLIST' tag, the default value is false, regardless of
+  // the playlist type.
+  {
+    for (const base::StringPiece type : {"", "EVENT", "VOD"}) {
+      auto fork = builder;
+      if (!type.empty()) {
+        fork.AppendLine("#EXT-X-PLAYLIST-TYPE:", type);
+      }
+      fork.ExpectPlaylist(IsEndList, false);
+      fork.ExpectOk();
+    }
+  }
+
+  // The 'EXT-X-ENDLIST' tag may not have any content
+  {
+    for (const base::StringPiece x : {"", "FOO=BAR", "1"}) {
+      auto fork = builder;
+      fork.AppendLine("#EXT-X-ENDLIST:", x);
       fork.ExpectError(ParseStatusCode::kMalformedTag);
     }
   }
 
-  // The EXT-X-BITRATE tag applies only to the segments that it appears after
-  builder.AppendLine("#EXTINF:9.2,");
+  // The EXT-X-ENDLIST tag can appear anywhere in the playlist
+  builder.AppendLine("#EXTINF:9.2,\t");
   builder.AppendLine("segment0.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 0);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
-  builder.ExpectSegment(HasBitRate, absl::nullopt);
 
-  builder.AppendLine("#EXT-X-BITRATE:15");
-  builder.AppendLine("#EXTINF:9.2,");
+  builder.AppendLine("#EXT-X-ENDLIST");
+  builder.ExpectPlaylist(IsEndList, true);
+
+  builder.AppendLine("#EXTINF:9.2,\n");
   builder.AppendLine("segment1.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 1);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment1.ts"));
-  builder.ExpectSegment(HasBitRate, 15000);
+  builder.ExpectOk();
 
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment2.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 2);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment2.ts"));
-  builder.ExpectSegment(HasBitRate, 15000);
+  // The EXT-X-ENDLIST tag may not appear twice
+  builder.AppendLine("#EXT-X-ENDLIST");
+  builder.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+}
 
-  // The EXT-X-BITRATE tag does not apply to segments that are byteranges
-  builder.AppendLine("#EXT-X-BYTERANGE:1024@0");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment3.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 3);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment3.ts"));
-  builder.ExpectSegment(HasByteRange, CreateByteRange(1024, 0));
-  builder.ExpectSegment(HasBitRate, absl::nullopt);
+TEST(HlsMediaPlaylistTest, XGapTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+  builder.ExpectPlaylist(HasVersion, 1);
+  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
 
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment4.ts");
+  // Default gap state is false
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 4);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment4.ts"));
-  builder.ExpectSegment(HasByteRange, absl::nullopt);
-  builder.ExpectSegment(HasBitRate, 15000);
+  builder.ExpectSegment(IsGap, false);
 
-  // The EXT-X-BITRATE tag is allowed to appear twice
-  builder.AppendLine("#EXT-X-BITRATE:20");
-  builder.AppendLine("#EXT-X-BITRATE:21");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment5.ts");
+  builder.AppendLine("#EXT-X-GAP");
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 5);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment5.ts"));
-  builder.ExpectSegment(HasBitRate, 21000);
+  builder.ExpectSegment(IsGap, true);
 
-  // A value of 0 is tolerated
-  builder.AppendLine("#EXT-X-BITRATE:0");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment6.ts");
+  // The gap tag does not apply to subsequent segments
+  builder.AppendLine("#EXTINF:9.9,\t");
+  builder.AppendLine("video.ts");
   builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 6);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment6.ts"));
-  builder.ExpectSegment(HasBitRate, 0);
+  builder.ExpectSegment(IsGap, false);
 
-  // Large values should saturate to `DecimalInteger::max`
-  builder.AppendLine("#EXT-X-BITRATE:18446744073709551");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment7.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 7);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment7.ts"));
-  builder.ExpectSegment(HasBitRate, 18446744073709551000u);
-
-  builder.AppendLine("#EXT-X-BITRATE:18446744073709552");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment8.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 8);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment8.ts"));
-  builder.ExpectSegment(HasBitRate,
-                        std::numeric_limits<types::DecimalInteger>::max());
-
-  builder.AppendLine("#EXT-X-BITRATE:18446744073709551615");
-  builder.AppendLine("#EXTINF:9.2,");
-  builder.AppendLine("segment9.ts");
-  builder.ExpectAdditionalSegment();
-  builder.ExpectSegment(HasMediaSequenceNumber, 9);
-  builder.ExpectSegment(HasUri, GURL("http://localhost/segment9.ts"));
-  builder.ExpectSegment(HasBitRate,
-                        std::numeric_limits<types::DecimalInteger>::max());
+  // The gap tag may only appear once per segment
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-GAP");
+    fork.AppendLine("#EXT-X-GAP");
+    fork.AppendLine("#EXTINF:9.9,\t");
+    fork.AppendLine("video.ts");
+    fork.ExpectAdditionalSegment();
+    fork.ExpectSegment(IsGap, true);
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
 
   builder.ExpectOk();
 }
 
+TEST(HlsMediaPlaylistTest, XIFramesOnlyTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // Without the 'EXT-X-I-FRAMES-ONLY' tag, the default value is false.
+  {
+    auto fork = builder;
+    fork.ExpectPlaylist(IsIFramesOnly, false);
+    fork.ExpectOk();
+  }
+
+  // The 'EXT-X-I-FRAMES-ONLY' tag may not have any content
+  {
+    for (const base::StringPiece x : {"", "FOO=BAR", "1"}) {
+      auto fork = builder;
+      fork.AppendLine("#EXT-X-I-FRAMES-ONLY:", x);
+      fork.ExpectError(ParseStatusCode::kMalformedTag);
+    }
+  }
+
+  builder.AppendLine("#EXT-X-I-FRAMES-ONLY");
+  builder.ExpectPlaylist(IsIFramesOnly, true);
+
+  // This should not affect the calculation of the playlist's duration
+  builder.AppendLine("#EXTINF:10,\t");
+  builder.AppendLine("segment0.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(10));
+
+  builder.AppendLine("#EXTINF:10,\t");
+  builder.AppendLine("segment1.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(10));
+
+  builder.ExpectPlaylist(HasComputedDuration, base::Seconds(20));
+  builder.ExpectOk();
+
+  // The 'EXT-X-I-FRAMES-ONLY' tag should not appear twice
+  builder.AppendLine("#EXT-X-I-FRAMES-ONLY");
+  builder.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+}
+
+TEST(HlsMediaPlaylistTest, XMapTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // The EXT-X-MAP tag must be valid
+  for (base::StringPiece x : {"", "BYTERANGE=\"10\"", "URI=foo.ts"}) {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-MAP:", x);
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+
+  // The EXT-X-MAP tag only applies to subsequent elements
+  builder.AppendLine("#EXTINF:9.2,\t");
+  builder.AppendLine("foo1.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(9.2));
+  builder.ExpectSegment(HasUri, GURL("http://localhost/foo1.ts"));
+  builder.ExpectSegment(HasInitializationSegment, nullptr);
+
+  builder.AppendLine("#EXT-X-MAP:URI=\"init1.ts\"");
+  auto init1 = base::MakeRefCounted<MediaSegment::InitializationSegment>(
+      GURL("http://localhost/init1.ts"), absl::nullopt);
+
+  builder.AppendLine("#EXTINF:9.2,\t");
+  builder.AppendLine("foo2.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(9.2));
+  builder.ExpectSegment(HasUri, GURL("http://localhost/foo2.ts"));
+  builder.ExpectSegment(HasInitializationSegment, init1);
+
+  builder.AppendLine("#EXTINF:9.2,\t");
+  builder.AppendLine("foo3.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(9.2));
+  builder.ExpectSegment(HasUri, GURL("http://localhost/foo3.ts"));
+  builder.ExpectSegment(HasInitializationSegment, init1);
+
+  // Consecutive EXT-X-MAP tags are tolerated
+  builder.AppendLine("#EXT-X-MAP:URI=\"init2.ts\"");
+  builder.AppendLine("#EXT-X-MAP:URI=\"init3.ts\",BYTERANGE=\"10@0\"");
+  auto init3 = base::MakeRefCounted<MediaSegment::InitializationSegment>(
+      GURL("http://localhost/init3.ts"),
+      types::ByteRange::Validate(10, 0).value());
+
+  builder.AppendLine("#EXTINF:9.2,\t");
+  builder.AppendLine("foo4.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(9.2));
+  builder.ExpectSegment(HasUri, GURL("http://localhost/foo4.ts"));
+  builder.ExpectSegment(HasInitializationSegment, init3);
+
+  // If the BYTERANGE offset is not specified, it defaults to 0 (even if the
+  // previous, initialization segment is a byterange of the same resource)
+  builder.AppendLine("#EXT-X-MAP:URI=\"init3.ts\",BYTERANGE=\"10\"");
+
+  builder.AppendLine("#EXTINF:9.2,\t");
+  builder.AppendLine("foo5.ts");
+  builder.ExpectAdditionalSegment();
+  builder.ExpectSegment(HasDuration, base::Seconds(9.2));
+  builder.ExpectSegment(HasUri, GURL("http://localhost/foo5.ts"));
+  builder.ExpectSegment(HasInitializationSegment, init3);
+
+  builder.ExpectOk();
+}
+
+TEST(HlsMediaPlaylistTest, XMediaSequenceTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // The EXT-X-MEDIA-SEQUENCE tag's content must be a valid DecimalInteger
+  {
+    for (const base::StringPiece x : {"", ":-1", ":{$foo}", ":1.5", ":one"}) {
+      auto fork = builder;
+      fork.AppendLine("#EXT-X-MEDIA-SEQUENCE", x);
+      fork.ExpectError(ParseStatusCode::kMalformedTag);
+    }
+  }
+  // The EXT-X-MEDIA-SEQUENCE tag may not appear twice
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:1");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+  // The EXT-X-MEDIA-SEQUENCE tag must appear before any media segment
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXTINF:9.8,\t");
+    fork.AppendLine("segment0.ts");
+    fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+    fork.ExpectError(ParseStatusCode::kMediaSegmentBeforeMediaSequenceTag);
+  }
+
+  const auto fill_playlist = [](auto& builder, auto first_sequence_number) {
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment0.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasUri, GURL("http://localhost/segment0.ts"));
+    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
+
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment1.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 1);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
+
+    builder.AppendLine("#EXTINF:9.8,\t");
+    builder.AppendLine("segment2.ts");
+    builder.ExpectAdditionalSegment();
+    builder.ExpectSegment(HasMediaSequenceNumber, first_sequence_number + 2);
+    builder.ExpectSegment(HasDiscontinuitySequenceNumber, 0);
+  };
+
+  // If the playlist does not contain the EXT-X-MEDIA-SEQUENCE tag, the default
+  // starting segment number is 0.
+  auto fork = builder;
+  fill_playlist(fork, 0);
+  fork.ExpectPlaylist(HasMediaSequenceTag, false);
+  fork.ExpectOk();
+
+  // If the playlist has the EXT-X-MEDIA-SEQUENCE tag, it specifies the starting
+  // segment number.
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+  fill_playlist(fork, 0);
+  fork.ExpectPlaylist(HasMediaSequenceTag, true);
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:15");
+  fill_playlist(fork, 15);
+  fork.ExpectPlaylist(HasMediaSequenceTag, true);
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-MEDIA-SEQUENCE:9999");
+  fill_playlist(fork, 9999);
+  fork.ExpectPlaylist(HasMediaSequenceTag, true);
+  fork.ExpectOk();
+}
+
 TEST(HlsMediaPlaylistTest, XPartInfTag) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
@@ -1173,6 +1131,64 @@
   fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
 }
 
+TEST(HlsMediaPlaylistTest, XPlaylistTypeTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // Without the EXT-X-PLAYLIST-TYPE tag, the playlist has no type.
+  {
+    auto fork = builder;
+    fork.ExpectPlaylist(HasType, absl::nullopt);
+    fork.ExpectOk();
+  }
+
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
+    fork.ExpectPlaylist(HasType, PlaylistType::kVOD);
+    fork.ExpectOk();
+  }
+
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:EVENT");
+    fork.ExpectPlaylist(HasType, PlaylistType::kEvent);
+    fork.ExpectOk();
+  }
+
+  // This tag may not be specified twice
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:EVENT");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+
+  // Unknown or invalid playlist types should trigger an error
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:FOOBAR");
+    fork.ExpectError(ParseStatusCode::kUnknownPlaylistType);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE:");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-PLAYLIST-TYPE");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+}
+
 TEST(HlsMediaPlaylistTest, XServerControlTag) {
   MediaPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
@@ -1320,4 +1336,64 @@
   fork.ExpectOk();
 }
 
+TEST(HlsMediaPlaylistTest, XSkipTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+
+  // The XSkip tag may not appear unless a playlist delta update was requested.
+  builder.AppendLine("#EXT-X-SKIP:SKIPPED-SEGMENTS=10");
+  builder.ExpectError(ParseStatusCode::kPlaylistHasUnexpectedDeltaUpdate);
+}
+
+TEST(HlsMediaPlaylistTest, XTargetDurationTag) {
+  MediaPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+
+  // The XTargetDurationTag tag is required
+  builder.ExpectError(ParseStatusCode::kMediaPlaylistMissingTargetDuration);
+
+  // The XTargetDurationTag must appear exactly once
+  builder.AppendLine("#EXT-X-TARGETDURATION:10");
+  builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10));
+  builder.ExpectOk();
+
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-TARGETDURATION:10");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-TARGETDURATION:11");
+    fork.ExpectError(ParseStatusCode::kPlaylistHasDuplicateTags);
+  }
+
+  // The XTargetDurationTag must be a valid DecimalInteger (unsigned)
+  for (base::StringPiece x : {"-1", "0.5", "-1.5", "999999999999999999999"}) {
+    MediaPlaylistTestBuilder builder2;
+    builder2.AppendLine("#EXTM3U");
+    builder2.AppendLine("#EXT-X-TARGETDURATION:", x);
+    builder2.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+
+  // The target duration value may not exceed this implementation's max
+  builder = MediaPlaylistTestBuilder();
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine(
+      "#EXT-X-TARGETDURATION:",
+      base::NumberToString(MediaPlaylist::kMaxTargetDuration.InSeconds()));
+  builder.ExpectPlaylist(
+      HasTargetDuration,
+      base::Seconds(MediaPlaylist::kMaxTargetDuration.InSeconds()));
+  builder.ExpectOk();
+
+  builder = MediaPlaylistTestBuilder();
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine(
+      "#EXT-X-TARGETDURATION:",
+      base::NumberToString(MediaPlaylist::kMaxTargetDuration.InSeconds() + 1));
+  builder.ExpectError(ParseStatusCode::kTargetDurationExceedsMax);
+}
+
 }  // namespace media::hls
diff --git a/media/formats/hls/media_segment.cc b/media/formats/hls/media_segment.cc
index 3c1491f..cb0418dc 100644
--- a/media/formats/hls/media_segment.cc
+++ b/media/formats/hls/media_segment.cc
@@ -10,26 +10,41 @@
 
 namespace media::hls {
 
-MediaSegment::MediaSegment(base::TimeDelta duration,
-                           types::DecimalInteger media_sequence_number,
-                           types::DecimalInteger discontinuity_sequence_number,
-                           GURL uri,
-                           absl::optional<types::ByteRange> byte_range,
-                           absl::optional<types::DecimalInteger> bitrate,
-                           bool has_discontinuity,
-                           bool is_gap)
+MediaSegment::InitializationSegment::InitializationSegment(
+    GURL uri,
+    absl::optional<types::ByteRange> byte_range)
+    : uri_(std::move(uri)), byte_range_(byte_range) {}
+
+MediaSegment::InitializationSegment::~InitializationSegment() = default;
+
+MediaSegment::MediaSegment(
+    base::TimeDelta duration,
+    types::DecimalInteger media_sequence_number,
+    types::DecimalInteger discontinuity_sequence_number,
+    GURL uri,
+    scoped_refptr<InitializationSegment> initialization_segment,
+    absl::optional<types::ByteRange> byte_range,
+    absl::optional<types::DecimalInteger> bitrate,
+    bool has_discontinuity,
+    bool is_gap)
     : duration_(duration),
       media_sequence_number_(media_sequence_number),
       discontinuity_sequence_number_(discontinuity_sequence_number),
       uri_(std::move(uri)),
+      initialization_segment_(std::move(initialization_segment)),
       byte_range_(byte_range),
       bitrate_(bitrate),
       has_discontinuity_(has_discontinuity),
       is_gap_(is_gap) {}
+
 MediaSegment::~MediaSegment() = default;
+
 MediaSegment::MediaSegment(const MediaSegment&) = default;
+
 MediaSegment::MediaSegment(MediaSegment&&) = default;
+
 MediaSegment& MediaSegment::operator=(const MediaSegment&) = default;
+
 MediaSegment& MediaSegment::operator=(MediaSegment&&) = default;
 
 }  // namespace media::hls
diff --git a/media/formats/hls/media_segment.h b/media/formats/hls/media_segment.h
index ed3d933..f3b3723 100644
--- a/media/formats/hls/media_segment.h
+++ b/media/formats/hls/media_segment.h
@@ -5,6 +5,8 @@
 #ifndef MEDIA_FORMATS_HLS_MEDIA_SEGMENT_H_
 #define MEDIA_FORMATS_HLS_MEDIA_SEGMENT_H_
 
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
 #include "media/base/media_export.h"
 #include "media/formats/hls/types.h"
@@ -14,10 +16,40 @@
 
 class MEDIA_EXPORT MediaSegment {
  public:
+  class MEDIA_EXPORT InitializationSegment
+      : public base::RefCounted<InitializationSegment> {
+    friend class base::RefCounted<InitializationSegment>;
+
+   public:
+    InitializationSegment(GURL uri, absl::optional<types::ByteRange>);
+    InitializationSegment(const InitializationSegment& copy) = delete;
+    InitializationSegment(InitializationSegment&& copy) = delete;
+    InitializationSegment& operator=(const InitializationSegment& copy) =
+        delete;
+    InitializationSegment& operator=(InitializationSegment&& copy) = delete;
+
+    // The URI, resolved against the playlist URI, of the resource containing
+    // the initialization segment.
+    const GURL& GetUri() const { return uri_; }
+
+    // If the initialization segment is a subrange of its resource, this
+    // indicates the range.
+    absl::optional<types::ByteRange> GetByteRange() const {
+      return byte_range_;
+    }
+
+   private:
+    ~InitializationSegment();
+
+    GURL uri_;
+    absl::optional<types::ByteRange> byte_range_;
+  };
+
   MediaSegment(base::TimeDelta duration,
                types::DecimalInteger media_sequence_number,
                types::DecimalInteger discontinuity_sequence_number,
                GURL uri,
+               scoped_refptr<InitializationSegment> initialization_segment,
                absl::optional<types::ByteRange> byte_range,
                absl::optional<types::DecimalInteger> bitrate,
                bool has_discontinuity,
@@ -46,6 +78,13 @@
   // `gap` is true, in which case this URI should not be used.
   const GURL& GetUri() const { return uri_; }
 
+  // Returns the initialization segment for this media segment, which may be
+  // null if this segment has none. Subsequent media segments may also share the
+  // same initialization segment.
+  scoped_refptr<InitializationSegment> GetInitializationSegment() const {
+    return initialization_segment_;
+  }
+
   // If this media segment is a subrange of its resource, this indicates the
   // range.
   absl::optional<types::ByteRange> GetByteRange() const { return byte_range_; }
@@ -67,6 +106,7 @@
   types::DecimalInteger media_sequence_number_;
   types::DecimalInteger discontinuity_sequence_number_;
   GURL uri_;
+  scoped_refptr<InitializationSegment> initialization_segment_;
   absl::optional<types::ByteRange> byte_range_;
   absl::optional<types::DecimalInteger> bitrate_;
   bool has_discontinuity_;
diff --git a/media/formats/hls/multivariant_playlist.cc b/media/formats/hls/multivariant_playlist.cc
index 678b6983..dfbd6f53 100644
--- a/media/formats/hls/multivariant_playlist.cc
+++ b/media/formats/hls/multivariant_playlist.cc
@@ -99,9 +99,26 @@
       }
 
       switch (static_cast<MultivariantPlaylistTagName>(*tag->GetName())) {
-        case MultivariantPlaylistTagName::kXMedia:
+        case MultivariantPlaylistTagName::kXContentSteering: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-CONTENT-STEERING tag
+          break;
+        }
+        case MultivariantPlaylistTagName::kXIFrameStreamInf: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-I-FRAME-STREAM-INF tag
+          break;
+        }
+        case MultivariantPlaylistTagName::kXMedia: {
           // TODO(crbug.com/1266991): Implement the EXT-X-MEDIA tag
           break;
+        }
+        case MultivariantPlaylistTagName::kXSessionData: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-DATA tag
+          break;
+        }
+        case MultivariantPlaylistTagName::kXSessionKey: {
+          // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-KEY tag
+          break;
+        }
         case MultivariantPlaylistTagName::kXStreamInf: {
           auto error = ParseUniqueTag(*tag, inf_tag, common_state.variable_dict,
                                       sub_buffer);
@@ -110,18 +127,6 @@
           }
           break;
         }
-        case MultivariantPlaylistTagName::kXIFrameStreamInf:
-          // TODO(crbug.com/1266991): Implement the EXT-X-I-FRAME-STREAM-INF tag
-          break;
-        case MultivariantPlaylistTagName::kXSessionData:
-          // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-DATA tag
-          break;
-        case MultivariantPlaylistTagName::kXSessionKey:
-          // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-KEY tag
-          break;
-        case MultivariantPlaylistTagName::kXContentSteering:
-          // TODO(crbug.com/1266991): Implement the EXT-X-CONTENT-STEERING tag
-          break;
       }
 
       continue;
diff --git a/media/formats/hls/multivariant_playlist_unittest.cc b/media/formats/hls/multivariant_playlist_unittest.cc
index 71b32122..5bc1809 100644
--- a/media/formats/hls/multivariant_playlist_unittest.cc
+++ b/media/formats/hls/multivariant_playlist_unittest.cc
@@ -12,6 +12,124 @@
 
 namespace media::hls {
 
+// This test is similar to the `HlsMediaPlaylistTest` test of the same name, but
+// due to subtle differences between media playlists and multivariant playlists
+// its difficult to combine them. If new cases are added here that are also
+// relevant to media playlists, they should be added to that test as well.
+TEST(HlsMultivariantPlaylistTest, VariableSubstitution) {
+  MultivariantPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+  builder.AppendLine("#EXT-X-VERSION:8");
+  builder.ExpectPlaylist(HasVersion, 8);
+
+  builder.AppendLine(
+      R"(#EXT-X-DEFINE:NAME="HOST",VALUE="http://www.example.com")");
+  builder.AppendLine(
+      R"(#EXT-X-DEFINE:NAME="CODECS",VALUE="mp4a.40.2,avc1.4d401e")");
+
+  // Valid variable references within URIs or quoted-string values may be
+  // substituted
+  builder.AppendLine(R"(#EXT-X-STREAM-INF:BANDWIDTH=100,CODECS="{$CODECS}")");
+  builder.AppendLine("{$HOST}/playlist1.m3u8");
+  builder.ExpectAdditionalVariant();
+  builder.ExpectVariant(HasPrimaryRenditionUri,
+                        GURL("http://www.example.com/playlist1.m3u8"));
+  builder.ExpectVariant(HasCodecs, "mp4a.40.2,avc1.4d401e");
+
+  // Invalid variable references should result in an error
+  {
+    auto fork = builder;
+    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=101");
+    fork.AppendLine("{$HOST}/{$movie}/playlist2.m3u8");
+    fork.ExpectError(ParseStatusCode::kVariableUndefined);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-STREAM-INF:BANDWIDTH=101,CODECS="{$CODEX}")");
+    fork.AppendLine("{$HOST}/playlist2.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+
+  // Variable references outside of valid substitution points should not be
+  // substituted
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="BW",VALUE="102")");
+    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH={$BW}");
+    fork.AppendLine("playlist3.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="AVG-BW",VALUE="102")");
+    fork.AppendLine(
+        "#EXT-X-STREAM-INF:BANDWIDTH=100,AVERAGE-BANDWIDTH={$AVG-BW}");
+    fork.AppendLine("playlist3.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="SCORE",VALUE="10")");
+    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,SCORE={$SCORE}");
+    fork.AppendLine("playlist3.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="RES",VALUE="1920x1080")");
+    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,RESOLUTION={$RES}");
+    fork.AppendLine("playlist3.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="FR",VALUE="30")");
+    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,FRAME-RATE={$FR}");
+    fork.AppendLine("playlist3.m3u8");
+    fork.ExpectError(ParseStatusCode::kMalformedTag);
+  }
+
+  // Redefinition is not allowed
+  {
+    auto fork = builder;
+    fork.AppendLine(
+        R"(#EXT-X-DEFINE:NAME="HOST",VALUE="https://www.google.com")");
+    fork.ExpectError(ParseStatusCode::kVariableDefinedMultipleTimes);
+  }
+
+  // Importing in a parentless playlist is not allowed
+  {
+    auto fork = builder;
+    fork.AppendLine(R"(#EXT-X-DEFINE:IMPORT="IMPORTED")");
+    fork.ExpectError(ParseStatusCode::kImportedVariableInParentlessPlaylist);
+  }
+
+  // Variables are not resolved recursively
+  builder.AppendLine(R"(#EXT-X-DEFINE:NAME="BAR",VALUE="BAZ")");
+  builder.AppendLine(R"(#EXT-X-DEFINE:NAME="FOO",VALUE="{$BAR}")");
+  builder.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=101");
+  builder.AppendLine("http://{$FOO}.com/playlist4.m3u8");
+  builder.ExpectAdditionalVariant();
+  builder.ExpectVariant(HasPrimaryRenditionUri,
+                        GURL("http://{$BAR}.com/playlist4.m3u8"));
+
+  builder.ExpectOk();
+}
+
+TEST(HlsMultivariantPlaylistTest, MediaPlaylistTag) {
+  MultivariantPlaylistTestBuilder builder;
+  builder.AppendLine("#EXTM3U");
+
+  // Multivariant playlists may not contain tags exclusive to media playlists
+  for (TagName name = ToTagName(MediaPlaylistTagName::kMinValue);
+       name <= ToTagName(MediaPlaylistTagName::kMaxValue); ++name) {
+    auto tag_line = "#" + std::string{TagNameToString(name)};
+    auto fork = builder;
+    fork.AppendLine(tag_line);
+    fork.ExpectError(ParseStatusCode::kMultivariantPlaylistHasMediaPlaylistTag);
+  }
+}
+
 TEST(HlsMultivariantPlaylistTest, XStreamInfTag) {
   MultivariantPlaylistTestBuilder builder;
   builder.AppendLine("#EXTM3U");
@@ -159,122 +277,4 @@
   builder.ExpectOk();
 }
 
-// This test is similar to the `HlsMediaPlaylistTest` test of the same name, but
-// due to subtle differences between media playlists and multivariant playlists
-// its difficult to combine them. If new cases are added here that are also
-// relevant to media playlists, they should be added to that test as well.
-TEST(HlsMultivariantPlaylistTest, VariableSubstitution) {
-  MultivariantPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-  builder.AppendLine("#EXT-X-VERSION:8");
-  builder.ExpectPlaylist(HasVersion, 8);
-
-  builder.AppendLine(
-      R"(#EXT-X-DEFINE:NAME="HOST",VALUE="http://www.example.com")");
-  builder.AppendLine(
-      R"(#EXT-X-DEFINE:NAME="CODECS",VALUE="mp4a.40.2,avc1.4d401e")");
-
-  // Valid variable references within URIs or quoted-string values may be
-  // substituted
-  builder.AppendLine(R"(#EXT-X-STREAM-INF:BANDWIDTH=100,CODECS="{$CODECS}")");
-  builder.AppendLine("{$HOST}/playlist1.m3u8");
-  builder.ExpectAdditionalVariant();
-  builder.ExpectVariant(HasPrimaryRenditionUri,
-                        GURL("http://www.example.com/playlist1.m3u8"));
-  builder.ExpectVariant(HasCodecs, "mp4a.40.2,avc1.4d401e");
-
-  // Invalid variable references should result in an error
-  {
-    auto fork = builder;
-    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=101");
-    fork.AppendLine("{$HOST}/{$movie}/playlist2.m3u8");
-    fork.ExpectError(ParseStatusCode::kVariableUndefined);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-STREAM-INF:BANDWIDTH=101,CODECS="{$CODEX}")");
-    fork.AppendLine("{$HOST}/playlist2.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-
-  // Variable references outside of valid substitution points should not be
-  // substituted
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="BW",VALUE="102")");
-    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH={$BW}");
-    fork.AppendLine("playlist3.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="AVG-BW",VALUE="102")");
-    fork.AppendLine(
-        "#EXT-X-STREAM-INF:BANDWIDTH=100,AVERAGE-BANDWIDTH={$AVG-BW}");
-    fork.AppendLine("playlist3.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="SCORE",VALUE="10")");
-    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,SCORE={$SCORE}");
-    fork.AppendLine("playlist3.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="RES",VALUE="1920x1080")");
-    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,RESOLUTION={$RES}");
-    fork.AppendLine("playlist3.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:NAME="FR",VALUE="30")");
-    fork.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=100,FRAME-RATE={$FR}");
-    fork.AppendLine("playlist3.m3u8");
-    fork.ExpectError(ParseStatusCode::kMalformedTag);
-  }
-
-  // Redefinition is not allowed
-  {
-    auto fork = builder;
-    fork.AppendLine(
-        R"(#EXT-X-DEFINE:NAME="HOST",VALUE="https://www.google.com")");
-    fork.ExpectError(ParseStatusCode::kVariableDefinedMultipleTimes);
-  }
-
-  // Importing in a parentless playlist is not allowed
-  {
-    auto fork = builder;
-    fork.AppendLine(R"(#EXT-X-DEFINE:IMPORT="IMPORTED")");
-    fork.ExpectError(ParseStatusCode::kImportedVariableInParentlessPlaylist);
-  }
-
-  // Variables are not resolved recursively
-  builder.AppendLine(R"(#EXT-X-DEFINE:NAME="BAR",VALUE="BAZ")");
-  builder.AppendLine(R"(#EXT-X-DEFINE:NAME="FOO",VALUE="{$BAR}")");
-  builder.AppendLine("#EXT-X-STREAM-INF:BANDWIDTH=101");
-  builder.AppendLine("http://{$FOO}.com/playlist4.m3u8");
-  builder.ExpectAdditionalVariant();
-  builder.ExpectVariant(HasPrimaryRenditionUri,
-                        GURL("http://{$BAR}.com/playlist4.m3u8"));
-
-  builder.ExpectOk();
-}
-
-TEST(HlsMultivariantPlaylistTest, MediaPlaylistTag) {
-  MultivariantPlaylistTestBuilder builder;
-  builder.AppendLine("#EXTM3U");
-
-  // Multivariant playlists may not contain tags exclusive to media playlists
-  for (TagName name = ToTagName(MediaPlaylistTagName::kMinValue);
-       name <= ToTagName(MediaPlaylistTagName::kMaxValue); ++name) {
-    auto tag_line = "#" + std::string{TagNameToString(name)};
-    auto fork = builder;
-    fork.AppendLine(tag_line);
-    fork.ExpectError(ParseStatusCode::kMultivariantPlaylistHasMediaPlaylistTag);
-  }
-}
-
 }  // namespace media::hls
diff --git a/media/formats/hls/parse_status.cc b/media/formats/hls/parse_status.cc
index 68d3ea5..aa2756f1 100644
--- a/media/formats/hls/parse_status.cc
+++ b/media/formats/hls/parse_status.cc
@@ -60,6 +60,7 @@
     PARSE_STATUS_CODE_CASE(kPartTargetDurationExceedsTargetDuration);
     PARSE_STATUS_CODE_CASE(kPartHoldBackDistanceTooLow);
     PARSE_STATUS_CODE_CASE(kPartInfTagWithoutPartHoldBack);
+    PARSE_STATUS_CODE_CASE(kPlaylistHasUnexpectedDeltaUpdate);
   }
 
   NOTREACHED();
diff --git a/media/formats/hls/parse_status.h b/media/formats/hls/parse_status.h
index 88fff6e..3015cac 100644
--- a/media/formats/hls/parse_status.h
+++ b/media/formats/hls/parse_status.h
@@ -57,6 +57,7 @@
   kPartTargetDurationExceedsTargetDuration,
   kPartHoldBackDistanceTooLow,
   kPartInfTagWithoutPartHoldBack,
+  kPlaylistHasUnexpectedDeltaUpdate,
 };
 
 struct ParseStatusTraits {
diff --git a/media/formats/hls/playlist_common.cc b/media/formats/hls/playlist_common.cc
index 3daf7d0..7c8295a 100644
--- a/media/formats/hls/playlist_common.cc
+++ b/media/formats/hls/playlist_common.cc
@@ -56,26 +56,12 @@
   DCHECK(tag.GetName() && GetTagKind(*tag.GetName()) == TagKind::kCommonTag);
 
   switch (static_cast<CommonTagName>(*tag.GetName())) {
-    case CommonTagName::kM3u:
+    case CommonTagName::kM3u: {
       // This tag is meant to occur on the first line (which we've already
       // checked), however the spec does not explicitly regard this as an
       // error if it appears elsewhere as well.
       DCHECK(tag.GetLineNumber() != 1);
       break;
-    case CommonTagName::kXVersion: {
-      auto error = ParseUniqueTag(tag, state->version_tag);
-      if (error.has_value()) {
-        return error;
-      }
-
-      // Max supported playlist version is 10
-      if (state->version_tag->version > 10) {
-        return ParseStatusCode::kPlaylistHasUnsupportedVersion;
-      }
-      break;
-    }
-    case CommonTagName::kXIndependentSegments: {
-      return ParseUniqueTag(tag, state->independent_segments_tag);
     }
     case CommonTagName::kXDefine: {
       auto tag_result = XDefineTag::Parse(tag);
@@ -104,7 +90,27 @@
                                        std::string{*tag_value.value})) {
         return ParseStatusCode::kVariableDefinedMultipleTimes;
       }
-    } break;
+      break;
+    }
+    case CommonTagName::kXIndependentSegments: {
+      return ParseUniqueTag(tag, state->independent_segments_tag);
+    }
+    case CommonTagName::kXStart: {
+      // TODO(crbug.com/1266991): Implement the EXT-X-START tag.
+      break;
+    }
+    case CommonTagName::kXVersion: {
+      auto error = ParseUniqueTag(tag, state->version_tag);
+      if (error.has_value()) {
+        return error;
+      }
+
+      // Max supported playlist version is 10
+      if (state->version_tag->version > 10) {
+        return ParseStatusCode::kPlaylistHasUnsupportedVersion;
+      }
+      break;
+    }
   }
 
   return absl::nullopt;
diff --git a/media/formats/hls/tag_name.cc b/media/formats/hls/tag_name.cc
index bf803d0..7057dc2e 100644
--- a/media/formats/hls/tag_name.cc
+++ b/media/formats/hls/tag_name.cc
@@ -54,6 +54,7 @@
     TagNameEntry("EXT-X-BYTERANGE", MediaPlaylistTagName::kXByteRange),
     TagNameEntry("EXT-X-CONTENT-STEERING",
                  MultivariantPlaylistTagName::kXContentSteering),
+    TagNameEntry("EXT-X-DATERANGE", MediaPlaylistTagName::kXDateRange),
     TagNameEntry("EXT-X-DEFINE", CommonTagName::kXDefine),
     TagNameEntry("EXT-X-DISCONTINUITY", MediaPlaylistTagName::kXDiscontinuity),
     TagNameEntry("EXT-X-DISCONTINUITY-SEQUENCE",
@@ -65,16 +66,25 @@
     TagNameEntry("EXT-X-I-FRAMES-ONLY", MediaPlaylistTagName::kXIFramesOnly),
     TagNameEntry("EXT-X-INDEPENDENT-SEGMENTS",
                  CommonTagName::kXIndependentSegments),
+    TagNameEntry("EXT-X-KEY", MediaPlaylistTagName::kXKey),
+    TagNameEntry("EXT-X-MAP", MediaPlaylistTagName::kXMap),
     TagNameEntry("EXT-X-MEDIA", MultivariantPlaylistTagName::kXMedia),
     TagNameEntry("EXT-X-MEDIA-SEQUENCE", MediaPlaylistTagName::kXMediaSequence),
     TagNameEntry("EXT-X-PART", MediaPlaylistTagName::kXPart),
     TagNameEntry("EXT-X-PART-INF", MediaPlaylistTagName::kXPartInf),
     TagNameEntry("EXT-X-PLAYLIST-TYPE", MediaPlaylistTagName::kXPlaylistType),
+    TagNameEntry("EXT-X-PRELOAD-HINT", MediaPlaylistTagName::kXPreloadHint),
+    TagNameEntry("EXT-X-PROGRAM-DATE-TIME",
+                 MediaPlaylistTagName::kXProgramDateTime),
+    TagNameEntry("EXT-X-RENDITION-REPORT",
+                 MediaPlaylistTagName::kXRenditionReport),
     TagNameEntry("EXT-X-SERVER-CONTROL", MediaPlaylistTagName::kXServerControl),
     TagNameEntry("EXT-X-SESSION-DATA",
                  MultivariantPlaylistTagName::kXSessionData),
     TagNameEntry("EXT-X-SESSION-KEY",
                  MultivariantPlaylistTagName::kXSessionKey),
+    TagNameEntry("EXT-X-SKIP", MediaPlaylistTagName::kXSkip),
+    TagNameEntry("EXT-X-START", CommonTagName::kXStart),
     TagNameEntry("EXT-X-STREAM-INF", MultivariantPlaylistTagName::kXStreamInf),
     TagNameEntry("EXT-X-TARGETDURATION",
                  MediaPlaylistTagName::kXTargetDuration),
diff --git a/media/formats/hls/tag_name.h b/media/formats/hls/tag_name.h
index cef49da..d7b68fce 100644
--- a/media/formats/hls/tag_name.h
+++ b/media/formats/hls/tag_name.h
@@ -26,45 +26,56 @@
 using TagName = uint32_t;
 
 // Tags common to multivariant and media playlists.
+// For organization, this list is in alphabetical order.
 enum class CommonTagName : TagName {
   kMinValue = 0,
   kM3u = kMinValue,
-  kXVersion,
-  kXIndependentSegments,
   kXDefine,
-  kMaxValue = kXDefine,
+  kXIndependentSegments,
+  kXStart,
+  kXVersion,
+  kMaxValue = kXVersion,
 };
 
 // Tags exclusive to multivariant playlists.
+// For organization, this list is in alphabetical order.
 enum class MultivariantPlaylistTagName : TagName {
   kMinValue = static_cast<TagName>(CommonTagName::kMaxValue) + 1,
-  kXMedia = kMinValue,
-  kXStreamInf,
+  kXContentSteering = kMinValue,
   kXIFrameStreamInf,
+  kXMedia,
   kXSessionData,
   kXSessionKey,
-  kXContentSteering,
-  kMaxValue = kXContentSteering,
+  kXStreamInf,
+  kMaxValue = kXStreamInf,
 };
 
 // Tags exclusive to media playlists.
+// For organization, this list is in alphabetical order.
 enum class MediaPlaylistTagName : TagName {
   kMinValue = static_cast<TagName>(MultivariantPlaylistTagName::kMaxValue) + 1,
   kInf = kMinValue,
-  kXTargetDuration,
-  kXEndList,
-  kXIFramesOnly,
-  kXDiscontinuity,
-  kXGap,
-  kXPlaylistType,
-  kXPartInf,
-  kXPart,
-  kXServerControl,
-  kXMediaSequence,
-  kXDiscontinuitySequence,
-  kXByteRange,
   kXBitrate,
-  kMaxValue = kXBitrate,
+  kXByteRange,
+  kXDateRange,
+  kXDiscontinuity,
+  kXDiscontinuitySequence,
+  kXEndList,
+  kXGap,
+  kXIFramesOnly,
+  kXKey,
+  kXMap,
+  kXMediaSequence,
+  kXPart,
+  kXPartInf,
+  kXPlaylistType,
+  kXPreloadHint,
+  kXProgramDateTime,
+  kXRenditionReport,
+  kXServerControl,
+  kXSkip,
+  kXTargetDuration,
+  kMaxValue = kXTargetDuration,
 };
 
 constexpr TagKind GetTagKind(CommonTagName) {
diff --git a/media/formats/hls/tags.cc b/media/formats/hls/tags.cc
index 0f2bce69..ffb1c27 100644
--- a/media/formats/hls/tags.cc
+++ b/media/formats/hls/tags.cc
@@ -105,17 +105,20 @@
   return "";
 }
 
-// Attributes expected in `EXT-X-PART-INF` tag contents.
+// Attributes expected in `EXT-X-MAP` tag contents.
 // These must remain sorted alphabetically.
-enum class XPartInfTagAttribute {
-  kPartTarget,
-  kMaxValue = kPartTarget,
+enum class XMapTagAttribute {
+  kByteRange,
+  kUri,
+  kMaxValue = kUri,
 };
 
-constexpr base::StringPiece GetAttributeName(XPartInfTagAttribute attribute) {
+constexpr base::StringPiece GetAttributeName(XMapTagAttribute attribute) {
   switch (attribute) {
-    case XPartInfTagAttribute::kPartTarget:
-      return "PART-TARGET";
+    case XMapTagAttribute::kByteRange:
+      return "BYTERANGE";
+    case XMapTagAttribute::kUri:
+      return "URI";
   }
 
   NOTREACHED();
@@ -148,7 +151,24 @@
   }
 }
 
-// Attributes expected in `EXT-X-SERVER-CONTROL tag contents.
+// Attributes expected in `EXT-X-PART-INF` tag contents.
+// These must remain sorted alphabetically.
+enum class XPartInfTagAttribute {
+  kPartTarget,
+  kMaxValue = kPartTarget,
+};
+
+constexpr base::StringPiece GetAttributeName(XPartInfTagAttribute attribute) {
+  switch (attribute) {
+    case XPartInfTagAttribute::kPartTarget:
+      return "PART-TARGET";
+  }
+
+  NOTREACHED();
+  return "";
+}
+
+// Attributes expected in `EXT-X-SERVER-CONTROL` tag contents.
 // These must remain sorted alphabetically.
 enum class XServerControlTagAttribute {
   kCanBlockReload,
@@ -247,86 +267,6 @@
 }
 
 // static
-ParseStatus::Or<XVersionTag> XVersionTag::Parse(TagItem tag) {
-  auto result = ParseDecimalIntegerTag(tag, &XVersionTag::version);
-  if (result.has_error()) {
-    return std::move(result).error();
-  }
-
-  // Reject invalid version numbers.
-  // For valid version numbers, caller will decide if the version is supported.
-  auto out = std::move(result).value();
-  if (out.version == 0) {
-    return ParseStatusCode::kInvalidPlaylistVersion;
-  }
-
-  return out;
-}
-
-// static
-ParseStatus::Or<InfTag> InfTag::Parse(TagItem tag) {
-  DCHECK(tag.GetName() == ToTagName(InfTag::kName));
-
-  if (!tag.GetContent()) {
-    return ParseStatusCode::kMalformedTag;
-  }
-  auto content = *tag.GetContent();
-
-  // Inf tags have the form #EXTINF:<duration>,[<title>]
-  // Find the comma.
-  auto comma = content.Str().find_first_of(',');
-  if (comma == base::StringPiece::npos) {
-    return ParseStatusCode::kMalformedTag;
-  }
-
-  auto duration_str = content.Substr(0, comma);
-  auto title_str = content.Substr(comma + 1);
-
-  // Extract duration
-  // TODO(crbug.com/1284763): Below version 3 this should be rounded to an
-  // integer
-  auto duration_result =
-      types::ParseDecimalFloatingPoint(duration_str.SkipVariableSubstitution());
-  if (duration_result.has_error()) {
-    return ParseStatus(ParseStatusCode::kMalformedTag)
-        .AddCause(std::move(duration_result).error());
-  }
-  const auto duration = base::Seconds(std::move(duration_result).value());
-
-  if (duration.is_max()) {
-    return ParseStatusCode::kValueOverflowsTimeDelta;
-  }
-
-  return InfTag{.duration = duration, .title = title_str};
-}
-
-// static
-ParseStatus::Or<XIndependentSegmentsTag> XIndependentSegmentsTag::Parse(
-    TagItem tag) {
-  return ParseEmptyTag<XIndependentSegmentsTag>(tag);
-}
-
-// static
-ParseStatus::Or<XEndListTag> XEndListTag::Parse(TagItem tag) {
-  return ParseEmptyTag<XEndListTag>(tag);
-}
-
-// static
-ParseStatus::Or<XIFramesOnlyTag> XIFramesOnlyTag::Parse(TagItem tag) {
-  return ParseEmptyTag<XIFramesOnlyTag>(tag);
-}
-
-// static
-ParseStatus::Or<XDiscontinuityTag> XDiscontinuityTag::Parse(TagItem tag) {
-  return ParseEmptyTag<XDiscontinuityTag>(tag);
-}
-
-// static
-ParseStatus::Or<XGapTag> XGapTag::Parse(TagItem tag) {
-  return ParseEmptyTag<XGapTag>(tag);
-}
-
-// static
 XDefineTag XDefineTag::CreateDefinition(types::VariableName name,
                                         base::StringPiece value) {
   return XDefineTag{.name = name, .value = value};
@@ -408,22 +348,26 @@
 }
 
 // static
-ParseStatus::Or<XPlaylistTypeTag> XPlaylistTypeTag::Parse(TagItem tag) {
-  DCHECK(tag.GetName() == ToTagName(XPlaylistTypeTag::kName));
+ParseStatus::Or<XIndependentSegmentsTag> XIndependentSegmentsTag::Parse(
+    TagItem tag) {
+  return ParseEmptyTag<XIndependentSegmentsTag>(tag);
+}
 
-  // This tag requires content
-  if (!tag.GetContent().has_value() || tag.GetContent()->Empty()) {
-    return ParseStatusCode::kMalformedTag;
+// static
+ParseStatus::Or<XVersionTag> XVersionTag::Parse(TagItem tag) {
+  auto result = ParseDecimalIntegerTag(tag, &XVersionTag::version);
+  if (result.has_error()) {
+    return std::move(result).error();
   }
 
-  if (tag.GetContent()->Str() == "EVENT") {
-    return XPlaylistTypeTag{.type = PlaylistType::kEvent};
-  }
-  if (tag.GetContent()->Str() == "VOD") {
-    return XPlaylistTypeTag{.type = PlaylistType::kVOD};
+  // Reject invalid version numbers.
+  // For valid version numbers, caller will decide if the version is supported.
+  auto out = std::move(result).value();
+  if (out.version == 0) {
+    return ParseStatusCode::kInvalidPlaylistVersion;
   }
 
-  return ParseStatusCode::kUnknownPlaylistType;
+  return out;
 }
 
 XStreamInfTag::XStreamInfTag() = default;
@@ -541,36 +485,102 @@
 }
 
 // static
-ParseStatus::Or<XTargetDurationTag> XTargetDurationTag::Parse(TagItem tag) {
-  DCHECK(tag.GetName() == ToTagName(XTargetDurationTag::kName));
-  if (!tag.GetContent().has_value()) {
+ParseStatus::Or<InfTag> InfTag::Parse(TagItem tag) {
+  DCHECK(tag.GetName() == ToTagName(InfTag::kName));
+
+  if (!tag.GetContent()) {
+    return ParseStatusCode::kMalformedTag;
+  }
+  auto content = *tag.GetContent();
+
+  // Inf tags have the form #EXTINF:<duration>,[<title>]
+  // Find the comma.
+  auto comma = content.Str().find_first_of(',');
+  if (comma == base::StringPiece::npos) {
     return ParseStatusCode::kMalformedTag;
   }
 
-  auto duration_result = types::ParseDecimalInteger(
-      tag.GetContent().value().SkipVariableSubstitution());
+  auto duration_str = content.Substr(0, comma);
+  auto title_str = content.Substr(comma + 1);
+
+  // Extract duration
+  // TODO(crbug.com/1284763): Below version 3 this should be rounded to an
+  // integer
+  auto duration_result =
+      types::ParseDecimalFloatingPoint(duration_str.SkipVariableSubstitution());
   if (duration_result.has_error()) {
     return ParseStatus(ParseStatusCode::kMalformedTag)
         .AddCause(std::move(duration_result).error());
   }
+  const auto duration = base::Seconds(std::move(duration_result).value());
 
-  auto duration = base::Seconds(std::move(duration_result).value());
   if (duration.is_max()) {
     return ParseStatusCode::kValueOverflowsTimeDelta;
   }
 
-  return XTargetDurationTag{.duration = duration};
+  return InfTag{.duration = duration, .title = title_str};
 }
 
 // static
-ParseStatus::Or<XPartInfTag> XPartInfTag::Parse(TagItem tag) {
-  DCHECK(tag.GetName() == ToTagName(XPartInfTag::kName));
+ParseStatus::Or<XBitrateTag> XBitrateTag::Parse(TagItem tag) {
+  return ParseDecimalIntegerTag(tag, &XBitrateTag::bitrate);
+}
+
+// static
+ParseStatus::Or<XByteRangeTag> XByteRangeTag::Parse(TagItem tag) {
+  DCHECK(tag.GetName() == ToTagName(XByteRangeTag::kName));
+  if (!tag.GetContent().has_value()) {
+    return ParseStatusCode::kMalformedTag;
+  }
+
+  auto range = types::ByteRangeExpression::Parse(
+      tag.GetContent()->SkipVariableSubstitution());
+  if (range.has_error()) {
+    return ParseStatus(ParseStatusCode::kMalformedTag)
+        .AddCause(std::move(range).error());
+  }
+
+  return XByteRangeTag{.range = std::move(range).value()};
+}
+
+// static
+ParseStatus::Or<XDiscontinuityTag> XDiscontinuityTag::Parse(TagItem tag) {
+  return ParseEmptyTag<XDiscontinuityTag>(tag);
+}
+
+// static
+ParseStatus::Or<XDiscontinuitySequenceTag> XDiscontinuitySequenceTag::Parse(
+    TagItem tag) {
+  return ParseDecimalIntegerTag(tag, &XDiscontinuitySequenceTag::number);
+}
+
+// static
+ParseStatus::Or<XEndListTag> XEndListTag::Parse(TagItem tag) {
+  return ParseEmptyTag<XEndListTag>(tag);
+}
+
+// static
+ParseStatus::Or<XGapTag> XGapTag::Parse(TagItem tag) {
+  return ParseEmptyTag<XGapTag>(tag);
+}
+
+// static
+ParseStatus::Or<XIFramesOnlyTag> XIFramesOnlyTag::Parse(TagItem tag) {
+  return ParseEmptyTag<XIFramesOnlyTag>(tag);
+}
+
+// static
+ParseStatus::Or<XMapTag> XMapTag::Parse(
+    TagItem tag,
+    const VariableDictionary& variable_dict,
+    VariableDictionary::SubstitutionBuffer& sub_buffer) {
+  DCHECK(tag.GetName() == ToTagName(XMapTag::kName));
   if (!tag.GetContent().has_value()) {
     return ParseStatusCode::kMalformedTag;
   }
 
   // Parse the attribute-list
-  TypedAttributeMap<XPartInfTagAttribute> map;
+  TypedAttributeMap<XMapTagAttribute> map;
   types::AttributeListIterator iter(*tag.GetContent());
   auto map_result = map.FillUntilError(&iter);
 
@@ -579,28 +589,40 @@
         .AddCause(std::move(map_result));
   }
 
-  // Extract the 'PART-TARGET' attribute
-  base::TimeDelta part_target;
-  if (map.HasValue(XPartInfTagAttribute::kPartTarget)) {
-    auto result = types::ParseDecimalFloatingPoint(
-        map.GetValue(XPartInfTagAttribute::kPartTarget)
-            .SkipVariableSubstitution());
-
+  absl::optional<ResolvedSourceString> uri;
+  if (map.HasValue(XMapTagAttribute::kUri)) {
+    auto result = types::ParseQuotedString(map.GetValue(XMapTagAttribute::kUri),
+                                           variable_dict, sub_buffer);
     if (result.has_error()) {
       return ParseStatus(ParseStatusCode::kMalformedTag)
           .AddCause(std::move(result).error());
     }
 
-    part_target = base::Seconds(std::move(result).value());
-
-    if (part_target.is_max()) {
-      return ParseStatusCode::kValueOverflowsTimeDelta;
-    }
+    uri = std::move(result).value();
   } else {
     return ParseStatusCode::kMalformedTag;
   }
 
-  return XPartInfTag{.target_duration = part_target};
+  absl::optional<types::ByteRangeExpression> byte_range;
+  if (map.HasValue(XMapTagAttribute::kByteRange)) {
+    auto result =
+        types::ParseQuotedString(map.GetValue(XMapTagAttribute::kByteRange),
+                                 variable_dict, sub_buffer)
+            .MapValue(types::ByteRangeExpression::Parse);
+    if (result.has_error()) {
+      return ParseStatus(ParseStatusCode::kMalformedTag)
+          .AddCause(std::move(result).error());
+    }
+
+    byte_range = std::move(result).value();
+  }
+
+  return XMapTag{.uri = uri.value(), .byte_range = byte_range};
+}
+
+// static
+ParseStatus::Or<XMediaSequenceTag> XMediaSequenceTag::Parse(TagItem tag) {
+  return ParseDecimalIntegerTag(tag, &XMediaSequenceTag::number);
 }
 
 // static
@@ -694,6 +716,66 @@
 }
 
 // static
+ParseStatus::Or<XPartInfTag> XPartInfTag::Parse(TagItem tag) {
+  DCHECK(tag.GetName() == ToTagName(XPartInfTag::kName));
+  if (!tag.GetContent().has_value()) {
+    return ParseStatusCode::kMalformedTag;
+  }
+
+  // Parse the attribute-list
+  TypedAttributeMap<XPartInfTagAttribute> map;
+  types::AttributeListIterator iter(*tag.GetContent());
+  auto map_result = map.FillUntilError(&iter);
+
+  if (map_result.code() != ParseStatusCode::kReachedEOF) {
+    return ParseStatus(ParseStatusCode::kMalformedTag)
+        .AddCause(std::move(map_result));
+  }
+
+  // Extract the 'PART-TARGET' attribute
+  base::TimeDelta part_target;
+  if (map.HasValue(XPartInfTagAttribute::kPartTarget)) {
+    auto result = types::ParseDecimalFloatingPoint(
+        map.GetValue(XPartInfTagAttribute::kPartTarget)
+            .SkipVariableSubstitution());
+
+    if (result.has_error()) {
+      return ParseStatus(ParseStatusCode::kMalformedTag)
+          .AddCause(std::move(result).error());
+    }
+
+    part_target = base::Seconds(std::move(result).value());
+
+    if (part_target.is_max()) {
+      return ParseStatusCode::kValueOverflowsTimeDelta;
+    }
+  } else {
+    return ParseStatusCode::kMalformedTag;
+  }
+
+  return XPartInfTag{.target_duration = part_target};
+}
+
+// static
+ParseStatus::Or<XPlaylistTypeTag> XPlaylistTypeTag::Parse(TagItem tag) {
+  DCHECK(tag.GetName() == ToTagName(XPlaylistTypeTag::kName));
+
+  // This tag requires content
+  if (!tag.GetContent().has_value() || tag.GetContent()->Empty()) {
+    return ParseStatusCode::kMalformedTag;
+  }
+
+  if (tag.GetContent()->Str() == "EVENT") {
+    return XPlaylistTypeTag{.type = PlaylistType::kEvent};
+  }
+  if (tag.GetContent()->Str() == "VOD") {
+    return XPlaylistTypeTag{.type = PlaylistType::kVOD};
+  }
+
+  return ParseStatusCode::kUnknownPlaylistType;
+}
+
+// static
 ParseStatus::Or<XServerControlTag> XServerControlTag::Parse(TagItem tag) {
   DCHECK(tag.GetName() == ToTagName(XServerControlTag::kName));
   if (!tag.GetContent().has_value()) {
@@ -801,36 +883,25 @@
 }
 
 // static
-ParseStatus::Or<XMediaSequenceTag> XMediaSequenceTag::Parse(TagItem tag) {
-  return ParseDecimalIntegerTag(tag, &XMediaSequenceTag::number);
-}
-
-// static
-ParseStatus::Or<XDiscontinuitySequenceTag> XDiscontinuitySequenceTag::Parse(
-    TagItem tag) {
-  return ParseDecimalIntegerTag(tag, &XDiscontinuitySequenceTag::number);
-}
-
-// static
-ParseStatus::Or<XByteRangeTag> XByteRangeTag::Parse(TagItem tag) {
-  DCHECK(tag.GetName() == ToTagName(XByteRangeTag::kName));
+ParseStatus::Or<XTargetDurationTag> XTargetDurationTag::Parse(TagItem tag) {
+  DCHECK(tag.GetName() == ToTagName(XTargetDurationTag::kName));
   if (!tag.GetContent().has_value()) {
     return ParseStatusCode::kMalformedTag;
   }
 
-  auto range = types::ByteRangeExpression::Parse(
-      tag.GetContent()->SkipVariableSubstitution());
-  if (range.has_error()) {
+  auto duration_result = types::ParseDecimalInteger(
+      tag.GetContent().value().SkipVariableSubstitution());
+  if (duration_result.has_error()) {
     return ParseStatus(ParseStatusCode::kMalformedTag)
-        .AddCause(std::move(range).error());
+        .AddCause(std::move(duration_result).error());
   }
 
-  return XByteRangeTag{.range = std::move(range).value()};
-}
+  auto duration = base::Seconds(std::move(duration_result).value());
+  if (duration.is_max()) {
+    return ParseStatusCode::kValueOverflowsTimeDelta;
+  }
 
-// static
-ParseStatus::Or<XBitrateTag> XBitrateTag::Parse(TagItem tag) {
-  return ParseDecimalIntegerTag(tag, &XBitrateTag::bitrate);
+  return XTargetDurationTag{.duration = duration};
 }
 
 }  // namespace media::hls
diff --git a/media/formats/hls/tags.h b/media/formats/hls/tags.h
index 74f243e..7fa3606 100644
--- a/media/formats/hls/tags.h
+++ b/media/formats/hls/tags.h
@@ -17,26 +17,15 @@
 
 class TagItem;
 
+// All currently implemented HLS tag types.
+// For organization, these appear in the same order as in `tag_name.h`.
+
 // Represents the contents of the #EXTM3U tag
 struct MEDIA_EXPORT M3uTag {
   static constexpr auto kName = CommonTagName::kM3u;
   static ParseStatus::Or<M3uTag> Parse(TagItem);
 };
 
-// Represents the contents of the #EXT-X-VERSION tag
-struct MEDIA_EXPORT XVersionTag {
-  static constexpr auto kName = CommonTagName::kXVersion;
-  static ParseStatus::Or<XVersionTag> Parse(TagItem);
-
-  types::DecimalInteger version;
-};
-
-// Represents the contents of the #EXT-X-INDEPENDENT-SEGMENTS tag
-struct MEDIA_EXPORT XIndependentSegmentsTag {
-  static constexpr auto kName = CommonTagName::kXIndependentSegments;
-  static ParseStatus::Or<XIndependentSegmentsTag> Parse(TagItem);
-};
-
 // Represents the contents of the #EXT-X-DEFINE tag
 struct MEDIA_EXPORT XDefineTag {
   static constexpr auto kName = CommonTagName::kXDefine;
@@ -57,58 +46,18 @@
   absl::optional<base::StringPiece> value;
 };
 
-// Represents the contents of the #EXTINF tag
-struct MEDIA_EXPORT InfTag {
-  static constexpr auto kName = MediaPlaylistTagName::kInf;
-  static ParseStatus::Or<InfTag> Parse(TagItem);
-
-  // Target duration of the media segment.
-  base::TimeDelta duration;
-
-  // Human-readable title of the media segment.
-  SourceString title;
+// Represents the contents of the #EXT-X-INDEPENDENT-SEGMENTS tag
+struct MEDIA_EXPORT XIndependentSegmentsTag {
+  static constexpr auto kName = CommonTagName::kXIndependentSegments;
+  static ParseStatus::Or<XIndependentSegmentsTag> Parse(TagItem);
 };
 
-// Represents the contents of the #EXT-X-ENDLIST tag
-struct MEDIA_EXPORT XEndListTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXEndList;
-  static ParseStatus::Or<XEndListTag> Parse(TagItem);
-};
+// Represents the contents of the #EXT-X-VERSION tag
+struct MEDIA_EXPORT XVersionTag {
+  static constexpr auto kName = CommonTagName::kXVersion;
+  static ParseStatus::Or<XVersionTag> Parse(TagItem);
 
-// Represents the contents of the #EXT-X-I-FRAMES-ONLY tag
-struct MEDIA_EXPORT XIFramesOnlyTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXIFramesOnly;
-  static ParseStatus::Or<XIFramesOnlyTag> Parse(TagItem);
-};
-
-// Represents the contents of the #EXT-X-DISCONTINUITY tag
-struct MEDIA_EXPORT XDiscontinuityTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXDiscontinuity;
-  static ParseStatus::Or<XDiscontinuityTag> Parse(TagItem);
-};
-
-// Represents the contents of the #EXT-X-GAP tag
-struct MEDIA_EXPORT XGapTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXGap;
-  static ParseStatus::Or<XGapTag> Parse(TagItem);
-};
-
-enum class PlaylistType {
-  // Indicates that this playlist may have segments appended upon reloading
-  // (until the #EXT-X-ENDLIST tag appears), but segments will not be removed.
-  kEvent,
-
-  // Indicates that this playlist is static, and will not have segments appended
-  // or removed.
-  kVOD,
-};
-
-// Represents the contents of the #EXT-X-PLAYLIST-TYPE tag
-struct MEDIA_EXPORT XPlaylistTypeTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXPlaylistType;
-  static ParseStatus::Or<XPlaylistTypeTag> Parse(TagItem);
-
-  PlaylistType type;
+  types::DecimalInteger version;
 };
 
 // Represents the contents of the #EXT-X-STREAM-INF tag
@@ -155,25 +104,98 @@
   absl::optional<types::DecimalFloatingPoint> frame_rate;
 };
 
-// Represents the contents of the #EXT-X-TARGETDURATION tag.
-struct MEDIA_EXPORT XTargetDurationTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXTargetDuration;
-  static ParseStatus::Or<XTargetDurationTag> Parse(TagItem);
+// Represents the contents of the #EXTINF tag
+struct MEDIA_EXPORT InfTag {
+  static constexpr auto kName = MediaPlaylistTagName::kInf;
+  static ParseStatus::Or<InfTag> Parse(TagItem);
 
-  // The upper bound on the duration of all media segments in the
-  // media playlist. The EXTINF duration of each Media Segment in a Playlist
-  // file, when rounded to the nearest integer, MUST be less than or equal to
-  // this duration.
+  // Target duration of the media segment.
   base::TimeDelta duration;
+
+  // Human-readable title of the media segment.
+  SourceString title;
 };
 
-// Represents the contents of the #EXT-PART-INF tag.
-struct MEDIA_EXPORT XPartInfTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXPartInf;
-  static ParseStatus::Or<XPartInfTag> Parse(TagItem);
+// Represents the contents of the #EXT-X-BITRATE tag.
+struct MEDIA_EXPORT XBitrateTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXBitrate;
+  static ParseStatus::Or<XBitrateTag> Parse(TagItem);
 
-  // This value indicates the target duration for partial media segments.
-  base::TimeDelta target_duration;
+  // The approximate bitrate of the following media segments, (except those that
+  // have the EXT-X-BYTERANGE tag) expressed in kilobits per second. The value
+  // must be within +-10% of the actual segment bitrate.
+  types::DecimalInteger bitrate;
+};
+
+// Represents the contents of the #EXT-X-BYTERANGE tag.
+struct MEDIA_EXPORT XByteRangeTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXByteRange;
+  static ParseStatus::Or<XByteRangeTag> Parse(TagItem);
+
+  types::ByteRangeExpression range;
+};
+
+// Represents the contents of the #EXT-X-DISCONTINUITY tag
+struct MEDIA_EXPORT XDiscontinuityTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXDiscontinuity;
+  static ParseStatus::Or<XDiscontinuityTag> Parse(TagItem);
+};
+
+// Represents the contents of the #EXT-X-DISCONTINUITY-SEQUENCE tag.
+struct MEDIA_EXPORT XDiscontinuitySequenceTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXDiscontinuitySequence;
+  static ParseStatus::Or<XDiscontinuitySequenceTag> Parse(TagItem);
+
+  // Indicates the discontinuity sequence number to assign to the first media
+  // segment in this playlist. These numbers are useful for synchronizing
+  // between variant stream timelines.
+  types::DecimalInteger number;
+};
+
+// Represents the contents of the #EXT-X-ENDLIST tag
+struct MEDIA_EXPORT XEndListTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXEndList;
+  static ParseStatus::Or<XEndListTag> Parse(TagItem);
+};
+
+// Represents the contents of the #EXT-X-GAP tag
+struct MEDIA_EXPORT XGapTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXGap;
+  static ParseStatus::Or<XGapTag> Parse(TagItem);
+};
+
+// Represents the contents of the #EXT-X-I-FRAMES-ONLY tag
+struct MEDIA_EXPORT XIFramesOnlyTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXIFramesOnly;
+  static ParseStatus::Or<XIFramesOnlyTag> Parse(TagItem);
+};
+
+// Represents the contents of the #EXT-X-MAP tag.
+struct MEDIA_EXPORT XMapTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXMap;
+  static ParseStatus::Or<XMapTag> Parse(
+      TagItem,
+      const VariableDictionary& variable_dict,
+      VariableDictionary::SubstitutionBuffer& sub_buffer);
+
+  // The URI of the resource containing the media initialization section.
+  ResolvedSourceString uri;
+
+  // This specifies a byte range into the resource containing the media
+  // initialization section.
+  absl::optional<types::ByteRangeExpression> byte_range;
+};
+
+// Represents the contents of the #EXT-X-MEDIA-SEQUENCE tag.
+struct MEDIA_EXPORT XMediaSequenceTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXMediaSequence;
+  static ParseStatus::Or<XMediaSequenceTag> Parse(TagItem);
+
+  // Indicates the media sequence number to assign to the first media segment in
+  // this playlist. These numbers are useful for validating the same media
+  // playlist across reloads, but not for synchronizing media segments between
+  // playlists.
+  types::DecimalInteger number;
 };
 
 // Represents the contents of the #EXT-X-PART tag.
@@ -202,6 +224,33 @@
   bool gap = false;
 };
 
+// Represents the contents of the #EXT-PART-INF tag.
+struct MEDIA_EXPORT XPartInfTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXPartInf;
+  static ParseStatus::Or<XPartInfTag> Parse(TagItem);
+
+  // This value indicates the target duration for partial media segments.
+  base::TimeDelta target_duration;
+};
+
+enum class PlaylistType {
+  // Indicates that this playlist may have segments appended upon reloading
+  // (until the #EXT-X-ENDLIST tag appears), but segments will not be removed.
+  kEvent,
+
+  // Indicates that this playlist is static, and will not have segments appended
+  // or removed.
+  kVOD,
+};
+
+// Represents the contents of the #EXT-X-PLAYLIST-TYPE tag
+struct MEDIA_EXPORT XPlaylistTypeTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXPlaylistType;
+  static ParseStatus::Or<XPlaylistTypeTag> Parse(TagItem);
+
+  PlaylistType type;
+};
+
 // Represents the contents of the #EXT-X-SERVER-CONTROL tag.
 struct MEDIA_EXPORT XServerControlTag {
   static constexpr auto kName = MediaPlaylistTagName::kXServerControl;
@@ -231,46 +280,16 @@
   bool can_block_reload = false;
 };
 
-// Represents the contents of the #EXT-X-MEDIA-SEQUENCE tag.
-struct MEDIA_EXPORT XMediaSequenceTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXMediaSequence;
-  static ParseStatus::Or<XMediaSequenceTag> Parse(TagItem);
+// Represents the contents of the #EXT-X-TARGETDURATION tag.
+struct MEDIA_EXPORT XTargetDurationTag {
+  static constexpr auto kName = MediaPlaylistTagName::kXTargetDuration;
+  static ParseStatus::Or<XTargetDurationTag> Parse(TagItem);
 
-  // Indicates the media sequence number to assign to the first media segment in
-  // this playlist. These numbers are useful for validating the same media
-  // playlist across reloads, but not for synchronizing media segments between
-  // playlists.
-  types::DecimalInteger number;
-};
-
-// Represents the contents of the #EXT-X-DISCONTINUITY-SEQUENCE tag.
-struct MEDIA_EXPORT XDiscontinuitySequenceTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXDiscontinuitySequence;
-  static ParseStatus::Or<XDiscontinuitySequenceTag> Parse(TagItem);
-
-  // Indicates the discontinuity sequence number to assign to the first media
-  // segment in this playlist. These numbers are useful for synchronizing
-  // between variant stream timelines.
-  types::DecimalInteger number;
-};
-
-// Represents the contents of the #EXT-X-BYTERANGE tag.
-struct MEDIA_EXPORT XByteRangeTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXByteRange;
-  static ParseStatus::Or<XByteRangeTag> Parse(TagItem);
-
-  types::ByteRangeExpression range;
-};
-
-// Represents the contents of the #EXT-X-BITRATE tag.
-struct MEDIA_EXPORT XBitrateTag {
-  static constexpr auto kName = MediaPlaylistTagName::kXBitrate;
-  static ParseStatus::Or<XBitrateTag> Parse(TagItem);
-
-  // The approximate bitrate of the following media segments, (except those that
-  // have the EXT-X-BYTERANGE tag) expressed in kilobits per second. The value
-  // must be within +-10% of the actual segment bitrate.
-  types::DecimalInteger bitrate;
+  // The upper bound on the duration of all media segments in the
+  // media playlist. The EXTINF duration of each Media Segment in a Playlist
+  // file, when rounded to the nearest integer, MUST be less than or equal to
+  // this duration.
+  base::TimeDelta duration;
 };
 
 }  // namespace media::hls
diff --git a/media/formats/hls/tags_unittest.cc b/media/formats/hls/tags_unittest.cc
index 001b5a5..9d52a80 100644
--- a/media/formats/hls/tags_unittest.cc
+++ b/media/formats/hls/tags_unittest.cc
@@ -98,8 +98,8 @@
 // `line` must be a sample line containing this tag, and must end with a
 // newline. This DOES NOT parse the item content (only that the item content
 // matches what was expected), use `OkTest` and `ErrorTest` for that.
-template <typename T>
 void RunTagIdenficationTest(
+    TagName name,
     base::StringPiece line,
     absl::optional<base::StringPiece> expected_content,
     const base::Location& from = base::Location::Current()) {
@@ -110,7 +110,7 @@
   auto item = std::move(item_result).value();
   auto* tag = absl::get_if<TagItem>(&item);
   ASSERT_NE(tag, nullptr) << from.ToString();
-  EXPECT_EQ(tag->GetName(), ToTagName(T::kName)) << from.ToString();
+  EXPECT_EQ(tag->GetName(), name) << from.ToString();
   EXPECT_EQ(tag->GetContent().has_value(), expected_content.has_value())
       << from.ToString();
   if (tag->GetContent().has_value() && expected_content.has_value()) {
@@ -118,6 +118,14 @@
   }
 }
 
+template <typename T>
+void RunTagIdenficationTest(
+    base::StringPiece line,
+    absl::optional<base::StringPiece> expected_content,
+    const base::Location& from = base::Location::Current()) {
+  RunTagIdenficationTest(ToTagName(T::kName), line, expected_content, from);
+}
+
 // Test helper for tags which are expected to have no content
 template <typename T>
 void RunEmptyTagTest() {
@@ -193,116 +201,6 @@
   RunEmptyTagTest<M3uTag>();
 }
 
-TEST(HlsTagsTest, ParseXVersionTag) {
-  RunTagIdenficationTest<XVersionTag>("#EXT-X-VERSION:123\n", "123");
-
-  // Test valid versions
-  auto result = OkTest<XVersionTag>("1");
-  EXPECT_EQ(result.tag.version, 1u);
-  result = OkTest<XVersionTag>("2");
-  EXPECT_EQ(result.tag.version, 2u);
-  result = OkTest<XVersionTag>("3");
-  EXPECT_EQ(result.tag.version, 3u);
-  result = OkTest<XVersionTag>("4");
-  EXPECT_EQ(result.tag.version, 4u);
-  result = OkTest<XVersionTag>("5");
-  EXPECT_EQ(result.tag.version, 5u);
-  result = OkTest<XVersionTag>("6");
-  EXPECT_EQ(result.tag.version, 6u);
-  result = OkTest<XVersionTag>("7");
-  EXPECT_EQ(result.tag.version, 7u);
-  result = OkTest<XVersionTag>("8");
-  EXPECT_EQ(result.tag.version, 8u);
-  result = OkTest<XVersionTag>("9");
-  EXPECT_EQ(result.tag.version, 9u);
-  result = OkTest<XVersionTag>("10");
-  EXPECT_EQ(result.tag.version, 10u);
-
-  // While unsupported playlist versions are rejected, that's NOT the
-  // responsibility of this tag parsing function. The playlist should be
-  // rejected at a higher level.
-  result = OkTest<XVersionTag>("99999");
-  EXPECT_EQ(result.tag.version, 99999u);
-
-  // Test invalid versions
-  ErrorTest<XVersionTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
-  ErrorTest<XVersionTag>("", ParseStatusCode::kMalformedTag);
-  ErrorTest<XVersionTag>("0", ParseStatusCode::kInvalidPlaylistVersion);
-  ErrorTest<XVersionTag>("-1", ParseStatusCode::kMalformedTag);
-  ErrorTest<XVersionTag>("1.0", ParseStatusCode::kMalformedTag);
-  ErrorTest<XVersionTag>("asdf", ParseStatusCode::kMalformedTag);
-  ErrorTest<XVersionTag>("  1 ", ParseStatusCode::kMalformedTag);
-}
-
-TEST(HlsTagsTest, ParseInfTag) {
-  RunTagIdenficationTest<InfTag>("#EXTINF:123,\t\n", "123,\t");
-
-  // Test some valid tags
-  auto result = OkTest<InfTag>("123,");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(123.0)));
-  EXPECT_EQ(result.tag.title.Str(), "");
-
-  result = OkTest<InfTag>("1.23,");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(1.23)));
-  EXPECT_EQ(result.tag.title.Str(), "");
-
-  // The spec implies that whitespace characters like this usually aren't
-  // permitted, but "\t" is a common occurrence for the title value.
-  result = OkTest<InfTag>("99.5,\t");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(99.5)));
-  EXPECT_EQ(result.tag.title.Str(), "\t");
-
-  result = OkTest<InfTag>("9.5,,,,");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(9.5)));
-  EXPECT_EQ(result.tag.title.Str(), ",,,");
-
-  result = OkTest<InfTag>("12,asdfsdf   ");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(12.0)));
-  EXPECT_EQ(result.tag.title.Str(), "asdfsdf   ");
-
-  // Test some invalid tags
-  ErrorTest<InfTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
-  ErrorTest<InfTag>("", ParseStatusCode::kMalformedTag);
-  ErrorTest<InfTag>(",", ParseStatusCode::kMalformedTag);
-  ErrorTest<InfTag>("-123,", ParseStatusCode::kMalformedTag);
-  ErrorTest<InfTag>("123", ParseStatusCode::kMalformedTag);
-  ErrorTest<InfTag>("asdf,", ParseStatusCode::kMalformedTag);
-
-  // Test max value
-  result = OkTest<InfTag>(base::NumberToString(MaxSeconds()) + ",\t");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(MaxSeconds())));
-  ErrorTest<InfTag>(base::NumberToString(MaxSeconds() + 1) + ",\t",
-                    ParseStatusCode::kValueOverflowsTimeDelta);
-}
-
-TEST(HlsTagsTest, ParseXIndependentSegmentsTag) {
-  RunTagIdenficationTest<XIndependentSegmentsTag>(
-      "#EXT-X-INDEPENDENT-SEGMENTS\n", absl::nullopt);
-  RunEmptyTagTest<XIndependentSegmentsTag>();
-}
-
-TEST(HlsTagsTest, ParseXEndListTag) {
-  RunTagIdenficationTest<XEndListTag>("#EXT-X-ENDLIST\n", absl::nullopt);
-  RunEmptyTagTest<XEndListTag>();
-}
-
-TEST(HlsTagsTest, ParseXIFramesOnlyTag) {
-  RunTagIdenficationTest<XIFramesOnlyTag>("#EXT-X-I-FRAMES-ONLY\n",
-                                          absl::nullopt);
-  RunEmptyTagTest<XIFramesOnlyTag>();
-}
-
-TEST(HlsTagsTest, ParseXDiscontinuityTag) {
-  RunTagIdenficationTest<XDiscontinuityTag>("#EXT-X-DISCONTINUITY\n",
-                                            absl::nullopt);
-  RunEmptyTagTest<XDiscontinuityTag>();
-}
-
-TEST(HlsTagsTest, ParseXGapTag) {
-  RunTagIdenficationTest<XGapTag>("#EXT-X-GAP\n", absl::nullopt);
-  RunEmptyTagTest<XGapTag>();
-}
-
 TEST(HlsTagsTest, ParseXDefineTag) {
   RunTagIdenficationTest<XDefineTag>(
       "#EXT-X-DEFINE:NAME=\"FOO\",VALUE=\"Bar\",\n",
@@ -363,22 +261,100 @@
                         ParseStatusCode::kMalformedTag);
 }
 
-TEST(HlsTagsTest, ParseXPlaylistTypeTag) {
-  RunTagIdenficationTest<XPlaylistTypeTag>("#EXT-X-PLAYLIST-TYPE:VOD\n", "VOD");
-  RunTagIdenficationTest<XPlaylistTypeTag>("#EXT-X-PLAYLIST-TYPE:EVENT\n",
-                                           "EVENT");
+TEST(HlsTagsTest, ParseXIndependentSegmentsTag) {
+  RunTagIdenficationTest<XIndependentSegmentsTag>(
+      "#EXT-X-INDEPENDENT-SEGMENTS\n", absl::nullopt);
+  RunEmptyTagTest<XIndependentSegmentsTag>();
+}
 
-  auto result = OkTest<XPlaylistTypeTag>("EVENT");
-  EXPECT_EQ(result.tag.type, PlaylistType::kEvent);
-  result = OkTest<XPlaylistTypeTag>("VOD");
-  EXPECT_EQ(result.tag.type, PlaylistType::kVOD);
+TEST(HlsTagsTest, ParseXStartTag) {
+  RunTagIdenficationTest(ToTagName(CommonTagName::kXStart),
+                         "#EXT-X-START:TIME-OFFSET=30,PRECISE=YES\n",
+                         "TIME-OFFSET=30,PRECISE=YES");
+  // TODO(crbug.com/1266991): Implement the EXT-X-START tag.
+}
 
-  ErrorTest<XPlaylistTypeTag>("FOOBAR", ParseStatusCode::kUnknownPlaylistType);
-  ErrorTest<XPlaylistTypeTag>("EEVENT", ParseStatusCode::kUnknownPlaylistType);
-  ErrorTest<XPlaylistTypeTag>(" EVENT", ParseStatusCode::kUnknownPlaylistType);
-  ErrorTest<XPlaylistTypeTag>("EVENT ", ParseStatusCode::kUnknownPlaylistType);
-  ErrorTest<XPlaylistTypeTag>("", ParseStatusCode::kMalformedTag);
-  ErrorTest<XPlaylistTypeTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
+TEST(HlsTagsTest, ParseXVersionTag) {
+  RunTagIdenficationTest<XVersionTag>("#EXT-X-VERSION:123\n", "123");
+
+  // Test valid versions
+  auto result = OkTest<XVersionTag>("1");
+  EXPECT_EQ(result.tag.version, 1u);
+  result = OkTest<XVersionTag>("2");
+  EXPECT_EQ(result.tag.version, 2u);
+  result = OkTest<XVersionTag>("3");
+  EXPECT_EQ(result.tag.version, 3u);
+  result = OkTest<XVersionTag>("4");
+  EXPECT_EQ(result.tag.version, 4u);
+  result = OkTest<XVersionTag>("5");
+  EXPECT_EQ(result.tag.version, 5u);
+  result = OkTest<XVersionTag>("6");
+  EXPECT_EQ(result.tag.version, 6u);
+  result = OkTest<XVersionTag>("7");
+  EXPECT_EQ(result.tag.version, 7u);
+  result = OkTest<XVersionTag>("8");
+  EXPECT_EQ(result.tag.version, 8u);
+  result = OkTest<XVersionTag>("9");
+  EXPECT_EQ(result.tag.version, 9u);
+  result = OkTest<XVersionTag>("10");
+  EXPECT_EQ(result.tag.version, 10u);
+
+  // While unsupported playlist versions are rejected, that's NOT the
+  // responsibility of this tag parsing function. The playlist should be
+  // rejected at a higher level.
+  result = OkTest<XVersionTag>("99999");
+  EXPECT_EQ(result.tag.version, 99999u);
+
+  // Test invalid versions
+  ErrorTest<XVersionTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
+  ErrorTest<XVersionTag>("", ParseStatusCode::kMalformedTag);
+  ErrorTest<XVersionTag>("0", ParseStatusCode::kInvalidPlaylistVersion);
+  ErrorTest<XVersionTag>("-1", ParseStatusCode::kMalformedTag);
+  ErrorTest<XVersionTag>("1.0", ParseStatusCode::kMalformedTag);
+  ErrorTest<XVersionTag>("asdf", ParseStatusCode::kMalformedTag);
+  ErrorTest<XVersionTag>("  1 ", ParseStatusCode::kMalformedTag);
+}
+
+TEST(HlsTagsTest, ParseXContentSteeringTag) {
+  RunTagIdenficationTest(
+      ToTagName(MultivariantPlaylistTagName::kXContentSteering),
+      "#EXT-X-CONTENT-STEERING:SERVER-URI=\"https://google.com/"
+      "manifest.json\"\n",
+      "SERVER-URI=\"https://google.com/manifest.json\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-CONTENT-STEERING tag.
+}
+
+TEST(HlsTagsTest, ParseXIFrameStreamInfTag) {
+  RunTagIdenficationTest(
+      ToTagName(MultivariantPlaylistTagName::kXIFrameStreamInf),
+      "#EXT-X-I-FRAME-STREAM-INF:URI=\"foo.m3u8\",BANDWIDTH=1000\n",
+      "URI=\"foo.m3u8\",BANDWIDTH=1000");
+  // TODO(crbug.com/1266991): Implement the EXT-X-I-FRAME-STREAM-INF tag.
+}
+
+TEST(HlsTagsTest, ParseXMediaTag) {
+  RunTagIdenficationTest(
+      ToTagName(MultivariantPlaylistTagName::kXMedia),
+      "#EXT-X-MEDIA:TYPE=VIDEO,URI=\"foo.m3u8\",GROUP-ID=\"HD\",NAME=\"Foo "
+      "HD\"\n",
+      "TYPE=VIDEO,URI=\"foo.m3u8\",GROUP-ID=\"HD\",NAME=\"Foo HD\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-MEDIA tag.
+}
+
+TEST(HlsTagsTest, ParseXSessionDataTag) {
+  RunTagIdenficationTest(
+      ToTagName(MultivariantPlaylistTagName::kXSessionData),
+      "#EXT-X-SESSION-DATA:DATA-ID=\"com.google.key\",VALUE=\"value\"\n",
+      "DATA-ID=\"com.google.key\",VALUE=\"value\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-DATA tag.
+}
+
+TEST(HlsTagsTest, ParseXSessionKeyTag) {
+  RunTagIdenficationTest(
+      ToTagName(MultivariantPlaylistTagName::kXSessionKey),
+      "#EXT-X-SESSION-KEY:METHOD=AES-128,URI=\"https://google.com/key\"\n",
+      "METHOD=AES-128,URI=\"https://google.com/key\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-SESSION-KEY tag.
 }
 
 TEST(HlsTagsTest, ParseXStreamInfTag) {
@@ -489,46 +465,50 @@
                            sub_buffer, ParseStatusCode::kMalformedTag);
 }
 
-TEST(HlsTagsTest, ParseXTargetDurationTag) {
-  RunTagIdenficationTest<XTargetDurationTag>("#EXT-X-TARGETDURATION:10\n",
-                                             "10");
+TEST(HlsTagsTest, ParseInfTag) {
+  RunTagIdenficationTest<InfTag>("#EXTINF:123,\t\n", "123,\t");
 
-  // Content must be a valid decimal-integer
-  ErrorTest<XTargetDurationTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("-1", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("1.5", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>(" 1", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("1 ", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("one", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("{$ONE}", ParseStatusCode::kMalformedTag);
-  ErrorTest<XTargetDurationTag>("1,", ParseStatusCode::kMalformedTag);
+  // Test some valid tags
+  auto result = OkTest<InfTag>("123,");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(123.0)));
+  EXPECT_EQ(result.tag.title.Str(), "");
 
-  auto result = OkTest<XTargetDurationTag>("0");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(0)));
+  result = OkTest<InfTag>("1.23,");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(1.23)));
+  EXPECT_EQ(result.tag.title.Str(), "");
 
-  result = OkTest<XTargetDurationTag>("1");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(1)));
+  // The spec implies that whitespace characters like this usually aren't
+  // permitted, but "\t" is a common occurrence for the title value.
+  result = OkTest<InfTag>("99.5,\t");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(99.5)));
+  EXPECT_EQ(result.tag.title.Str(), "\t");
 
-  result = OkTest<XTargetDurationTag>("99");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(99)));
+  result = OkTest<InfTag>("9.5,,,,");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(9.5)));
+  EXPECT_EQ(result.tag.title.Str(), ",,,");
+
+  result = OkTest<InfTag>("12,asdfsdf   ");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(12.0)));
+  EXPECT_EQ(result.tag.title.Str(), "asdfsdf   ");
+
+  // Test some invalid tags
+  ErrorTest<InfTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
+  ErrorTest<InfTag>("", ParseStatusCode::kMalformedTag);
+  ErrorTest<InfTag>(",", ParseStatusCode::kMalformedTag);
+  ErrorTest<InfTag>("-123,", ParseStatusCode::kMalformedTag);
+  ErrorTest<InfTag>("123", ParseStatusCode::kMalformedTag);
+  ErrorTest<InfTag>("asdf,", ParseStatusCode::kMalformedTag);
 
   // Test max value
-  result = OkTest<XTargetDurationTag>(base::NumberToString(MaxSeconds()));
-  EXPECT_EQ(result.tag.duration, base::Seconds(MaxSeconds()));
-  ErrorTest<XTargetDurationTag>(base::NumberToString(MaxSeconds() + 1),
-                                ParseStatusCode::kValueOverflowsTimeDelta);
+  result = OkTest<InfTag>(base::NumberToString(MaxSeconds()) + ",\t");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(MaxSeconds())));
+  ErrorTest<InfTag>(base::NumberToString(MaxSeconds() + 1) + ",\t",
+                    ParseStatusCode::kValueOverflowsTimeDelta);
 }
 
-TEST(HlsTagsTest, ParseXMediaSequenceTag) {
-  RunTagIdenficationTest<XMediaSequenceTag>("#EXT-X-MEDIA-SEQUENCE:3\n", "3");
-  RunDecimalIntegerTagTest(&XMediaSequenceTag::number);
-}
-
-TEST(HlsTagsTest, ParseXDiscontinuitySequenceTag) {
-  RunTagIdenficationTest<XDiscontinuitySequenceTag>(
-      "#EXT-X-DISCONTINUITY-SEQUENCE:3\n", "3");
-  RunDecimalIntegerTagTest(&XDiscontinuitySequenceTag::number);
+TEST(HlsTagsTest, ParseXBitrateTag) {
+  RunTagIdenficationTest<XBitrateTag>("#EXT-X-BITRATE:3\n", "3");
+  RunDecimalIntegerTagTest(&XBitrateTag::bitrate);
 }
 
 TEST(HlsTagsTest, ParseXByteRangeTag) {
@@ -551,9 +531,217 @@
   ErrorTest<XByteRangeTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
 }
 
-TEST(HlsTagsTest, ParseXBitrateTag) {
-  RunTagIdenficationTest<XBitrateTag>("#EXT-X-BITRATE:3\n", "3");
-  RunDecimalIntegerTagTest(&XBitrateTag::bitrate);
+TEST(HlsTagsTest, ParseXDateRangeTag) {
+  RunTagIdenficationTest(
+      ToTagName(MediaPlaylistTagName::kXDateRange),
+      "#EXT-X-DATERANGE:ID=\"ad\",START-DATE=\"2022-07-19T01:04:57+0000\"\n",
+      "ID=\"ad\",START-DATE=\"2022-07-19T01:04:57+0000\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-DATERANGE tag.
+}
+
+TEST(HlsTagsTest, ParseXDiscontinuityTag) {
+  RunTagIdenficationTest<XDiscontinuityTag>("#EXT-X-DISCONTINUITY\n",
+                                            absl::nullopt);
+  RunEmptyTagTest<XDiscontinuityTag>();
+}
+
+TEST(HlsTagsTest, ParseXDiscontinuitySequenceTag) {
+  RunTagIdenficationTest<XDiscontinuitySequenceTag>(
+      "#EXT-X-DISCONTINUITY-SEQUENCE:3\n", "3");
+  RunDecimalIntegerTagTest(&XDiscontinuitySequenceTag::number);
+}
+
+TEST(HlsTagsTest, ParseXEndListTag) {
+  RunTagIdenficationTest<XEndListTag>("#EXT-X-ENDLIST\n", absl::nullopt);
+  RunEmptyTagTest<XEndListTag>();
+}
+
+TEST(HlsTagsTest, ParseXGapTag) {
+  RunTagIdenficationTest<XGapTag>("#EXT-X-GAP\n", absl::nullopt);
+  RunEmptyTagTest<XGapTag>();
+}
+
+TEST(HlsTagsTest, ParseXIFramesOnlyTag) {
+  RunTagIdenficationTest<XIFramesOnlyTag>("#EXT-X-I-FRAMES-ONLY\n",
+                                          absl::nullopt);
+  RunEmptyTagTest<XIFramesOnlyTag>();
+}
+
+TEST(HlsTagsTest, ParseXKeyTag) {
+  RunTagIdenficationTest(ToTagName(MediaPlaylistTagName::kXKey),
+                         "#EXT-X-KEY:METHOD=NONE\n", "METHOD=NONE");
+  // TODO(crbug.com/1266991): Implement the EXT-X-KEY tag.
+}
+
+TEST(HlsTagsTest, ParseXMapTag) {
+  RunTagIdenficationTest<XMapTag>("#EXT-X-MAP:URI=\"foo.ts\",BYTERANGE=12@0\n",
+                                  "URI=\"foo.ts\",BYTERANGE=12@0");
+
+  VariableDictionary variable_dict = CreateBasicDictionary();
+  EXPECT_TRUE(variable_dict.Insert(CreateVarName("ONE"), "1"));
+  EXPECT_TRUE(variable_dict.Insert(CreateVarName("TWO"), "2"));
+  EXPECT_TRUE(variable_dict.Insert(CreateVarName("THREE"), "3"));
+  VariableDictionary::SubstitutionBuffer sub_buffer;
+
+  // The URI attribute is required
+  ErrorTest<XMapTag>(absl::nullopt, variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  ErrorTest<XMapTag>("", variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  ErrorTest<XMapTag>("BYTERANGE=12", variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  ErrorTest<XMapTag>("URI=foo.ts", variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  auto result =
+      OkTest<XMapTag>("URI=\"foo.ts\",FUTURE=PROOF", variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+
+  // The URI attribute is subject to variable substitution
+  ErrorTest<XMapTag>("URI=\"{$UNDEFINED}.ts\"", variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  result =
+      OkTest<XMapTag>("URI=\"{$FOO}_{$BAR}.ts\"", variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "bar_baz.ts");
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+
+  // Test the BYTERANGE attribute
+  ErrorTest<XMapTag>("URI=\"foo.ts\",BYTERANGE=\"{$UNDEFINED}\"", variable_dict,
+                     sub_buffer, ParseStatusCode::kMalformedTag);
+  ErrorTest<XMapTag>("URI=\"foo.ts\",BYTERANGE=\"\"", variable_dict, sub_buffer,
+                     ParseStatusCode::kMalformedTag);
+  result = OkTest<XMapTag>("URI=\"foo.ts\",BYTERANGE=\"10\"", variable_dict,
+                           sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.byte_range->length, 10u);
+  EXPECT_EQ(result.tag.byte_range->offset, absl::nullopt);
+
+  // The BYTERANGE attribute is subject to variable substitution
+  result = OkTest<XMapTag>("URI=\"foo.ts\",BYTERANGE=\"{$ONE}{$TWO}@{$THREE}\"",
+                           variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.byte_range->length, 12u);
+  EXPECT_EQ(result.tag.byte_range->offset, 3u);
+}
+
+TEST(HlsTagsTest, ParseXMediaSequenceTag) {
+  RunTagIdenficationTest<XMediaSequenceTag>("#EXT-X-MEDIA-SEQUENCE:3\n", "3");
+  RunDecimalIntegerTagTest(&XMediaSequenceTag::number);
+}
+
+TEST(HlsTagsTest, ParseXPartTag) {
+  RunTagIdenficationTest<XPartTag>("#EXT-X-PART:URI=\"foo.ts\",DURATION=1\n",
+                                   "URI=\"foo.ts\",DURATION=1");
+
+  VariableDictionary variable_dict = CreateBasicDictionary();
+  EXPECT_TRUE(variable_dict.Insert(CreateVarName("NUMBER"), "9"));
+  VariableDictionary::SubstitutionBuffer sub_buffer;
+
+  // The URI and DURATION attributes are required
+  ErrorTest<XPartTag>(absl::nullopt, variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  ErrorTest<XPartTag>("", variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  ErrorTest<XPartTag>("URI=\"foo.ts\"", variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  ErrorTest<XPartTag>("DURATION=1", variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  ErrorTest<XPartTag>("URI=\"\",DURATION=1", variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  auto result =
+      OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1", variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, false);
+
+  // Test URI attribute
+  ErrorTest<XPartTag>("URI=\"{$UNDEFINED}.ts\",DURATION=1", variable_dict,
+                      sub_buffer, ParseStatusCode::kMalformedTag);
+  result = OkTest<XPartTag>("URI=\"{$BAR}.ts\",DURATION=1", variable_dict,
+                            sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "baz.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, false);
+
+  // Test DURATION attribute
+  result = OkTest<XPartTag>(
+      "URI=\"foo.ts\",DURATION=" + base::NumberToString(MaxSeconds()),
+      variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(MaxSeconds())));
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, false);
+  ErrorTest<XPartTag>(
+      "URI=\"foo.ts\",DURATION=" + base::NumberToString(MaxSeconds() + 1),
+      variable_dict, sub_buffer, ParseStatusCode::kValueOverflowsTimeDelta);
+
+  // Test BYTERANGE attribute
+  ErrorTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"{$UNDEFINED}\"",
+                      variable_dict, sub_buffer,
+                      ParseStatusCode::kMalformedTag);
+  ErrorTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"\"", variable_dict,
+                      sub_buffer, ParseStatusCode::kMalformedTag);
+  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"12\"",
+                            variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range->length, 12u);
+  EXPECT_EQ(result.tag.byte_range->offset, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, false);
+
+  result =
+      OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"{$NUMBER}@3\"",
+                       variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range->length, 9u);
+  EXPECT_EQ(result.tag.byte_range->offset, 3u);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, false);
+
+  // Test the INDEPENDENT attribute
+  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,INDEPENDENT=YES",
+                            variable_dict, sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, true);
+  EXPECT_EQ(result.tag.gap, false);
+
+  for (std::string x : {"NO", "Y", "TRUE", "1", "yes"}) {
+    result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,INDEPENDENT=" + x,
+                              variable_dict, sub_buffer);
+    EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+    EXPECT_EQ(result.tag.duration, base::Seconds(1));
+    EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+    EXPECT_EQ(result.tag.independent, false);
+    EXPECT_EQ(result.tag.gap, false);
+  }
+
+  // Test the GAP attribute
+  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,GAP=YES", variable_dict,
+                            sub_buffer);
+  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+  EXPECT_EQ(result.tag.duration, base::Seconds(1));
+  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+  EXPECT_EQ(result.tag.independent, false);
+  EXPECT_EQ(result.tag.gap, true);
+
+  for (std::string x : {"NO", "Y", "TRUE", "1", "yes"}) {
+    result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,GAP=" + x,
+                              variable_dict, sub_buffer);
+    EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
+    EXPECT_EQ(result.tag.duration, base::Seconds(1));
+    EXPECT_EQ(result.tag.byte_range, absl::nullopt);
+    EXPECT_EQ(result.tag.independent, false);
+    EXPECT_EQ(result.tag.gap, false);
+  }
 }
 
 TEST(HlsTagsTest, ParseXPartInfTag) {
@@ -592,6 +780,47 @@
       ParseStatusCode::kValueOverflowsTimeDelta);
 }
 
+TEST(HlsTagsTest, ParseXPlaylistTypeTag) {
+  RunTagIdenficationTest<XPlaylistTypeTag>("#EXT-X-PLAYLIST-TYPE:VOD\n", "VOD");
+  RunTagIdenficationTest<XPlaylistTypeTag>("#EXT-X-PLAYLIST-TYPE:EVENT\n",
+                                           "EVENT");
+
+  auto result = OkTest<XPlaylistTypeTag>("EVENT");
+  EXPECT_EQ(result.tag.type, PlaylistType::kEvent);
+  result = OkTest<XPlaylistTypeTag>("VOD");
+  EXPECT_EQ(result.tag.type, PlaylistType::kVOD);
+
+  ErrorTest<XPlaylistTypeTag>("FOOBAR", ParseStatusCode::kUnknownPlaylistType);
+  ErrorTest<XPlaylistTypeTag>("EEVENT", ParseStatusCode::kUnknownPlaylistType);
+  ErrorTest<XPlaylistTypeTag>(" EVENT", ParseStatusCode::kUnknownPlaylistType);
+  ErrorTest<XPlaylistTypeTag>("EVENT ", ParseStatusCode::kUnknownPlaylistType);
+  ErrorTest<XPlaylistTypeTag>("", ParseStatusCode::kMalformedTag);
+  ErrorTest<XPlaylistTypeTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
+}
+
+TEST(HlsTagsTest, ParseXPreloadHintTag) {
+  RunTagIdenficationTest(ToTagName(MediaPlaylistTagName::kXPreloadHint),
+                         "#EXT-X-PRELOAD-HINT:TYPE=PART,URI=\"foo.ts\"\n",
+                         "TYPE=PART,URI=\"foo.ts\"");
+  // TODO(crbug.com/1266991): Implement the EXT-X-PRELOAD-HINT tag.
+}
+
+TEST(HlsTagsTest, ParseXProgramDateTimeTag) {
+  RunTagIdenficationTest(
+      ToTagName(MediaPlaylistTagName::kXProgramDateTime),
+      "#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00\n",
+      "2010-02-19T14:54:23.031+08:00");
+  // TODO(crbug.com/1266991): Implement the EXT-X-PROGRAM-DATE-TIME tag.
+}
+
+TEST(HlsTagsTest, ParseXRenditionReportTag) {
+  RunTagIdenficationTest(
+      ToTagName(MediaPlaylistTagName::kXRenditionReport),
+      "#EXT-X-RENDITION-REPORT:URI=\"foo.m3u8\",LAST-MSN=200\n",
+      "URI=\"foo.m3u8\",LAST-MSN=200");
+  // TODO(crbug.com/1266991): Implement the EXT-X-RENDITION-REPORT tag.
+}
+
 TEST(HlsTagsTest, ParseXServerControlTag) {
   RunTagIdenficationTest<XServerControlTag>(
       "#EXT-X-SERVER-CONTROL:SKIP-UNTIL=10\n", "SKIP-UNTIL=10");
@@ -738,119 +967,42 @@
   EXPECT_EQ(result.tag.can_block_reload, true);
 }
 
-TEST(HlsTagsTest, ParseXPartTag) {
-  RunTagIdenficationTest<XPartTag>("#EXT-X-PART:URI=\"foo.ts\",DURATION=1\n",
-                                   "URI=\"foo.ts\",DURATION=1");
+TEST(HlsTagsTest, ParseXSkipTag) {
+  RunTagIdenficationTest(ToTagName(MediaPlaylistTagName::kXSkip),
+                         "#EXT-X-SKIP:SKIPPED-SEGMENTS=10\n",
+                         "SKIPPED-SEGMENTS=10");
+  // TODO(crbug.com/1266991): Implement the EXT-X-SKIP tag.
+}
 
-  VariableDictionary variable_dict = CreateBasicDictionary();
-  EXPECT_TRUE(variable_dict.Insert(CreateVarName("NUMBER"), "9"));
-  VariableDictionary::SubstitutionBuffer sub_buffer;
+TEST(HlsTagsTest, ParseXTargetDurationTag) {
+  RunTagIdenficationTest<XTargetDurationTag>("#EXT-X-TARGETDURATION:10\n",
+                                             "10");
 
-  // The URI and DURATION attributes are required
-  ErrorTest<XPartTag>(absl::nullopt, variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  ErrorTest<XPartTag>("", variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  ErrorTest<XPartTag>("URI=\"foo.ts\"", variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  ErrorTest<XPartTag>("DURATION=1", variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  ErrorTest<XPartTag>("URI=\"\",DURATION=1", variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  auto result =
-      OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1", variable_dict, sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, false);
+  // Content must be a valid decimal-integer
+  ErrorTest<XTargetDurationTag>(absl::nullopt, ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("-1", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("1.5", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>(" 1", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("1 ", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("one", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("{$ONE}", ParseStatusCode::kMalformedTag);
+  ErrorTest<XTargetDurationTag>("1,", ParseStatusCode::kMalformedTag);
 
-  // Test URI attribute
-  ErrorTest<XPartTag>("URI=\"{$UNDEFINED}.ts\",DURATION=1", variable_dict,
-                      sub_buffer, ParseStatusCode::kMalformedTag);
-  result = OkTest<XPartTag>("URI=\"{$BAR}.ts\",DURATION=1", variable_dict,
-                            sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "baz.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, false);
+  auto result = OkTest<XTargetDurationTag>("0");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(0)));
 
-  // Test DURATION attribute
-  result = OkTest<XPartTag>(
-      "URI=\"foo.ts\",DURATION=" + base::NumberToString(MaxSeconds()),
-      variable_dict, sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(MaxSeconds())));
-  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, false);
-  ErrorTest<XPartTag>(
-      "URI=\"foo.ts\",DURATION=" + base::NumberToString(MaxSeconds() + 1),
-      variable_dict, sub_buffer, ParseStatusCode::kValueOverflowsTimeDelta);
+  result = OkTest<XTargetDurationTag>("1");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(1)));
 
-  // Test BYTERANGE attribute
-  ErrorTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"{$UNDEFINED}\"",
-                      variable_dict, sub_buffer,
-                      ParseStatusCode::kMalformedTag);
-  ErrorTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"\"", variable_dict,
-                      sub_buffer, ParseStatusCode::kMalformedTag);
-  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"12\"",
-                            variable_dict, sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range->length, 12u);
-  EXPECT_EQ(result.tag.byte_range->offset, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, false);
+  result = OkTest<XTargetDurationTag>("99");
+  EXPECT_TRUE(RoughlyEqual(result.tag.duration, base::Seconds(99)));
 
-  result =
-      OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,BYTERANGE=\"{$NUMBER}@3\"",
-                       variable_dict, sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range->length, 9u);
-  EXPECT_EQ(result.tag.byte_range->offset, 3u);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, false);
-
-  // Test the INDEPENDENT attribute
-  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,INDEPENDENT=YES",
-                            variable_dict, sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, true);
-  EXPECT_EQ(result.tag.gap, false);
-
-  for (std::string x : {"NO", "Y", "TRUE", "1", "yes"}) {
-    result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,INDEPENDENT=" + x,
-                              variable_dict, sub_buffer);
-    EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-    EXPECT_EQ(result.tag.duration, base::Seconds(1));
-    EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-    EXPECT_EQ(result.tag.independent, false);
-    EXPECT_EQ(result.tag.gap, false);
-  }
-
-  // Test the GAP attribute
-  result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,GAP=YES", variable_dict,
-                            sub_buffer);
-  EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-  EXPECT_EQ(result.tag.duration, base::Seconds(1));
-  EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-  EXPECT_EQ(result.tag.independent, false);
-  EXPECT_EQ(result.tag.gap, true);
-
-  for (std::string x : {"NO", "Y", "TRUE", "1", "yes"}) {
-    result = OkTest<XPartTag>("URI=\"foo.ts\",DURATION=1,GAP=" + x,
-                              variable_dict, sub_buffer);
-    EXPECT_EQ(result.tag.uri.Str(), "foo.ts");
-    EXPECT_EQ(result.tag.duration, base::Seconds(1));
-    EXPECT_EQ(result.tag.byte_range, absl::nullopt);
-    EXPECT_EQ(result.tag.independent, false);
-    EXPECT_EQ(result.tag.gap, false);
-  }
+  // Test max value
+  result = OkTest<XTargetDurationTag>(base::NumberToString(MaxSeconds()));
+  EXPECT_EQ(result.tag.duration, base::Seconds(MaxSeconds()));
+  ErrorTest<XTargetDurationTag>(base::NumberToString(MaxSeconds() + 1),
+                                ParseStatusCode::kValueOverflowsTimeDelta);
 }
 
 }  // namespace media::hls
diff --git a/media/gpu/android/direct_shared_image_video_provider.cc b/media/gpu/android/direct_shared_image_video_provider.cc
index 782bf3c..d391bce 100644
--- a/media/gpu/android/direct_shared_image_video_provider.cc
+++ b/media/gpu/android/direct_shared_image_video_provider.cc
@@ -213,7 +213,7 @@
   // Create a shared image.
   // TODO(vikassoni): This shared image need to be thread safe eventually for
   // webview to work with shared images.
-  auto shared_image = gpu::SharedImageVideo::Create(
+  auto shared_image = gpu::AndroidVideoImageBacking::Create(
       mailbox, coded_size, spec.color_space, kTopLeft_GrSurfaceOrigin,
       kPremul_SkAlphaType, std::move(image), std::move(shared_context),
       std::move(drdc_lock));
diff --git a/media/gpu/android/frame_info_helper.cc b/media/gpu/android/frame_info_helper.cc
index 95fc6834..95b9c26 100644
--- a/media/gpu/android/frame_info_helper.cc
+++ b/media/gpu/android/frame_info_helper.cc
@@ -103,7 +103,7 @@
           info.emplace();
           info->coded_size = coded_size;
           info->visible_rect = visible_rect;
-          info->ycbcr_info = gpu::SharedImageVideo::GetYcbcrInfo(
+          info->ycbcr_info = gpu::AndroidVideoImageBacking::GetYcbcrInfo(
               texture_owner.get(), vulkan_context_provider_);
         }
       }
diff --git a/media/gpu/chromeos/image_processor.h b/media/gpu/chromeos/image_processor.h
index 3bc34b6c..a8f4918 100644
--- a/media/gpu/chromeos/image_processor.h
+++ b/media/gpu/chromeos/image_processor.h
@@ -111,6 +111,15 @@
     return needs_linear_output_buffers_;
   }
 
+  // Returns true if the image processor supports buffers allocated
+  // incoherently. The MTK MDP3 image processor has coherency issues, but the
+  // Libyuv image processor benefits greatly from incoherent allocations.
+  // Defaults to false, since only Libyuv has been shown to support this feature
+  // so far.
+  bool SupportsIncoherentBufs() const {
+    return backend_ && backend_->supports_incoherent_buffers();
+  }
+
  protected:
   // Container for both FrameReadyCB and LegacyFrameReadyCB. With this class,
   // we could store both kind of callback in the same container.
diff --git a/media/gpu/chromeos/image_processor_backend.cc b/media/gpu/chromeos/image_processor_backend.cc
index 5bfa471..529ffb4 100644
--- a/media/gpu/chromeos/image_processor_backend.cc
+++ b/media/gpu/chromeos/image_processor_backend.cc
@@ -99,6 +99,10 @@
   return false;
 }
 
+bool ImageProcessorBackend::supports_incoherent_buffers() const {
+  return false;
+}
+
 }  // namespace media
 
 namespace std {
diff --git a/media/gpu/chromeos/image_processor_backend.h b/media/gpu/chromeos/image_processor_backend.h
index 8a57eee..80a20be 100644
--- a/media/gpu/chromeos/image_processor_backend.h
+++ b/media/gpu/chromeos/image_processor_backend.h
@@ -114,6 +114,8 @@
 
   virtual bool needs_linear_output_buffers() const;
 
+  virtual bool supports_incoherent_buffers() const;
+
  protected:
   friend struct std::default_delete<ImageProcessorBackend>;
 
diff --git a/media/gpu/chromeos/image_processor_with_pool.h b/media/gpu/chromeos/image_processor_with_pool.h
index 71475d43..e83de42 100644
--- a/media/gpu/chromeos/image_processor_with_pool.h
+++ b/media/gpu/chromeos/image_processor_with_pool.h
@@ -49,6 +49,13 @@
   // returned by |ready_cb|.
   void Reset();
 
+  // Returns true if the image processor supports buffers allocated
+  // incoherently. The MTK MDP3 image processor has coherency issues, but the
+  // Libyuv image processor benefits greatly from incoherent allocations.
+  bool SupportsIncoherentBufs() const {
+    return image_processor_ && image_processor_->SupportsIncoherentBufs();
+  }
+
  private:
   friend class VideoDecoderPipelineTest;
 
diff --git a/media/gpu/chromeos/libyuv_image_processor_backend.cc b/media/gpu/chromeos/libyuv_image_processor_backend.cc
index f73d66e..03e1e739 100644
--- a/media/gpu/chromeos/libyuv_image_processor_backend.cc
+++ b/media/gpu/chromeos/libyuv_image_processor_backend.cc
@@ -548,4 +548,8 @@
   return supported_formats;
 }
 
+bool LibYUVImageProcessorBackend::supports_incoherent_buffers() const {
+  return true;
+}
+
 }  // namespace media
diff --git a/media/gpu/chromeos/libyuv_image_processor_backend.h b/media/gpu/chromeos/libyuv_image_processor_backend.h
index 6a48cf5..df0b4411 100644
--- a/media/gpu/chromeos/libyuv_image_processor_backend.h
+++ b/media/gpu/chromeos/libyuv_image_processor_backend.h
@@ -49,6 +49,8 @@
 
   static std::vector<Fourcc> GetSupportedOutputFormats(Fourcc input_format);
 
+  bool supports_incoherent_buffers() const override;
+
  private:
   LibYUVImageProcessorBackend(
       std::unique_ptr<VideoFrameMapper> input_frame_mapper,
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc
index a3ac647..ec2f1c9f 100644
--- a/media/gpu/chromeos/video_decoder_pipeline.cc
+++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -861,6 +861,10 @@
   }
 
   image_processor_ = std::move(status_or_image_processor).value();
+
+  if (decoder_)
+    decoder_->SetDmaIncoherentV4L2(image_processor_->SupportsIncoherentBufs());
+
   // TODO(b/203240043): Currently, the modifier is not read by any callers of
   // this function. We can eventually provide it by making it available to fetch
   // through the |image_processor|.
diff --git a/media/gpu/chromeos/video_decoder_pipeline.h b/media/gpu/chromeos/video_decoder_pipeline.h
index 24588db..c432be2 100644
--- a/media/gpu/chromeos/video_decoder_pipeline.h
+++ b/media/gpu/chromeos/video_decoder_pipeline.h
@@ -115,6 +115,10 @@
   // AMD). Default implementation returns false.
   virtual bool NeedsTranscryption();
 
+  // Set the DMA coherency of the video decoder buffers. Only relevant for
+  // V4L2.
+  virtual void SetDmaIncoherentV4L2(bool incoherent) {}
+
  protected:
   const std::unique_ptr<MediaLog> media_log_;
 
diff --git a/media/gpu/mac/vt_video_decode_accelerator_mac.cc b/media/gpu/mac/vt_video_decode_accelerator_mac.cc
index 702cb3d..e2f355ef 100644
--- a/media/gpu/mac/vt_video_decode_accelerator_mac.cc
+++ b/media/gpu/mac/vt_video_decode_accelerator_mac.cc
@@ -2140,7 +2140,7 @@
           gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
       gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage();
 
-      gpu::SharedImageBackingGLCommon::InitializeGLTextureParams gl_params;
+      gpu::GLTextureImageBackingHelper::InitializeGLTextureParams gl_params;
       // ANGLE-on-Metal exposes IOSurfaces via GL_TEXTURE_2D. Be robust to that.
       gl_params.target = gl_client_.supports_arb_texture_rectangle
                              ? GL_TEXTURE_RECTANGLE_ARB
@@ -2149,7 +2149,7 @@
       gl_params.format = gl_format;
       gl_params.type = GL_UNSIGNED_BYTE;
       gl_params.is_cleared = true;
-      gpu::SharedImageBackingGLCommon::UnpackStateAttribs gl_attribs;
+      gpu::GLTextureImageBackingHelper::UnpackStateAttribs gl_attribs;
 
       // Making the GL context current before performing below shared image
       // tasks.
@@ -2160,7 +2160,7 @@
         return false;
       }
 
-      auto shared_image = std::make_unique<gpu::SharedImageBackingGLImage>(
+      auto shared_image = std::make_unique<gpu::GLImageBacking>(
           gl_image, mailbox, viz_resource_format, plane_size, color_space,
           kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, shared_image_usage,
           gl_params, gl_attribs, gl_client_.is_passthrough);
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
index d205262..d24013d 100644
--- a/media/gpu/v4l2/v4l2_device.cc
+++ b/media/gpu/v4l2/v4l2_device.cc
@@ -1107,11 +1107,15 @@
   return absl::nullopt;
 }
 
-size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
+size_t V4L2Queue::AllocateBuffers(size_t count,
+                                  enum v4l2_memory memory,
+                                  bool incoherent) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!free_buffers_);
   DCHECK(queued_buffers_.empty());
 
+  incoherent_ = incoherent;
+
   if (IsStreaming()) {
     VQLOGF(1) << "Cannot allocate buffers while streaming.";
     return 0;
@@ -1142,7 +1146,9 @@
   reqbufs.count = count;
   reqbufs.type = type_;
   reqbufs.memory = memory;
+  reqbufs.flags = incoherent ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
   DVQLOGF(3) << "Requesting " << count << " buffers.";
+  DVQLOGF(3) << "Incoherent flag is " << incoherent << ".";
 
   int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
   if (ret) {
@@ -1200,6 +1206,7 @@
   reqbufs.count = 0;
   reqbufs.type = type_;
   reqbufs.memory = memory_;
+  reqbufs.flags = incoherent_ ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
 
   int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
   if (ret) {
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h
index 339c80d..740667eb 100644
--- a/media/gpu/v4l2/v4l2_device.h
+++ b/media/gpu/v4l2/v4l2_device.h
@@ -350,11 +350,19 @@
   // or zero if an error occurred, or if references to any previously allocated
   // buffers are still held by any clients.
   //
+  // Setting the |incoherent| flag will allocate the buffers with the
+  // V4L2_MEMORY_FLAG_NON_COHERENT flag set. This allows caching, which is a
+  // potential performance improvement when reading from CPU, but may not be
+  // safe for all V4L2 hardware. In particular, the MDP won't work with
+  // incoherent memory.
+  //
   // The number of allocated buffers may be larger than the number requested, so
   // callers must always check the return value.
   //
   // Calling this method while buffers are still allocated results in an error.
-  [[nodiscard]] size_t AllocateBuffers(size_t count, enum v4l2_memory memory);
+  [[nodiscard]] size_t AllocateBuffers(size_t count,
+                                       enum v4l2_memory memory,
+                                       bool incoherent);
 
   // Deallocate all buffers previously allocated by |AllocateBuffers|. Any
   // references to buffers previously allocated held by the client must be
@@ -485,6 +493,8 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<V4L2Queue> weak_this_factory_;
+
+  bool incoherent_ = false;
 };
 
 class V4L2Request;
diff --git a/media/gpu/v4l2/v4l2_image_processor_backend.cc b/media/gpu/v4l2/v4l2_image_processor_backend.cc
index 3dbd184..b90b1c9 100644
--- a/media/gpu/v4l2/v4l2_image_processor_backend.cc
+++ b/media/gpu/v4l2/v4l2_image_processor_backend.cc
@@ -90,7 +90,9 @@
   if (memory_type == V4L2_MEMORY_DMABUF)
     requested_buffers = VIDEO_MAX_FRAME;
 
-  if (queue->AllocateBuffers(requested_buffers, memory_type) == 0u)
+  // Note that MDP does not support incoherent buffer allocations.
+  if (queue->AllocateBuffers(requested_buffers, memory_type,
+                             /*incoherent=*/false) == 0u)
     return false;
 
   if (queue->AllocatedBuffersCount() < num_buffers) {
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
index 9e40a53..d788c39 100644
--- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -655,8 +655,8 @@
   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
   DCHECK(!input_queue_->IsStreaming());
 
-  if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP) <
-      kNumInputBuffers) {
+  if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP,
+                                    /*incoherent=*/false) < kNumInputBuffers) {
     LOG(ERROR) << "Failed AllocateBuffers";
     NOTIFY_ERROR(PLATFORM_FAILURE);
     return false;
@@ -1387,8 +1387,8 @@
       (image_processor_device_ || output_mode_ == Config::OutputMode::ALLOCATE
            ? V4L2_MEMORY_MMAP
            : V4L2_MEMORY_DMABUF);
-  if (output_queue_->AllocateBuffers(buffers.size(), memory) !=
-      buffers.size()) {
+  if (output_queue_->AllocateBuffers(buffers.size(), memory,
+                                     /*incoherent=*/false) != buffers.size()) {
     LOG(ERROR) << "Could not allocate enough output buffers";
     NOTIFY_ERROR(PLATFORM_FAILURE);
     return;
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
index 656e52b..c54c735 100644
--- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -417,7 +417,8 @@
   else
     memory = V4L2_MEMORY_MMAP;
 
-  if (output_queue_->AllocateBuffers(buffers.size(), memory) == 0) {
+  if (output_queue_->AllocateBuffers(buffers.size(), memory,
+                                     /*incoherent=*/false) == 0) {
     LOG(ERROR) << "Failed to request buffers!";
     NOTIFY_ERROR(PLATFORM_FAILURE);
     return;
@@ -2226,7 +2227,8 @@
   DCHECK_EQ(decoder_state_, kInitialized);
   DCHECK(input_queue_);
 
-  if (input_queue_->AllocateBuffers(kInputBufferCount, V4L2_MEMORY_MMAP) == 0) {
+  if (input_queue_->AllocateBuffers(kInputBufferCount, V4L2_MEMORY_MMAP,
+                                    /*incoherent=*/false) == 0) {
     LOG(ERROR) << "Failed allocating input buffers";
     NOTIFY_ERROR(PLATFORM_FAILURE);
     return false;
diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc
index 3f0b0fd..ac21ea7 100644
--- a/media/gpu/v4l2/v4l2_video_decoder.cc
+++ b/media/gpu/v4l2/v4l2_video_decoder.cc
@@ -341,7 +341,8 @@
     return V4L2Status::Codes::kBadFormat;
   }
 
-  if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP) == 0) {
+  if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP,
+                                    incoherent_) == 0) {
     VLOGF(1) << "Failed to allocate input buffer.";
     return V4L2Status::Codes::kFailedResourceAllocation;
   }
@@ -736,7 +737,8 @@
   const size_t v4l2_num_buffers =
       (type == V4L2_MEMORY_DMABUF) ? VIDEO_MAX_FRAME : num_output_frames_;
 
-  if (output_queue_->AllocateBuffers(v4l2_num_buffers, type) == 0) {
+  if (output_queue_->AllocateBuffers(v4l2_num_buffers, type, incoherent_) ==
+      0) {
     VLOGF(1) << "Failed to request output buffers.";
     SetState(State::kError);
     return CroStatus::Codes::kFailedToChangeResolution;
@@ -853,6 +855,10 @@
   return client_->GetVideoFramePool();
 }
 
+void V4L2VideoDecoder::SetDmaIncoherentV4L2(bool incoherent) {
+  incoherent_ = incoherent;
+}
+
 void V4L2VideoDecoder::SetState(State new_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
   DVLOGF(3) << "Change state from " << static_cast<int>(state_) << " to "
diff --git a/media/gpu/v4l2/v4l2_video_decoder.h b/media/gpu/v4l2/v4l2_video_decoder.h
index c51b11c6f..14ccc06f 100644
--- a/media/gpu/v4l2/v4l2_video_decoder.h
+++ b/media/gpu/v4l2/v4l2_video_decoder.h
@@ -84,6 +84,8 @@
                    base::TimeDelta timestamp) override;
   DmabufVideoFramePool* GetVideoFramePool() const override;
 
+  void SetDmaIncoherentV4L2(bool incoherent) override;
+
  private:
   friend class V4L2VideoDecoderTest;
 
@@ -215,6 +217,10 @@
   // |decoder_task_runner_|.
   base::WeakPtr<V4L2VideoDecoder> weak_this_for_polling_;
   base::WeakPtrFactory<V4L2VideoDecoder> weak_this_for_polling_factory_;
+
+  // Whether or not our V4L2Queues should be requested with
+  // V4L2_MEMORY_FLAG_NON_COHERENT
+  bool incoherent_ = false;
 };
 
 }  // namespace media
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 3d28ebb..8b6f57b 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -1936,8 +1936,8 @@
       break;
   }
 
-  if (input_queue_->AllocateBuffers(num_buffers, input_memory_type_) <
-      kInputBufferCount) {
+  if (input_queue_->AllocateBuffers(num_buffers, input_memory_type_,
+                                    /*incoherent=*/false) < kInputBufferCount) {
     VLOGF(1) << "Failed to allocate V4L2 input buffers.";
     return false;
   }
@@ -1952,7 +1952,8 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
   DCHECK(!output_queue_->IsStreaming());
 
-  if (output_queue_->AllocateBuffers(kOutputBufferCount, V4L2_MEMORY_MMAP) <
+  if (output_queue_->AllocateBuffers(kOutputBufferCount, V4L2_MEMORY_MMAP,
+                                     /*incoherent=*/false) <
       kOutputBufferCount) {
     VLOGF(1) << "Failed to allocate V4L2 output buffers.";
     return false;
diff --git a/media/gpu/windows/d3d11_texture_wrapper.cc b/media/gpu/windows/d3d11_texture_wrapper.cc
index ed5d320..09366552 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -242,10 +242,9 @@
     }
   }
 
-  auto shared_image_backings =
-      gpu::SharedImageBackingD3D::CreateFromVideoTexture(
-          mailboxes, dxgi_format, size, usage, texture, array_slice,
-          std::move(dxgi_shared_handle_state));
+  auto shared_image_backings = gpu::D3DImageBacking::CreateFromVideoTexture(
+      mailboxes, dxgi_format, size, usage, texture, array_slice,
+      std::move(dxgi_shared_handle_state));
   if (shared_image_backings.empty()) {
     std::move(on_error_cb)
         .Run(std::move(D3D11Status::Codes::kCreateSharedImageFailed));
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index ee94c69..8e0d6cf 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -3254,14 +3254,14 @@
     gl::GLImageDXGI* gl_image_dxgi =
         gl::GLImageDXGI::FromGLImage(picture_buffer->gl_image().get());
     if (gl_image_dxgi) {
-      shared_image = gpu::SharedImageBackingD3D::CreateFromGLTexture(
+      shared_image = gpu::D3DImageBacking::CreateFromGLTexture(
           mailbox, viz_formats[texture_idx],
           picture_buffer->texture_size(texture_idx),
           picture_buffer->color_space(), kTopLeft_GrSurfaceOrigin,
           kPremul_SkAlphaType, shared_image_usage, gl_image_dxgi->texture(),
           std::move(gl_texture));
     } else {
-      shared_image = gpu::SharedImageBackingGLImage::CreateFromGLTexture(
+      shared_image = gpu::GLImageBacking::CreateFromGLTexture(
           picture_buffer->gl_image(), mailbox, viz_formats[texture_idx],
           picture_buffer->size(), picture_buffer->color_space(),
           kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, shared_image_usage,
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.h b/media/gpu/windows/dxva_video_decode_accelerator_win.h
index 3f8c140..8ca4d60 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.h
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -382,8 +382,8 @@
   void DisableSharedTextureSupport();
 
   // Creates ScopedSharedImages for the provided PictureBuffer. If the buffer
-  // has a GLImageDXGI this function will create SharedImageBackingD3D using the
-  // DX11 texture. Otherwise it will create thin SharedImageBackingGLImage
+  // has a GLImageDXGI this function will create D3DImageBacking using the
+  // DX11 texture. Otherwise it will create thin GLImageBacking
   // wrappers around the existing textures in |picture_buffer|.
   std::vector<scoped_refptr<Picture::ScopedSharedImage>>
   GetSharedImagesFromPictureBuffer(DXVAPictureBuffer* picture_buffer);
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index 7605b0e3..4bb99ac 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -31,7 +31,6 @@
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/gpu/raster_context_provider.h"
 #include "components/viz/common/quads/compositor_render_pass.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
@@ -52,6 +51,7 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/skia_conversions.h"
+#include "ui/gfx/video_types.h"
 #include "ui/gl/gl_enums.h"
 #include "ui/gl/trace_util.h"
 
@@ -663,7 +663,8 @@
     }
     case VideoFrameResourceType::RGBA:
     case VideoFrameResourceType::RGBA_PREMULTIPLIED:
-    case VideoFrameResourceType::RGB: {
+    case VideoFrameResourceType::RGB:
+    case VideoFrameResourceType::STREAM_TEXTURE: {
       DCHECK_EQ(frame_resources_.size(), 1u);
       if (frame_resources_.size() < 1u)
         break;
@@ -683,6 +684,10 @@
                            SkColors::kTransparent, opacity, flipped,
                            nearest_neighbor, false, protected_video_type);
       texture_quad->set_resource_size_in_pixels(coded_size);
+      // Set the is_stream_video flag for STREAM_TEXTURE. Is used downstream
+      // (e.g. *_layer_overlay.cc).
+      texture_quad->is_stream_video =
+          frame_resource_type_ == VideoFrameResourceType::STREAM_TEXTURE;
       texture_quad->is_video_frame = true;
       texture_quad->hdr_metadata = frame->hdr_metadata();
       for (viz::ResourceId resource_id : texture_quad->resources) {
@@ -691,21 +696,6 @@
 
       break;
     }
-    case VideoFrameResourceType::STREAM_TEXTURE: {
-      DCHECK_EQ(frame_resources_.size(), 1u);
-      if (frame_resources_.size() < 1u)
-        break;
-      auto* stream_video_quad =
-          render_pass->CreateAndAppendDrawQuad<viz::StreamVideoDrawQuad>();
-      stream_video_quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect,
-                                needs_blending, frame_resources_[0].id,
-                                frame_resources_[0].size_in_pixels, uv_top_left,
-                                uv_bottom_right);
-      for (viz::ResourceId resource_id : stream_video_quad->resources) {
-        resource_provider_->ValidateResource(resource_id);
-      }
-      break;
-    }
     case VideoFrameResourceType::NONE:
       NOTIMPLEMENTED();
       break;
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 481a043..d899d10 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -1245,7 +1245,7 @@
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
       // TODO(crbug.com/1241537): Always add the flag once the
-      // SharedImageBackingOzone is by default turned on.
+      // OzoneImageBacking is by default turned on.
       if (base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kEnableUnsafeWebGPU)) {
         usage |= gpu::SHARED_IMAGE_USAGE_WEBGPU;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index b3caf9a3..a984853 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1172,6 +1172,8 @@
 
   if (is_linux || is_chromeos_lacros) {
     sources += [
+      # TODO(crbug.com/1331211): Remove network_change_notifier_linux for Lacros
+      # when BindNertworkChangeManager is supported by default.
       "base/network_change_notifier_linux.cc",
       "base/network_change_notifier_linux.h",
       "proxy_resolution/proxy_config_service_linux.cc",
@@ -1321,7 +1323,7 @@
     }
   }
 
-  if (is_android || is_chromeos_ash) {
+  if (is_android || is_chromeos) {
     sources += [
       "base/network_change_notifier_posix.cc",
       "base/network_change_notifier_posix.h",
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 7842adf..2ecf535 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -33,13 +33,11 @@
 
 #if BUILDFLAG(IS_WIN)
 #include "net/base/network_change_notifier_win.h"
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#elif BUILDFLAG(IS_LINUX)
 #include "net/base/network_change_notifier_linux.h"
 #elif BUILDFLAG(IS_APPLE)
 #include "net/base/network_change_notifier_mac.h"
-#elif BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
+#elif BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
 #include "net/base/network_change_notifier_posix.h"
 #elif BUILDFLAG(IS_FUCHSIA)
 #include "net/base/network_change_notifier_fuchsia.h"
@@ -320,10 +318,10 @@
   // service in a separate process.
   return std::make_unique<NetworkChangeNotifierPosix>(initial_type,
                                                       initial_subtype);
-#elif BUILDFLAG(IS_CHROMEOS_ASH)
+#elif BUILDFLAG(IS_CHROMEOS)
   return std::make_unique<NetworkChangeNotifierPosix>(initial_type,
                                                       initial_subtype);
-#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#elif BUILDFLAG(IS_LINUX)
   return std::make_unique<NetworkChangeNotifierLinux>(
       std::unordered_set<std::string>());
 #elif BUILDFLAG(IS_APPLE)
diff --git a/net/base/network_change_notifier_posix.cc b/net/base/network_change_notifier_posix.cc
index 7718c570..6bc215c 100644
--- a/net/base/network_change_notifier_posix.cc
+++ b/net/base/network_change_notifier_posix.cc
@@ -92,7 +92,7 @@
 NetworkChangeNotifier::NetworkChangeCalculatorParams
 NetworkChangeNotifierPosix::NetworkChangeCalculatorParamsPosix() {
   NetworkChangeCalculatorParams params;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // Delay values arrived at by simple experimentation and adjusted so as to
   // produce a single signal when switching between network connections.
   params.ip_address_offline_delay_ = base::Milliseconds(4000);
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc
index 5b3c22a..aed8dbf 100644
--- a/net/http/http_stream_factory_job.cc
+++ b/net/http/http_stream_factory_job.cc
@@ -335,6 +335,18 @@
       require_dns_https_alpn, destination_);
 }
 
+bool HttpStreamFactory::Job::TargettedSocketGroupHasActiveSocket() const {
+  DCHECK(!using_quic_);
+  DCHECK(!is_websocket_);
+  ClientSocketPool* pool = session_->GetSocketPool(
+      HttpNetworkSession::NORMAL_SOCKET_POOL, proxy_info_.proxy_server());
+  DCHECK(pool);
+  ClientSocketPool::GroupId connection_group(
+      destination_, request_info_.privacy_mode,
+      request_info_.network_isolation_key, request_info_.secure_dns_policy);
+  return pool->HasActiveSocket(connection_group);
+}
+
 bool HttpStreamFactory::Job::was_alpn_negotiated() const {
   return was_alpn_negotiated_;
 }
diff --git a/net/http/http_stream_factory_job.h b/net/http/http_stream_factory_job.h
index 6ec50d0..c5a47f9 100644
--- a/net/http/http_stream_factory_job.h
+++ b/net/http/http_stream_factory_job.h
@@ -199,6 +199,10 @@
   // QUIC session.
   bool HasAvailableQuicSession() const;
 
+  // Returns true if a connected (idle or handed out) or connecting socket
+  // exists for the job. This method is not supported for WebSocket and QUIC.
+  bool TargettedSocketGroupHasActiveSocket() const;
+
   const GURL& origin_url() const { return origin_url_; }
   RequestPriority priority() const { return priority_; }
   bool was_alpn_negotiated() const;
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc
index 748fd87..41a36d4 100644
--- a/net/http/http_stream_factory_job_controller.cc
+++ b/net/http/http_stream_factory_job_controller.cc
@@ -909,18 +909,13 @@
 
   ClearInappropriateJobs();
 
-  if (alternative_job_ || dns_alpn_h3_job_) {
-    // TODO(crbug.com/1317943): Consider not to block the main job when an
-    // active session is available for the main job and |alternative_job_|
-    // doesn't exists and |dns_alpn_h3_job_| exists. This may make the fallback
-    // logic faster when QUIC connection is unstable on the network. But we need
-    // to support DNS alpn job for preconnect before doing so. Currently
-    // preconnect job is triggered for all navigations by
-    // features::kNavigationRequestPreconnect. And the preconnect job doesn't
-    // support DNS HTTPS alpn and establishes non-HTTP/3 connection for the
-    // first connection. So when this method is called after the preconnect
-    // request, an active session may be available for the main job, and the
-    // DNS alpn job may be unintentionally disturbed.
+  if (main_job_ && (alternative_job_ ||
+                    (dns_alpn_h3_job_ &&
+                     (!main_job_->TargettedSocketGroupHasActiveSocket() &&
+                      !main_job_->HasAvailableSpdySession())))) {
+    // We don't block |main_job_| when |alternative_job_| doesn't exists and
+    // |dns_alpn_h3_job_| exists and an active socket is available for
+    // |main_job_|. This is intended to make the fallback logic faster.
     main_job_is_blocked_ = true;
   }
 
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc
index d9c3950..a6601095 100644
--- a/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -250,6 +250,8 @@
       quic_data2_->AddSocketDataToFactory(session_deps_.socket_factory.get());
     if (tcp_data_)
       session_deps_.socket_factory->AddSocketDataProvider(tcp_data_.get());
+    if (tcp_data2_)
+      session_deps_.socket_factory->AddSocketDataProvider(tcp_data2_.get());
 
     session_deps_.proxy_resolution_service->SetProxyDelegate(
         test_proxy_delegate_.get());
@@ -300,6 +302,10 @@
       EXPECT_TRUE(tcp_data_->AllReadDataConsumed());
       EXPECT_TRUE(tcp_data_->AllWriteDataConsumed());
     }
+    if (tcp_data2_) {
+      EXPECT_TRUE(tcp_data2_->AllReadDataConsumed());
+      EXPECT_TRUE(tcp_data2_->AllWriteDataConsumed());
+    }
   }
 
   void SetAlternativeService(const HttpRequestInfo& request_info,
@@ -366,6 +372,7 @@
   raw_ptr<HttpStreamFactory::JobController> job_controller_ = nullptr;
   std::unique_ptr<HttpStreamRequest> request_;
   std::unique_ptr<SequencedSocketData> tcp_data_;
+  std::unique_ptr<SequencedSocketData> tcp_data2_;
   std::unique_ptr<MockQuicData> quic_data_;
   std::unique_ptr<MockQuicData> quic_data2_;
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
@@ -3010,11 +3017,6 @@
             NetLogWithSource(), HttpStreamRequest::HTTP_STREAM,
             DEFAULT_PRIORITY);
 
-    if (dns_https_alpn_enabled()) {
-      EXPECT_CALL(*job_factory_.main_job(), Resume())
-          .Times(1)
-          .WillOnce([this]() { job_factory_.main_job()->DoResume(); });
-    }
     base::RunLoop run_loop;
     EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _, _))
         .WillOnce([&run_loop]() { run_loop.Quit(); });
@@ -3888,73 +3890,44 @@
   }
 
   void CreateJobController(const HttpRequestInfo& request_info) {
-    auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
-        factory_, &request_delegate_, session_.get(), &default_job_factory_,
-        request_info, is_preconnect_, false /* is_websocket */,
-        enable_ip_based_pooling_, enable_alternative_services_,
-        delay_main_job_with_available_spdy_session_, SSLConfig(), SSLConfig());
-    job_controller_ = job_controller.get();
-    HttpStreamFactoryPeer::AddJobController(factory_,
-                                            std::move(job_controller));
+    CreateJobControllerImpl(&job_controller_, &request_delegate_, request_info);
   }
 
   std::unique_ptr<HttpStreamRequest> CreateJobControllerAndStart(
       const HttpRequestInfo& request_info) {
-    CreateJobController(request_info);
-    return job_controller_->Start(
-        &request_delegate_, nullptr, net_log_with_source_,
-        HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+    return CreateJobControllerAndStartImpl(&job_controller_, &request_delegate_,
+                                           request_info);
   }
 
-  void PrepareForMainJob() {
-    tcp_data_ = std::make_unique<SequencedSocketData>();
-    tcp_data_->set_connect_data(MockConnect(ASYNC, ERR_IO_PENDING)); /* pause */
-    ssl_data_ = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
-    session_deps_.socket_factory->AddSSLSocketDataProvider(ssl_data_.get());
+  std::unique_ptr<HttpStreamRequest> CreateSecondJobControllerAndStart(
+      const HttpRequestInfo& request_info) {
+    return CreateJobControllerAndStartImpl(&job_controller2_,
+                                           &request_delegate2_, request_info);
   }
 
-  void PrepareForFirstQuicJob() {
-    crypto_client_stream_factory_.set_handshake_mode(
-        MockCryptoClientStream::COLD_START);
-    quic_data_ = std::make_unique<MockQuicData>(version_);
-    quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    if (version_.UsesHttp3()) {
-      quic_data_->AddWrite(
-          SYNCHRONOUS,
-          CreateQuicTestPacketMakerForClient().MakeInitialSettingsPacket(1));
-    }
+  void PrepareForMainJob() { PrepareForMainJobImpl(&tcp_data_, &ssl_data_); }
+  void PrepareForSecondMainJob() {
+    PrepareForMainJobImpl(&tcp_data2_, &ssl_data2_);
   }
+
+  void PrepareForFirstQuicJob() { PrepareForQuicJobImpl(&quic_data_); }
+  void PrepareForSecondQuicJob() { PrepareForQuicJobImpl(&quic_data2_); }
+
   void PrepareForFirstQuicJobFailure() {
-    crypto_client_stream_factory_.set_handshake_mode(
-        MockCryptoClientStream::COLD_START);
-    quic_data_ = std::make_unique<MockQuicData>(version_);
-    quic_data_->AddRead(ASYNC, ERR_IO_PENDING);  // Pause
-    quic_data_->AddRead(ASYNC, ERR_FAILED);
+    PrepareForQuicJobFailureImpl(&quic_data_);
   }
-
-  void PrepareForSecondQuicJob() {
-    quic_data2_ = std::make_unique<MockQuicData>(version_);
-    quic_data2_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    if (version_.UsesHttp3()) {
-      quic_data2_->AddWrite(
-          SYNCHRONOUS,
-          CreateQuicTestPacketMakerForClient().MakeInitialSettingsPacket(1));
-    }
+  void PrepareForSecondQuicJobFailure() {
+    PrepareForQuicJobFailureImpl(&quic_data2_);
   }
 
   void MakeMainJobSucceed(bool expect_stream_ready) {
-    if (expect_stream_ready) {
-      base::RunLoop run_loop;
-      EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _))
-          .Times(1)
-          .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
-      tcp_data_->socket()->OnConnectComplete(MockConnect());
-      run_loop.Run();
-    } else {
-      EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)).Times(0);
-      tcp_data_->socket()->OnConnectComplete(MockConnect());
-      base::RunLoop().RunUntilIdle();
-    }
+    MakeMainJobSucceedImpl(request_delegate_, tcp_data_.get(),
+                           expect_stream_ready);
+  }
+
+  void MakeSecondMainJobSucceed(bool expect_stream_ready) {
+    MakeMainJobSucceedImpl(request_delegate2_, tcp_data2_.get(),
+                           expect_stream_ready);
   }
 
   void MakeQuicJobScceed(size_t index, bool expect_stream_ready) {
@@ -3981,10 +3954,18 @@
                        bool alternative_job_exists,
                        bool dns_alpn_h3_job_exists,
                        const std::string& scoped_trace_message = "") {
-    SCOPED_TRACE(scoped_trace_message);
-    EXPECT_EQ(main_job_exists, !!job_controller_->main_job());
-    EXPECT_EQ(alternative_job_exists, !!job_controller_->alternative_job());
-    EXPECT_EQ(dns_alpn_h3_job_exists, !!job_controller_->dns_alpn_h3_job());
+    CheckJobsStatusImpl(job_controller_.get(), main_job_exists,
+                        alternative_job_exists, dns_alpn_h3_job_exists,
+                        scoped_trace_message);
+  }
+
+  void CheckSecondJobsStatus(bool main_job_exists,
+                             bool alternative_job_exists,
+                             bool dns_alpn_h3_job_exists,
+                             const std::string& scoped_trace_message = "") {
+    CheckJobsStatusImpl(job_controller2_.get(), main_job_exists,
+                        alternative_job_exists, dns_alpn_h3_job_exists,
+                        scoped_trace_message);
   }
 
   std::unique_ptr<QuicHttpStream> ConnectQuicHttpStream(
@@ -4034,6 +4015,10 @@
         NetworkIsolationKey());
   }
 
+  raw_ptr<HttpStreamFactory::JobController> job_controller2_ = nullptr;
+
+  MockHttpStreamRequestDelegate request_delegate2_;
+
  private:
   QuicTestPacketMaker CreateQuicTestPacketMakerForClient() {
     return QuicTestPacketMaker(version_,
@@ -4043,12 +4028,94 @@
                                quic::Perspective::IS_CLIENT, false);
   }
 
+  void CreateJobControllerImpl(
+      raw_ptr<HttpStreamFactory::JobController>* job_controller,
+      MockHttpStreamRequestDelegate* request_delegate,
+      const HttpRequestInfo& request_info) {
+    auto controller = std::make_unique<HttpStreamFactory::JobController>(
+        factory_, request_delegate, session_.get(), &default_job_factory_,
+        request_info, is_preconnect_, false /* is_websocket */,
+        enable_ip_based_pooling_, enable_alternative_services_,
+        delay_main_job_with_available_spdy_session_, SSLConfig(), SSLConfig());
+    *job_controller = controller.get();
+    HttpStreamFactoryPeer::AddJobController(factory_, std::move(controller));
+  }
+
+  std::unique_ptr<HttpStreamRequest> CreateJobControllerAndStartImpl(
+      raw_ptr<HttpStreamFactory::JobController>* job_controller,
+      MockHttpStreamRequestDelegate* request_delegate,
+      const HttpRequestInfo& request_info) {
+    CreateJobControllerImpl(job_controller, request_delegate, request_info);
+    return (*job_controller)
+        ->Start(request_delegate, nullptr, net_log_with_source_,
+                HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+  }
+
+  void PrepareForMainJobImpl(std::unique_ptr<SequencedSocketData>* tcp_data,
+                             std::unique_ptr<SSLSocketDataProvider>* ssl_data) {
+    *tcp_data = std::make_unique<SequencedSocketData>();
+    (*tcp_data)->set_connect_data(
+        MockConnect(ASYNC, ERR_IO_PENDING)); /* pause */
+    (*ssl_data) = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
+    session_deps_.socket_factory->AddSSLSocketDataProvider(ssl_data->get());
+  }
+
+  void PrepareForQuicJobImpl(std::unique_ptr<MockQuicData>* quic_data) {
+    crypto_client_stream_factory_.set_handshake_mode(
+        MockCryptoClientStream::COLD_START);
+    *quic_data = std::make_unique<MockQuicData>(version_);
+    (*quic_data)->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+    if (version_.UsesHttp3()) {
+      (*quic_data)
+          ->AddWrite(SYNCHRONOUS, CreateQuicTestPacketMakerForClient()
+                                      .MakeInitialSettingsPacket(1));
+    }
+  }
+
+  void PrepareForQuicJobFailureImpl(std::unique_ptr<MockQuicData>* quic_data) {
+    crypto_client_stream_factory_.set_handshake_mode(
+        MockCryptoClientStream::COLD_START);
+    *quic_data = std::make_unique<MockQuicData>(version_);
+    (*quic_data)->AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+    (*quic_data)->AddRead(ASYNC, ERR_FAILED);
+  }
+
+  void MakeMainJobSucceedImpl(MockHttpStreamRequestDelegate& request_delegate,
+                              SequencedSocketData* tcp_data,
+                              bool expect_stream_ready) {
+    if (expect_stream_ready) {
+      base::RunLoop run_loop;
+      EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _, _))
+          .Times(1)
+          .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
+      tcp_data->socket()->OnConnectComplete(MockConnect());
+      run_loop.Run();
+    } else {
+      EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _, _)).Times(0);
+      tcp_data->socket()->OnConnectComplete(MockConnect());
+      base::RunLoop().RunUntilIdle();
+    }
+  }
+
+  static void CheckJobsStatusImpl(
+      HttpStreamFactory::JobController* job_controller,
+      bool main_job_exists,
+      bool alternative_job_exists,
+      bool dns_alpn_h3_job_exists,
+      const std::string& scoped_trace_message) {
+    SCOPED_TRACE(scoped_trace_message);
+    EXPECT_EQ(main_job_exists, !!job_controller->main_job());
+    EXPECT_EQ(alternative_job_exists, !!job_controller->alternative_job());
+    EXPECT_EQ(dns_alpn_h3_job_exists, !!job_controller->dns_alpn_h3_job());
+  }
+
   // Use real Jobs so that Job::Resume() is not mocked out. When main job is
   // resumed it will use mock socket data.
   HttpStreamFactory::JobFactory default_job_factory_;
 
   // Used for man job connection.
   std::unique_ptr<SSLSocketDataProvider> ssl_data_;
+  std::unique_ptr<SSLSocketDataProvider> ssl_data2_;
 };
 
 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
@@ -4333,6 +4400,13 @@
 
   Initialize(HttpRequestInfo());
 
+  // Set |is_quic_known_to_work_on_current_network| flag so that
+  // the delaying logic of main job would work when the main job is blocked.
+  // Note: In this test, we don't need this because the main job is not blocked.
+  // But we set here because we want to check that the main job is not blocked.
+  QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+  quic_stream_factory->set_is_quic_known_to_work_on_current_network(true);
+
   // Put a SpdySession in the pool.
   SpdySessionKey key(HostPortPair::FromURL(request_info.url),
                      ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
@@ -4347,6 +4421,9 @@
                   /*dns_alpn_h3_job_exists=*/true,
                   "Main job and DNS ALPN job must be created.");
 
+  // Main job must not be waiting because an active session is available.
+  EXPECT_FALSE(job_controller_->main_job()->is_waiting());
+
   base::HistogramTester histogram_tester;
   // Run the message loop to make |main_job| succeed and status will be
   // reported to Request.
@@ -4375,6 +4452,112 @@
   EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
 }
 
+TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest, MainJobHasActiveSocket) {
+  HttpRequestInfo request_info = CreateTestHttpRequestInfo();
+
+  PrepareForMainJob();
+  PrepareForSecondMainJob();
+
+  PrepareForFirstQuicJobFailure();
+  RegisterMockHttpsRecord();
+
+  Initialize(HttpRequestInfo());
+
+  // Set |is_quic_known_to_work_on_current_network| flag so that
+  // the delaying logic of main job would work when the main job is blocked.
+  QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+  quic_stream_factory->set_is_quic_known_to_work_on_current_network(true);
+
+  request_ = CreateJobControllerAndStart(request_info);
+  CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
+                  /*dns_alpn_h3_job_exists=*/true,
+                  "Main job and DNS ALPN job must be created.");
+
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(1));
+  EXPECT_FALSE(job_controller_->main_job()->is_waiting());
+
+  auto request2 = CreateSecondJobControllerAndStart(request_info);
+  CheckSecondJobsStatus(
+      /*main_job_exists=*/true, /*alternative_job_exists=*/false,
+      /*dns_alpn_h3_job_exists=*/true,
+      "Main job and DNS ALPN job must be created for the second request.");
+
+  // When an active socket is available for the main job, the main job should
+  // not be blocked.
+  EXPECT_FALSE(job_controller2_->main_job()->is_waiting());
+
+  quic_data_->Resume();
+  base::RunLoop().RunUntilIdle();
+
+  MakeMainJobSucceed(/*expect_stream_ready=*/true);
+  MakeSecondMainJobSucceed(/*expect_stream_ready=*/true);
+}
+
+TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
+       MainJobHasActiveSocketAltSvcRegistered) {
+  HttpRequestInfo request_info = CreateTestHttpRequestInfo();
+
+  PrepareForMainJob();
+  PrepareForSecondMainJob();
+
+  PrepareForFirstQuicJobFailure();
+  PrepareForSecondQuicJobFailure();
+
+  RegisterMockHttpsRecord();
+
+  Initialize(HttpRequestInfo());
+
+  // Set |is_quic_known_to_work_on_current_network| flag so that
+  // the delaying logic of main job would work when the main job is blocked.
+  QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+  quic_stream_factory->set_is_quic_known_to_work_on_current_network(true);
+
+  url::SchemeHostPort server(request_info.url);
+  AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
+  SetAlternativeService(request_info, alternative_service);
+
+  request_ = CreateJobControllerAndStart(request_info);
+  CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
+                  /*dns_alpn_h3_job_exists=*/true,
+                  "All types of jobs are created");
+
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(1));
+  EXPECT_FALSE(job_controller_->main_job()->is_waiting());
+
+  auto request2 = CreateSecondJobControllerAndStart(request_info);
+  CheckSecondJobsStatus(
+      /*main_job_exists=*/true, /*alternative_job_exists=*/true,
+      /*dns_alpn_h3_job_exists=*/true,
+      "All types of jobs must be created for the second request.");
+
+  // The main job should be waiting until kDefaultDelayMilliSecsForWaitingJob
+  // amount of time has passed, when an alternative service was registered,
+  // even when an active socket is available for the main job.
+  // This is intended to switch to QUIC from TCP for the first connection
+  // when the server supports Alt-Svc but doesn't support HTTP DNS records with
+  // alpn.
+  // Note: When QuicParams.delay_main_job_with_available_spdy_session is false,
+  // main job is not blocked.
+  EXPECT_TRUE(job_controller2_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
+  EXPECT_TRUE(job_controller2_->main_job()->is_waiting());
+  FastForwardBy(base::Milliseconds(1));
+  EXPECT_FALSE(job_controller2_->main_job()->is_waiting());
+
+  quic_data_->Resume();
+  quic_data2_->Resume();
+  base::RunLoop().RunUntilIdle();
+
+  MakeMainJobSucceed(/*expect_stream_ready=*/true);
+  MakeSecondMainJobSucceed(/*expect_stream_ready=*/true);
+}
+
 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
        ActiveSessionAvailableForAltSvcJob) {
   PrepareForMainJob();
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h
index fe34158..d91478a 100644
--- a/net/socket/client_socket_pool.h
+++ b/net/socket/client_socket_pool.h
@@ -329,6 +329,10 @@
   virtual base::Value GetInfoAsValue(const std::string& name,
                                      const std::string& type) const = 0;
 
+  // Returns whether a connected (idle or handed out) or connecting socket
+  // exists for the group. This method is not supported for WebSockets.
+  virtual bool HasActiveSocket(const GroupId& group_id) const = 0;
+
   // Returns the maximum amount of time to wait before retrying a connect.
   static const int kMaxConnectRetryIntervalMs = 250;
 
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc
index 9552997..39e6f110 100644
--- a/net/socket/transport_client_socket_pool.cc
+++ b/net/socket/transport_client_socket_pool.cc
@@ -744,6 +744,10 @@
   return base::Value(std::move(dict));
 }
 
+bool TransportClientSocketPool::HasActiveSocket(const GroupId& group_id) const {
+  return HasGroup(group_id);
+}
+
 bool TransportClientSocketPool::IdleSocket::IsUsable(
     const char** net_log_reason_utf8) const {
   DCHECK(net_log_reason_utf8);
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h
index e215025..724c8c0 100644
--- a/net/socket/transport_client_socket_pool.h
+++ b/net/socket/transport_client_socket_pool.h
@@ -224,6 +224,7 @@
                          const ClientSocketHandle* handle) const override;
   base::Value GetInfoAsValue(const std::string& name,
                              const std::string& type) const override;
+  bool HasActiveSocket(const GroupId& group_id) const override;
 
   bool RequestInGroupWithHandleHasJobForTesting(
       const GroupId& group_id,
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc
index 3a6e3e1..ab55ba4 100644
--- a/net/socket/transport_client_socket_pool_unittest.cc
+++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -2063,6 +2063,73 @@
             session_deps_.host_resolver->request_network_isolation_key(2));
 }
 
+TEST_F(TransportClientSocketPoolTest, HasActiveSocket) {
+  const url::SchemeHostPort kEndpoint1(url::kHttpScheme, "host1.test", 80);
+  const url::SchemeHostPort kEndpoint2(url::kHttpScheme, "host2.test", 80);
+
+  ClientSocketHandle handle;
+  ClientSocketPool::GroupId group_id1(
+      kEndpoint1, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+      SecureDnsPolicy::kAllow);
+  ClientSocketPool::GroupId group_id2(
+      kEndpoint2, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+      SecureDnsPolicy::kAllow);
+
+  // HasActiveSocket() must return false before creating a socket.
+  EXPECT_FALSE(pool_->HasActiveSocket(group_id1));
+
+  TestCompletionCallback callback1;
+  int rv1 =
+      handle.Init(group_id1, params_, absl::nullopt /* proxy_annotation_tag */,
+                  LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+                  callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  pool_.get(), NetLogWithSource());
+  EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
+
+  // HasActiveSocket() must return true while connecting.
+  EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
+  EXPECT_FALSE(handle.is_initialized());
+  EXPECT_FALSE(handle.socket());
+
+  EXPECT_THAT(callback1.WaitForResult(), IsOk());
+
+  // HasActiveSocket() must return true after handed out.
+  EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
+  EXPECT_TRUE(handle.is_initialized());
+  EXPECT_TRUE(handle.socket());
+
+  handle.Reset();
+
+  // HasActiveSocket returns true for the idle socket.
+  EXPECT_TRUE(pool_->HasActiveSocket(group_id1));
+  // Now we should have 1 idle socket.
+  EXPECT_EQ(1, pool_->IdleSocketCount());
+
+  // HasActiveSocket() for group_id2 must still return false.
+  EXPECT_FALSE(pool_->HasActiveSocket(group_id2));
+
+  TestCompletionCallback callback2;
+  int rv2 =
+      handle.Init(group_id2, params_, absl::nullopt /* proxy_annotation_tag */,
+                  LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+                  callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  pool_.get(), NetLogWithSource());
+  EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
+
+  // HasActiveSocket(group_id2) must return true while connecting.
+  EXPECT_TRUE(pool_->HasActiveSocket(group_id2));
+
+  // HasActiveSocket(group_id1) must still return true.
+  EXPECT_TRUE(pool_->HasActiveSocket(group_id2));
+
+  // Close the sockets.
+  pool_->FlushWithError(ERR_NETWORK_CHANGED, "Network changed");
+
+  // HasActiveSocket() must return false after closing the socket.
+  EXPECT_FALSE(pool_->HasActiveSocket(group_id1));
+  EXPECT_FALSE(pool_->HasActiveSocket(group_id2));
+}
+
 // Test that SocketTag passed into TransportClientSocketPool is applied to
 // returned sockets.
 #if BUILDFLAG(IS_ANDROID)
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc
index 4aebaf8b..78ee11d3 100644
--- a/net/socket/websocket_transport_client_socket_pool.cc
+++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -250,6 +250,13 @@
   return base::Value(std::move(dict));
 }
 
+bool WebSocketTransportClientSocketPool::HasActiveSocket(
+    const GroupId& group_id) const {
+  // This method is not supported for WebSocket.
+  NOTREACHED();
+  return false;
+}
+
 bool WebSocketTransportClientSocketPool::IsStalled() const {
   return !stalled_request_queue_.empty();
 }
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h
index 2f88e43f..64d2cc5c 100644
--- a/net/socket/websocket_transport_client_socket_pool.h
+++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -92,6 +92,7 @@
                          const ClientSocketHandle* handle) const override;
   base::Value GetInfoAsValue(const std::string& name,
                              const std::string& type) const override;
+  bool HasActiveSocket(const GroupId& group_id) const override;
 
   // HigherLayeredPool implementation.
   bool IsStalled() const override;
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index e4ab1f5..cefb7d1 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -90,6 +90,24 @@
 // Key that specifies the requested media width in microns.
 const char kSettingMediaSizeWidthMicrons[] = "width_microns";
 
+// Key that specifies the left side of the bounding box for the requested
+// media's printable area.
+const char kSettingsImageableAreaLeftMicrons[] = "imageable_area_left_microns";
+
+// Key that specifies the bottom side of the bounding box for the requested
+// media's printable area.
+const char kSettingsImageableAreaBottomMicrons[] =
+    "imageable_area_bottom_microns";
+
+// Key that specifies the right side of the bounding box for the requested
+// media's printable area.
+const char kSettingsImageableAreaRightMicrons[] =
+    "imageable_area_right_microns";
+
+// Key that specifies the top side of the bounding box for the requested
+// media's printable area.
+const char kSettingsImageableAreaTopMicrons[] = "imageable_area_top_microns";
+
 // Key that specifies the requested media platform specific vendor id.
 const char kSettingMediaSizeVendorId[] = "vendor_id";
 
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 941be88..857454e 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -59,6 +59,14 @@
 COMPONENT_EXPORT(PRINTING_BASE)
 extern const char kSettingMediaSizeWidthMicrons[];
 COMPONENT_EXPORT(PRINTING_BASE)
+extern const char kSettingsImageableAreaLeftMicrons[];
+COMPONENT_EXPORT(PRINTING_BASE)
+extern const char kSettingsImageableAreaBottomMicrons[];
+COMPONENT_EXPORT(PRINTING_BASE)
+extern const char kSettingsImageableAreaRightMicrons[];
+COMPONENT_EXPORT(PRINTING_BASE)
+extern const char kSettingsImageableAreaTopMicrons[];
+COMPONENT_EXPORT(PRINTING_BASE)
 extern const char kSettingMediaSizeVendorId[];
 COMPONENT_EXPORT(PRINTING_BASE)
 extern const char kSettingMediaSizeIsDefault[];
diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc
index 8bcf70df..285703016 100644
--- a/printing/print_settings_conversion.cc
+++ b/printing/print_settings_conversion.cc
@@ -24,6 +24,8 @@
 #include "printing/print_job_constants.h"
 #include "printing/print_settings.h"
 #include "printing/units.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace printing {
 
@@ -75,6 +77,43 @@
   job_settings.Set(json_path, std::move(dict));
 }
 
+void SetPrintableAreaIfValid(PrintSettings& settings,
+                             const gfx::Size& size_microns,
+                             const base::Value::Dict& media_size) {
+  absl::optional<int> left_microns =
+      media_size.FindInt(kSettingsImageableAreaLeftMicrons);
+  absl::optional<int> bottom_microns =
+      media_size.FindInt(kSettingsImageableAreaBottomMicrons);
+  absl::optional<int> right_microns =
+      media_size.FindInt(kSettingsImageableAreaRightMicrons);
+  absl::optional<int> top_microns =
+      media_size.FindInt(kSettingsImageableAreaTopMicrons);
+  if (!bottom_microns.has_value() || !left_microns.has_value() ||
+      !right_microns.has_value() || !top_microns.has_value()) {
+    return;
+  }
+
+  // Scale the page size and printable area to device units.
+  float x_scale =
+      static_cast<float>(settings.dpi_horizontal()) / kMicronsPerInch;
+  float y_scale = static_cast<float>(settings.dpi_vertical()) / kMicronsPerInch;
+  gfx::Size page_size = gfx::ScaleToRoundedSize(size_microns, x_scale, y_scale);
+  // Flip the y-axis since the imageable area origin is at the bottom-left,
+  // while the gfx::Rect origin is at the top-left.
+  gfx::Rect printable_area = gfx::ScaleToRoundedRect(
+      {left_microns.value(), size_microns.height() - top_microns.value(),
+       right_microns.value() - left_microns.value(),
+       top_microns.value() - bottom_microns.value()},
+      x_scale, y_scale);
+  // Sanity check that the printable area makes sense.
+  if (printable_area.IsEmpty() ||
+      !gfx::Rect(page_size).Contains(printable_area)) {
+    return;
+  }
+  settings.SetPrinterPrintableArea(page_size, printable_area,
+                                   /*landscape_needs_flip=*/true);
+}
+
 }  // namespace
 
 PageRanges GetPageRangesFromJobSettings(const base::Value::Dict& job_settings) {
@@ -184,6 +223,8 @@
     if (width_microns.has_value() && height_microns.has_value()) {
       requested_media.size_microns =
           gfx::Size(width_microns.value(), height_microns.value());
+      SetPrintableAreaIfValid(*settings, requested_media.size_microns,
+                              *media_size_value);
     }
 
     const std::string* vendor_id =
diff --git a/printing/print_settings_conversion_unittest.cc b/printing/print_settings_conversion_unittest.cc
index 6334d97..522cecc 100644
--- a/printing/print_settings_conversion_unittest.cc
+++ b/printing/print_settings_conversion_unittest.cc
@@ -48,6 +48,33 @@
   "pinValue": "0000"
 })";
 
+const char kPrinterSettingsWithImageableArea[] = R"({
+  "headerFooterEnabled": false,
+  "title": "Test Doc",
+  "url": "http://localhost/",
+  "shouldPrintBackgrounds": false,
+  "shouldPrintSelectionOnly": false,
+  "mediaSize": {
+    "height_microns": 297000,
+    "imageable_area_bottom_microns": 1000,
+    "imageable_area_left_microns": 0,
+    "imageable_area_right_microns": 180000,
+    "imageable_area_top_microns": 297000,
+    "width_microns": 210000
+  },
+  "collate": false,
+  "copies": 1,
+  "color": 2,
+  "duplex": 0,
+  "landscape": false,
+  "deviceName": "printer",
+  "scaleFactor": 100,
+  "rasterizePDF": false,
+  "pagesPerSheet": 1,
+  "dpiHorizontal": 300,
+  "dpiVertical": 300,
+})";
+
 }  // namespace
 
 TEST(PrintSettingsConversionTest, InvalidSettings) {
@@ -82,6 +109,59 @@
   EXPECT_FALSE(settings);
 }
 
+TEST(PrintSettingsConversionTest, ConversionTestWithValidImageableArea) {
+  base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
+  ASSERT_TRUE(value.is_dict());
+  auto& dict = value.GetDict();
+  std::unique_ptr<PrintSettings> settings = PrintSettingsFromJobSettings(dict);
+  ASSERT_TRUE(settings);
+  EXPECT_EQ(settings->dpi_horizontal(), 300);
+  EXPECT_EQ(settings->dpi_vertical(), 300);
+  EXPECT_EQ(settings->page_setup_device_units().physical_size(),
+            gfx::Size(2480, 3508));
+  EXPECT_EQ(settings->page_setup_device_units().printable_area(),
+            gfx::Rect(0, 0, 2126, 3496));
+}
+
+TEST(PrintSettingsConversionTest, ConversionTestWithValidFlippedImageableArea) {
+  base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
+  ASSERT_TRUE(value.is_dict());
+  auto& dict = value.GetDict();
+  dict.Set("landscape", true);
+  std::unique_ptr<PrintSettings> settings = PrintSettingsFromJobSettings(dict);
+  ASSERT_TRUE(settings);
+  EXPECT_EQ(settings->page_setup_device_units().physical_size(),
+            gfx::Size(3508, 2480));
+  EXPECT_EQ(settings->page_setup_device_units().printable_area(),
+            gfx::Rect(0, 354, 3496, 2126));
+}
+
+TEST(PrintSettingsConversionTest, ConversionTestWithOutOfBoundsImageableArea) {
+  base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
+  ASSERT_TRUE(value.is_dict());
+  auto& dict = value.GetDict();
+  auto* media_size_dict = dict.FindDict("mediaSize");
+  ASSERT_TRUE(media_size_dict);
+  media_size_dict->Set("imageable_area_left_microns", -500);
+  std::unique_ptr<PrintSettings> settings = PrintSettingsFromJobSettings(dict);
+  ASSERT_TRUE(settings);
+  EXPECT_TRUE(settings->page_setup_device_units().physical_size().IsEmpty());
+  EXPECT_TRUE(settings->page_setup_device_units().printable_area().IsEmpty());
+}
+
+TEST(PrintSettingsConversionTest, ConversionTestWithMissingImageableAreaValue) {
+  base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
+  ASSERT_TRUE(value.is_dict());
+  auto& dict = value.GetDict();
+  auto* media_size_dict = dict.FindDict("mediaSize");
+  ASSERT_TRUE(media_size_dict);
+  media_size_dict->Remove("imageable_area_left_microns");
+  std::unique_ptr<PrintSettings> settings = PrintSettingsFromJobSettings(dict);
+  ASSERT_TRUE(settings);
+  EXPECT_TRUE(settings->page_setup_device_units().physical_size().IsEmpty());
+  EXPECT_TRUE(settings->page_setup_device_units().printable_area().IsEmpty());
+}
+
 TEST(PrintSettingsConversionTest, MissingDeviceName) {
   base::Value value = base::test::ParseJson(kPrinterSettings);
   ASSERT_TRUE(value.is_dict());
diff --git a/printing/printing_context.cc b/printing/printing_context.cc
index c23742bb..6cca846 100644
--- a/printing/printing_context.cc
+++ b/printing/printing_context.cc
@@ -168,9 +168,13 @@
   if (!open_in_external_preview &&
       (printer_type == mojom::PrinterType::kPdf ||
        printer_type == mojom::PrinterType::kExtension)) {
-    SetDefaultPrintableAreaForVirtualPrinters();
+    if (settings_->page_setup_device_units().printable_area().IsEmpty())
+      SetDefaultPrintableAreaForVirtualPrinters();
     return mojom::ResultCode::kSuccess;
   }
+
+  // The `open_in_external_preview` case does not care about the printable area.
+  // Local printers set their printable area within UpdatePrinterSettings().
   DCHECK(open_in_external_preview ||
          printer_type == mojom::PrinterType::kLocal);
 
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index b03d612..9df9588 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -309,6 +309,7 @@
 
   if (is_linux || is_chromeos) {
     sources += [
+      "compute_pressure/core_times_unittest.cc",
       "compute_pressure/cpu_probe_linux_unittest.cc",
       "compute_pressure/procfs_stat_cpu_parser_unittest.cc",
     ]
diff --git a/services/device/compute_pressure/BUILD.gn b/services/device/compute_pressure/BUILD.gn
index f0ad9fe..31a42fc 100644
--- a/services/device/compute_pressure/BUILD.gn
+++ b/services/device/compute_pressure/BUILD.gn
@@ -26,6 +26,8 @@
 
   if (is_linux || is_chromeos) {
     sources += [
+      "core_times.cc",
+      "core_times.h",
       "cpu_probe_linux.cc",
       "cpu_probe_linux.h",
       "procfs_stat_cpu_parser.cc",
diff --git a/services/device/compute_pressure/core_times.cc b/services/device/compute_pressure/core_times.cc
new file mode 100644
index 0000000..3dd8c95
--- /dev/null
+++ b/services/device/compute_pressure/core_times.cc
@@ -0,0 +1,63 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/device/compute_pressure/core_times.h"
+
+namespace device {
+
+double CoreTimes::TimeUtilization(const CoreTimes& baseline) const {
+  // Each of the blocks below consists of a check and a subtraction. The check
+  // is used to bail on invalid input (/proc/stat counters should never
+  // decrease over time).
+  //
+  // The check is also essential for the correctness of the subtraction -- the
+  // result of the subtraction is stored in a temporary `uint64_t` before being
+  // accumulated in `active_delta`, and this intermediate result must not be
+  // negative.
+
+  if (user() < baseline.user())
+    return -1;
+  double active_delta = user() - baseline.user();
+
+  if (nice() < baseline.nice())
+    return -1;
+  active_delta += nice() - baseline.nice();
+
+  if (system() < baseline.system())
+    return -1;
+  active_delta += system() - baseline.system();
+
+  if (idle() < baseline.idle())
+    return -1;
+  uint64_t idle_delta = idle() - baseline.idle();
+
+  // iowait() is unreliable, according to the Linux kernel documentation at
+  // https://www.kernel.org/doc/Documentation/filesystems/proc.txt.
+
+  if (irq() < baseline.irq())
+    return -1;
+  active_delta += irq() - baseline.irq();
+
+  if (softirq() < baseline.softirq())
+    return -1;
+  active_delta += softirq() - baseline.softirq();
+
+  if (steal() < baseline.steal())
+    return -1;
+  active_delta += steal() - baseline.steal();
+
+  // guest() and guest_nice() are included in user(). Full analysis in
+  // https://unix.stackexchange.com/a/303224/
+
+  double total_delta = active_delta + idle_delta;
+  if (total_delta == 0) {
+    // The two snapshots represent the same point in time, so the time interval
+    // between the two snapshots is empty.
+    return -1;
+  }
+
+  return active_delta / total_delta;
+}
+
+}  // namespace device
diff --git a/services/device/compute_pressure/core_times.h b/services/device/compute_pressure/core_times.h
new file mode 100644
index 0000000..17afea5
--- /dev/null
+++ b/services/device/compute_pressure/core_times.h
@@ -0,0 +1,57 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_DEVICE_COMPUTE_PRESSURE_CORE_TIMES_H_
+#define SERVICES_DEVICE_COMPUTE_PRESSURE_CORE_TIMES_H_
+
+#include <stdint.h>
+
+namespace device {
+
+// CPU core utilization statistics.
+//
+// Linux:
+// Quantities are expressed in "user hertz", which is a Linux kernel
+// configuration knob (USER_HZ). Typical values range between 1/100 seconds
+// and 1/1000 seconds. The denominator can be obtained from
+// sysconf(_SC_CLK_TCK).
+//
+// Mac:
+// Quantities are expressed in "CPU Ticks", which is an arbitrary unit of time
+// recording how many intervals of time elapsed, typically 1/100 of a second.
+struct CoreTimes {
+  // Normal processes executing in user mode.
+  uint64_t user() const { return times[0]; }
+  // Niced processes executing in user mode.
+  uint64_t nice() const { return times[1]; }
+  // Processes executing in kernel mode.
+  uint64_t system() const { return times[2]; }
+  // Twiddling thumbs.
+  uint64_t idle() const { return times[3]; }
+  // Waiting for I/O to complete. Unreliable.
+  uint64_t iowait() const { return times[4]; }
+  // Servicing interrupts.
+  uint64_t irq() const { return times[5]; }
+  // Servicing softirqs.
+  uint64_t softirq() const { return times[6]; }
+  // Involuntary wait.
+  uint64_t steal() const { return times[7]; }
+  // Running a normal guest.
+  uint64_t guest() const { return times[8]; }
+  // Running a niced guest.
+  uint64_t guest_nice() const { return times[9]; }
+
+  uint64_t times[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+  // Computes a CPU's utilization over the time between two stat snapshots.
+  //
+  // Returns a value between 0.0 and 1.0 on success, and -1.0 when given
+  // invalid data, such as a `baseline` that does not represent a stat
+  // snapshot collected before `this` snapshot.
+  double TimeUtilization(const CoreTimes& baseline) const;
+};
+
+}  // namespace device
+
+#endif  // SERVICES_DEVICE_COMPUTE_PRESSURE_CORE_TIMES_H_
diff --git a/services/device/compute_pressure/core_times_unittest.cc b/services/device/compute_pressure/core_times_unittest.cc
new file mode 100644
index 0000000..abba05aa
--- /dev/null
+++ b/services/device/compute_pressure/core_times_unittest.cc
@@ -0,0 +1,115 @@
+
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/device/compute_pressure/core_times.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+using CoreTimesTest = testing::Test;
+
+TEST_F(CoreTimesTest, TimeUtilization_Balanced) {
+  CoreTimes baseline = {
+      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
+
+  std::vector<CoreTimes> test_cases = {
+      // Individual components get summed up correctly.
+      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 215, 305, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 205, 315, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 615, 705, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 605, 715, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 605, 705, 815, 905, 1005}},
+      // Ignored components are not added to the sum.
+      {.times = {115, 205, 305, 415, 595, 605, 705, 805, 905, 1005}},
+      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 995, 1005}},
+      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1095}},
+      // Negative changes in ignored components are not flagged.
+      {.times = {115, 205, 305, 415, 500, 605, 705, 805, 905, 1005}},
+      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 900, 1005}},
+      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1000}},
+  };
+
+  for (const CoreTimes& times : test_cases) {
+    SCOPED_TRACE(times.times);
+    EXPECT_EQ(0.5, times.TimeUtilization(baseline));
+  }
+}
+
+TEST_F(CoreTimesTest, TimeUtilization_EmptyRange) {
+  CoreTimes baseline = {
+      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
+
+  std::vector<CoreTimes> test_cases = {
+      // Identical times.
+      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}},
+      // Changes in ignored components.
+      {.times = {105, 205, 305, 405, 515, 605, 705, 805, 905, 1005}},
+      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 915, 1005}},
+      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1015}},
+  };
+
+  for (const CoreTimes& times : test_cases) {
+    SCOPED_TRACE(times.times);
+    EXPECT_EQ(-1, times.TimeUtilization(baseline));
+  }
+}
+
+TEST_F(CoreTimesTest, TimeUtilization_NegativeRange) {
+  CoreTimes baseline = {
+      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
+
+  std::vector<CoreTimes> test_cases = {
+      {.times = {100, 205, 305, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 200, 305, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 205, 300, 415, 505, 605, 705, 805, 905, 1005}},
+      {.times = {115, 205, 305, 400, 505, 605, 705, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 600, 705, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 605, 700, 805, 905, 1005}},
+      {.times = {105, 205, 305, 415, 505, 605, 705, 800, 905, 1005}},
+  };
+
+  for (const CoreTimes& times : test_cases) {
+    SCOPED_TRACE(times.times);
+    EXPECT_EQ(-1, times.TimeUtilization(baseline));
+  }
+}
+
+TEST_F(CoreTimesTest, TimeUtilization_Computation) {
+  CoreTimes baseline = {
+      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
+
+  struct TestCase {
+    CoreTimes times;
+    double utilization;
+  };
+
+  std::vector<TestCase> test_cases = {
+      // No idling.
+      {{.times = {115, 205, 305, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
+      {{.times = {115, 215, 305, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
+      {{.times = {115, 215, 315, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
+      {{.times = {115, 215, 315, 405, 505, 615, 705, 805, 905, 1005}}, 1.0},
+      {{.times = {115, 215, 315, 405, 505, 615, 715, 805, 905, 1005}}, 1.0},
+      {{.times = {115, 215, 315, 405, 505, 615, 715, 815, 905, 1005}}, 1.0},
+      // All idling.
+      {{.times = {105, 205, 305, 415, 505, 605, 705, 805, 905, 1005}}, 0.0},
+      // Fractions
+      {{.times = {115, 225, 305, 415, 505, 605, 705, 805, 905, 1005}}, 0.75},
+      {{.times = {115, 225, 345, 415, 505, 605, 705, 805, 905, 1005}}, 0.875},
+      {{.times = {115, 205, 305, 435, 505, 605, 705, 805, 905, 1005}}, 0.25},
+      {{.times = {115, 205, 305, 475, 505, 605, 705, 805, 905, 1005}}, 0.125},
+  };
+
+  for (const TestCase& test_case : test_cases) {
+    SCOPED_TRACE(test_case.times.times);
+    EXPECT_EQ(test_case.utilization, test_case.times.TimeUtilization(baseline));
+  }
+}
+
+}  // namespace device
diff --git a/services/device/compute_pressure/cpu_probe_linux.cc b/services/device/compute_pressure/cpu_probe_linux.cc
index 8202a1c..b0bae35f 100644
--- a/services/device/compute_pressure/cpu_probe_linux.cc
+++ b/services/device/compute_pressure/cpu_probe_linux.cc
@@ -40,15 +40,14 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   stat_parser_.Update();
-  const std::vector<ProcfsStatCpuParser::CoreTimes>& core_times =
-      stat_parser_.core_times();
+  const std::vector<CoreTimes>& core_times = stat_parser_.core_times();
 
   double utilization_sum = 0.0;
   int utilization_cores = 0;
   for (size_t i = 0; i < core_times.size(); ++i) {
     DCHECK_GE(last_core_times_.size(), i);
 
-    const ProcfsStatCpuParser::CoreTimes& current_core_times = core_times[i];
+    const CoreTimes& current_core_times = core_times[i];
 
     if (last_core_times_.size() == i) {
       InitializeCore(static_cast<int>(i), current_core_times);
@@ -79,9 +78,8 @@
   return last_sample_;
 }
 
-void CpuProbeLinux::InitializeCore(
-    int core_index,
-    const ProcfsStatCpuParser::CoreTimes& initial_core_times) {
+void CpuProbeLinux::InitializeCore(int core_index,
+                                   const CoreTimes& initial_core_times) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(core_index, 0);
   DCHECK_EQ(last_core_times_.size(), static_cast<size_t>(core_index));
diff --git a/services/device/compute_pressure/cpu_probe_linux.h b/services/device/compute_pressure/cpu_probe_linux.h
index 63db509..67485ae 100644
--- a/services/device/compute_pressure/cpu_probe_linux.h
+++ b/services/device/compute_pressure/cpu_probe_linux.h
@@ -13,6 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/sequence_checker.h"
 #include "base/thread_annotations.h"
+#include "services/device/compute_pressure/core_times.h"
 #include "services/device/compute_pressure/cpu_probe.h"
 #include "services/device/compute_pressure/pressure_sample.h"
 #include "services/device/compute_pressure/procfs_stat_cpu_parser.h"
@@ -44,8 +45,7 @@
   //
   // For most systems, the cores listed in /proc/stat are static. However, it is
   // theoretically possible for cores to go online and offline.
-  void InitializeCore(int core_index,
-                      const ProcfsStatCpuParser::CoreTimes& initial_core_times);
+  void InitializeCore(int core_index, const CoreTimes& initial_core_times);
 
   SEQUENCE_CHECKER(sequence_checker_);
 
@@ -53,8 +53,7 @@
   ProcfsStatCpuParser stat_parser_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   // Most recent per-core times from /proc/stat.
-  std::vector<ProcfsStatCpuParser::CoreTimes> last_core_times_
-      GUARDED_BY_CONTEXT(sequence_checker_);
+  std::vector<CoreTimes> last_core_times_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   PressureSample last_sample_ GUARDED_BY_CONTEXT(sequence_checker_);
 };
diff --git a/services/device/compute_pressure/procfs_stat_cpu_parser.cc b/services/device/compute_pressure/procfs_stat_cpu_parser.cc
index 76b2e03a..4043eef 100644
--- a/services/device/compute_pressure/procfs_stat_cpu_parser.cc
+++ b/services/device/compute_pressure/procfs_stat_cpu_parser.cc
@@ -20,61 +20,6 @@
 
 namespace device {
 
-double ProcfsStatCpuParser::CoreTimes::TimeUtilization(
-    const CoreTimes& baseline) const {
-  // Each of the blocks below consists of a check and a subtraction. The check
-  // is used to bail on invalid input (/proc/stat counters should never
-  // decrease over time).
-  //
-  // The check is also essential for the correctness of the subtraction -- the
-  // result of the subtraction is stored in a temporary `uint64_t` before being
-  // accumulated in `active_delta`, and this intermediate result must not be
-  // negative.
-
-  if (user() < baseline.user())
-    return -1;
-  double active_delta = user() - baseline.user();
-
-  if (nice() < baseline.nice())
-    return -1;
-  active_delta += nice() - baseline.nice();
-
-  if (system() < baseline.system())
-    return -1;
-  active_delta += system() - baseline.system();
-
-  if (idle() < baseline.idle())
-    return -1;
-  uint64_t idle_delta = idle() - baseline.idle();
-
-  // iowait() is unreliable, according to the Linux kernel documentation at
-  // https://www.kernel.org/doc/Documentation/filesystems/proc.txt.
-
-  if (irq() < baseline.irq())
-    return -1;
-  active_delta += irq() - baseline.irq();
-
-  if (softirq() < baseline.softirq())
-    return -1;
-  active_delta += softirq() - baseline.softirq();
-
-  if (steal() < baseline.steal())
-    return -1;
-  active_delta += steal() - baseline.steal();
-
-  // guest() and guest_nice() are included in user(). Full analysis in
-  // https://unix.stackexchange.com/a/303224/
-
-  double total_delta = active_delta + idle_delta;
-  if (total_delta == 0) {
-    // The two snapshots represent the same point in time, so the time interval
-    // between the two snapshots is empty.
-    return -1;
-  }
-
-  return active_delta / total_delta;
-}
-
 constexpr base::FilePath::CharType ProcfsStatCpuParser::kProcfsStatPath[];
 
 ProcfsStatCpuParser::ProcfsStatCpuParser(base::FilePath stat_path)
diff --git a/services/device/compute_pressure/procfs_stat_cpu_parser.h b/services/device/compute_pressure/procfs_stat_cpu_parser.h
index 115b8ca..873d74e 100644
--- a/services/device/compute_pressure/procfs_stat_cpu_parser.h
+++ b/services/device/compute_pressure/procfs_stat_cpu_parser.h
@@ -13,6 +13,7 @@
 #include "base/sequence_checker.h"
 #include "base/strings/string_piece.h"
 #include "base/thread_annotations.h"
+#include "services/device/compute_pressure/core_times.h"
 
 namespace device {
 
@@ -23,44 +24,6 @@
 // different sequence.
 class ProcfsStatCpuParser {
  public:
-  // CPU core utilization statistics.
-  //
-  // Quantities are expressed in "user hertz", which is a Linux kernel
-  // configuration knob (USER_HZ). Typical values range between 1/100 seconds
-  // and 1/1000 seconds. The denominator can be obtained from
-  // sysconf(_SC_CLK_TCK).
-  struct CoreTimes {
-    // Normal processes executing in user mode.
-    uint64_t user() const { return times[0]; }
-    // Niced processes executing in user mode.
-    uint64_t nice() const { return times[1]; }
-    // Processes executing in kernel mode.
-    uint64_t system() const { return times[2]; }
-    // Twiddling thumbs.
-    uint64_t idle() const { return times[3]; }
-    // Waiting for I/O to complete. Unreliable.
-    uint64_t iowait() const { return times[4]; }
-    // Servicing interrupts.
-    uint64_t irq() const { return times[5]; }
-    // Servicing softirqs.
-    uint64_t softirq() const { return times[6]; }
-    // Involuntary wait.
-    uint64_t steal() const { return times[7]; }
-    // Running a normal guest.
-    uint64_t guest() const { return times[8]; }
-    // Running a niced guest.
-    uint64_t guest_nice() const { return times[9]; }
-
-    uint64_t times[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-    // Computes a CPU's utilization over the time between two stat snapshots.
-    //
-    // Returns a value between 0.0 and 1.0 on success, and -1.0 when given
-    // invalid data, such as a `baseline` that does not represent a stat
-    // snapshot collected before `this` snapshot.
-    double TimeUtilization(const CoreTimes& baseline) const;
-  };
-
   // The "production" `procfs_path` value for the constructor.
   static constexpr base::FilePath::CharType kProcfsStatPath[] =
       FILE_PATH_LITERAL("/proc/stat");
diff --git a/services/device/compute_pressure/procfs_stat_cpu_parser_unittest.cc b/services/device/compute_pressure/procfs_stat_cpu_parser_unittest.cc
index ecf83b6..1510667 100644
--- a/services/device/compute_pressure/procfs_stat_cpu_parser_unittest.cc
+++ b/services/device/compute_pressure/procfs_stat_cpu_parser_unittest.cc
@@ -426,108 +426,4 @@
   }
 }
 
-TEST_F(ProcfsStatCpuParserTest, CoreTimes_TimeUtilization_Balanced) {
-  ProcfsStatCpuParser::CoreTimes baseline = {
-      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
-
-  std::vector<ProcfsStatCpuParser::CoreTimes> test_cases = {
-      // Individual components get summed up correctly.
-      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 215, 305, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 205, 315, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 615, 705, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 605, 715, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 605, 705, 815, 905, 1005}},
-
-      // Ignored components are not added to the sum.
-      {.times = {115, 205, 305, 415, 595, 605, 705, 805, 905, 1005}},
-      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 995, 1005}},
-      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1095}},
-
-      // Negative changes in ignored components are not flagged.
-      {.times = {115, 205, 305, 415, 500, 605, 705, 805, 905, 1005}},
-      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 900, 1005}},
-      {.times = {115, 205, 305, 415, 505, 605, 705, 805, 905, 1000}},
-  };
-
-  for (const ProcfsStatCpuParser::CoreTimes& times : test_cases) {
-    SCOPED_TRACE(times.times);
-    EXPECT_EQ(0.5, times.TimeUtilization(baseline));
-  }
-}
-
-TEST_F(ProcfsStatCpuParserTest, CoreTimes_TimeUtilization_EmptyRange) {
-  ProcfsStatCpuParser::CoreTimes baseline = {
-      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
-
-  std::vector<ProcfsStatCpuParser::CoreTimes> test_cases = {
-      // Identical times.
-      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}},
-
-      // Changes in ignored components.
-      {.times = {105, 205, 305, 405, 515, 605, 705, 805, 905, 1005}},
-      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 915, 1005}},
-      {.times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1015}},
-  };
-
-  for (const ProcfsStatCpuParser::CoreTimes& times : test_cases) {
-    SCOPED_TRACE(times.times);
-    EXPECT_EQ(-1, times.TimeUtilization(baseline));
-  }
-}
-
-TEST_F(ProcfsStatCpuParserTest, CoreTimes_TimeUtilization_NegativeRange) {
-  ProcfsStatCpuParser::CoreTimes baseline = {
-      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
-
-  std::vector<ProcfsStatCpuParser::CoreTimes> test_cases = {
-      {.times = {100, 205, 305, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 200, 305, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 205, 300, 415, 505, 605, 705, 805, 905, 1005}},
-      {.times = {115, 205, 305, 400, 505, 605, 705, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 600, 705, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 605, 700, 805, 905, 1005}},
-      {.times = {105, 205, 305, 415, 505, 605, 705, 800, 905, 1005}},
-  };
-
-  for (const ProcfsStatCpuParser::CoreTimes& times : test_cases) {
-    SCOPED_TRACE(times.times);
-    EXPECT_EQ(-1, times.TimeUtilization(baseline));
-  }
-}
-
-TEST_F(ProcfsStatCpuParserTest, CoreTimes_TimeUtilization_Computation) {
-  ProcfsStatCpuParser::CoreTimes baseline = {
-      .times = {105, 205, 305, 405, 505, 605, 705, 805, 905, 1005}};
-
-  struct TestCase {
-    ProcfsStatCpuParser::CoreTimes times;
-    double utilization;
-  };
-
-  std::vector<TestCase> test_cases = {
-      // No idling.
-      {{.times = {115, 205, 305, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
-      {{.times = {115, 215, 305, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
-      {{.times = {115, 215, 315, 405, 505, 605, 705, 805, 905, 1005}}, 1.0},
-      {{.times = {115, 215, 315, 405, 505, 615, 705, 805, 905, 1005}}, 1.0},
-      {{.times = {115, 215, 315, 405, 505, 615, 715, 805, 905, 1005}}, 1.0},
-      {{.times = {115, 215, 315, 405, 505, 615, 715, 815, 905, 1005}}, 1.0},
-
-      // All idling.
-      {{.times = {105, 205, 305, 415, 505, 605, 705, 805, 905, 1005}}, 0.0},
-
-      // Fractions
-      {{.times = {115, 225, 305, 415, 505, 605, 705, 805, 905, 1005}}, 0.75},
-      {{.times = {115, 225, 345, 415, 505, 605, 705, 805, 905, 1005}}, 0.875},
-      {{.times = {115, 205, 305, 435, 505, 605, 705, 805, 905, 1005}}, 0.25},
-      {{.times = {115, 205, 305, 475, 505, 605, 705, 805, 905, 1005}}, 0.125},
-  };
-
-  for (const TestCase& test_case : test_cases) {
-    SCOPED_TRACE(test_case.times.times);
-    EXPECT_EQ(test_case.utilization, test_case.times.TimeUtilization(baseline));
-  }
-}
-
 }  // namespace device
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 7dd783f2..2dbb457 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -859,9 +859,9 @@
   // TODO(https://crbug.com/1339708): In-memory cache should support DevTools.
   absl::optional<std::string> cache_key;
   if (memory_cache_ && !request_.devtools_request_id.has_value()) {
-    cache_key = memory_cache_->CanServe(request_,
-                                        isolation_info_.network_isolation_key(),
-                                        cross_origin_embedder_policy_);
+    cache_key = memory_cache_->CanServe(
+        options_, request_, isolation_info_.network_isolation_key(),
+        cross_origin_embedder_policy_, GetClientSecurityState());
   }
 
   if (cache_key.has_value()) {
diff --git a/services/network/network_change_manager.cc b/services/network/network_change_manager.cc
index 3009cdfc..d673fd3 100644
--- a/services/network/network_change_manager.cc
+++ b/services/network/network_change_manager.cc
@@ -50,7 +50,7 @@
   clients_.push_back(std::move(client_remote));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
 void NetworkChangeManager::OnNetworkChanged(
     bool dns_changed,
     bool ip_address_changed,
diff --git a/services/network/network_change_manager.h b/services/network/network_change_manager.h
index b5bc84fd..e7c60206 100644
--- a/services/network/network_change_manager.h
+++ b/services/network/network_change_manager.h
@@ -45,7 +45,7 @@
       mojo::PendingRemote<mojom::NetworkChangeManagerClient> client_remote)
       override;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
   void OnNetworkChanged(
       bool dns_changed,
       bool ip_address_changed,
diff --git a/services/network/network_service_memory_cache.cc b/services/network/network_service_memory_cache.cc
index e43501bb..53e55c3f 100644
--- a/services/network/network_service_memory_cache.cc
+++ b/services/network/network_service_memory_cache.cc
@@ -18,6 +18,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/mime_sniffer.h"
 #include "net/base/network_isolation_key.h"
+#include "net/base/transport_info.h"
 #include "net/cert/cert_status_flags.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_request_info.h"
@@ -30,11 +31,14 @@
 #include "services/network/network_context.h"
 #include "services/network/network_service_memory_cache_url_loader.h"
 #include "services/network/network_service_memory_cache_writer.h"
+#include "services/network/private_network_access_checker.h"
 #include "services/network/public/cpp/corb/corb_api.h"
 #include "services/network/public/cpp/cross_origin_resource_policy.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/private_network_access_check_result.h"
 #include "services/network/public/cpp/request_destination.h"
 #include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/url_loader.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -153,6 +157,20 @@
   return decision == corb::ResponseAnalyzer::Decision::kAllow;
 }
 
+bool CheckPrivateNetworkAccess(
+    uint32_t load_options,
+    const ResourceRequest& resource_request,
+    const mojom::ClientSecurityState* client_security_state,
+    const net::TransportInfo& transport_info) {
+  mojom::URLLoaderFactoryParams factory_params;
+  if (client_security_state)
+    factory_params.client_security_state = client_security_state->Clone();
+  PrivateNetworkAccessChecker checker(resource_request, &factory_params,
+                                      load_options);
+  PrivateNetworkAccessCheckResult result = checker.Check(transport_info);
+  return !PrivateNetworkAccessCheckResultToCorsError(result).has_value();
+}
+
 // Checks whether Vary header in the cached response only has headers that the
 // in-memory cache can handle.
 bool VaryHasSupportedHeadersOnly(
@@ -221,10 +239,12 @@
 
 struct NetworkServiceMemoryCache::Entry {
   Entry(const net::HttpVaryData& vary_data,
+        const net::TransportInfo& transport_info,
         mojom::URLResponseHeadPtr response_head,
         scoped_refptr<base::RefCountedBytes> content,
         int64_t encoded_body_length)
       : vary_data(vary_data),
+        transport_info(transport_info),
         response_head(std::move(response_head)),
         content(std::move(content)),
         encoded_body_length(encoded_body_length) {}
@@ -237,6 +257,7 @@
   Entry& operator=(const Entry&) = delete;
 
   net::HttpVaryData vary_data;
+  net::TransportInfo transport_info;
   mojom::URLResponseHeadPtr response_head;
   scoped_refptr<base::RefCountedBytes> content;
   int64_t encoded_body_length;
@@ -275,6 +296,7 @@
 NetworkServiceMemoryCache::MaybeCreateWriter(
     net::URLRequest* url_request,
     mojom::RequestDestination request_destination,
+    const net::TransportInfo& transport_info,
     const mojom::URLResponseHeadPtr& response) {
   DCHECK(url_request);
 
@@ -338,7 +360,8 @@
 
   return std::make_unique<NetworkServiceMemoryCacheWriter>(
       weak_ptr_factory_.GetWeakPtr(), GetNextTraceId(), max_per_entry_bytes_,
-      std::move(*cache_key), url_request, request_destination, response);
+      std::move(*cache_key), url_request, request_destination, transport_info,
+      response);
 }
 
 void NetworkServiceMemoryCache::StoreResponse(
@@ -346,6 +369,7 @@
     const URLLoaderCompletionStatus& status,
     mojom::RequestDestination request_destination,
     const net::HttpVaryData& vary_data,
+    const net::TransportInfo& transport_info,
     mojom::URLResponseHeadPtr response_head,
     std::vector<unsigned char> data) {
   DCHECK_GE(max_per_entry_bytes_, data.size());
@@ -393,18 +417,20 @@
 
   scoped_refptr<base::RefCountedBytes> content =
       base::RefCountedBytes::TakeVector(&data);
-  auto entry =
-      std::make_unique<Entry>(vary_data, std::move(response_head),
-                              std::move(content), status.encoded_body_length);
+  auto entry = std::make_unique<Entry>(
+      vary_data, transport_info, std::move(response_head), std::move(content),
+      status.encoded_body_length);
   entries_.Put(cache_key, std::move(entry));
 
   ShrinkToTotalBytes();
 }
 
 absl::optional<std::string> NetworkServiceMemoryCache::CanServe(
+    uint32_t load_options,
     const ResourceRequest& resource_request,
     const net::NetworkIsolationKey& network_isolation_key,
-    const CrossOriginEmbedderPolicy& cross_origin_embedder_policy) {
+    const CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
+    const mojom::ClientSecurityState* client_security_state) {
   // TODO(https://crbug.com/1339708): Support automatically assigned network
   // isolation key for request from browsers. See comments in
   // CorsURLLoaderFactory::CorsURLLoaderFactory.
@@ -438,6 +464,12 @@
     return absl::nullopt;
   }
 
+  if (!CheckPrivateNetworkAccess(load_options, resource_request,
+                                 client_security_state,
+                                 it->second->transport_info)) {
+    return absl::nullopt;
+  }
+
   const mojom::URLResponseHeadPtr& response = it->second->response_head;
 
   absl::optional<mojom::BlockedByResponseReason> blocked_reason =
diff --git a/services/network/network_service_memory_cache.h b/services/network/network_service_memory_cache.h
index c3cc4921..e5b882e7 100644
--- a/services/network/network_service_memory_cache.h
+++ b/services/network/network_service_memory_cache.h
@@ -28,6 +28,7 @@
 class NetLogWithSource;
 class NetworkIsolationKey;
 class URLRequest;
+struct TransportInfo;
 }  // namespace net
 
 namespace network {
@@ -62,6 +63,7 @@
   std::unique_ptr<NetworkServiceMemoryCacheWriter> MaybeCreateWriter(
       net::URLRequest* url_request,
       mojom::RequestDestination request_destination,
+      const net::TransportInfo& transport_info,
       const mojom::URLResponseHeadPtr& response);
 
   // Stores an HTTP response into `this`. Called when a writer finished reading
@@ -70,6 +72,7 @@
                      const URLLoaderCompletionStatus& status,
                      mojom::RequestDestination request_destination,
                      const net::HttpVaryData& vary_data,
+                     const net::TransportInfo& transport_info,
                      mojom::URLResponseHeadPtr response_head,
                      std::vector<unsigned char> data);
 
@@ -77,9 +80,11 @@
   // The returned cache key is valid only for the current call stack. It must be
   // used synchronously.
   absl::optional<std::string> CanServe(
+      uint32_t load_options,
       const ResourceRequest& resource_request,
       const net::NetworkIsolationKey& network_isolation_key,
-      const CrossOriginEmbedderPolicy& cross_origin_embedder_policy);
+      const CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
+      const mojom::ClientSecurityState* client_security_state);
 
   // Creates and starts a custom URLLoader that serves a response from the
   // in-memory cache, instead of creating a network::URLLoader. Must be called
diff --git a/services/network/network_service_memory_cache_unittest.cc b/services/network/network_service_memory_cache_unittest.cc
index 7215c09..72b2942 100644
--- a/services/network/network_service_memory_cache_unittest.cc
+++ b/services/network/network_service_memory_cache_unittest.cc
@@ -255,8 +255,9 @@
       net::URLRequest* url_request,
       const mojom::URLResponseHeadPtr& response_head) {
     std::unique_ptr<NetworkServiceMemoryCacheWriter> writer =
-        memory_cache().MaybeCreateWriter(
-            url_request, mojom::RequestDestination::kDocument, response_head);
+        memory_cache().MaybeCreateWriter(url_request,
+                                         mojom::RequestDestination::kDocument,
+                                         net::TransportInfo(), response_head);
     return writer.get() != nullptr;
   }
 
@@ -279,7 +280,9 @@
       const net::NetworkIsolationKey& network_isolation_key,
       const CrossOriginEmbedderPolicy& cross_origin_embedder_policy) {
     return memory_cache()
-        .CanServe(request, network_isolation_key, cross_origin_embedder_policy)
+        .CanServe(mojom::kURLLoadOptionNone, request, network_isolation_key,
+                  cross_origin_embedder_policy,
+                  /*client_security_state=*/nullptr)
         .has_value();
   }
 
@@ -767,7 +770,9 @@
                                                  /*frame_site=*/site);
 
   absl::optional<std::string> cache_key = memory_cache().CanServe(
-      request, network_isolation_key, CrossOriginEmbedderPolicy());
+      mojom::kURLLoadOptionNone, request, network_isolation_key,
+      CrossOriginEmbedderPolicy(),
+      /*client_security_state=*/nullptr);
   ASSERT_TRUE(cache_key.has_value());
   mojom::URLResponseHeadPtr response =
       memory_cache().GetResponseHeadForTesting(*cache_key);
diff --git a/services/network/network_service_memory_cache_writer.cc b/services/network/network_service_memory_cache_writer.cc
index d1e920e..17c1eec 100644
--- a/services/network/network_service_memory_cache_writer.cc
+++ b/services/network/network_service_memory_cache_writer.cc
@@ -19,6 +19,7 @@
     std::string cache_key,
     net::URLRequest* url_request,
     mojom::RequestDestination request_destination,
+    const net::TransportInfo& transport_info,
     const mojom::URLResponseHeadPtr& response_head)
     : cache_(std::move(cache)),
       trace_id_(trace_id),
@@ -26,6 +27,7 @@
       cache_key_(std::move(cache_key)),
       url_request_(url_request),
       request_destination_(request_destination),
+      transport_info_(transport_info),
       response_head_(response_head.Clone()) {
   DCHECK(cache_);
   DCHECK(url_request_);
@@ -63,7 +65,8 @@
   if (cache_) {
     cache_->StoreResponse(cache_key_, status, request_destination_,
                           url_request_->response_info().vary_data,
-                          std::move(response_head_), std::move(received_data_));
+                          transport_info_, std::move(response_head_),
+                          std::move(received_data_));
   }
   // `this` will be deleted by the owner.
 }
diff --git a/services/network/network_service_memory_cache_writer.h b/services/network/network_service_memory_cache_writer.h
index d614f3e..eeb6ec6 100644
--- a/services/network/network_service_memory_cache_writer.h
+++ b/services/network/network_service_memory_cache_writer.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "net/base/transport_info.h"
 #include "services/network/public/mojom/url_loader_completion_status.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 
@@ -36,6 +37,7 @@
       std::string cache_key,
       net::URLRequest* request,
       mojom::RequestDestination request_destination,
+      const net::TransportInfo& transport_info,
       const mojom::URLResponseHeadPtr& response_head);
 
   ~NetworkServiceMemoryCacheWriter();
@@ -64,6 +66,7 @@
 
   mojom::RequestDestination request_destination_;
 
+  const net::TransportInfo transport_info_;
   mojom::URLResponseHeadPtr response_head_;
   std::vector<unsigned char> received_data_;
 };
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 3e35e9c..12405dd 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -312,7 +312,7 @@
   }
 
   enabled_features = []
-  if (is_android || is_chromeos_ash) {
+  if (is_android || is_chromeos) {
     enabled_features += [ "network_change_notifier_in_browser" ]
   }
 
diff --git a/services/network/sct_auditing/sct_auditing_handler_unittest.cc b/services/network/sct_auditing/sct_auditing_handler_unittest.cc
index 7176a3ea..a24c9ce 100644
--- a/services/network/sct_auditing/sct_auditing_handler_unittest.cc
+++ b/services/network/sct_auditing/sct_auditing_handler_unittest.cc
@@ -221,8 +221,7 @@
 }
 
 // Tests that if reporting is disabled, reports are not created.
-// crbug.com/1341847 Disable the test due to flakiness
-TEST_F(SCTAuditingHandlerTest, DISABLED_DisableReporting) {
+TEST_F(SCTAuditingHandlerTest, DisableReporting) {
   // Create a report which would normally trigger a send.
   const net::HostPortPair host_port_pair("example.com", 443);
   net::SignedCertificateTimestampAndStatusList sct_list;
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index dc11c70..7fa57f0 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1241,6 +1241,7 @@
                            const net::TransportInfo& info,
                            net::CompletionOnceCallback callback) {
   DCHECK_EQ(url_request, url_request_.get());
+  transport_info_ = info;
 
   // Now that the request endpoint's address has been resolved, check if
   // this request should be blocked per Private Network Access.
@@ -1557,7 +1558,7 @@
   // TODO(https://crbug.com/1339708): In-memory cache should support DevTools.
   if (memory_cache_ && !devtools_request_id().has_value()) {
     memory_cache_writer_ = memory_cache_->MaybeCreateWriter(
-        url_request_.get(), request_destination_, response_);
+        url_request_.get(), request_destination_, transport_info_, response_);
   }
 
   ContinueOnResponseStarted();
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 158eaacb..7a1d7fe5 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -25,6 +25,7 @@
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/load_states.h"
 #include "net/base/network_delegate.h"
+#include "net/base/transport_info.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
 #include "services/network/keepalive_statistics_recorder.h"
@@ -58,7 +59,6 @@
 class HttpResponseHeaders;
 class IPEndPoint;
 struct RedirectInfo;
-struct TransportInfo;
 class URLRequestContext;
 }  // namespace net
 
@@ -569,6 +569,8 @@
 
   base::WeakPtr<NetworkServiceMemoryCache> memory_cache_;
   std::unique_ptr<NetworkServiceMemoryCacheWriter> memory_cache_writer_;
+  // Passed to `memory_cache_writer_`. Do not use other purposes.
+  net::TransportInfo transport_info_;
 
   bool first_auth_attempt_ = true;
 
diff --git a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
index 7d8a2b2..10dd4744 100644
--- a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -59,6 +59,7 @@
 #include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h"
 #include "skia/public/mojom/tile_mode_mojom_traits.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkString.h"
@@ -1017,15 +1018,19 @@
                             vertex_opacity, y_flipped, nearest_neighbor,
                             secure_output_only, protected_video_type);
 
+  // Create a stream video TextureDrawQuad.
   const gfx::Rect rect6(321, 765, 11109, 151413);
   const bool needs_blending6 = false;
   const ResourceId resource_id6(1234);
   const gfx::Size resource_size_in_pixels(1234, 5678);
-  StreamVideoDrawQuad* stream_video_draw_quad =
-      render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
-  stream_video_draw_quad->SetNew(sqs, rect6, rect6, needs_blending6,
-                                 resource_id6, resource_size_in_pixels,
-                                 uv_top_left, uv_bottom_right);
+  const float stream_draw_quad_opacity[] = {1, 1, 1, 1};
+  TextureDrawQuad* stream_video_draw_quad =
+      render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
+  stream_video_draw_quad->SetAll(
+      sqs, rect6, rect6, needs_blending6, resource_id6, resource_size_in_pixels,
+      false, uv_top_left, uv_bottom_right, SkColors::kTransparent,
+      stream_draw_quad_opacity, false, false, false, protected_video_type);
+  stream_video_draw_quad->is_stream_video = true;
 
   std::unique_ptr<CompositorRenderPass> output;
   mojo::test::SerializeAndDeserialize<mojom::CompositorRenderPass>(render_pass,
@@ -1101,8 +1106,9 @@
   EXPECT_EQ(nearest_neighbor, out_texture_draw_quad->nearest_neighbor);
   EXPECT_EQ(secure_output_only, out_texture_draw_quad->secure_output_only);
 
-  const StreamVideoDrawQuad* out_stream_video_draw_quad =
-      StreamVideoDrawQuad::MaterialCast(output->quad_list.ElementAt(5));
+  const TextureDrawQuad* out_stream_video_draw_quad =
+      TextureDrawQuad::MaterialCast(output->quad_list.ElementAt(5));
+  EXPECT_TRUE(out_stream_video_draw_quad->is_stream_video);
   EXPECT_EQ(rect6, out_stream_video_draw_quad->rect);
   EXPECT_EQ(rect6, out_stream_video_draw_quad->visible_rect);
   EXPECT_EQ(needs_blending6, out_stream_video_draw_quad->needs_blending);
diff --git a/services/viz/public/cpp/compositing/quads_mojom_traits.cc b/services/viz/public/cpp/compositing/quads_mojom_traits.cc
index 08834f6..c8869a5 100644
--- a/services/viz/public/cpp/compositing/quads_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/quads_mojom_traits.cc
@@ -4,7 +4,9 @@
 
 #include "services/viz/public/cpp/compositing/quads_mojom_traits.h"
 
+#include "base/notreached.h"
 #include "components/viz/common/quads/shared_element_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
 #include "services/viz/public/cpp/compositing/compositor_render_pass_id_mojom_traits.h"
 #include "services/viz/public/cpp/compositing/resource_id_mojom_traits.h"
 #include "services/viz/public/cpp/crash_keys.h"
@@ -32,10 +34,6 @@
       quad = list->AllocateAndConstruct<viz::SolidColorDrawQuad>();
       quad->material = viz::DrawQuad::Material::kSolidColor;
       return quad;
-    case viz::mojom::DrawQuadStateDataView::Tag::kStreamVideoQuadState:
-      quad = list->AllocateAndConstruct<viz::StreamVideoDrawQuad>();
-      quad->material = viz::DrawQuad::Material::kStreamVideoContent;
-      return quad;
     case viz::mojom::DrawQuadStateDataView::Tag::kSurfaceQuadState:
       quad = list->AllocateAndConstruct<viz::SurfaceDrawQuad>();
       quad->material = viz::DrawQuad::Material::kSurfaceContent;
@@ -118,19 +116,6 @@
 }
 
 // static
-bool StructTraits<viz::mojom::StreamVideoQuadStateDataView, viz::DrawQuad>::
-    Read(viz::mojom::StreamVideoQuadStateDataView data, viz::DrawQuad* out) {
-  auto* quad = static_cast<viz::StreamVideoDrawQuad*>(out);
-  quad->resources.count = 1;
-  return data.ReadResourceSizeInPixels(
-             &quad->overlay_resources.size_in_pixels) &&
-         data.ReadUvTopLeft(&quad->uv_top_left) &&
-         data.ReadUvBottomRight(&quad->uv_bottom_right) &&
-         data.ReadResourceId(
-             &quad->resources.ids[viz::StreamVideoDrawQuad::kResourceIdIndex]);
-}
-
-// static
 bool StructTraits<viz::mojom::SurfaceQuadStateDataView, viz::DrawQuad>::Read(
     viz::mojom::SurfaceQuadStateDataView data,
     viz::DrawQuad* out) {
@@ -178,6 +163,7 @@
   quad->y_flipped = data.y_flipped();
   quad->nearest_neighbor = data.nearest_neighbor();
   quad->secure_output_only = data.secure_output_only();
+  quad->is_stream_video = data.is_stream_video();
   quad->is_video_frame = data.is_video_frame();
 
   if (!data.ReadDamageRect(&quad->damage_rect))
diff --git a/services/viz/public/cpp/compositing/quads_mojom_traits.h b/services/viz/public/cpp/compositing/quads_mojom_traits.h
index 70bad2f..8623c44 100644
--- a/services/viz/public/cpp/compositing/quads_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -15,7 +15,6 @@
 #include "components/viz/common/quads/picture_draw_quad.h"
 #include "components/viz/common/quads/shared_element_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/tile_draw_quad.h"
@@ -128,8 +127,6 @@
         return viz::mojom::DrawQuadStateDataView::Tag::kRenderPassQuadState;
       case viz::DrawQuad::Material::kSolidColor:
         return viz::mojom::DrawQuadStateDataView::Tag::kSolidColorQuadState;
-      case viz::DrawQuad::Material::kStreamVideoContent:
-        return viz::mojom::DrawQuadStateDataView::Tag::kStreamVideoQuadState;
       case viz::DrawQuad::Material::kSurfaceContent:
         return viz::mojom::DrawQuadStateDataView::Tag::kSurfaceQuadState;
       case viz::DrawQuad::Material::kTextureContent:
@@ -206,8 +203,6 @@
         return data.ReadTextureQuadState(out);
       case viz::mojom::DrawQuadStateDataView::Tag::kTileQuadState:
         return data.ReadTileQuadState(out);
-      case viz::mojom::DrawQuadStateDataView::Tag::kStreamVideoQuadState:
-        return data.ReadStreamVideoQuadState(out);
       case viz::mojom::DrawQuadStateDataView::Tag::kVideoHoleQuadState:
         return data.ReadVideoHoleQuadState(out);
       case viz::mojom::DrawQuadStateDataView::Tag::kYuvVideoQuadState:
@@ -352,36 +347,6 @@
 };
 
 template <>
-struct StructTraits<viz::mojom::StreamVideoQuadStateDataView, viz::DrawQuad> {
-  static viz::ResourceId resource_id(const viz::DrawQuad& input) {
-    const viz::StreamVideoDrawQuad* quad =
-        viz::StreamVideoDrawQuad::MaterialCast(&input);
-    return quad->resources.ids[viz::StreamVideoDrawQuad::kResourceIdIndex];
-  }
-
-  static const gfx::Size& resource_size_in_pixels(const viz::DrawQuad& input) {
-    const viz::StreamVideoDrawQuad* quad =
-        viz::StreamVideoDrawQuad::MaterialCast(&input);
-    return quad->overlay_resources.size_in_pixels;
-  }
-
-  static const gfx::PointF& uv_top_left(const viz::DrawQuad& input) {
-    const viz::StreamVideoDrawQuad* quad =
-        viz::StreamVideoDrawQuad::MaterialCast(&input);
-    return quad->uv_top_left;
-  }
-
-  static const gfx::PointF& uv_bottom_right(const viz::DrawQuad& input) {
-    const viz::StreamVideoDrawQuad* quad =
-        viz::StreamVideoDrawQuad::MaterialCast(&input);
-    return quad->uv_bottom_right;
-  }
-
-  static bool Read(viz::mojom::StreamVideoQuadStateDataView data,
-                   viz::DrawQuad* out);
-};
-
-template <>
 struct StructTraits<viz::mojom::SurfaceQuadStateDataView, viz::DrawQuad> {
   static const viz::SurfaceRange& surface_range(const viz::DrawQuad& input) {
     const viz::SurfaceDrawQuad* quad =
@@ -479,6 +444,12 @@
     return quad->secure_output_only;
   }
 
+  static bool is_stream_video(const viz::DrawQuad& input) {
+    const viz::TextureDrawQuad* quad =
+        viz::TextureDrawQuad::MaterialCast(&input);
+    return quad->is_stream_video;
+  }
+
   static bool is_video_frame(const viz::DrawQuad& input) {
     const viz::TextureDrawQuad* quad =
         viz::TextureDrawQuad::MaterialCast(&input);
diff --git a/services/viz/public/mojom/compositing/quads.mojom b/services/viz/public/mojom/compositing/quads.mojom
index d1319d9..9b9eb798 100644
--- a/services/viz/public/mojom/compositing/quads.mojom
+++ b/services/viz/public/mojom/compositing/quads.mojom
@@ -70,13 +70,6 @@
   bool force_anti_aliasing_off;
 };
 
-struct StreamVideoQuadState {
-  ResourceId resource_id;
-  gfx.mojom.Size resource_size_in_pixels;
-  gfx.mojom.PointF uv_top_left;
-  gfx.mojom.PointF uv_bottom_right;
-};
-
 struct SurfaceQuadState {
   SurfaceRange surface_range;
   skia.mojom.SkColor4f default_background_color;
@@ -96,6 +89,7 @@
   bool y_flipped;
   bool nearest_neighbor;
   bool secure_output_only;
+  bool is_stream_video;
   bool is_video_frame;
   ProtectedVideoState protected_video_type;
   gfx.mojom.HDRMetadata? hdr_metadata;
@@ -142,7 +136,6 @@
   DebugBorderQuadState debug_border_quad_state;
   CompositorRenderPassQuadState render_pass_quad_state;
   SolidColorQuadState solid_color_quad_state;
-  StreamVideoQuadState stream_video_quad_state;
   SurfaceQuadState surface_quad_state;
   TextureQuadState texture_quad_state;
   TileQuadState tile_quad_state;
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc
index e3eb949..4bc6b2f 100644
--- a/storage/browser/quota/quota_database.cc
+++ b/storage/browser/quota/quota_database.cc
@@ -27,6 +27,7 @@
 #include "sql/statement.h"
 #include "sql/transaction.h"
 #include "storage/browser/quota/quota_database_migrations.h"
+#include "storage/browser/quota/quota_internals.mojom.h"
 #include "storage/browser/quota/special_storage_policy.h"
 #include "url/gurl.h"
 
@@ -104,6 +105,25 @@
   statement.BindInt(10, durability);
 }
 
+// Fields to be retrieved from the database and stored in a
+// `BucketTableEntryPtr`.
+#define BUCKET_TABLE_ENTRY_FIELDS_SELECTOR \
+  "id, storage_key, type, name, use_count, last_accessed, last_modified "
+
+mojom::BucketTableEntryPtr BucketTableEntryFromSqlStatement(
+    sql::Statement& statement) {
+  mojom::BucketTableEntryPtr entry = mojom::BucketTableEntry::New();
+  entry->bucket_id = statement.ColumnInt64(0);
+  entry->storage_key = statement.ColumnString(1);
+  entry->type =
+      static_cast<storage::mojom::StorageType>(statement.ColumnInt(2));
+  entry->name = statement.ColumnString(3);
+  entry->use_count = statement.ColumnInt(4);
+  entry->last_accessed = statement.ColumnTime(5);
+  entry->last_modified = statement.ColumnTime(6);
+  return entry;
+}
+
 // Fields to be retrieved from the database and stored in a `BucketInfo`.
 #define BUCKET_INFO_FIELDS_SELECTOR \
   " id, storage_key, type, name, expiration, quota, persistent, durability "
@@ -172,31 +192,6 @@
 };
 const size_t QuotaDatabase::kIndexCount = std::size(QuotaDatabase::kIndexes);
 
-QuotaDatabase::BucketTableEntry::BucketTableEntry() = default;
-
-QuotaDatabase::BucketTableEntry::~BucketTableEntry() = default;
-
-QuotaDatabase::BucketTableEntry::BucketTableEntry(const BucketTableEntry&) =
-    default;
-QuotaDatabase::BucketTableEntry& QuotaDatabase::BucketTableEntry::operator=(
-    const QuotaDatabase::BucketTableEntry&) = default;
-
-QuotaDatabase::BucketTableEntry::BucketTableEntry(
-    BucketId bucket_id,
-    StorageKey storage_key,
-    StorageType type,
-    std::string name,
-    int use_count,
-    const base::Time& last_accessed,
-    const base::Time& last_modified)
-    : bucket_id(std::move(bucket_id)),
-      storage_key(std::move(storage_key)),
-      type(type),
-      name(std::move(name)),
-      use_count(use_count),
-      last_accessed(last_accessed),
-      last_modified(last_modified) {}
-
 // QuotaDatabase ------------------------------------------------------------
 QuotaDatabase::QuotaDatabase(const base::FilePath& profile_path)
     : storage_directory_(
@@ -583,7 +578,7 @@
   return QuotaError::kNone;
 }
 
-QuotaErrorOr<QuotaDatabase::BucketTableEntry> QuotaDatabase::GetBucketInfo(
+QuotaErrorOr<mojom::BucketTableEntryPtr> QuotaDatabase::GetBucketInfo(
     BucketId bucket_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!bucket_id.is_null());
@@ -593,13 +588,7 @@
 
   static constexpr char kSql[] =
       // clang-format off
-      "SELECT "
-          "storage_key,"
-          "type,"
-          "name,"
-          "use_count,"
-          "last_accessed,"
-          "last_modified "
+      "SELECT " BUCKET_TABLE_ENTRY_FIELDS_SELECTOR
         "FROM buckets "
         "WHERE id = ?";
   // clang-format on
@@ -612,14 +601,13 @@
   }
 
   absl::optional<StorageKey> storage_key =
-      StorageKey::Deserialize(statement.ColumnString(0));
+      StorageKey::Deserialize(statement.ColumnString(1));
   if (!storage_key.has_value())
     return QuotaError::kNotFound;
 
-  return BucketTableEntry(bucket_id, std::move(storage_key).value(),
-                          static_cast<StorageType>(statement.ColumnInt(1)),
-                          statement.ColumnString(2), statement.ColumnInt(3),
-                          statement.ColumnTime(4), statement.ColumnTime(5));
+  mojom::BucketTableEntryPtr entry =
+      BucketTableEntryFromSqlStatement(statement);
+  return entry;
 }
 
 QuotaError QuotaDatabase::DeleteHostQuota(const std::string& host,
@@ -1136,30 +1124,20 @@
 
   static constexpr char kSql[] =
       // clang-format off
-      "SELECT "
-          "id,"
-          "storage_key,"
-          "type,"
-          "name,"
-          "use_count,"
-          "last_accessed,"
-          "last_modified "
+      "SELECT " BUCKET_TABLE_ENTRY_FIELDS_SELECTOR
         "FROM buckets";
   // clang-format on
   sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
 
   while (statement.Step()) {
-    BucketId bucket_id = BucketId(statement.ColumnInt64(0));
     absl::optional<StorageKey> storage_key =
         StorageKey::Deserialize(statement.ColumnString(1));
     if (!storage_key.has_value())
       continue;
-    BucketTableEntry entry(std::move(bucket_id), std::move(storage_key).value(),
-                           static_cast<StorageType>(statement.ColumnInt(2)),
-                           statement.ColumnString(3), statement.ColumnInt(4),
-                           statement.ColumnTime(5), statement.ColumnTime(6));
 
-    if (!callback.Run(entry))
+    auto entry = BucketTableEntryFromSqlStatement(statement);
+
+    if (!callback.Run(std::move(entry)))
       return QuotaError::kNone;
   }
   return statement.Succeeded() ? QuotaError::kNone : QuotaError::kDatabaseError;
@@ -1198,10 +1176,4 @@
   return result;
 }
 
-bool operator<(const QuotaDatabase::BucketTableEntry& lhs,
-               const QuotaDatabase::BucketTableEntry& rhs) {
-  return std::tie(lhs.storage_key, lhs.type, lhs.use_count, lhs.last_accessed) <
-         std::tie(rhs.storage_key, rhs.type, rhs.use_count, rhs.last_accessed);
-}
-
 }  // namespace storage
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h
index dd99bfe8..4537bbd 100644
--- a/storage/browser/quota/quota_database.h
+++ b/storage/browser/quota/quota_database.h
@@ -26,6 +26,7 @@
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "components/services/storage/public/cpp/buckets/constants.h"
 #include "components/services/storage/public/cpp/quota_error_or.h"
+#include "storage/browser/quota/quota_internals.mojom-forward.h"
 #include "storage/browser/quota/storage_directory.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
@@ -38,7 +39,7 @@
 namespace sql {
 class Database;
 class MetaTable;
-}
+}  // namespace sql
 
 namespace storage {
 
@@ -65,34 +66,6 @@
 // constructor, must called on the DB thread.
 class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
  public:
-  struct COMPONENT_EXPORT(STORAGE_BROWSER) BucketTableEntry {
-    BucketTableEntry();
-    BucketTableEntry(BucketId bucket_id,
-                     blink::StorageKey storage_key,
-                     blink::mojom::StorageType type,
-                     std::string name,
-                     int use_count,
-                     const base::Time& last_accessed,
-                     const base::Time& last_modified);
-    ~BucketTableEntry();
-
-    BucketTableEntry(const BucketTableEntry&);
-    BucketTableEntry& operator=(const BucketTableEntry&);
-
-    BucketLocator ToBucketLocator() const {
-      return BucketLocator(bucket_id, storage_key, type,
-                           name == kDefaultBucketName);
-    }
-
-    BucketId bucket_id;
-    blink::StorageKey storage_key;
-    blink::mojom::StorageType type = blink::mojom::StorageType::kUnknown;
-    std::string name;
-    int use_count = 0;
-    base::Time last_accessed;
-    base::Time last_modified;
-  };
-
   static constexpr char kDatabaseName[] = "QuotaManager";
 
   // If `profile_path` is empty, an in-memory database will be used.
@@ -203,7 +176,7 @@
 
   // Returns the BucketTableEntry for `bucket` if one exists. Returns a
   // QuotaError if not found or the operation has failed.
-  QuotaErrorOr<BucketTableEntry> GetBucketInfo(BucketId bucket_id);
+  QuotaErrorOr<mojom::BucketTableEntryPtr> GetBucketInfo(BucketId bucket_id);
 
   // Deletes the bucket from the database as well as the bucket directory in the
   // storage directory.
@@ -273,9 +246,6 @@
   friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator<(
       const QuotaTableEntry& lhs,
       const QuotaTableEntry& rhs);
-  friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator<(
-      const BucketTableEntry& lhs,
-      const BucketTableEntry& rhs);
 
   // Structures used for CreateSchema.
   struct TableSchema {
@@ -292,7 +262,7 @@
   using QuotaTableCallback =
       base::RepeatingCallback<bool(const QuotaTableEntry&)>;
   using BucketTableCallback =
-      base::RepeatingCallback<bool(const BucketTableEntry&)>;
+      base::RepeatingCallback<bool(mojom::BucketTableEntryPtr)>;
 
   // For long-running transactions support.  We always keep a transaction open
   // so that multiple transactions can be batched.  They are flushed
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc
index 904c857..bc6b36a 100644
--- a/storage/browser/quota/quota_database_unittest.cc
+++ b/storage/browser/quota/quota_database_unittest.cc
@@ -32,6 +32,7 @@
 #include "sql/test/test_helpers.h"
 #include "storage/browser/quota/quota_client_type.h"
 #include "storage/browser/quota/quota_database.h"
+#include "storage/browser/quota/quota_internals.mojom.h"
 #include "storage/browser/quota/storage_directory_util.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -50,6 +51,11 @@
 static const blink::mojom::StorageType kPerm =
     blink::mojom::StorageType::kPersistent;
 
+static const storage::mojom::StorageType kStorageTemp =
+    storage::mojom::StorageType::kTemporary;
+static const storage::mojom::StorageType kStoragePerm =
+    storage::mojom::StorageType::kPersistent;
+
 static constexpr char kDatabaseName[] = "QuotaManager";
 
 bool ContainsBucket(const std::set<BucketLocator>& buckets,
@@ -64,7 +70,7 @@
 // mode. True will create the database in memory.
 class QuotaDatabaseTest : public testing::TestWithParam<bool> {
  protected:
-  using BucketTableEntry = QuotaDatabase::BucketTableEntry;
+  using BucketTableEntry = mojom::BucketTableEntry;
 
   void SetUp() override { ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); }
 
@@ -93,12 +99,15 @@
   struct EntryVerifier {
     std::set<EntryType> table;
 
-    template <typename Iterator>
-    EntryVerifier(Iterator itr, Iterator end)
-        : table(itr, end) {}
+    template <size_t length>
+    explicit EntryVerifier(const EntryType (&entries)[length]) {
+      for (size_t i = 0; i < length; ++i) {
+        table.insert(entries[i]->Clone());
+      }
+    }
 
-    bool Run(const EntryType& entry) {
-      EXPECT_EQ(1u, table.erase(entry));
+    bool Run(EntryType entry) {
+      EXPECT_EQ(1u, table.erase(std::move(entry)));
       return true;
     }
   };
@@ -163,14 +172,18 @@
           quota_database->db_->GetCachedStatement(SQL_FROM_HERE, kSql));
       ASSERT_TRUE(statement.is_valid());
 
-      statement.BindInt64(0, entry.bucket_id.value());
-      statement.BindString(1, entry.storage_key.Serialize());
-      statement.BindString(2, entry.storage_key.origin().host());
-      statement.BindInt(3, static_cast<int>(entry.type));
-      statement.BindString(4, entry.name);
-      statement.BindInt(5, entry.use_count);
-      statement.BindTime(6, entry.last_accessed);
-      statement.BindTime(7, entry.last_modified);
+      absl::optional<StorageKey> storage_key =
+          StorageKey::Deserialize(entry->storage_key);
+      ASSERT_TRUE(storage_key.has_value());
+
+      statement.BindInt64(0, entry->bucket_id);
+      statement.BindString(1, entry->storage_key);
+      statement.BindString(2, std::move(storage_key).value().origin().host());
+      statement.BindInt(3, static_cast<int>(entry->type));
+      statement.BindString(4, entry->name);
+      statement.BindInt(5, static_cast<int>(entry->use_count));
+      statement.BindTime(6, entry->last_accessed);
+      statement.BindTime(7, entry->last_modified);
       EXPECT_TRUE(statement.Run());
     }
     quota_database->Commit();
@@ -566,37 +579,52 @@
 
   // Insert bucket entries into BucketTable.
   base::Time now = base::Time::Now();
-  using Entry = QuotaDatabase::BucketTableEntry;
-  Entry bucket1 = Entry(
-      BucketId(1), StorageKey::CreateFromStringForTesting("http://example-a/"),
-      kTemp, kDefaultBucketName, 99, now, now);
-  Entry bucket2 = Entry(
-      BucketId(2), StorageKey::CreateFromStringForTesting("http://example-b/"),
-      kTemp, kDefaultBucketName, 0, now, now);
-  Entry bucket3 = Entry(
-      BucketId(3), StorageKey::CreateFromStringForTesting("http://example-c/"),
-      kTemp, "bucket_c", 1, now, now);
-  Entry bucket4 = Entry(
-      BucketId(4), StorageKey::CreateFromStringForTesting("http://example-d/"),
-      kPerm, "bucket_d", 5, now, now);
-  Entry kTableEntries[] = {bucket1, bucket2, bucket3, bucket4};
+  using Entry = mojom::BucketTableEntryPtr;
+  StorageKey storage_key1 =
+      StorageKey::CreateFromStringForTesting("http://example-a/");
+  StorageKey storage_key2 =
+      StorageKey::CreateFromStringForTesting("http://example-b/");
+  StorageKey storage_key3 =
+      StorageKey::CreateFromStringForTesting("http://example-c/");
+  StorageKey storage_key4 =
+      StorageKey::CreateFromStringForTesting("http://example-d/");
+
+  BucketId bucket_id1 = BucketId(1);
+  BucketId bucket_id2 = BucketId(2);
+  BucketId bucket_id3 = BucketId(3);
+  BucketId bucket_id4 = BucketId(4);
+
+  Entry bucket1 = mojom::BucketTableEntry::New(
+      bucket_id1.value(), storage_key1.Serialize(), kStorageTemp,
+      kDefaultBucketName, -1, 99, now, now);
+  Entry bucket2 = mojom::BucketTableEntry::New(
+      bucket_id2.value(), storage_key2.Serialize(), kStorageTemp,
+      kDefaultBucketName, -1, 0, now, now);
+  Entry bucket3 =
+      mojom::BucketTableEntry::New(bucket_id3.value(), storage_key3.Serialize(),
+                                   kStorageTemp, "bucket_c", -1, 1, now, now);
+  Entry bucket4 =
+      mojom::BucketTableEntry::New(bucket_id4.value(), storage_key4.Serialize(),
+                                   kStoragePerm, "bucket_d", -1, 5, now, now);
+  Entry kTableEntries[] = {bucket1->Clone(), bucket2->Clone(), bucket3->Clone(),
+                           bucket4->Clone()};
   AssignBucketTable(db.get(), kTableEntries);
 
   // Update access time for three temporary storages, and
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket1.bucket_id,
-                                        base::Time::FromJavaTime(10)),
-            QuotaError::kNone);
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket2.bucket_id,
-                                        base::Time::FromJavaTime(20)),
-            QuotaError::kNone);
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket3.bucket_id,
-                                        base::Time::FromJavaTime(30)),
-            QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id1, base::Time::FromJavaTime(10)),
+      QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id2, base::Time::FromJavaTime(20)),
+      QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id3, base::Time::FromJavaTime(30)),
+      QuotaError::kNone);
 
   // One persistent.
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket4.bucket_id,
-                                        base::Time::FromJavaTime(40)),
-            QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id4, base::Time::FromJavaTime(40)),
+      QuotaError::kNone);
 
   // One non-existent.
   EXPECT_EQ(
@@ -605,53 +633,58 @@
 
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket1.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id1, result.value().id);
 
   // Test that unlimited origins are excluded from eviction, but
   // protected origins are not excluded.
   auto policy = base::MakeRefCounted<MockSpecialStoragePolicy>();
-  policy->AddUnlimited(bucket1.storage_key.origin().GetURL());
-  policy->AddProtected(bucket2.storage_key.origin().GetURL());
+  policy->AddUnlimited(storage_key1.origin().GetURL());
+  policy->AddProtected(storage_key2.origin().GetURL());
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, policy.get());
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket2.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id2, result.value().id);
 
   // Test that durable origins are excluded from eviction.
-  policy->AddDurable(bucket2.storage_key.origin().GetURL());
+  policy->AddDurable(storage_key2.origin().GetURL());
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, policy.get());
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket3.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id3, result.value().id);
 
   // Bucket exceptions exclude specified buckets.
-  bucket_exceptions.insert(bucket1.bucket_id);
+  bucket_exceptions.insert(bucket_id1);
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket2.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id2, result.value().id);
 
-  bucket_exceptions.insert(bucket2.bucket_id);
+  bucket_exceptions.insert(bucket_id2);
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket3.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id3, result.value().id);
 
-  bucket_exceptions.insert(bucket3.bucket_id);
+  bucket_exceptions.insert(bucket_id3);
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_FALSE(result.ok());
   EXPECT_EQ(result.error(), QuotaError::kNotFound);
 
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket1.bucket_id, base::Time::Now()),
+  EXPECT_EQ(db->SetBucketLastAccessTime(bucket_id1, base::Time::Now()),
             QuotaError::kNone);
 
+  BucketLocator bucketLocator =
+      BucketLocator(bucket_id3, storage_key3,
+                    static_cast<blink::mojom::StorageType>(bucket3->type),
+                    bucket3->name == kDefaultBucketName);
+
   // Delete storage_key/type last access time information.
-  EXPECT_EQ(db->DeleteBucketData(bucket3.ToBucketLocator()), QuotaError::kNone);
+  EXPECT_EQ(db->DeleteBucketData(bucketLocator), QuotaError::kNone);
 
   // Querying again to see if the deletion has worked.
   bucket_exceptions.clear();
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket2.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id2, result.value().id);
 
-  bucket_exceptions.insert(bucket1.bucket_id);
-  bucket_exceptions.insert(bucket2.bucket_id);
+  bucket_exceptions.insert(bucket_id1);
+  bucket_exceptions.insert(bucket_id2);
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_FALSE(result.ok());
   EXPECT_EQ(result.error(), QuotaError::kNotFound);
@@ -669,31 +702,40 @@
 
   // Insert bucket entries into BucketTable.
   base::Time now = base::Time::Now();
-  using Entry = QuotaDatabase::BucketTableEntry;
-  Entry bucket1 = Entry(
-      BucketId(1), StorageKey::CreateFromStringForTesting("http://example-a/"),
-      kTemp, kDefaultBucketName, 99, now, now);
-  Entry bucket2 = Entry(
-      BucketId(2), StorageKey::CreateFromStringForTesting("http://example-b/"),
-      kTemp, kDefaultBucketName, 0, now, now);
-  Entry kTableEntries[] = {bucket1, bucket2};
+  using Entry = mojom::BucketTableEntryPtr;
+
+  StorageKey storage_key1 =
+      StorageKey::CreateFromStringForTesting("http://example-a/");
+  StorageKey storage_key2 =
+      StorageKey::CreateFromStringForTesting("http://example-b/");
+
+  BucketId bucket_id1 = BucketId(1);
+  BucketId bucket_id2 = BucketId(2);
+
+  Entry bucket1 = mojom::BucketTableEntry::New(
+      bucket_id1.value(), storage_key1.Serialize(), kStorageTemp,
+      kDefaultBucketName, -1, 99, now, now);
+  Entry bucket2 = mojom::BucketTableEntry::New(
+      bucket_id2.value(), storage_key2.Serialize(), kStorageTemp,
+      kDefaultBucketName, -1, 0, now, now);
+  Entry kTableEntries[] = {bucket1->Clone(), bucket2->Clone()};
   AssignBucketTable(db.get(), kTableEntries);
 
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket1.bucket_id,
-                                        base::Time::FromJavaTime(10)),
-            QuotaError::kNone);
-  EXPECT_EQ(db->SetBucketLastAccessTime(bucket2.bucket_id,
-                                        base::Time::FromJavaTime(20)),
-            QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id1, base::Time::FromJavaTime(10)),
+      QuotaError::kNone);
+  EXPECT_EQ(
+      db->SetBucketLastAccessTime(bucket_id2, base::Time::FromJavaTime(20)),
+      QuotaError::kNone);
 
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket1.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id1, result.value().id);
 
-  ASSERT_TRUE(db->UpdateBucketPersistence(bucket1.bucket_id, true).ok());
+  ASSERT_TRUE(db->UpdateBucketPersistence(bucket_id1, true).ok());
   result = db->GetLruEvictableBucket(kTemp, bucket_exceptions, nullptr);
   EXPECT_TRUE(result.ok());
-  EXPECT_EQ(bucket2.bucket_id, result.value().id);
+  EXPECT_EQ(bucket_id2, result.value().id);
 }
 
 TEST_P(QuotaDatabaseTest, SetStorageKeyLastAccessTime) {
@@ -714,11 +756,10 @@
   EXPECT_EQ(db->SetStorageKeyLastAccessTime(storage_key, kTemp, now),
             QuotaError::kNone);
 
-  QuotaErrorOr<QuotaDatabase::BucketTableEntry> info =
-      db->GetBucketInfo(bucket->id);
+  QuotaErrorOr<mojom::BucketTableEntryPtr> info = db->GetBucketInfo(bucket->id);
   EXPECT_TRUE(info.ok());
-  EXPECT_EQ(now, info->last_accessed);
-  EXPECT_EQ(1, info->use_count);
+  EXPECT_EQ(now, info.value()->last_accessed);
+  EXPECT_EQ(1, info.value()->use_count);
 }
 
 TEST_P(QuotaDatabaseTest, GetStorageKeysForType) {
@@ -889,10 +930,10 @@
                     kDefaultBucketName, kTemp);
   ASSERT_TRUE(bucket_result.ok());
 
-  QuotaErrorOr<QuotaDatabase::BucketTableEntry> info =
+  QuotaErrorOr<mojom::BucketTableEntryPtr> info =
       db->GetBucketInfo(bucket_result->id);
   EXPECT_TRUE(info.ok());
-  EXPECT_EQ(0, info->use_count);
+  EXPECT_EQ(0, info.value()->use_count);
 
   EXPECT_EQ(db->SetStorageKeyLastAccessTime(
                 StorageKey::CreateFromStringForTesting("http://a/"), kTemp,
@@ -900,26 +941,35 @@
             QuotaError::kNone);
   info = db->GetBucketInfo(bucket_result->id);
   EXPECT_TRUE(info.ok());
-  EXPECT_EQ(1, info->use_count);
+  EXPECT_EQ(1, info.value()->use_count);
 
   EXPECT_EQ(db->RegisterInitialStorageKeyInfo(storage_keys_by_type),
             QuotaError::kNone);
 
   info = db->GetBucketInfo(bucket_result->id);
   EXPECT_TRUE(info.ok());
-  EXPECT_EQ(1, info->use_count);
+  EXPECT_EQ(1, info.value()->use_count);
 }
 
 TEST_P(QuotaDatabaseTest, DumpBucketTable) {
   base::Time now = base::Time::Now();
-  using Entry = QuotaDatabase::BucketTableEntry;
+  using Entry = mojom::BucketTableEntryPtr;
+
+  StorageKey storage_key1 =
+      StorageKey::CreateFromStringForTesting("http://go/");
+  StorageKey storage_key2 =
+      StorageKey::CreateFromStringForTesting("http://oo/");
+  StorageKey storage_key3 =
+      StorageKey::CreateFromStringForTesting("http://gle/");
+
   Entry kTableEntries[] = {
-      Entry(BucketId(1), StorageKey::CreateFromStringForTesting("http://go/"),
-            kTemp, kDefaultBucketName, 2147483647, now, now),
-      Entry(BucketId(2), StorageKey::CreateFromStringForTesting("http://oo/"),
-            kTemp, kDefaultBucketName, 0, now, now),
-      Entry(BucketId(3), StorageKey::CreateFromStringForTesting("http://gle/"),
-            kTemp, kDefaultBucketName, 1, now, now),
+      mojom::BucketTableEntry::New(1, storage_key1.Serialize(), kStorageTemp,
+                                   kDefaultBucketName, -1, 2147483647, now,
+                                   now),
+      mojom::BucketTableEntry::New(2, storage_key2.Serialize(), kStorageTemp,
+                                   kDefaultBucketName, -1, 0, now, now),
+      mojom::BucketTableEntry::New(3, storage_key3.Serialize(), kStorageTemp,
+                                   kDefaultBucketName, -1, 1, now, now),
   };
 
   auto db = CreateDatabase(use_in_memory_db());
@@ -927,7 +977,7 @@
   AssignBucketTable(db.get(), kTableEntries);
 
   using Verifier = EntryVerifier<Entry>;
-  Verifier verifier(kTableEntries, std::end(kTableEntries));
+  Verifier verifier(kTableEntries);
   EXPECT_EQ(DumpBucketTable(db.get(),
                             base::BindRepeating(&Verifier::Run,
                                                 base::Unretained(&verifier))),
@@ -936,32 +986,34 @@
 }
 
 TEST_P(QuotaDatabaseTest, GetBucketInfo) {
-  using Entry = QuotaDatabase::BucketTableEntry;
-  Entry kTableEntries[] = {
-      Entry(BucketId(123), StorageKey::CreateFromStringForTesting("http://go/"),
-            kTemp, "test_bucket", 100, base::Time(), base::Time())};
+  using Entry = mojom::BucketTableEntryPtr;
+  StorageKey storage_key = StorageKey::CreateFromStringForTesting("http://go/");
+  BucketId bucket_id = BucketId(123);
+  storage::mojom::StorageType type = kStorageTemp;
+
+  Entry kTableEntries[] = {mojom::BucketTableEntry::New(
+      bucket_id.value(), storage_key.Serialize(), type, "test_bucket", -1, 100,
+      base::Time(), base::Time())};
 
   auto db = CreateDatabase(use_in_memory_db());
   EXPECT_TRUE(EnsureOpened(db.get()));
   AssignBucketTable(db.get(), kTableEntries);
 
   {
-    QuotaErrorOr<QuotaDatabase::BucketTableEntry> entry =
-        db->GetBucketInfo(kTableEntries[0].bucket_id);
+    QuotaErrorOr<Entry> entry = db->GetBucketInfo(bucket_id);
     EXPECT_TRUE(entry.ok());
-    EXPECT_EQ(kTableEntries[0].bucket_id, entry->bucket_id);
-    EXPECT_EQ(kTableEntries[0].type, entry->type);
-    EXPECT_EQ(kTableEntries[0].storage_key, entry->storage_key);
-    EXPECT_EQ(kTableEntries[0].name, entry->name);
-    EXPECT_EQ(kTableEntries[0].use_count, entry->use_count);
-    EXPECT_EQ(kTableEntries[0].last_accessed, entry->last_accessed);
-    EXPECT_EQ(kTableEntries[0].last_modified, entry->last_modified);
+    EXPECT_EQ(bucket_id.value(), entry.value()->bucket_id);
+    EXPECT_EQ(type, entry.value()->type);
+    EXPECT_EQ(storage_key.Serialize(), entry.value()->storage_key);
+    EXPECT_EQ(kTableEntries[0]->name, entry.value()->name);
+    EXPECT_EQ(kTableEntries[0]->use_count, entry.value()->use_count);
+    EXPECT_EQ(kTableEntries[0]->last_accessed, entry.value()->last_accessed);
+    EXPECT_EQ(kTableEntries[0]->last_modified, entry.value()->last_modified);
   }
 
   {
     // BucketId 456 is not in the database.
-    QuotaErrorOr<QuotaDatabase::BucketTableEntry> entry =
-        db->GetBucketInfo(BucketId(456));
+    QuotaErrorOr<Entry> entry = db->GetBucketInfo(BucketId(456));
     EXPECT_FALSE(entry.ok());
   }
 }
diff --git a/storage/browser/quota/quota_internals.mojom b/storage/browser/quota/quota_internals.mojom
index 2e311777..39d676f 100644
--- a/storage/browser/quota/quota_internals.mojom
+++ b/storage/browser/quota/quota_internals.mojom
@@ -11,9 +11,9 @@
 struct BucketTableEntry {
     int64 bucket_id;
     string storage_key;
-    string type;
+    StorageType type;
     string name;
-    int64 usage;
+    int64 usage = -1;
     int64 use_count;
     mojo_base.mojom.Time last_accessed;
     mojo_base.mojom.Time last_modified;
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc
index a958fbf..f0a13738 100644
--- a/storage/browser/quota/quota_manager_impl.cc
+++ b/storage/browser/quota/quota_manager_impl.cc
@@ -14,6 +14,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/barrier_callback.h"
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -95,21 +96,6 @@
   return type == StorageType::kTemporary || type == StorageType::kPersistent;
 }
 
-std::string StorageTypeEnumToString(StorageType type) {
-  switch (type) {
-    case StorageType::kTemporary:
-      return "temporary";
-    case StorageType::kPersistent:
-      return "persistent";
-    case StorageType::kSyncable:
-      return "syncable";
-    case StorageType::kDeprecatedQuotaNotManaged:
-      return "quota-not-managed";
-    case StorageType::kUnknown:
-      return "unknown";
-  }
-}
-
 StorageType GetBlinkStorageType(storage::mojom::StorageType type) {
   switch (type) {
     case storage::mojom::StorageType::kTemporary:
@@ -1005,12 +991,12 @@
       return;
     }
     manager->DidDatabaseWork(error != QuotaError::kDatabaseError);
-    std::move(callback).Run(entries_);
+    std::move(callback).Run(std::move(entries_));
   }
 
  private:
-  bool AppendEntry(const BucketTableEntry& entry) {
-    entries_.push_back(entry);
+  bool AppendEntry(mojom::BucketTableEntryPtr entry) {
+    entries_.push_back(std::move(entry));
     return true;
   }
 
@@ -2102,51 +2088,44 @@
 
 void QuotaManagerImpl::RetrieveBucketUsageForBucketTable(
     RetrieveBucketsTableCallback callback,
-    const BucketTableEntries& entries) {
+    BucketTableEntries entries) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  auto* buckets = new std::vector<storage::mojom::BucketTableEntryPtr>;
-
-  base::RepeatingClosure barrier = base::BarrierClosure(
-      entries.size(),
-      base::BindOnce(
-          [](RetrieveBucketsTableCallback callback,
-             std::vector<storage::mojom::BucketTableEntryPtr>* buckets) {
-            std::move(callback).Run(std::move(*buckets));
-          },
-          std::move(callback), base::Owned(buckets)));
+  base::RepeatingCallback<void(mojom::BucketTableEntryPtr)> barrier =
+      base::BarrierCallback<mojom::BucketTableEntryPtr>(entries.size(),
+                                                        std::move(callback));
 
   for (auto& entry : entries) {
-    DCHECK(IsSupportedType(entry.type));
+    StorageType type = static_cast<StorageType>(entry->type);
+    DCHECK(IsSupportedType(type));
+
+    absl::optional<StorageKey> storage_key =
+        StorageKey::Deserialize(entry->storage_key);
+    DCHECK(storage_key.has_value());
+
+    BucketId bucket_id = BucketId(entry->bucket_id);
+
+    BucketLocator bucket_locator =
+        BucketLocator(bucket_id, std::move(storage_key).value(), type,
+                      entry->name == kDefaultBucketName);
 
     GetBucketUsageWithBreakdown(
-        entry.ToBucketLocator(),
+        bucket_locator,
         base::BindOnce(&QuotaManagerImpl::AddBucketTableEntry,
-                       weak_factory_.GetWeakPtr(), entry, barrier, buckets));
+                       weak_factory_.GetWeakPtr(), std::move(entry), barrier));
   }
 }
 
 void QuotaManagerImpl::AddBucketTableEntry(
-    const BucketTableEntry& entry,
-    base::OnceClosure barrier_callback,
-    std::vector<storage::mojom::BucketTableEntryPtr>* buckets,
+    mojom::BucketTableEntryPtr entry,
+    base::OnceCallback<void(mojom::BucketTableEntryPtr)> barrier_callback,
     int64_t usage,
-    blink::mojom::UsageBreakdownPtr bucketUsageBreakdown) {
+    blink::mojom::UsageBreakdownPtr bucket_usage_breakdown) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  storage::mojom::BucketTableEntryPtr mojo_entry =
-      storage::mojom::BucketTableEntry::New();
-  mojo_entry->bucket_id = entry.bucket_id.value();
-  mojo_entry->storage_key = entry.storage_key.Serialize();
-  mojo_entry->type = StorageTypeEnumToString(entry.type);
-  mojo_entry->name = entry.name;
-  mojo_entry->use_count = entry.use_count;
-  mojo_entry->last_accessed = entry.last_accessed;
-  mojo_entry->last_modified = entry.last_modified;
-  mojo_entry->usage = usage;
+  entry->usage = usage;
 
-  buckets->emplace_back(std::move(mojo_entry));
-  std::move(barrier_callback).Run();
+  std::move(barrier_callback).Run(std::move(entry));
 }
 
 void QuotaManagerImpl::StartEviction() {
@@ -2183,7 +2162,7 @@
 }
 
 void QuotaManagerImpl::DidBucketDataEvicted(
-    QuotaDatabase::BucketTableEntry entry,
+    mojom::BucketTableEntryPtr entry,
     blink::mojom::QuotaStatusCode status) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(io_thread_->BelongsToCurrentThread());
@@ -2199,10 +2178,10 @@
     base::Time now = QuotaDatabase::GetNow();
     base::UmaHistogramCounts1M(
         QuotaManagerImpl::kEvictedBucketAccessedCountHistogram,
-        entry.use_count);
+        entry->use_count);
     base::UmaHistogramCounts1000(
         QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram,
-        (now - entry.last_accessed).InDays());
+        (now - entry->last_accessed).InDays());
   }
 
   std::move(eviction_context_.evict_bucket_data_callback).Run(status);
@@ -2453,24 +2432,27 @@
 }
 
 void QuotaManagerImpl::DidDumpBucketTableForHistogram(
-    const BucketTableEntries& entries) {
+    BucketTableEntries entries) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::map<StorageKey, int64_t> usage_map =
       GetUsageTracker(StorageType::kTemporary)->GetCachedStorageKeysUsage();
   base::Time now = QuotaDatabase::GetNow();
   for (const auto& info : entries) {
-    if (info.type != StorageType::kTemporary)
+    if (info->type != storage::mojom::StorageType::kTemporary)
       continue;
 
+    absl::optional<StorageKey> storage_key =
+        StorageKey::Deserialize(info->storage_key);
+
     // Ignore stale database entries. If there is no map entry, the storage
     // key's data has been deleted.
-    auto it = usage_map.find(info.storage_key);
+    auto it = usage_map.find(*storage_key);
     if (it == usage_map.end() || it->second == 0)
       continue;
 
     base::TimeDelta age =
-        now - std::max(info.last_accessed, info.last_modified);
+        now - std::max(info->last_accessed, info->last_modified);
     UMA_HISTOGRAM_COUNTS_1000("Quota.AgeOfOriginInDays", age.InDays());
 
     int64_t kilobytes = std::max(it->second / int64_t{1024}, int64_t{1});
@@ -2558,7 +2540,7 @@
 
 void QuotaManagerImpl::DidGetBucketInfoForEviction(
     const BucketLocator& bucket,
-    QuotaErrorOr<QuotaDatabase::BucketTableEntry> result) {
+    QuotaErrorOr<mojom::BucketTableEntryPtr> result) {
   DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError);
 
   if (!result.ok()) {
@@ -2570,7 +2552,7 @@
   DeleteBucketDataInternal(
       bucket, AllQuotaClientTypes(),
       base::BindOnce(&QuotaManagerImpl::DidBucketDataEvicted,
-                     weak_factory_.GetWeakPtr(), result.value()));
+                     weak_factory_.GetWeakPtr(), std::move(result.value())));
 }
 
 void QuotaManagerImpl::GetEvictionRoundInfo(
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h
index 924c296..75ffaf97 100644
--- a/storage/browser/quota/quota_manager_impl.h
+++ b/storage/browser/quota/quota_manager_impl.h
@@ -531,15 +531,13 @@
     std::set<int> active_override_session_ids;
   };
 
-  using BucketTableEntry = QuotaDatabase::BucketTableEntry;
-  using BucketTableEntries = std::vector<BucketTableEntry>;
+  using BucketTableEntries = std::vector<mojom::BucketTableEntryPtr>;
   using StorageKeysByType =
       base::flat_map<blink::mojom::StorageType, std::set<blink::StorageKey>>;
 
   using QuotaSettingsCallback = base::OnceCallback<void(const QuotaSettings&)>;
 
-  using DumpBucketTableCallback =
-      base::OnceCallback<void(const BucketTableEntries&)>;
+  using DumpBucketTableCallback = base::OnceCallback<void(BucketTableEntries)>;
 
   // The values returned total_space, available_space.
   using StorageCapacityCallback = base::OnceCallback<void(int64_t, int64_t)>;
@@ -591,13 +589,12 @@
       GetDiskAvailabilityAndTempPoolSizeCallback callback,
       std::unique_ptr<AccumulateQuotaInternalsInfo> info);
   void RetrieveBucketUsageForBucketTable(RetrieveBucketsTableCallback callback,
-                                         const BucketTableEntries& entries);
+                                         BucketTableEntries entries);
   void AddBucketTableEntry(
-      const BucketTableEntry& entry,
-      base::OnceClosure barrier_callback,
-      std::vector<storage::mojom::BucketTableEntryPtr>* buckets,
+      mojom::BucketTableEntryPtr entry,
+      base::OnceCallback<void(mojom::BucketTableEntryPtr)> barrier_callback,
       int64_t usage,
-      blink::mojom::UsageBreakdownPtr bucketUsageBreakdown);
+      blink::mojom::UsageBreakdownPtr bucket_usage_breakdown);
 
   // Runs BucketDataDeleter which calls QuotaClients to clear data for the
   // bucket. Once the task is complete, calls the QuotaDatabase to delete the
@@ -638,7 +635,7 @@
   void DeleteBucketFromDatabase(const BucketLocator& bucket,
                                 base::OnceCallback<void(QuotaError)> callback);
 
-  void DidBucketDataEvicted(QuotaDatabase::BucketTableEntry entry,
+  void DidBucketDataEvicted(mojom::BucketTableEntryPtr entry,
                             blink::mojom::QuotaStatusCode status);
 
   void ReportHistogram();
@@ -649,7 +646,7 @@
                                          int64_t available_space);
   void DidGetPersistentGlobalUsageForHistogram(int64_t usage,
                                                int64_t unlimited_usage);
-  void DidDumpBucketTableForHistogram(const BucketTableEntries& entries);
+  void DidDumpBucketTableForHistogram(BucketTableEntries entries);
 
   // Returns the list of bucket ids that should be excluded from eviction due to
   // consistent errors after multiple attempts.
@@ -666,7 +663,7 @@
 
   void DidGetBucketInfoForEviction(
       const BucketLocator& bucket,
-      QuotaErrorOr<QuotaDatabase::BucketTableEntry> result);
+      QuotaErrorOr<mojom::BucketTableEntryPtr> result);
 
   void DidGetEvictionRoundInfo();
 
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index b8963c1..5464dd6f 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -67,6 +67,11 @@
 const StorageType kPerm = StorageType::kPersistent;
 const StorageType kSync = StorageType::kSyncable;
 
+const storage::mojom::StorageType kStorageTemp =
+    storage::mojom::StorageType::kTemporary;
+const storage::mojom::StorageType kStoragePerm =
+    storage::mojom::StorageType::kPersistent;
+
 // Values in bytes.
 const int64_t kAvailableSpaceForApp = 13377331U;
 const int64_t kMustRemainAvailableForSystem = kAvailableSpaceForApp / 2;
@@ -132,10 +137,11 @@
 }
 
 MATCHER_P3(MatchesBucketTableEntry, storage_key, type, use_count, "") {
-  return testing::ExplainMatchResult(storage_key, arg.storage_key,
+  return testing::ExplainMatchResult(storage_key, arg->storage_key,
                                      result_listener) &&
-         testing::ExplainMatchResult(type, arg.type, result_listener) &&
-         testing::ExplainMatchResult(use_count, arg.use_count, result_listener);
+         testing::ExplainMatchResult(type, arg->type, result_listener) &&
+         testing::ExplainMatchResult(use_count, arg->use_count,
+                                     result_listener);
 }
 
 }  // namespace
@@ -456,9 +462,8 @@
 
   BucketTableEntries DumpBucketTable() {
     base::test::TestFuture<BucketTableEntries> future;
-    quota_manager_impl_->DumpBucketTable(
-        future.GetCallback<const BucketTableEntries&>());
-    return future.Get();
+    quota_manager_impl_->DumpBucketTable(future.GetCallback());
+    return future.Take();
   }
 
   std::vector<storage::mojom::BucketTableEntryPtr> RetrieveBucketsTable() {
@@ -2469,17 +2474,21 @@
 
   const BucketTableEntries& entries = DumpBucketTable();
   for (const auto& entry : entries) {
-    if (entry.type != kTemp)
+    if (entry->type != kStorageTemp)
       continue;
 
+    absl::optional<StorageKey> storage_key =
+        StorageKey::Deserialize(entry->storage_key);
+    ASSERT_TRUE(storage_key.has_value());
+
     EXPECT_NE(std::string("http://foo.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("http://foo.com:1/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("https://foo.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("http://bar.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              std::move(storage_key).value().origin().GetURL().spec());
   }
 
   global_usage_result = GetGlobalUsage(kTemp);
@@ -2561,17 +2570,21 @@
 
   const BucketTableEntries& entries = DumpBucketTable();
   for (const auto& entry : entries) {
-    if (entry.type != kPerm)
+    if (entry->type != kStoragePerm)
       continue;
 
+    absl::optional<StorageKey> storage_key =
+        StorageKey::Deserialize(entry->storage_key);
+    ASSERT_TRUE(storage_key.has_value());
+
     EXPECT_NE(std::string("http://foo.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("http://foo.com:1/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("https://foo.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              storage_key.value().origin().GetURL().spec());
     EXPECT_NE(std::string("http://bar.com/"),
-              entry.storage_key.origin().GetURL().spec());
+              std::move(storage_key).value().origin().GetURL().spec());
   }
 
   global_usage_result = GetGlobalUsage(kTemp);
@@ -3111,9 +3124,11 @@
   task_environment_.RunUntilIdle();
 
   const BucketTableEntries& entries = DumpBucketTable();
-  EXPECT_THAT(entries, testing::UnorderedElementsAre(
-                           MatchesBucketTableEntry(kStorageKey, kTemp, 1),
-                           MatchesBucketTableEntry(kStorageKey, kPerm, 2)));
+  EXPECT_THAT(
+      entries,
+      testing::UnorderedElementsAre(
+          MatchesBucketTableEntry(kStorageKey.Serialize(), kStorageTemp, 1),
+          MatchesBucketTableEntry(kStorageKey.Serialize(), kStoragePerm, 2)));
 }
 
 TEST_F(QuotaManagerImplTest, RetrieveBucketsTable) {
@@ -3144,7 +3159,7 @@
       FindBucketTableEntry(bucket_table_entries, temp_bucket->id);
   EXPECT_TRUE(temp_entry);
   EXPECT_EQ(temp_entry->storage_key, kSerializedStorageKey);
-  EXPECT_EQ(temp_entry->type, "temporary");
+  EXPECT_EQ(temp_entry->type, kStorageTemp);
   EXPECT_EQ(temp_entry->name, kDefaultBucketName);
   EXPECT_EQ(temp_entry->use_count, 1);
   EXPECT_EQ(temp_entry->last_accessed, kAccessTime);
@@ -3156,7 +3171,7 @@
       FindBucketTableEntry(bucket_table_entries, perm_bucket->id);
   EXPECT_TRUE(perm_entry);
   EXPECT_EQ(perm_entry->storage_key, kSerializedStorageKey);
-  EXPECT_EQ(perm_entry->type, "persistent");
+  EXPECT_EQ(perm_entry->type, kStoragePerm);
   EXPECT_EQ(perm_entry->name, kDefaultBucketName);
   EXPECT_EQ(perm_entry->use_count, 1);
   EXPECT_EQ(perm_entry->last_accessed, kAccessTime);
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 3e559ab..69cf7c46 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1932,7 +1932,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R105-14943.0.0",
+        "cros_img": "atlas-release/R105-14961.0.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1948,7 +1948,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R104-14909.26.0",
+        "cros_img": "atlas-release/R104-14909.52.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1980,7 +1980,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R105-14959.0.0",
+        "cros_img": "eve-release/R105-14979.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1996,7 +1996,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R104-14909.26.0",
+        "cros_img": "eve-release/R105-14961.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2012,7 +2012,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R104-14909.26.0",
+        "cros_img": "eve-release/R104-14909.52.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2087,7 +2087,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R105-14959.0.0",
+        "cros_img": "hana-release/R105-14979.0.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2119,7 +2119,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.26.0",
+        "cros_img": "hana-release/R104-14909.52.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2151,7 +2151,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R105-14959.0.0",
+        "cros_img": "jacuzzi-release/R105-14979.0.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2183,7 +2183,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.26.0",
+        "cros_img": "jacuzzi-release/R104-14909.52.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_BETA",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index ef06443d..3650f7f5 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -3571,7 +3571,8 @@
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
-          "--git-revision=${got_revision}"
+          "--git-revision=${got_revision}",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter"
         ],
         "isolate_profile_data": true,
         "merge": {
@@ -8267,15 +8268,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8301,7 +8302,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8352,15 +8353,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8386,7 +8387,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8777,15 +8778,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8811,7 +8812,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8862,15 +8863,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8896,7 +8897,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 68be087..6914b80b 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46513,15 +46513,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46547,7 +46547,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46598,15 +46598,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46632,7 +46632,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47023,15 +47023,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47057,7 +47057,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47108,15 +47108,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47142,7 +47142,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47537,15 +47537,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47571,7 +47571,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47622,15 +47622,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47656,7 +47656,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48047,15 +48047,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48081,7 +48081,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48132,15 +48132,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48166,7 +48166,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48629,15 +48629,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48663,7 +48663,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48714,15 +48714,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48748,7 +48748,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49139,15 +49139,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49173,7 +49173,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49224,15 +49224,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49258,7 +49258,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49721,15 +49721,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49755,7 +49755,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49806,15 +49806,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49840,7 +49840,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50231,15 +50231,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50265,7 +50265,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.139"
+              "revision": "version:103.0.5060.140"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50316,15 +50316,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50350,7 +50350,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.57"
+              "revision": "version:104.0.5112.59"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/filters/android.emulator_11.gl_tests.filter b/testing/buildbot/filters/android.emulator_11.gl_tests.filter
index c9c440c..416a201 100644
--- a/testing/buildbot/filters/android.emulator_11.gl_tests.filter
+++ b/testing/buildbot/filters/android.emulator_11.gl_tests.filter
@@ -8,10 +8,10 @@
 -CopyType/GLCopyTextureCHROMIUMTest.ImmutableTexture/1
 -GLBGRAMipMapTest.GenerateMipmapsSucceeds
 -RasterInProcessCommandBufferTest.AllowedBetweenBeginEndRasterCHROMIUM
--SharedImageBackingFactoryAHBTest.Basic
--SharedImageBackingFactoryAHBTest.CanHaveMultipleReaders
--SharedImageBackingFactoryAHBTest.CannotReadWhileWriting
--SharedImageBackingFactoryAHBTest.CannotWriteWhileReading
--SharedImageBackingFactoryAHBTest.GLSkiaGL
--SharedImageBackingFactoryAHBTest.InitialData
--SharedImageBackingFactoryAHBTest.Overlay
+-AHardwareBufferImageBackingFactoryTest.Basic
+-AHardwareBufferImageBackingFactoryTest.CanHaveMultipleReaders
+-AHardwareBufferImageBackingFactoryTest.CannotReadWhileWriting
+-AHardwareBufferImageBackingFactoryTest.CannotWriteWhileReading
+-AHardwareBufferImageBackingFactoryTest.GLSkiaGL
+-AHardwareBufferImageBackingFactoryTest.InitialData
+-AHardwareBufferImageBackingFactoryTest.Overlay
diff --git a/testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter
new file mode 100644
index 0000000..a8b411e
--- /dev/null
+++ b/testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter
@@ -0,0 +1,11 @@
+# TODO(crbug/1280257)
+-org.chromium.chrome.browser.tasks.tab_management.TabSuggestionMessageCardTest.closeTabSuggestionReviewedAndDismissed
+
+# TODO(crbug/1231259)
+-org.chromium.chrome.browser.keyboard_accessory.sheet_tabs.AddressAccessoryIntegrationTest.testFillsSuggestionOnClick
+
+# TODO(crbug/1345499)
+-org.chromium.chrome.browser.tasks.tab_management.TabGridDialogTest.testSwipeToDismiss_Dialog
+
+# TODO(crbug/1345504)
+-org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testTextDetection
diff --git a/testing/buildbot/filters/chromeos.amd64-generic.gl_tests_validating.filter b/testing/buildbot/filters/chromeos.amd64-generic.gl_tests_validating.filter
index 8e7c3a2b..1761966 100644
--- a/testing/buildbot/filters/chromeos.amd64-generic.gl_tests_validating.filter
+++ b/testing/buildbot/filters/chromeos.amd64-generic.gl_tests_validating.filter
@@ -21,8 +21,8 @@
 -TranslatorVariants/EXTBlendFuncExtendedES3DrawTest.ES3GettersArray*
 
 # crbug.com/1314124
--ExternalVkImageFactoryTest.SkiaVulkanWrite_DawnRead
--ExternalVkImageFactoryTest.DawnWrite_SkiaVulkanRead
+-ExternalVkImageBackingFactoryTest.SkiaVulkanWrite_DawnRead
+-ExternalVkImageBackingFactoryTest.DawnWrite_SkiaVulkanRead
 
 # crbug.com/1314468
 -GpuMemoryBufferTestEGL.GLCreateImageCHROMIUMFromNativePixmap
diff --git a/testing/buildbot/filters/chromeos.kevin.gl_tests_validating.filter b/testing/buildbot/filters/chromeos.kevin.gl_tests_validating.filter
index a848f717..bc47c40 100644
--- a/testing/buildbot/filters/chromeos.kevin.gl_tests_validating.filter
+++ b/testing/buildbot/filters/chromeos.kevin.gl_tests_validating.filter
@@ -9,8 +9,8 @@
 -WebGPUTest.*
 
 # crbug.com/1314124
--ExternalVkImageFactoryTest.SkiaVulkanWrite_DawnRead
--ExternalVkImageFactoryTest.DawnWrite_SkiaVulkanRead
+-ExternalVkImageBackingFactoryTest.SkiaVulkanWrite_DawnRead
+-ExternalVkImageBackingFactoryTest.DawnWrite_SkiaVulkanRead
 -WebGPUTest.ExplicitFallbackAdapterIsDisallowed
 
 # crbug.com/1314463
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 6ada5f19..145b892 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1037,7 +1037,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14959.0.0",
+        "cros_img": "octopus-release/R105-14979.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1049,7 +1049,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14943.0.0",
+        "cros_img": "octopus-release/R105-14961.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1061,7 +1061,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.26.0",
+        "cros_img": "octopus-release/R104-14909.52.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1085,7 +1085,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14959.0.0",
+        "cros_img": "octopus-release/R105-14979.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1096,7 +1096,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14943.0.0",
+        "cros_img": "octopus-release/R105-14961.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1107,7 +1107,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.26.0",
+        "cros_img": "octopus-release/R104-14909.52.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1136,7 +1136,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14959.0.0",
+        "cros_img": "strongbad-release/R105-14979.0.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1148,7 +1148,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14943.0.0",
+        "cros_img": "strongbad-release/R105-14961.0.0",
         "name": "lacros_all_tast_tests strongbad_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1160,7 +1160,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.26.0",
+        "cros_img": "strongbad-release/R104-14909.52.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1184,7 +1184,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14959.0.0",
+        "cros_img": "strongbad-release/R105-14979.0.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1195,7 +1195,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14943.0.0",
+        "cros_img": "strongbad-release/R105-14961.0.0",
         "name": "ozone_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1206,7 +1206,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.26.0",
+        "cros_img": "strongbad-release/R104-14909.52.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1228,7 +1228,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14959.0.0",
+        "cros_img": "strongbad-release/R105-14979.0.0",
         "name": "viz_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1239,7 +1239,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14943.0.0",
+        "cros_img": "strongbad-release/R105-14961.0.0",
         "name": "viz_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
@@ -1250,7 +1250,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.26.0",
+        "cros_img": "strongbad-release/R104-14909.52.0",
         "name": "viz_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 72ae133..7a2bb81d 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1284,6 +1284,11 @@
           'shards': 25,
         },
       },
+      'android-nougat-x86-rel': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter',
+        ],
+      },
       'android-pie-arm64-rel': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64_rel.chrome_public_test_apk.filter', # https://crbug.com/1010211
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index a202a09..2fb73c5 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -529,16 +529,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -546,23 +546,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57'
+          'revision': 'version:104.0.5112.59',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -570,10 +570,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139'
+          'revision': 'version:103.0.5060.140',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -673,16 +673,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -690,23 +690,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57'
+          'revision': 'version:104.0.5112.59',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -714,10 +714,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139'
+          'revision': 'version:103.0.5060.140',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -817,16 +817,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
-      '--client-version=104'
+      '--client-version=104',
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -834,23 +834,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.57'
+          'revision': 'version:104.0.5112.59',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
-      '--client-version=103'
+      '--client-version=103',
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -858,10 +858,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.139'
+          'revision': 'version:103.0.5060.140',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -971,8 +971,8 @@
   'CROS_ATLAS_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '105.0.5140.0',
-      'cros_img': 'atlas-release/R105-14943.0.0',
+      'cros_chrome_version': '105.0.5161.0',
+      'cros_img': 'atlas-release/R105-14961.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_DEV',
@@ -980,8 +980,8 @@
   'CROS_ATLAS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'atlas-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'atlas-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_BETA',
@@ -998,8 +998,8 @@
   'CROS_EVE_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '105.0.5158.0',
-      'cros_img': 'eve-release/R105-14959.0.0',
+      'cros_chrome_version': '105.0.5180.0',
+      'cros_img': 'eve-release/R105-14979.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_LKGM',
@@ -1007,8 +1007,8 @@
   'CROS_EVE_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'eve-release/R104-14909.26.0',
+      'cros_chrome_version': '105.0.5161.0',
+      'cros_img': 'eve-release/R105-14961.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_DEV',
@@ -1016,8 +1016,8 @@
   'CROS_EVE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'eve-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'eve-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_BETA',
@@ -1043,8 +1043,8 @@
   'CROS_HANA_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '105.0.5158.0',
-      'cros_img': 'hana-release/R105-14959.0.0',
+      'cros_chrome_version': '105.0.5180.0',
+      'cros_img': 'hana-release/R105-14979.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_LKGM',
@@ -1061,8 +1061,8 @@
   'CROS_HANA_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'hana-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'hana-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_BETA',
@@ -1079,8 +1079,8 @@
   'CROS_JACUZZI_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '105.0.5158.0',
-      'cros_img': 'jacuzzi-release/R105-14959.0.0',
+      'cros_chrome_version': '105.0.5180.0',
+      'cros_img': 'jacuzzi-release/R105-14979.0.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_LKGM',
@@ -1097,8 +1097,8 @@
   'CROS_JACUZZI_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'jacuzzi-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'jacuzzi-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_BETA',
@@ -1124,8 +1124,8 @@
   'CROS_OCTOPUS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '105.0.5158.0',
-      'cros_img': 'octopus-release/R105-14959.0.0',
+      'cros_chrome_version': '105.0.5180.0',
+      'cros_img': 'octopus-release/R105-14979.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_LKGM',
@@ -1133,8 +1133,8 @@
   'CROS_OCTOPUS_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '105.0.5140.0',
-      'cros_img': 'octopus-release/R105-14943.0.0',
+      'cros_chrome_version': '105.0.5161.0',
+      'cros_img': 'octopus-release/R105-14961.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_DEV',
@@ -1142,8 +1142,8 @@
   'CROS_OCTOPUS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'octopus-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'octopus-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_BETA',
@@ -1160,8 +1160,8 @@
   'CROS_STRONGBAD_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '105.0.5158.0',
-      'cros_img': 'strongbad-release/R105-14959.0.0',
+      'cros_chrome_version': '105.0.5180.0',
+      'cros_img': 'strongbad-release/R105-14979.0.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_LKGM',
@@ -1169,8 +1169,8 @@
   'CROS_STRONGBAD_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '105.0.5140.0',
-      'cros_img': 'strongbad-release/R105-14943.0.0',
+      'cros_chrome_version': '105.0.5161.0',
+      'cros_img': 'strongbad-release/R105-14961.0.0',
     },
     'enabled': True,
     'identifier': 'strongbad_RELEASE_DEV',
@@ -1178,8 +1178,8 @@
   'CROS_STRONGBAD_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '104.0.5112.23',
-      'cros_img': 'strongbad-release/R104-14909.26.0',
+      'cros_chrome_version': '104.0.5112.36',
+      'cros_img': 'strongbad-release/R104-14909.52.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_BETA',
diff --git a/testing/scripts/run_finch_smoke_tests_android.py b/testing/scripts/run_finch_smoke_tests_android.py
index cce1cb6..77af282 100755
--- a/testing/scripts/run_finch_smoke_tests_android.py
+++ b/testing/scripts/run_finch_smoke_tests_android.py
@@ -329,8 +329,10 @@
     ret = super(FinchTestCase, self).run_test()
     self.stop_browser()
 
+    self._include_variation_prefix(test_run_variation)
+    self.process_and_upload_results()
     with open(self.wpt_output, 'r') as curr_test_results:
-      curr_results_dict = json.loads(curr_test_results.read())
+      curr_results_dict = json.load(curr_test_results)
       results_dict['tests'][test_run_variation] = curr_results_dict['tests']
       # Compare screenshots with baselines stored in Skia Gold
       ret |= self._compare_screenshots_with_baselines(curr_results_dict)
@@ -341,6 +343,13 @@
 
     return ret
 
+  def _include_variation_prefix(self, test_run_variation):
+    with open(self.wpt_output, 'r') as test_results_file:
+      results = json.load(test_results_file)
+    results.setdefault('metadata', {})['test_name_prefix'] = test_run_variation
+    with open(self.wpt_output, 'w+') as test_results_file:
+      json.dump(results, test_results_file)
+
   def stop_browser(self):
     logger.info('Stopping package %s', self.browser_package_name)
     self._device.ForceStop(self.browser_package_name)
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py
index dfb22c1f..f1ab0ad 100755
--- a/testing/scripts/run_wpt_tests.py
+++ b/testing/scripts/run_wpt_tests.py
@@ -198,7 +198,11 @@
                 os.makedirs(self._metadata_dir)
             return super().run_test()
 
+    def do_post_test_run_tasks(self):
+        self.process_and_upload_results()
+
     def clean_up_after_test_run(self):
+        super().clean_up_after_test_run()
         # Avoid having a dangling reference to the temp directory
         # which was deleted
         self._metadata_dir = None
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py
index 33cb0c3..6cf00ced 100644
--- a/testing/scripts/wpt_common.py
+++ b/testing/scripts/wpt_common.py
@@ -49,9 +49,6 @@
         self.fs = host.filesystem
         self.path_finder = PathFinder(self.fs)
         self.port = host.port_factory.get()
-        # Path to the output of the test run. Comes from the args passed to the
-        # run, parsed after this constructor. Can be overwritten by tests.
-        self.wpt_output = None
         self.wptreport = None
         self._include_filename = None
         self.layout_test_results_subdir = 'layout-test-results'
@@ -242,8 +239,12 @@
         if report is not None:
             if not report:
                 report = self._default_wpt_report()
-            wpt_output = self.options.isolated_script_test_output
-            self.wptreport = self.fs.join(self.fs.dirname(wpt_output), report)
+            self.wptreport = self.fs.join(self.fs.dirname(self.wpt_output),
+                                          report)
+
+    @property
+    def wpt_output(self):
+        return self.options.isolated_script_test_output
 
     def _show_wpt_help(self):
         command = [
@@ -317,10 +318,7 @@
                 rest_args.append(unknown_arg)
         return rest_args
 
-    def do_post_test_run_tasks(self):
-        if not self.wpt_output and self.options:
-            self.wpt_output = self.options.isolated_script_test_output
-
+    def process_and_upload_results(self):
         command = [
             self.select_python_executable(),
             os.path.join(BLINK_TOOLS_DIR, 'wpt_process_results.py'),
@@ -340,6 +338,7 @@
             command.extend(['--wpt-report', self.wptreport])
         common.run_command(command)
 
+    def clean_up_after_test_run(self):
         if self._include_filename:
             self.fs.remove(self._include_filename)
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 482ab77..4a59473 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2234,6 +2234,19 @@
                     ]
                 }
             ]
+        },
+        {
+            "platforms": [
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "ChromeRootStoreUsed"
+                    ]
+                }
+            ]
         }
     ],
     "ChangeExtensionEventPageSuspendDelay": [
@@ -6181,24 +6194,6 @@
             ]
         }
     ],
-    "OmniboxPedalsActionsIOS": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_Variation2",
-                    "params": {
-                        "PopupUIVariant": "variant-two"
-                    },
-                    "enable_features": [
-                        "IOSOmniboxUpdatedPopupUI"
-                    ]
-                }
-            ]
-        }
-    ],
     "OmniboxPostTaskFocusTabAndroid": [
         {
             "platforms": [
@@ -6647,22 +6642,6 @@
             ]
         }
     ],
-    "PartitionAllocPCScanBlinkPartitions": [
-        {
-            "platforms": [
-                "windows",
-                "linux"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PartitionAllocPCScanBlinkPartitions"
-                    ]
-                }
-            ]
-        }
-    ],
     "PartitionAllocSortActiveSlotSpans": [
         {
             "platforms": [
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index acb427e..a31447c 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -669,6 +669,10 @@
                                     ax::mojom::EventFrom event_from,
                                     ax::mojom::Action event_from_action) {}
 
+  // Adds automatic label annotations for |obj| and stores them
+  // in |dst|. This method assumes the object is an image.
+  virtual void AddImageAnnotations(WebAXObject& obj, ui::AXNodeData* dst) {}
+
   // Audio Output Devices API --------------------------------------------
 
   // Checks that the given audio sink exists and is authorized. The result is
diff --git a/third_party/blink/renderer/core/css/css_image_set_value.cc b/third_party/blink/renderer/core/css/css_image_set_value.cc
index c62e08b9..6cc75477 100644
--- a/third_party/blink/renderer/core/css/css_image_set_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -109,7 +109,7 @@
     // TODO(fs): Forward the image request behavior when other code is prepared
     // to handle it.
     FetchParameters params = image_value.PrepareFetch(
-        document, FetchParameters::kNone, cross_origin);
+        document, FetchParameters::ImageRequestBehavior::kNone, cross_origin);
     cached_image_ = MakeGarbageCollected<StyleFetchedImageSet>(
         ImageResourceContent::Fetch(params, document.Fetcher()),
         image.scale_factor, this, params.Url());
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index f66e81b..ff7b398 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -105,7 +105,8 @@
   }
 
   bool is_lazily_loaded =
-      image_request_behavior == FetchParameters::kDeferImageLoad &&
+      image_request_behavior ==
+          FetchParameters::ImageRequestBehavior::kDeferImageLoad &&
       // Only http/https images are eligible to be lazily loaded.
       params.Url().ProtocolIsInHTTPFamily();
   if (is_lazily_loaded)
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index 41e9777..bd837a1 100644
--- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
+++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -82,10 +82,10 @@
         pre_cached_container_sizes_(pre_cached_container_sizes),
         device_scale_factor_(device_scale_factor) {}
 
-  StyleImage* Load(
-      CSSValue&,
-      FetchParameters::ImageRequestBehavior = FetchParameters::kNone,
-      CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
+  StyleImage* Load(CSSValue&,
+                   FetchParameters::ImageRequestBehavior =
+                       FetchParameters::ImageRequestBehavior::kNone,
+                   CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
 
  private:
   StyleImage* CrossfadeArgument(CSSValue&, CrossOriginAttributeValue);
@@ -152,7 +152,8 @@
   // a LayoutObject) that we can't meet with the current implementation.
   if (IsA<CSSPaintValue>(value))
     return nullptr;
-  return Load(value, FetchParameters::kNone, cross_origin);
+  return Load(value, FetchParameters::ImageRequestBehavior::kNone,
+              cross_origin);
 }
 
 }  // namespace
@@ -326,7 +327,7 @@
           if (auto* pending_value =
                   PendingCssValue(background_layer->GetImage())) {
             FetchParameters::ImageRequestBehavior image_request_behavior =
-                FetchParameters::kNone;
+                FetchParameters::ImageRequestBehavior::kNone;
             StyleImage* new_image =
                 loader.Load(*pending_value, image_request_behavior);
             if (new_image && new_image->IsLazyloadPossiblyDeferred()) {
@@ -393,9 +394,9 @@
         for (FillLayer* mask_layer = &style.AccessMaskLayers(); mask_layer;
              mask_layer = mask_layer->Next()) {
           if (auto* pending_value = PendingCssValue(mask_layer->GetImage())) {
-            mask_layer->SetImage(loader.Load(*pending_value,
-                                             FetchParameters::kNone,
-                                             kCrossOriginAttributeAnonymous));
+            mask_layer->SetImage(loader.Load(
+                *pending_value, FetchParameters::ImageRequestBehavior::kNone,
+                kCrossOriginAttributeAnonymous));
           }
         }
         break;
@@ -403,9 +404,9 @@
       case CSSPropertyID::kShapeOutside:
         if (ShapeValue* shape_value = style.ShapeOutside()) {
           if (auto* pending_value = PendingCssValue(shape_value->GetImage())) {
-            shape_value->SetImage(loader.Load(*pending_value,
-                                              FetchParameters::kNone,
-                                              kCrossOriginAttributeAnonymous));
+            shape_value->SetImage(loader.Load(
+                *pending_value, FetchParameters::ImageRequestBehavior::kNone,
+                kCrossOriginAttributeAnonymous));
           }
         }
         break;
diff --git a/third_party/blink/renderer/core/css/style_image_cache.cc b/third_party/blink/renderer/core/css/style_image_cache.cc
index d2856723..d36c2f7a 100644
--- a/third_party/blink/renderer/core/css/style_image_cache.cc
+++ b/third_party/blink/renderer/core/css/style_image_cache.cc
@@ -19,7 +19,8 @@
   if (result.is_new_entry || !result.stored_value->value) {
     result.stored_value->value = MakeGarbageCollected<StyleFetchedImage>(
         ImageResourceContent::Fetch(params, document.Fetcher()), document,
-        params.GetImageRequestBehavior() == FetchParameters::kDeferImageLoad,
+        params.GetImageRequestBehavior() ==
+            FetchParameters::ImageRequestBehavior::kDeferImageLoad,
         origin_clean == OriginClean::kTrue, is_ad_related, params.Url());
   }
   return result.stored_value->value;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index 74464a1..f9e77d6c 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -832,6 +832,18 @@
   return elements_to_reveal.size();
 }
 
+static bool CheckSelfIfInclusive(const Node* node, bool inclusive_check) {
+  if (inclusive_check) {
+    if (auto* element = DynamicTo<Element>(node)) {
+      if (auto* context = element->GetDisplayLockContext()) {
+        if (!context->ShouldPaintChildren())
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
 bool DisplayLockUtilities::IsDisplayLockedPreventingPaint(
     const Node* node,
     bool inclusive_check) {
@@ -839,8 +851,10 @@
   // result. Otherwise, fallback to get-element versions.
   if (memoizer_) {
     auto result = memoizer_->IsNodeLocked(node);
-    if (result)
-      return *result;
+    if (result) {
+      // The memoizer can only be used for non-inclusive checks.
+      return *result || CheckSelfIfInclusive(node, inclusive_check);
+    }
   } else {
     return inclusive_check
                ? DisplayLockUtilities::LockedInclusiveAncestorPreventingPaint(
@@ -848,7 +862,7 @@
                : DisplayLockUtilities::LockedAncestorPreventingPaint(*node);
   }
 
-  // Do some sanity checks that we cwan early out on.
+  // Do some sanity checks that we can early out on.
   if (!node->isConnected() ||
       node->GetDocument()
               .GetDisplayLockDocumentState()
@@ -860,14 +874,8 @@
   // Handle the inclusive check -- that is, check the node itself. Note that
   // it's important not to memoize that since the memoization consists of
   // ancestor checks only.
-  if (inclusive_check) {
-    if (auto* element = DynamicTo<Element>(node)) {
-      if (auto* context = element->GetDisplayLockContext()) {
-        if (!context->ShouldPaintChildren())
-          return true;
-      }
-    }
-  }
+  if (CheckSelfIfInclusive(node, inclusive_check))
+    return true;
 
   // Walk up the ancestor chain, and consult with both the memoizer and check
   // directly if we're skipping paint. When we find a result (or finish the
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
index 4af6908..97ec10f 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
@@ -52,7 +52,6 @@
 void TextFragmentHandler::RequestSelector(RequestSelectorCallback callback) {
   DCHECK(shared_highlighting::ShouldOfferLinkToText(
       GURL(GetFrame()->GetDocument()->Url())));
-  DCHECK(!GetFrame()->Selection().SelectedText().IsEmpty());
 
   response_callback_ = std::move(callback);
   selector_ready_status_ =
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.cc b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
index 536ecc1..0a3bd58 100644
--- a/third_party/blink/renderer/core/frame/attribution_src_loader.cc
+++ b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
@@ -89,7 +89,8 @@
     LocalFrame* frame,
     HTMLElement* element,
     absl::optional<uint64_t> request_id,
-    AttributionSrcLoader::RegisterContext context) {
+    AttributionSrcLoader::RegisterContext context,
+    bool log_issues) {
   DCHECK(frame);
 
   LocalDOMWindow* window = frame->DomWindow();
@@ -102,22 +103,26 @@
       mojom::blink::PermissionsPolicyFeature::kAttributionReporting);
 
   if (!feature_policy_enabled) {
-    MaybeLogAuditIssue(frame,
-                       AttributionReportingIssueType::kPermissionPolicyDisabled,
-                       /*string=*/absl::nullopt, element, request_id);
+    if (log_issues) {
+      MaybeLogAuditIssue(
+          frame, AttributionReportingIssueType::kPermissionPolicyDisabled,
+          /*string=*/absl::nullopt, element, request_id);
+    }
     return false;
   }
 
   // The API is only allowed in secure contexts.
   if (!window->IsSecureContext()) {
-    MaybeLogAuditIssue(
-        frame,
-        context == AttributionSrcLoader::RegisterContext::kAttributionSrc
-            ? AttributionReportingIssueType::
-                  kAttributionSourceUntrustworthyOrigin
-            : AttributionReportingIssueType::kAttributionUntrustworthyOrigin,
-        frame->GetSecurityContext()->GetSecurityOrigin()->ToString(), element,
-        request_id);
+    if (log_issues) {
+      MaybeLogAuditIssue(
+          frame,
+          context == AttributionSrcLoader::RegisterContext::kAttributionSrc
+              ? AttributionReportingIssueType::
+                    kAttributionSourceUntrustworthyOrigin
+              : AttributionReportingIssueType::kAttributionUntrustworthyOrigin,
+          frame->GetSecurityContext()->GetSecurityOrigin()->ToString(), element,
+          request_id);
+    }
     return false;
   }
 
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.h b/third_party/blink/renderer/core/frame/attribution_src_loader.h
index 2d5b3b77..e81b671 100644
--- a/third_party/blink/renderer/core/frame/attribution_src_loader.h
+++ b/third_party/blink/renderer/core/frame/attribution_src_loader.h
@@ -113,7 +113,8 @@
     LocalFrame* frame,
     HTMLElement* element,
     absl::optional<uint64_t> request_id,
-    AttributionSrcLoader::RegisterContext context);
+    AttributionSrcLoader::RegisterContext context,
+    bool log_issues = true);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index 5a70206..b61682e 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -613,6 +613,8 @@
   "parser/html_token.h",
   "parser/html_tokenizer.cc",
   "parser/html_tokenizer.h",
+  "parser/html_tokenizer_metrics_reporter.cc",
+  "parser/html_tokenizer_metrics_reporter.h",
   "parser/html_tree_builder.cc",
   "parser/html_tree_builder.h",
   "parser/html_view_source_parser.cc",
@@ -718,6 +720,7 @@
   "parser/background_html_scanner_test.cc",
   "parser/html_resource_preloader_test.cc",
   "parser/html_srcset_parser_test.cc",
+  "parser/html_tokenizer_metrics_reporter_test.cc",
   "parser/html_tokenizer_test.cc",
   "parser/html_view_source_parser_test.cc",
   "parser/text_resource_decoder_builder_test.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 580f69e..9bcc47f 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -39,6 +39,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -422,8 +423,7 @@
       return nullptr;
     SetNeedsUnbufferedInputEvents(true);
     frame_dispatcher_ = std::make_unique<CanvasResourceDispatcher>(
-        nullptr,
-        surface_layer_bridge_->GetFrameSinkId().client_id(),
+        nullptr, surface_layer_bridge_->GetFrameSinkId().client_id(),
         surface_layer_bridge_->GetFrameSinkId().sink_id(),
         CanvasResourceDispatcher::kInvalidPlaceholderCanvasId, size_);
     // We don't actually need the begin frame signal when in low latency mode,
@@ -745,6 +745,8 @@
                   SharedGpuContext::ContextProviderWrapper()),
               kBackBuffer, gfx::ColorSpace::CreateREC709(),
               std::move(split_callback.first))) {
+        TRACE_EVENT1("blink", "HTMLCanvasElement::NotifyListenersCanvasChanged",
+                     "OneCopyCanvasCapture", true);
         continue;
       }
     }
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index ff72ed2c..fc55208 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -541,6 +541,12 @@
         document.UkmSourceID(), document.UkmRecorder());
   }
 
+  if (GetDocument()->IsInOutermostMainFrame() &&
+      !task_runner_state_->IsSynchronous()) {
+    tokenizer_metrics_reporter_ =
+        std::make_unique<HTMLTokenizerMetricsReporter>(tokenizer_.get());
+  }
+
   // Don't create preloader for parsing clipboard content.
   if (content_policy == kDisallowScriptingAndPluginContent)
     return;
@@ -587,6 +593,8 @@
   insertion_preload_scanner_.reset();
   background_script_scanner_.Reset();
   background_scanner_.Reset();
+  // `tokenizer_metrics_reporter_` has a reference to `tokenizer_`.
+  tokenizer_metrics_reporter_.reset();
   // Oilpan: It is important to clear token_ to deallocate backing memory of
   // HTMLToken::data_ and let the allocator reuse the memory for
   // HTMLToken::data_ of a next HTMLDocumentParser. We need to clear
@@ -829,6 +837,9 @@
       RUNTIME_CALL_TIMER_SCOPE(
           V8PerIsolateData::MainThreadIsolate(),
           RuntimeCallStats::CounterId::kHTMLTokenizerNextToken);
+      if (tokenizer_metrics_reporter_)
+        tokenizer_metrics_reporter_->WillProcessNextToken(input_.Current());
+
       if (!tokenizer_->NextToken(input_.Current(), Token()))
         break;
       budget--;
@@ -951,6 +962,11 @@
   // parser.
   Token().Clear();
 
+  if (tokenizer_metrics_reporter_) {
+    tokenizer_metrics_reporter_->WillConstructTreeFromToken(atomic_token,
+                                                            input_.Current());
+  }
+
   tree_builder_->ConstructTree(&atomic_token);
   CheckIfBlockingStylesheetAdded();
 }
@@ -971,6 +987,9 @@
   TRACE_EVENT2("blink", "HTMLDocumentParser::insert", "source_length",
                source.length(), "parser", (void*)this);
 
+  if (tokenizer_metrics_reporter_ && !source.IsEmpty())
+    tokenizer_metrics_reporter_->OnDocumentWrite(input_.Current());
+
   SegmentedString excluded_line_number_source(source);
   excluded_line_number_source.SetExcludeLineNumbers();
   input_.InsertAtCurrentInsertionPoint(excluded_line_number_source);
@@ -1045,6 +1064,8 @@
     }
   }
 
+  if (tokenizer_metrics_reporter_)
+    tokenizer_metrics_reporter_->WillAppend(input_source);
   input_.AppendToEnd(source);
   task_runner_state_->MarkSeenFirstByte();
 
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.h b/third_party/blink/renderer/core/html/parser/html_document_parser.h
index 01e4cc50..04b14d56 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -41,6 +41,7 @@
 #include "third_party/blink/renderer/core/html/parser/html_preload_scanner.h"
 #include "third_party/blink/renderer/core/html/parser/html_token.h"
 #include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h"
 #include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h"
 #include "third_party/blink/renderer/core/html/parser/preload_request.h"
 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
@@ -108,6 +109,16 @@
 
   HTMLTokenizer* Tokenizer() const { return tokenizer_.get(); }
 
+  void SetTokenizerState(const AtomicHTMLToken& token,
+                         HTMLTokenizer::State state) {
+    DCHECK(tokenizer_);
+    if (tokenizer_metrics_reporter_) {
+      tokenizer_metrics_reporter_->WillChangeTokenizerState(input_.Current(),
+                                                            token, state);
+    }
+    tokenizer_->SetState(state);
+  }
+
   TextPosition GetTextPosition() const final;
   OrdinalNumber LineNumber() const final;
 
@@ -208,11 +219,12 @@
 
   HTMLToken& Token() { return *token_; }
 
-  HTMLParserOptions options_;
+  const HTMLParserOptions options_;
   HTMLInputStream input_;
   Member<HTMLParserReentryPermit> reentry_permit_ =
       MakeGarbageCollected<HTMLParserReentryPermit>();
 
+  std::unique_ptr<HTMLTokenizerMetricsReporter> tokenizer_metrics_reporter_;
   std::unique_ptr<HTMLToken> token_;
   std::unique_ptr<HTMLTokenizer> tokenizer_;
   Member<HTMLParserScriptRunner> script_runner_;
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index 8991282d..18a2a41 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -42,6 +42,7 @@
 #include "third_party/blink/renderer/core/css/parser/sizes_attribute_parser.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/execution_context/security_context.h"
+#include "third_party/blink/renderer/core/frame/attribution_src_loader.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/viewport_data.h"
@@ -288,6 +289,7 @@
 
     bool is_module = (type_attribute_value_ == script_type_names::kModule);
     bool is_script = Match(tag_impl_, html_names::kScriptTag);
+    bool is_img = Match(tag_impl_, html_names::kImgTag);
     if ((is_script && is_module) || IsLinkRelModulePreload()) {
       is_module = true;
       request->SetScriptType(mojom::blink::ScriptType::kModule);
@@ -320,7 +322,7 @@
     }
     request->SetRenderBlockingBehavior(render_blocking_behavior);
 
-    if (type == ResourceType::kImage && Match(tag_impl_, html_names::kImgTag) &&
+    if (type == ResourceType::kImage && is_img &&
         IsLazyLoadImageDeferable(document_parameters)) {
       return nullptr;
     }
@@ -339,6 +341,12 @@
     if (scanner_type_ == ScannerType::kInsertion)
       request->SetFromInsertionScanner(true);
 
+    if (attributionsrc_attr_set_ &&
+        document_parameters.can_register_attribution) {
+      DCHECK(is_script || is_img);
+      request->SetAttributionReportingEligibleImgOrScript(true);
+    }
+
     return request;
   }
 
@@ -380,6 +388,8 @@
     } else if (RuntimeEnabledFeatures::BlockingAttributeEnabled() &&
                Match(attribute_name, html_names::kBlockingAttr)) {
       blocking_attribute_value_ = attribute_value;
+    } else if (Match(attribute_name, html_names::kAttributionsrcAttr)) {
+      attributionsrc_attr_set_ = true;
     }
   }
 
@@ -419,6 +429,8 @@
                RuntimeEnabledFeatures::LazyImageLoadingEnabled()) {
       height_attr_dimension_type_ =
           HTMLImageElement::GetAttributeLazyLoadDimensionType(attribute_value);
+    } else if (Match(attribute_name, html_names::kAttributionsrcAttr)) {
+      attributionsrc_attr_set_ = true;
     }
   }
 
@@ -764,6 +776,7 @@
   // For explanation, see TokenPreloadScanner's declaration.
   bool priority_hints_origin_trial_enabled_;
   const HashSet<String>* disabled_image_types_;
+  bool attributionsrc_attr_set_ = false;
 };
 
 TokenPreloadScanner::TokenPreloadScanner(
@@ -1186,6 +1199,13 @@
   }
   probe::GetDisabledImageTypes(document->GetExecutionContext(),
                                &disabled_image_types);
+
+  can_register_attribution = CanRegisterAttributionInContext(
+      document->Loader()->GetFrame(),
+      /*element=*/nullptr,
+      /*request_id=*/absl::nullopt,
+      AttributionSrcLoader::RegisterContext::kAttributionSrc,
+      /*log_issues=*/false);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index 5cb6c28..0b62b16 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -92,6 +92,7 @@
   SubresourceIntegrity::IntegrityFeatures integrity_features;
   LocalFrame::LazyLoadImageSetting lazy_load_image_setting;
   HashSet<String> disabled_image_types;
+  bool can_register_attribution;
 };
 
 class TokenPreloadScanner {
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index 76110e45..1bf19f9 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -22,7 +22,9 @@
 #include "third_party/blink/renderer/core/media_type_names.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
+#include "third_party/blink/renderer/platform/loader/attribution_header_constants.h"
 #include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
+#include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -95,6 +97,12 @@
   bool lazy_load_image_enabled;
 };
 
+struct AttributionSrcTestCase {
+  bool use_secure_document_url;
+  const char* input_html;
+  const char* expected_header;
+};
+
 class HTMLMockHTMLResourcePreloader : public ResourcePreloader {
  public:
   explicit HTMLMockHTMLResourcePreloader(const KURL& document_url)
@@ -233,6 +241,19 @@
     }
   }
 
+  void AttributionSrcRequestVerification(Document* document,
+                                         const char* expected_header) {
+    ASSERT_TRUE(preload_request_.get());
+    Resource* resource = preload_request_->Start(document);
+    ASSERT_TRUE(resource);
+
+    EXPECT_EQ(!!expected_header,
+              preload_request_->IsAttributionReportingEligibleImgOrScript());
+
+    EXPECT_EQ(expected_header, resource->GetResourceRequest().HttpHeaderField(
+                                   http_names::kAttributionReportingEligible));
+  }
+
  protected:
   void Preload(std::unique_ptr<PreloadRequest> preload_request) override {
     preload_request_ = std::move(preload_request);
@@ -404,6 +425,17 @@
         test_case.lazy_load_image_enabled);
   }
 
+  void Test(AttributionSrcTestCase test_case) {
+    SCOPED_TRACE(test_case.input_html);
+    HTMLMockHTMLResourcePreloader preloader(GetDocument().Url());
+    KURL base_url("http://example.test/");
+    scanner_->AppendToEnd(String(test_case.input_html));
+    std::unique_ptr<PendingPreloadData> preload_data = scanner_->Scan(base_url);
+    preloader.TakePreloadData(std::move(preload_data));
+    preloader.AttributionSrcRequestVerification(&GetDocument(),
+                                                test_case.expected_header);
+  }
+
  private:
   std::unique_ptr<HTMLPreloadScanner> scanner_;
 };
@@ -1057,6 +1089,31 @@
   }
 }
 
+TEST_F(HTMLPreloadScannerTest, testAttributionSrc) {
+  AttributionSrcTestCase test_cases[] = {
+      // Insecure context
+      {false, "<img src='/image' attributionsrc>", nullptr},
+      {false, "<script src='/script' attributionsrc></script>", nullptr},
+      // No attributionsrc attribute
+      {true, "<img src='/image'>", nullptr},
+      {true, "<script src='/script'></script>", nullptr},
+      // Irrelevant element type
+      {true, "<video poster='/image' attributionsrc>", nullptr},
+      // Secure context, attributionsrc attribute
+      {true, "<img src='/image' attributionsrc>",
+       kAttributionEligibleEventSourceAndTrigger},
+      {true, "<script src='/script' attributionsrc></script>",
+       kAttributionEligibleEventSourceAndTrigger},
+  };
+
+  for (const auto& test_case : test_cases) {
+    RunSetUp(kViewportDisabled, kPreloadEnabled,
+             network::mojom::ReferrerPolicy::kDefault,
+             /*use_secure_document_url=*/test_case.use_secure_document_url);
+    Test(test_case);
+  }
+}
+
 // Tests that a document-level referrer policy (e.g. one set by HTTP header) is
 // applied for preload requests.
 TEST_F(HTMLPreloadScannerTest, testReferrerPolicyOnDocument) {
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer.cc b/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
index 3b76e97..3497a2ad 100644
--- a/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
@@ -1668,21 +1668,26 @@
 }
 
 void HTMLTokenizer::UpdateStateFor(const String& tag_name) {
-  if (ThreadSafeMatch(tag_name, html_names::kTextareaTag) ||
-      ThreadSafeMatch(tag_name, html_names::kTitleTag))
-    SetState(HTMLTokenizer::kRCDATAState);
-  else if (ThreadSafeMatch(tag_name, html_names::kPlaintextTag))
-    SetState(HTMLTokenizer::kPLAINTEXTState);
-  else if (ThreadSafeMatch(tag_name, html_names::kScriptTag))
-    SetState(HTMLTokenizer::kScriptDataState);
-  else if (ThreadSafeMatch(tag_name, html_names::kStyleTag) ||
-           ThreadSafeMatch(tag_name, html_names::kIFrameTag) ||
-           ThreadSafeMatch(tag_name, html_names::kXmpTag) ||
-           ThreadSafeMatch(tag_name, html_names::kNoembedTag) ||
-           ThreadSafeMatch(tag_name, html_names::kNoframesTag) ||
-           (ThreadSafeMatch(tag_name, html_names::kNoscriptTag) &&
-            options_.scripting_flag))
-    SetState(HTMLTokenizer::kRAWTEXTState);
+  auto state = SpeculativeStateForTag(AtomicString(tag_name));
+  if (state)
+    SetState(*state);
+}
+
+absl::optional<HTMLTokenizer::State> HTMLTokenizer::SpeculativeStateForTag(
+    const AtomicString& tag_name) const {
+  if (tag_name == html_names::kTextareaTag || tag_name == html_names::kTitleTag)
+    return HTMLTokenizer::kRCDATAState;
+  if (tag_name == html_names::kPlaintextTag)
+    return HTMLTokenizer::kPLAINTEXTState;
+  if (tag_name == html_names::kScriptTag)
+    return HTMLTokenizer::kScriptDataState;
+  if (tag_name == html_names::kStyleTag || tag_name == html_names::kIFrameTag ||
+      tag_name == html_names::kXmpTag || tag_name == html_names::kNoembedTag ||
+      tag_name == html_names::kNoframesTag ||
+      (tag_name == html_names::kNoscriptTag && options_.scripting_flag)) {
+    return HTMLTokenizer::kRAWTEXTState;
+  }
+  return absl::nullopt;
 }
 
 inline bool HTMLTokenizer::TemporaryBufferIs(const String& expected_string) {
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer.h b/third_party/blink/renderer/core/html/parser/html_tokenizer.h
index f0c71f6..63cba1e 100644
--- a/third_party/blink/renderer/core/html/parser/html_tokenizer.h
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer.h
@@ -29,6 +29,7 @@
 
 #include "base/check_op.h"
 #include "base/memory/ptr_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_options.h"
 #include "third_party/blink/renderer/core/html/parser/html_token.h"
@@ -142,7 +143,12 @@
     return temporary_buffer_.size() ? temporary_buffer_.size() + 2 : 0;
   }
 
-  // Updates the tokenizer's state according to the given tag name. This is
+  // Potentially sets the tokenizer state for the given tag name. Specifically
+  // the state is set if SpeculativeStateForTag() returns a value, see it for
+  // details and caveats.
+  void UpdateStateFor(const String& tag_name);
+
+  // Returns the tokenizer state for the given tag name. This is
   // an approximation of how the tree builder would update the tokenizer's
   // state. This method is useful for approximating HTML tokenization. To
   // get exactly the correct tokenization, you need the real tree builder.
@@ -156,7 +162,9 @@
   //  * CDATA sections in foreign content will be tokenized as bogus comments
   //    instead of as character tokens.
   //
-  void UpdateStateFor(const String& tag_name);
+  // The return value is empty if a state change is not necessary.
+  absl::optional<State> SpeculativeStateForTag(
+      const AtomicString& tag_name) const;
 
   bool ForceNullCharacterReplacement() const {
     return force_null_character_replacement_;
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.cc b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.cc
new file mode 100644
index 0000000..e54b7e49
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.cc
@@ -0,0 +1,200 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "third_party/blink/renderer/core/html/parser/atomic_html_token.h"
+#include "third_party/blink/renderer/core/html/parser/html_token.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
+#include "third_party/blink/renderer/platform/text/segmented_string.h"
+
+namespace blink {
+namespace {
+
+const LChar kCData[] = "<![CDATA[";
+// Don't include the \0 in the count.
+constexpr wtf_size_t kCDataLength =
+    static_cast<wtf_size_t>(std::size(kCData) - 1);
+
+}  // namespace
+
+// static
+base::RepeatingClosure*
+    HTMLTokenizerMetricsReporter::metrics_logged_callback_for_test_ = nullptr;
+
+HTMLTokenizerMetricsReporter::BackgroundReporter::~BackgroundReporter() {
+  // Only log if something was actually parsed.
+  if (input_length_encountered_ == 0)
+    return;
+
+  const int bitmask =
+      (document_write_encountered_ ? 1 : 0) |
+      (speculative_state_mismatch_ ? 2 : 0) |
+      (index_of_null_char_ != std::numeric_limits<unsigned>::max() ? 4 : 0) |
+      (index_of_cdata_section_ != std::numeric_limits<unsigned>::max() ? 8 : 0);
+  base::UmaHistogramExactLinear("Blink.Tokenizer.MainDocument.ATypicalStates",
+                                bitmask, 16);
+  if (bitmask != 0) {
+    const unsigned min_position = std::min(
+        std::min(write_or_state_mismatch_position_, index_of_null_char_),
+        index_of_cdata_section_);
+    base::UmaHistogramCounts10M(
+        "Blink.Tokenizer.MainDocument.LocationOfFirstATypicalState",
+        min_position);
+  }
+  if (metrics_logged_callback_for_test_)
+    metrics_logged_callback_for_test_->Run();
+}
+
+void HTMLTokenizerMetricsReporter::BackgroundReporter::WillAppend(
+    const String& content) {
+  UpdateIndexOfNullChar(content);
+  UpdateIndexOfCDATA(content);
+  input_length_encountered_ += content.length();
+}
+
+void HTMLTokenizerMetricsReporter::BackgroundReporter::DocumentWriteEncountered(
+    int position) {
+  DCHECK(!document_write_encountered_);
+  document_write_encountered_ = true;
+  write_or_state_mismatch_position_ = std::min(
+      write_or_state_mismatch_position_, static_cast<unsigned>(position));
+}
+
+void HTMLTokenizerMetricsReporter::BackgroundReporter::SpeculativeStateMismatch(
+    int position) {
+  DCHECK(!speculative_state_mismatch_);
+  speculative_state_mismatch_ = true;
+  write_or_state_mismatch_position_ = std::min(
+      write_or_state_mismatch_position_, static_cast<unsigned>(position));
+}
+
+void HTMLTokenizerMetricsReporter::BackgroundReporter::UpdateIndexOfNullChar(
+    const String& string) {
+  if (index_of_null_char_ != std::numeric_limits<unsigned>::max())
+    return;
+
+  index_of_null_char_ = string.find(static_cast<UChar>('\0'));
+  if (index_of_null_char_ != kNotFound)
+    index_of_null_char_ += input_length_encountered_;
+  else
+    index_of_null_char_ = std::numeric_limits<unsigned>::max();
+}
+
+bool HTMLTokenizerMetricsReporter::BackgroundReporter::
+    MatchPossibleCDataSection(const String& string,
+                              wtf_size_t start_string_index) {
+  DCHECK_GT(num_matching_cdata_chars_, 0u);
+  DCHECK_LT(start_string_index, kNotFound);
+  const wtf_size_t string_length = string.length();
+  wtf_size_t i = 0;
+  // Iterate through `string` while it matches `kCData`. i starts at 0, but is
+  // relative to `start_string_index`. `num_matching_cdata_chars_` is the
+  // position into `kCData` to start the match from (portion of previous string
+  // that matched).
+  while (i + num_matching_cdata_chars_ < kCDataLength &&
+         (i + start_string_index) < string_length &&
+         string[i + start_string_index] ==
+             kCData[i + num_matching_cdata_chars_]) {
+    ++i;
+  }
+  if (i + num_matching_cdata_chars_ == kCDataLength) {
+    // Matched all cdata.
+    index_of_cdata_section_ =
+        input_length_encountered_ + i + start_string_index - kCDataLength;
+    return true;
+  }
+  if ((i + start_string_index) == string_length) {
+    // This branch is hit in the case of matching all available data, but
+    // more is required for a full match.
+    num_matching_cdata_chars_ += i;
+    return true;
+  }
+  return false;
+}
+
+void HTMLTokenizerMetricsReporter::BackgroundReporter::UpdateIndexOfCDATA(
+    const String& string) {
+  if (index_of_cdata_section_ != std::numeric_limits<unsigned>::max())
+    return;
+
+  if (num_matching_cdata_chars_ != 0) {
+    if (MatchPossibleCDataSection(string, 0))
+      return;
+    num_matching_cdata_chars_ = 0;
+  }
+
+  for (wtf_size_t next_possible_index = 0; next_possible_index != kNotFound;
+       next_possible_index = string.find(kCData[0], next_possible_index)) {
+    num_matching_cdata_chars_ = 1;
+    if (MatchPossibleCDataSection(string, next_possible_index + 1))
+      return;
+    ++next_possible_index;
+  }
+  num_matching_cdata_chars_ = 0;
+}
+
+HTMLTokenizerMetricsReporter::HTMLTokenizerMetricsReporter(
+    const HTMLTokenizer* tokenizer)
+    : tokenizer_(tokenizer),
+      background_reporter_(worker_pool::CreateSequencedTaskRunner(
+          {base::TaskPriority::BEST_EFFORT})) {}
+
+void HTMLTokenizerMetricsReporter::WillConstructTreeFromToken(
+    const AtomicHTMLToken& token,
+    const SegmentedString& input) {
+  if (speculative_state_mismatch_)
+    return;
+
+  if (token.GetType() == HTMLToken::kStartTag) {
+    last_token_was_start_ = true;
+    tokenizer_state_for_start_ =
+        tokenizer_->SpeculativeStateForTag(token.GetName());
+  }
+}
+
+void HTMLTokenizerMetricsReporter::WillChangeTokenizerState(
+    const SegmentedString& input,
+    const AtomicHTMLToken& token,
+    HTMLTokenizer::State state) {
+  if (speculative_state_mismatch_)
+    return;
+
+  if (token.GetType() != HTMLToken::kStartTag &&
+      state != tokenizer_->GetState()) {
+    RecordSpeculativeStateMismatch(input.NumberOfCharactersConsumed());
+  }
+}
+
+void HTMLTokenizerMetricsReporter::OnDocumentWrite(
+    const SegmentedString& input) {
+  if (document_write_encountered_)
+    return;
+  document_write_encountered_ = true;
+  // At the time this is called `input` should have a next segment string with
+  // the data before the write. See InsertionPointRecord.
+  const int length =
+      input.NextSegmentedString()
+          ? input.NextSegmentedString()->NumberOfCharactersConsumed()
+          : input.NumberOfCharactersConsumed();
+  background_reporter_.AsyncCall(&BackgroundReporter::DocumentWriteEncountered)
+      .WithArgs(length);
+}
+
+void HTMLTokenizerMetricsReporter::WillAppend(const String& content) {
+  background_reporter_.AsyncCall(&BackgroundReporter::WillAppend)
+      .WithArgs(content);
+}
+
+void HTMLTokenizerMetricsReporter::RecordSpeculativeStateMismatch(
+    int position) {
+  DCHECK(!speculative_state_mismatch_);
+  speculative_state_mismatch_ = true;
+  background_reporter_.AsyncCall(&BackgroundReporter::SpeculativeStateMismatch)
+      .WithArgs(position);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h
new file mode 100644
index 0000000..4206dd6
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h
@@ -0,0 +1,143 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TOKENIZER_METRICS_REPORTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TOKENIZER_METRICS_REPORTER_H_
+
+#include <limits>
+
+#include "base/callback.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/sequence_bound.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace blink {
+
+class AtomicHTMLToken;
+class SegmentedString;
+
+// HTMLTokenizerMetricsReporter is used to track how often a handful of
+// non-typical cases occur when tokenizing. It specifically tracks the
+// following:
+// . document.write().
+// . A null character.
+// . CDATA section.
+// . How often SpeculativeStateForTag() doesn't match the actual state.
+// This code is called on the critical path, so detection of a null character
+// and CDATA are done in the background. Logging is done once in the destructor
+// (in the background).
+//
+// TODO(crbug.com/1345267): remove this class once data has been collected.
+class CORE_EXPORT HTMLTokenizerMetricsReporter {
+  USING_FAST_MALLOC(HTMLTokenizerMetricsReporter);
+
+ public:
+  explicit HTMLTokenizerMetricsReporter(const HTMLTokenizer* tokenizer);
+
+  // Called prior to HTMLTokenizer::NextToken().
+  void WillProcessNextToken(const SegmentedString& input) {
+    if (speculative_state_mismatch_)
+      return;
+
+    if (last_token_was_start_) {
+      last_token_was_start_ = false;
+      if (tokenizer_state_for_start_.has_value() &&
+          tokenizer_state_for_start_ != tokenizer_->GetState()) {
+        RecordSpeculativeStateMismatch(input.NumberOfCharactersConsumed());
+      }
+    }
+  }
+
+  // Called after a token has been created by the tokenizer but before
+  // ConstructTree().
+  void WillConstructTreeFromToken(const AtomicHTMLToken& token,
+                                  const SegmentedString& input);
+
+  // Called when the state of the tokenizer is going to be explicitly set.
+  void WillChangeTokenizerState(const SegmentedString& input,
+                                const AtomicHTMLToken& token,
+                                HTMLTokenizer::State state);
+
+  // Called when document.write() occurs.
+  void OnDocumentWrite(const SegmentedString& input);
+
+  // Called when data is available to be tokenized.
+  void WillAppend(const String& content);
+
+  // BackgroundReporter does the actual metric recording, as well as any
+  // non-trivial processing. The public methods of HTMLTokenizerMetricsReporter
+  // call through to this object so that it can log the metrics in the
+  // destructor.
+  //
+  // NOTE: public for tests, treat as private.
+  class CORE_EXPORT BackgroundReporter {
+    USING_FAST_MALLOC(BackgroundReporter);
+
+   public:
+    ~BackgroundReporter();
+
+    void WillAppend(const String& content);
+    void DocumentWriteEncountered(int position);
+    void SpeculativeStateMismatch(int position);
+
+    unsigned index_of_null_char() const { return index_of_null_char_; }
+
+    unsigned index_of_cdata_section() const { return index_of_cdata_section_; }
+
+   private:
+    void UpdateIndexOfNullChar(const String& string);
+    // Attempts to match a possible cdata secition. `string` is the string to
+    // search in, starting at `start_string_index`. Returns true on success,
+    // or the section matches but the end of input is reached (partial match).
+    bool MatchPossibleCDataSection(const String& string,
+                                   wtf_size_t start_string_index);
+    void UpdateIndexOfCDATA(const String& string);
+
+    bool document_write_encountered_ = false;
+    bool speculative_state_mismatch_ = false;
+    unsigned write_or_state_mismatch_position_ =
+        std::numeric_limits<unsigned>::max();
+
+    // Amount of data encountered to date (sum of length of strings supplied
+    // to WillAppend()).
+    unsigned input_length_encountered_ = 0;
+
+    unsigned index_of_null_char_ = std::numeric_limits<unsigned>::max();
+
+    // Following is used to match a CDATA section:
+    unsigned index_of_cdata_section_ = std::numeric_limits<unsigned>::max();
+    unsigned num_matching_cdata_chars_ = 0;
+  };
+
+  // Run when metrics have been logged. Provided for tests. This callback is
+  // run on a background thread.
+  static base::RepeatingClosure* metrics_logged_callback_for_test_;
+
+ private:
+  void RecordSpeculativeStateMismatch(int position);
+
+  const HTMLTokenizer* tokenizer_;
+
+  // True if the last token was a start.
+  bool last_token_was_start_ = false;
+
+  // If the last token was a start tag, this is the corresponding speculative
+  // state (which may not be set).
+  absl::optional<HTMLTokenizer::State> tokenizer_state_for_start_;
+
+  // Whether document.write() was encountered.
+  bool document_write_encountered_ = false;
+
+  // Whether the Tokenizer state from the builder does not match the
+  // speculative state.
+  bool speculative_state_mismatch_ = false;
+
+  WTF::SequenceBound<BackgroundReporter> background_reporter_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_TOKENIZER_METRICS_REPORTER_H_
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter_test.cc b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter_test.cc
new file mode 100644
index 0000000..e0fb1dc
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter_test.cc
@@ -0,0 +1,112 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/parser/html_tokenizer_metrics_reporter.h"
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/html/html_document.h"
+#include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+
+namespace blink {
+
+TEST(HTMLTokenizerMetricsReporterTest, FindNullChar) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend(String("123\0", 4u));
+  EXPECT_EQ(3u, reporter.index_of_null_char());
+}
+
+TEST(HTMLTokenizerMetricsReporterTest, FindNullCharSecondChunk) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend("abc");
+  reporter.WillAppend(String("d\0f", 3u));
+  EXPECT_EQ(4u, reporter.index_of_null_char());
+}
+
+TEST(HTMLTokenizerMetricsReporterTest, SimpleCData) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend("abcdef<<![CDATA[");
+  EXPECT_EQ(7u, reporter.index_of_cdata_section());
+}
+
+TEST(HTMLTokenizerMetricsReporterTest, SplitCData) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend("abc<![");
+  reporter.WillAppend("CD");
+  reporter.WillAppend("ATA[");
+  EXPECT_EQ(3u, reporter.index_of_cdata_section());
+}
+
+TEST(HTMLTokenizerMetricsReporterTest, IncompleteCData) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend("abcdef<<![CDATA");
+  EXPECT_EQ(std::numeric_limits<unsigned>::max(),
+            reporter.index_of_cdata_section());
+}
+
+TEST(HTMLTokenizerMetricsReporterTest, SplitWithPartialThenFull) {
+  HTMLTokenizerMetricsReporter::BackgroundReporter reporter;
+  reporter.WillAppend("abc<![");
+  reporter.WillAppend("<![CDATA[");
+  EXPECT_EQ(6u, reporter.index_of_cdata_section());
+}
+
+class HTMLTokenizerMetricsReporterSimTest : public SimTest {
+ public:
+  void LoadPageWithContentForReporter(const String& string) {
+    // To ensure metrics reporter is created.
+    Document::SetForceSynchronousParsingForTesting(false);
+    base::RunLoop run_loop;
+    auto quit_closure = run_loop.QuitClosure();
+    HTMLTokenizerMetricsReporter::metrics_logged_callback_for_test_ =
+        &quit_closure;
+
+    String source("https://example.com/p1");
+    SimRequest main_resource(source, "text/html");
+    LoadURL(source);
+    main_resource.Complete(string);
+
+    // Because SetForceSynchronousParsingForTesting(false) was called,
+    // tokenizing doesn't happen immediately. Use this to ensure it runs.
+    base::RunLoop().RunUntilIdle();
+
+    String source2("https://example.com/p2");
+    SimRequest resource2(source2, "text/html");
+    Document::SetForceSynchronousParsingForTesting(true);
+    LoadURL(source2);
+    resource2.Complete("empty");
+
+    run_loop.Run();
+    HTMLTokenizerMetricsReporter::metrics_logged_callback_for_test_ = nullptr;
+  }
+};
+
+TEST_F(HTMLTokenizerMetricsReporterSimTest, UnexpectedState) {
+  base::HistogramTester tester;
+  LoadPageWithContentForReporter("<svg><style></style></svg>");
+  // Bucket 2 means a state mismatch.
+  tester.ExpectUniqueSample("Blink.Tokenizer.MainDocument.ATypicalStates", 2,
+                            1);
+}
+
+TEST_F(HTMLTokenizerMetricsReporterSimTest, DocumentWrite) {
+  base::HistogramTester tester;
+  LoadPageWithContentForReporter("<script>document.write('test');</script>");
+  // Bucket 1 is for document.write().
+  tester.ExpectUniqueSample("Blink.Tokenizer.MainDocument.ATypicalStates", 1,
+                            1);
+}
+
+TEST_F(HTMLTokenizerMetricsReporterSimTest, EmbeddedNull) {
+  base::HistogramTester tester;
+  LoadPageWithContentForReporter(String("<div>t\0ext", 10u));
+  tester.ExpectUniqueSample("Blink.Tokenizer.MainDocument.ATypicalStates", 4,
+                            1);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 6763177..dfa3804 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -688,7 +688,7 @@
   if (token->GetName() == html_names::kPlaintextTag) {
     ProcessFakePEndTagIfPInButtonScope();
     tree_.InsertHTMLElement(token);
-    parser_->Tokenizer()->SetState(HTMLTokenizer::kPLAINTEXTState);
+    parser_->SetTokenizerState(*token, HTMLTokenizer::kPLAINTEXTState);
     return;
   }
   if (token->GetName() == html_names::kButtonTag) {
@@ -805,7 +805,7 @@
   if (token->GetName() == html_names::kTextareaTag) {
     tree_.InsertHTMLElement(token);
     should_skip_leading_newline_ = true;
-    parser_->Tokenizer()->SetState(HTMLTokenizer::kRCDATAState);
+    parser_->SetTokenizerState(*token, HTMLTokenizer::kRCDATAState);
     original_insertion_mode_ = insertion_mode_;
     frameset_ok_ = false;
     SetInsertionMode(kTextMode);
@@ -2230,7 +2230,7 @@
 
         // We must set the tokenizer's state to DataState explicitly if the
         // tokenizer didn't have a chance to.
-        parser_->Tokenizer()->SetState(HTMLTokenizer::kDataState);
+        parser_->SetTokenizerState(*token, HTMLTokenizer::kDataState);
         return;
       }
       tree_.OpenElements()->Pop();
@@ -2763,7 +2763,7 @@
 void HTMLTreeBuilder::ProcessGenericRCDATAStartTag(AtomicHTMLToken* token) {
   DCHECK_EQ(token->GetType(), HTMLToken::kStartTag);
   tree_.InsertHTMLElement(token);
-  parser_->Tokenizer()->SetState(HTMLTokenizer::kRCDATAState);
+  parser_->SetTokenizerState(*token, HTMLTokenizer::kRCDATAState);
   original_insertion_mode_ = insertion_mode_;
   SetInsertionMode(kTextMode);
 }
@@ -2771,7 +2771,7 @@
 void HTMLTreeBuilder::ProcessGenericRawTextStartTag(AtomicHTMLToken* token) {
   DCHECK_EQ(token->GetType(), HTMLToken::kStartTag);
   tree_.InsertHTMLElement(token);
-  parser_->Tokenizer()->SetState(HTMLTokenizer::kRAWTEXTState);
+  parser_->SetTokenizerState(*token, HTMLTokenizer::kRAWTEXTState);
   original_insertion_mode_ = insertion_mode_;
   SetInsertionMode(kTextMode);
 }
@@ -2779,7 +2779,7 @@
 void HTMLTreeBuilder::ProcessScriptStartTag(AtomicHTMLToken* token) {
   DCHECK_EQ(token->GetType(), HTMLToken::kStartTag);
   tree_.InsertScriptElement(token);
-  parser_->Tokenizer()->SetState(HTMLTokenizer::kScriptDataState);
+  parser_->SetTokenizerState(*token, HTMLTokenizer::kScriptDataState);
   original_insertion_mode_ = insertion_mode_;
 
   TextPosition position = parser_->GetTextPosition();
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc
index 6e4059c..244cbe7 100644
--- a/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -15,11 +15,13 @@
 #include "third_party/blink/renderer/core/loader/preload_helper.h"
 #include "third_party/blink/renderer/core/script/document_write_intervention.h"
 #include "third_party/blink/renderer/core/script/script_loader.h"
+#include "third_party/blink/renderer/platform/loader/attribution_header_constants.h"
 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 
@@ -107,6 +109,12 @@
 
   resource_request.SetFetchPriorityHint(fetch_priority_hint_);
 
+  if (is_attribution_reporting_eligible_img_or_script_) {
+    resource_request.SetHttpHeaderField(
+        http_names::kAttributionReportingEligible,
+        kAttributionEligibleEventSourceAndTrigger);
+  }
+
   ResourceLoaderOptions options(document->domWindow()->GetCurrentWorld());
   options.initiator_info = initiator_info;
   FetchParameters params(std::move(resource_request), options);
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.h b/third_party/blink/renderer/core/html/parser/preload_request.h
index 7480ab7..645f920 100644
--- a/third_party/blink/renderer/core/html/parser/preload_request.h
+++ b/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -135,6 +135,14 @@
     render_blocking_behavior_ = render_blocking_behavior;
   }
 
+  bool IsAttributionReportingEligibleImgOrScript() const {
+    return is_attribution_reporting_eligible_img_or_script_;
+  }
+
+  void SetAttributionReportingEligibleImgOrScript(bool eligible) {
+    is_attribution_reporting_eligible_img_or_script_ = eligible;
+  }
+
  private:
   PreloadRequest(const String& initiator_name,
                  const TextPosition& initiator_position,
@@ -179,6 +187,7 @@
   const ResourceFetcher::IsImageSet is_image_set_;
   bool is_lazy_load_image_enabled_ = false;
   base::TimeTicks creation_time_ = base::TimeTicks::Now();
+  bool is_attribution_reporting_eligible_img_or_script_ = false;
 };
 
 typedef Vector<std::unique_ptr<PreloadRequest>> PreloadRequestStream;
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 0d1c11c..b6e7915b 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -799,6 +799,14 @@
   if (IsCustomItem())
     GetCustomLayoutChild()->styleMap()->UpdateStyle(GetDocument(), StyleRef());
 
+  if (diff.NeedsPaintInvalidation()) {
+    if (const AtomicString& old_anchor_scroll =
+            old_style ? old_style->AnchorScroll() : g_null_atom;
+        StyleRef().AnchorScroll() != old_anchor_scroll) {
+      SetNeedsPaintPropertyUpdate();
+    }
+  }
+
   // Non-atomic inlines should be LayoutInline or LayoutText, not LayoutBox.
   DCHECK(!IsInline() || IsAtomicInlineLevel());
 }
@@ -987,8 +995,10 @@
                                ShouldApplyPaintContainment()) &&
                               RespectsCSSOverflow();
   if (should_clip_overflow != HasNonVisibleOverflow()) {
-    if (GetScrollableArea())
+    if (GetScrollableArea()) {
       GetScrollableArea()->InvalidateAllStickyConstraints();
+      GetScrollableArea()->InvalidateAllAnchorPositionedLayers();
+    }
     // The overflow clip paint property depends on whether overflow clip is
     // present so we need to update paint properties if this changes.
     SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
index 73d752a9b..454c1f2 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
@@ -161,8 +161,8 @@
                            const ComputedStyle& container_style,
                            const WritingMode container_writing_mode)
     : node(node),
+      parent_grid(nullptr),
       is_sizing_dependent_on_block_size(false),
-      is_subgridded_to_parent_grid(false),
       is_considered_for_column_sizing(true),
       is_considered_for_row_sizing(true),
       can_subgrid_items_in_column_direction(false),
@@ -373,30 +373,18 @@
   }
 }
 
-void GridItems::ReserveInitialCapacity(wtf_size_t initial_capacity) {
-  reordered_item_indices.ReserveInitialCapacity(initial_capacity);
-  item_data.ReserveInitialCapacity(initial_capacity);
-}
-
-void GridItems::ReserveCapacity(wtf_size_t new_capacity) {
-  reordered_item_indices.ReserveCapacity(new_capacity);
-  item_data.ReserveCapacity(new_capacity);
-}
-
 void GridItems::RemoveSubgriddedItems() {
   wtf_size_t new_item_count = 0;
   for (const auto& grid_item : item_data) {
-    if (grid_item.is_subgridded_to_parent_grid)
+    if (grid_item->ParentGrid())
       break;
     ++new_item_count;
   }
 
 #if DCHECK_IS_ON()
   for (wtf_size_t i = new_item_count; i < item_data.size(); ++i)
-    DCHECK(item_data[i].is_subgridded_to_parent_grid);
+    DCHECK(item_data[i]->ParentGrid());
 #endif
-
-  reordered_item_indices.Shrink(new_item_count);
   item_data.Shrink(new_item_count);
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h
index 4bfffc4..c5f7c97 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h
@@ -28,9 +28,7 @@
   GridItemIndices offset_in_range;
 };
 
-struct CORE_EXPORT GridItemData {
-  DISALLOW_NEW();
-
+struct CORE_EXPORT GridItemData : public GarbageCollected<GridItemData> {
   GridItemData(const NGBlockNode node,
                const ComputedStyle& container_style,
                const WritingMode container_writing_mode);
@@ -104,6 +102,8 @@
     return false;
   }
 
+  GridItemData* ParentGrid() const { return parent_grid.Get(); }
+
   bool IsConsideredForSizing(
       const GridTrackSizingDirection track_direction) const {
     return (track_direction == kForColumns) ? is_considered_for_column_sizing
@@ -152,15 +152,18 @@
         .HasProperty(TrackSpanProperties::kHasFixedMaximumTrack);
   }
 
-  void Trace(Visitor* visitor) const { visitor->Trace(node); }
+  void Trace(Visitor* visitor) const {
+    visitor->Trace(node);
+    visitor->Trace(parent_grid);
+  }
 
   NGBlockNode node;
   GridArea resolved_position;
+  Member<GridItemData> parent_grid;
 
   bool is_block_axis_overflow_safe : 1;
   bool is_inline_axis_overflow_safe : 1;
   bool is_sizing_dependent_on_block_size : 1;
-  bool is_subgridded_to_parent_grid : 1;
   bool is_considered_for_column_sizing : 1;
   bool is_considered_for_row_sizing : 1;
   bool can_subgrid_items_in_column_direction : 1;
@@ -194,70 +197,90 @@
   OutOfFlowItemPlacement row_placement;
 };
 
-using GridItemDataVector = Vector<GridItemData*, 16>;
-
 struct CORE_EXPORT GridItems {
-  DISALLOW_NEW();
+  STACK_ALLOCATED();
 
  public:
-  using GridItemStorageVector = HeapVector<GridItemData, 16>;
+  using GridItemDataVector = HeapVector<Member<GridItemData>, 16>;
 
-  class Iterator : public std::iterator<std::input_iterator_tag, GridItemData> {
+  template <bool is_const>
+  class IteratorBase {
     STACK_ALLOCATED();
 
    public:
-    Iterator(GridItemStorageVector* item_data,
-             Vector<wtf_size_t>::const_iterator current_index)
-        : item_data_(item_data), current_index_(current_index) {
+    using value_type = typename std::
+        conditional<is_const, const GridItemData, GridItemData>::type;
+
+    using GridItemDataVectorPtr =
+        typename std::conditional<is_const,
+                                  const GridItemDataVector*,
+                                  GridItemDataVector*>::type;
+
+    IteratorBase(GridItemDataVectorPtr item_data, wtf_size_t current_index)
+        : current_index_(current_index), item_data_(item_data) {
       DCHECK(item_data_);
+      DCHECK_LE(current_index_, item_data_->size());
     }
 
-    bool operator!=(const Iterator& other) const {
+    bool operator!=(const IteratorBase& other) {
       return current_index_ != other.current_index_ ||
              item_data_ != other.item_data_;
     }
 
-    Iterator& operator++() {
+    IteratorBase& operator++() {
       ++current_index_;
       return *this;
     }
 
-    GridItemData& operator*() const {
-      DCHECK(current_index_ && *current_index_ < item_data_->size());
-      return item_data_->at(*current_index_);
+    IteratorBase operator++(int) {
+      auto current_iterator = *this;
+      ++current_index_;
+      return current_iterator;
     }
 
-    GridItemData* operator->() const { return &operator*(); }
+    value_type* operator->() const {
+      DCHECK_LT(current_index_, item_data_->size());
+      return item_data_->at(current_index_).Get();
+    }
+
+    value_type& operator*() const { return *operator->(); }
 
    private:
-    GridItemStorageVector* item_data_;
-    HeapVector<wtf_size_t>::const_iterator current_index_;
+    wtf_size_t current_index_;
+    GridItemDataVectorPtr item_data_;
   };
 
-  Iterator begin() {
-    return Iterator(&item_data, reordered_item_indices.begin());
-  }
-  Iterator end() { return Iterator(&item_data, reordered_item_indices.end()); }
+  typedef IteratorBase<false> Iterator;
+  typedef IteratorBase<true> ConstIterator;
 
-  void Append(GridItemData&& new_item_data) {
-    reordered_item_indices.push_back(item_data.size());
-    item_data.emplace_back(new_item_data);
-  }
+  Iterator begin() { return {&item_data, 0}; }
+  Iterator end() { return {&item_data, item_data.size()}; }
 
-  void ReserveInitialCapacity(wtf_size_t initial_capacity);
-  void ReserveCapacity(wtf_size_t new_capacity);
-  void RemoveSubgriddedItems();
+  ConstIterator begin() const { return {&item_data, 0}; }
+  ConstIterator end() const { return {&item_data, item_data.size()}; }
 
   wtf_size_t Size() const { return item_data.size(); }
   bool IsEmpty() const { return item_data.IsEmpty(); }
 
-  void Trace(Visitor* visitor) const { visitor->Trace(item_data); }
+  GridItemData& operator[](wtf_size_t index) { return *item_data[index]; }
 
-  // Grid items are appended in document order, but we want to rearrange them in
-  // order-modified document order since auto-placement and painting rely on it
-  // later in the algorithm.
-  GridItemStorageVector item_data;
-  Vector<wtf_size_t> reordered_item_indices;
+  void Append(GridItemData* new_item_data) {
+    DCHECK(new_item_data);
+    item_data.emplace_back(new_item_data);
+  }
+
+  void RemoveSubgriddedItems();
+
+  void ReserveInitialCapacity(wtf_size_t initial_capacity) {
+    item_data.ReserveInitialCapacity(initial_capacity);
+  }
+  void ReserveCapacity(wtf_size_t new_capacity) {
+    item_data.ReserveCapacity(new_capacity);
+  }
+
+  // Grid items are rearranged in order-modified document order since
+  // auto-placement and painting rely on it later in the algorithm.
+  GridItemDataVector item_data;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 80d5109d..ac097cdf 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -90,7 +90,7 @@
 namespace {
 
 bool HasBlockSizeDependentGridItem(const GridItems& grid_items) {
-  for (const auto& grid_item : grid_items.item_data) {
+  for (const auto& grid_item : grid_items) {
     if (grid_item.is_sizing_dependent_on_block_size)
       return true;
   }
@@ -102,7 +102,7 @@
     const WritingMode container_writing_mode) {
   NGGridProperties grid_properties;
 
-  for (const auto& grid_item : grid_items.item_data) {
+  for (const auto& grid_item : grid_items) {
     grid_properties.has_baseline_column |=
         grid_item.IsBaselineSpecifiedForDirection(kForColumns);
     grid_properties.has_baseline_row |=
@@ -151,14 +151,15 @@
           grid_item.SetTrackSpanProperty(property, track_direction);
       };
 
-  GridItemDataVector grid_items_spanning_multiple_ranges;
-  for (auto& grid_item : grid_items->item_data) {
+  GridItems grid_items_spanning_multiple_ranges;
+  for (auto& grid_item : *grid_items) {
     const auto& range_indices = grid_item.RangeIndices(track_direction);
 
     // If a grid item spans only one range, then we can just cache the track
     // span properties directly. On the contrary, if a grid item spans multiple
     // tracks, it is added to |grid_items_spanning_multiple_ranges| as we need
     // to do more work to cache its track span properties.
+    //
     // TODO(layout-dev): Investigate applying this concept to spans > 1.
     if (range_indices.begin == range_indices.end) {
       CacheTrackSpanProperty(grid_item, range_indices.begin,
@@ -172,20 +173,20 @@
       CacheTrackSpanProperty(grid_item, range_indices.begin,
                              TrackSpanProperties::kHasFixedMaximumTrack);
     } else {
-      grid_items_spanning_multiple_ranges.emplace_back(&grid_item);
+      grid_items_spanning_multiple_ranges.Append(&grid_item);
     }
   }
 
   if (grid_items_spanning_multiple_ranges.IsEmpty())
     return;
 
-  auto CompareGridItemsByStartLine = [track_direction](
-                                         const GridItemData* lhs,
-                                         const GridItemData* rhs) -> bool {
+  auto CompareGridItemsByStartLine =
+      [track_direction](const Member<GridItemData>& lhs,
+                        const Member<GridItemData>& rhs) -> bool {
     return lhs->StartLine(track_direction) < rhs->StartLine(track_direction);
   };
-  std::sort(grid_items_spanning_multiple_ranges.begin(),
-            grid_items_spanning_multiple_ranges.end(),
+  std::sort(grid_items_spanning_multiple_ranges.item_data.begin(),
+            grid_items_spanning_multiple_ranges.item_data.end(),
             CompareGridItemsByStartLine);
 
   auto CacheTrackSpanPropertyForAllGridItems =
@@ -197,7 +198,7 @@
         wtf_size_t current_range_index = 0;
         const wtf_size_t range_count = track_collection.RangeCount();
 
-        for (auto* grid_item : grid_items_spanning_multiple_ranges) {
+        for (auto& grid_item : grid_items_spanning_multiple_ranges) {
           // We want to find the first range in the collection that:
           //   - Spans tracks located AFTER the start line of the current grid
           //   item; this can be done by checking that the last track number of
@@ -209,7 +210,7 @@
           //   - Contains a track that fulfills the specified property.
           while (current_range_index < range_count &&
                  (track_collection.RangeEndLine(current_range_index) <=
-                      grid_item->StartLine(track_direction) ||
+                      grid_item.StartLine(track_direction) ||
                   !track_collection.RangeHasTrackSpanProperty(
                       current_range_index, property))) {
             ++current_range_index;
@@ -230,8 +231,8 @@
           // range are excluded from the grid item's span, meaning that such
           // item cannot satisfy the property we are looking for.
           if (track_collection.RangeEndLine(current_range_index) <=
-              grid_item->EndLine(track_direction)) {
-            grid_item->SetTrackSpanProperty(property, track_direction);
+              grid_item.EndLine(track_direction)) {
+            grid_item.SetTrackSpanProperty(property, track_direction);
           }
         }
       };
@@ -279,7 +280,7 @@
     intrinsic_block_size = grid_data->intrinsic_block_size;
     layout_data = grid_data->layout_data;
 
-    for (auto& grid_item : grid_items.item_data) {
+    for (auto& grid_item : grid_items) {
       grid_item.ComputeSetIndices(*layout_data.Columns());
       grid_item.ComputeSetIndices(*layout_data.Rows());
     }
@@ -423,7 +424,7 @@
       LayoutTrackCollection(placement_data, kForColumns, &grid_items),
       LayoutTrackCollection(placement_data, kForRows, &grid_items));
 
-  for (auto& grid_item : grid_items.item_data) {
+  for (auto& grid_item : grid_items) {
     grid_item.ComputeSetIndices(*layout_data.Columns());
     grid_item.ComputeSetIndices(*layout_data.Rows());
   }
@@ -659,7 +660,7 @@
         *row_builder_collection, is_block_available_size_indefinite);
   }
 
-  for (auto& grid_item : grid_items->item_data) {
+  for (auto& grid_item : *grid_items) {
     grid_item.ComputeSetIndices(*layout_data->Columns());
     grid_item.ComputeSetIndices(*layout_data->Rows());
   }
@@ -852,7 +853,7 @@
   absl::optional<NGDisableSideEffectsScope> disable_side_effects;
   if (!node.GetLayoutBox()->NeedsLayout() &&
       (sizing_constraint != SizingConstraint::kLayout ||
-       grid_item.is_subgridded_to_parent_grid)) {
+       grid_item.ParentGrid())) {
     disable_side_effects.emplace();
   }
   return node.Layout(constraint_space);
@@ -1368,7 +1369,7 @@
 
   const auto track_direction = track_collection->Direction();
 
-  for (auto& grid_item : grid_items->item_data) {
+  for (auto& grid_item : *grid_items) {
     auto& range_indices = grid_item.RangeIndices(track_direction);
     track_collection->EnsureTrackCoverage(grid_item.StartLine(track_direction),
                                           grid_item.SpanSize(track_direction),
@@ -1466,7 +1467,7 @@
       track_collection->SetMinorBaseline(set_index, candidate_baseline);
   };
 
-  for (auto& grid_item : grid_items->item_data) {
+  for (auto& grid_item : *grid_items) {
     if (!grid_item.IsBaselineSpecifiedForDirection(track_direction))
       continue;
 
@@ -1607,7 +1608,7 @@
 namespace {
 
 struct BlockSizeDependentGridItem {
-  const GridItemData* item_data;
+  GridItemIndices row_set_indices;
   LayoutUnit cached_block_size;
 };
 
@@ -1619,18 +1620,16 @@
   Vector<BlockSizeDependentGridItem> dependent_items;
   dependent_items.ReserveInitialCapacity(grid_items.Size());
 
-  for (const auto& grid_item : grid_items.item_data) {
+  for (const auto& grid_item : grid_items) {
     if (!grid_item.is_sizing_dependent_on_block_size)
       continue;
 
     const auto& set_indices = grid_item.SetIndices(kForRows);
     BlockSizeDependentGridItem dependent_item = {
-        &grid_item, track_collection.ComputeSetSpanSize(set_indices.begin,
-                                                        set_indices.end)};
+        set_indices, track_collection.ComputeSetSpanSize(set_indices.begin,
+                                                         set_indices.end)};
     dependent_items.emplace_back(std::move(dependent_item));
   }
-
-  dependent_items.ShrinkToFit();
   return dependent_items;
 }
 
@@ -1640,9 +1639,8 @@
   DCHECK_EQ(track_collection.Direction(), kForRows);
 
   for (const auto& grid_item : dependent_items) {
-    const auto& set_indices = grid_item.item_data->SetIndices(kForRows);
-    const LayoutUnit block_size =
-        track_collection.ComputeSetSpanSize(set_indices.begin, set_indices.end);
+    const LayoutUnit block_size = track_collection.ComputeSetSpanSize(
+        grid_item.row_set_indices.begin, grid_item.row_set_indices.end);
 
     DCHECK_NE(block_size, kIndefiniteSize);
     if (block_size != grid_item.cached_block_size)
@@ -2191,8 +2189,8 @@
 }  // namespace
 
 void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems(
-    GridItemDataVector::iterator group_begin,
-    GridItemDataVector::iterator group_end,
+    GridItems::Iterator group_begin,
+    GridItems::Iterator group_end,
     const NGGridLayoutData& layout_data,
     const bool is_group_spanning_flex_track,
     const SizingConstraint sizing_constraint,
@@ -2208,9 +2206,9 @@
 
   GridSetVector sets_to_grow;
   GridSetVector sets_to_grow_beyond_limit;
-  for (auto** it = group_begin; it != group_end; ++it) {
-    GridItemData& grid_item = **it;
 
+  while (group_begin != group_end) {
+    GridItemData& grid_item = *(group_begin++);
     DCHECK(grid_item.IsSpanningIntrinsicTrack(track_direction));
 
     sets_to_grow.Shrink(0);
@@ -2308,12 +2306,12 @@
   DCHECK(track_collection && grid_items);
   const auto track_direction = track_collection->Direction();
 
-  GridItemDataVector reordered_grid_items;
+  GridItems reordered_grid_items;
   reordered_grid_items.ReserveInitialCapacity(grid_items->Size());
 
-  for (auto& grid_item : grid_items->item_data) {
+  for (auto& grid_item : *grid_items) {
     if (grid_item.IsSpanningIntrinsicTrack(track_direction))
-      reordered_grid_items.push_back(&grid_item);
+      reordered_grid_items.Append(&grid_item);
   }
 
   // Reorder grid items to process them as follows:
@@ -2323,8 +2321,8 @@
   //   not spanning a flexible track have been considered.
   //   - Finally, consider all items spanning a flexible track.
   auto CompareGridItemsForIntrinsicTrackResolution =
-      [track_direction](const GridItemData* lhs,
-                        const GridItemData* rhs) -> bool {
+      [track_direction](const Member<GridItemData>& lhs,
+                        const Member<GridItemData>& rhs) -> bool {
     if (lhs->IsSpanningFlexibleTrack(track_direction) ||
         rhs->IsSpanningFlexibleTrack(track_direction)) {
       // Ignore span sizes if one of the items spans a track with a flexible
@@ -2333,24 +2331,25 @@
     }
     return lhs->SpanSize(track_direction) < rhs->SpanSize(track_direction);
   };
-  std::sort(reordered_grid_items.begin(), reordered_grid_items.end(),
+  std::sort(reordered_grid_items.item_data.begin(),
+            reordered_grid_items.item_data.end(),
             CompareGridItemsForIntrinsicTrackResolution);
 
   // First, process the items that don't span a flexible track.
-  auto** current_group_begin = reordered_grid_items.begin();
+  auto current_group_begin = reordered_grid_items.begin();
   while (current_group_begin != reordered_grid_items.end() &&
-         !(*current_group_begin)->IsSpanningFlexibleTrack(track_direction)) {
+         !current_group_begin->IsSpanningFlexibleTrack(track_direction)) {
     // Each iteration considers all items with the same span size.
     wtf_size_t current_group_span_size =
-        (*current_group_begin)->SpanSize(track_direction);
+        current_group_begin->SpanSize(track_direction);
 
-    auto** current_group_end = current_group_begin;
+    auto current_group_end = current_group_begin;
     do {
-      DCHECK(!(*current_group_end)->IsSpanningFlexibleTrack(track_direction));
+      DCHECK(!current_group_end->IsSpanningFlexibleTrack(track_direction));
       ++current_group_end;
     } while (current_group_end != reordered_grid_items.end() &&
-             !(*current_group_end)->IsSpanningFlexibleTrack(track_direction) &&
-             (*current_group_end)->SpanSize(track_direction) ==
+             !current_group_end->IsSpanningFlexibleTrack(track_direction) &&
+             current_group_end->SpanSize(track_direction) ==
                  current_group_span_size);
 
     IncreaseTrackSizesToAccommodateGridItems(
@@ -2385,8 +2384,8 @@
   //   sizing function...
 #if DCHECK_IS_ON()
   // Every grid item of the remaining group should span a flexible track.
-  for (auto** it = current_group_begin; it != reordered_grid_items.end(); ++it)
-    DCHECK((*it)->IsSpanningFlexibleTrack(track_direction));
+  for (auto it = current_group_begin; it != reordered_grid_items.end(); ++it)
+    DCHECK(it->IsSpanningFlexibleTrack(track_direction));
 #endif
 
   // Now, process items spanning flexible tracks (if any).
@@ -2621,7 +2620,7 @@
     //   - For each grid item that crosses a flexible track, the result of
     //   finding the size of an fr using all the grid tracks that the item
     //   crosses and a space to fill of the item’s max-content contribution.
-    for (auto& grid_item : grid_items->item_data) {
+    for (auto& grid_item : *grid_items) {
       if (grid_item.IsSpanningFlexibleTrack(track_direction)) {
         double grid_item_fr_size = FindFrSize(
             GetSetIteratorForItem(grid_item, *track_collection),
@@ -2999,7 +2998,7 @@
 
   BaselineAccumulator baseline_accumulator;
 
-  for (const auto& grid_item : grid_items.item_data) {
+  for (const auto& grid_item : grid_items) {
     LogicalRect containing_grid_area;
     const auto space = CreateConstraintSpaceForLayout(grid_item, layout_data,
                                                       &containing_grid_area);
@@ -3220,7 +3219,7 @@
     auto child_break_token_it = child_break_tokens.begin();
     auto* placement_data_it = grid_items_placement_data->begin();
 
-    for (const auto& grid_item : grid_items.item_data) {
+    for (const auto& grid_item : grid_items) {
       // Grab the offsets and break-token (if present) for this child.
       auto& item_placement_data = *(placement_data_it++);
       const NGBlockBreakToken* break_token = nullptr;
@@ -3388,7 +3387,7 @@
   // Adjust by |delta| the pre-computed item-offset for all grid items with a
   // row begin index greater or equal than |row_index|.
   auto AdjustItemOffsets = [&](wtf_size_t row_index, LayoutUnit delta) {
-    const auto* current_item = grid_items.item_data.begin();
+    auto current_item = grid_items.begin();
 
     for (auto& item_placement_data : *grid_items_placement_data) {
       if (row_index <= (current_item++)->SetIndices(kForRows).begin)
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
index dcbaa1e0..109241f 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -127,8 +127,8 @@
                                   GridItems* grid_items) const;
 
   void IncreaseTrackSizesToAccommodateGridItems(
-      GridItemDataVector::iterator group_begin,
-      GridItemDataVector::iterator group_end,
+      GridItems::Iterator group_begin,
+      GridItems::Iterator group_end,
       const NGGridLayoutData& layout_data,
       const bool is_group_spanning_flex_track,
       const SizingConstraint sizing_constraint,
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
index f961770..8f83aa44 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
@@ -42,27 +42,18 @@
 
   void BuildGridItemsAndTrackCollections(NGGridLayoutAlgorithm& algorithm) {
     auto placement_data = algorithm.PlacementData();
-    items_->grid_items_ =
+    auto grid_items =
         algorithm.Node().GridItemsIncludingSubgridded(&placement_data);
 
-    // Build block track collections.
-    NGGridBlockTrackCollection column_block_track_collection(
-        algorithm.Style(), placement_data, kForColumns);
-    NGGridBlockTrackCollection row_block_track_collection(
-        algorithm.Style(), placement_data, kForRows);
-
-    algorithm.BuildBlockTrackCollection(&items_->grid_items_,
-                                        &column_block_track_collection);
-    algorithm.BuildBlockTrackCollection(&items_->grid_items_,
-                                        &row_block_track_collection);
-
     LayoutUnit unused_intrinsic_block_size;
-    algorithm.ComputeGridGeometry(placement_data, &items_->grid_items_,
-                                  &layout_data_, &unused_intrinsic_block_size);
+    algorithm.ComputeGridGeometry(placement_data, &grid_items, &layout_data_,
+                                  &unused_intrinsic_block_size);
+
+    *cached_grid_items_ = grid_items.item_data;
   }
 
   const GridItemData& GridItem(wtf_size_t index) {
-    return items_->grid_items_.item_data[index];
+    return *cached_grid_items_->at(index);
   }
 
   const NGGridSizingTrackCollection& TrackCollection(
@@ -83,12 +74,12 @@
 
   // Helper methods to access private data on NGGridLayoutAlgorithm. This class
   // is a friend of NGGridLayoutAlgorithm but the individual tests are not.
-  wtf_size_t GridItemCount() { return items_->grid_items_.item_data.size(); }
+  wtf_size_t GridItemCount() { return cached_grid_items_->size(); }
 
   Vector<GridArea> GridItemGridAreas(const NGGridLayoutAlgorithm& algorithm) {
     Vector<GridArea> results;
-    for (const auto& item : items_->grid_items_.item_data)
-      results.push_back(item.resolved_position);
+    for (const auto& grid_item : *cached_grid_items_)
+      results.push_back(grid_item->resolved_position);
     return results;
   }
 
@@ -160,13 +151,8 @@
     return fragment->DumpFragmentTree(flags);
   }
 
-  struct Items final : public GarbageCollected<Items> {
-    void Trace(Visitor* visitor) const { visitor->Trace(grid_items_); }
-    GridItems grid_items_;
-  };
-
-  Persistent<Items> items_ = MakeGarbageCollected<Items>();
-
+  Persistent<GridItems::GridItemDataVector> cached_grid_items_ =
+      MakeGarbageCollected<GridItems::GridItemDataVector>();
   NGGridLayoutData layout_data_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
index 43cef79..d9c4ecf2 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h"
 
-#include "third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h"
 #include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h"
 
 namespace blink {
@@ -45,22 +44,23 @@
   const int initial_order = ComputedStyleInitialValues::InitialOrder();
 
   for (auto child = FirstChild(); child; child = child.NextSibling()) {
-    GridItemData grid_item(To<NGBlockNode>(child), container_style,
-                           container_style.GetWritingMode());
+    auto* grid_item = MakeGarbageCollected<GridItemData>(
+        To<NGBlockNode>(child), container_style,
+        container_style.GetWritingMode());
 
     // Order all of our in-flow children by their order property.
-    if (!grid_item.IsOutOfFlow()) {
+    if (!grid_item->IsOutOfFlow()) {
       should_sort_grid_items_by_order_property |=
           child.Style().Order() != initial_order;
-      grid_items.Append(std::move(grid_item));
+      grid_items.Append(grid_item);
     }
   }
 
   // We only need to sort this when we encounter a non-initial order property.
   if (should_sort_grid_items_by_order_property) {
-    auto CompareItemsByOrderProperty = [](const GridItemData& lhs,
-                                          const GridItemData& rhs) {
-      return lhs.node.Style().Order() < rhs.node.Style().Order();
+    auto CompareItemsByOrderProperty = [](const Member<GridItemData>& lhs,
+                                          const Member<GridItemData>& rhs) {
+      return lhs->node.Style().Order() < rhs->node.Style().Order();
     };
     std::stable_sort(grid_items.item_data.begin(), grid_items.item_data.end(),
                      CompareItemsByOrderProperty);
@@ -89,7 +89,7 @@
 
   // Copy each resolved position to its respective grid item data.
   auto* resolved_position = cached_placement_data->grid_item_positions.begin();
-  for (auto& grid_item : grid_items.item_data)
+  for (auto& grid_item : grid_items)
     grid_item.resolved_position = *(resolved_position++);
   return grid_items;
 }
@@ -109,14 +109,14 @@
     if (!has_standalone_columns && !has_standalone_rows)
       return grid_items;
 
-    for (auto& grid_item : grid_items.item_data) {
+    for (auto& grid_item : grid_items) {
       grid_item.can_subgrid_items_in_column_direction = has_standalone_columns;
       grid_item.can_subgrid_items_in_row_direction = has_standalone_rows;
     }
   }
 
   for (wtf_size_t i = 0; i < grid_items.Size(); ++i) {
-    auto& current_item = grid_items.item_data[i];
+    auto& current_item = grid_items[i];
 
     // TODO(ethavar): Don't consider subgrids with size containment.
     if (!current_item.node.IsGrid())
@@ -170,18 +170,14 @@
 
     // TODO(ethavar): Compute automatic repetitions for subgridded axes as
     // described in https://drafts.csswg.org/css-grid-2/#auto-repeat.
+
     auto subgridded_items = subgrid.ConstructGridItems(&subgrid_placement_data);
+    grid_items.ReserveCapacity(grid_items.Size() + subgridded_items.Size());
 
     const wtf_size_t column_start_line = current_item.StartLine(kForColumns);
     const wtf_size_t row_start_line = current_item.StartLine(kForRows);
 
-    // Don't use |current_item| after we reserve the new capacity; the reference
-    // becomes invalid because |grid_items| is reallocated.
-    grid_items.ReserveCapacity(grid_items.Size() + subgridded_items.Size());
-
-    for (auto& subgridded_item : subgridded_items.item_data) {
-      subgridded_item.is_subgridded_to_parent_grid = true;
-
+    for (auto& subgridded_item : subgridded_items) {
       subgridded_item.resolved_position.columns.Translate(column_start_line);
       subgridded_item.resolved_position.rows.Translate(row_start_line);
 
@@ -195,7 +191,8 @@
       subgridded_item.can_subgrid_items_in_row_direction =
           should_subgrid_items_in_row_direction;
 
-      grid_items.Append(std::move(subgridded_item));
+      subgridded_item.parent_grid = &current_item;
+      grid_items.Append(&subgridded_item);
     }
   }
   return grid_items;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h
index b966f12..11bdba5 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h
@@ -7,12 +7,11 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h"
+#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 
 namespace blink {
 
-struct GridItems;
-
 // Grid specific extensions to NGBlockNode.
 class CORE_EXPORT NGGridNode final : public NGBlockNode {
  public:
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
index c0f254c..517299e6 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
@@ -131,7 +131,7 @@
   placement_data_.grid_item_positions.ReserveInitialCapacity(grid_items.Size());
   placement_data_.column_start_offset = placement_data_.row_start_offset = 0;
 
-  for (const auto& grid_item : grid_items.item_data) {
+  for (const auto& grid_item : grid_items) {
     const auto& item_style = grid_item.node.Style();
 
     GridArea position;
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 5f2ff69..f6ad7ee5 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -306,6 +306,12 @@
     UpdateLayerPosition();
   }
 
+  if (LayoutBox* box = DynamicTo<LayoutBox>(GetLayoutObject());
+      box && box->AnchorScrollContainer()) {
+    PaintLayer* scroll_container_layer = box->AnchorScrollContainer()->Layer();
+    scroll_container_layer->GetScrollableArea()->AddAnchorPositionedLayer(this);
+  }
+
   // Display-locked elements always have a PaintLayer, meaning that the
   // PaintLayer traversal won't skip locked elements. Thus, we don't have to do
   // an ancestor check, and simply skip iterating children when this element is
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 3f58fda..a48c4f6 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -124,6 +124,7 @@
 
 void PaintLayerScrollableAreaRareData::Trace(Visitor* visitor) const {
   visitor->Trace(sticky_layers_);
+  visitor->Trace(anchor_positioned_layers_);
 }
 
 const int kResizerControlExpandRatioForTouch = 2;
@@ -541,6 +542,7 @@
 
 void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange() {
   InvalidatePaintForStickyDescendants();
+  InvalidatePaintForAnchorPositionedLayers();
 
   auto* box = GetLayoutBox();
   auto* frame_view = box->GetFrameView();
@@ -947,6 +949,7 @@
 
 void PaintLayerScrollableArea::UpdateAfterLayout() {
   InvalidateAllStickyConstraints();
+  InvalidateAllAnchorPositionedLayers();
 
   bool is_horizontal_scrollbar_frozen;
   bool is_vertical_scrollbar_frozen;
@@ -2098,6 +2101,31 @@
   }
 }
 
+void PaintLayerScrollableArea::AddAnchorPositionedLayer(PaintLayer* layer) {
+  auto add_result = EnsureRareData().anchor_positioned_layers_.insert(layer);
+  if (add_result.is_new_entry)
+    layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
+}
+
+void PaintLayerScrollableArea::InvalidateAllAnchorPositionedLayers() {
+  if (rare_data_)
+    rare_data_->anchor_positioned_layers_.clear();
+}
+
+void PaintLayerScrollableArea::InvalidatePaintForAnchorPositionedLayers() {
+  // If this is called during layout, anchor_positioned_layers_ may contain
+  // stale pointers. Return because we'll InvalidateAllAnchorPositionedLayers(),
+  // and we'll SetNeedsPaintPropertyUpdate() when updating anchor positioned
+  // layers.
+  if (GetLayoutBox()->NeedsLayout())
+    return;
+
+  if (PaintLayerScrollableAreaRareData* d = RareData()) {
+    for (PaintLayer* anchor_positioned_layer : d->anchor_positioned_layers_)
+      anchor_positioned_layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
+  }
+}
+
 gfx::Vector2d PaintLayerScrollableArea::OffsetFromResizeCorner(
     const gfx::Point& absolute_point) const {
   // Currently the resize corner is either the bottom right corner or the bottom
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index 7df374a..98f3824 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -50,6 +50,7 @@
 #include "third_party/blink/renderer/core/layout/scroll_anchor.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -80,6 +81,7 @@
   void Trace(Visitor* visitor) const;
 
   HeapLinkedHashSet<Member<PaintLayer>> sticky_layers_;
+  HeapHashSet<Member<PaintLayer>> anchor_positioned_layers_;
   absl::optional<cc::SnapContainerData> snap_container_data_;
   bool snap_container_data_needs_update_ = true;
   bool needs_resnap_ = false;
@@ -522,6 +524,10 @@
   void InvalidateAllStickyConstraints();
   void InvalidatePaintForStickyDescendants();
 
+  void AddAnchorPositionedLayer(PaintLayer*);
+  void InvalidateAllAnchorPositionedLayers();
+  void InvalidatePaintForAnchorPositionedLayers();
+
   uint32_t GetNonCompositedMainThreadScrollingReasons() {
     return non_composited_main_thread_scrolling_reasons_;
   }
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index cdf443e..1059a6e 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -256,7 +256,8 @@
                 "lighting-color", "shape-rendering", "clip-rule", "fill-rule",
                 "color-interpolation", "color-interpolation-filters", "paint-order",
                 "fill", "fill-opacity", "stroke", "stroke-opacity",
-                "-internal-visited-stroke", "stroke-dashoffset", "ColorSchemeForced"],
+                "-internal-visited-stroke", "stroke-dashoffset", "ColorSchemeForced",
+                "anchor-scroll"],
         methods_to_diff: [
           {
             method: "Visibility()",
@@ -281,6 +282,10 @@
           {
             method: "AccentColorResolved()",
             field_dependencies: ["accent-color", "color"]
+          },
+          {
+            method: "AnchorScroll()",
+            field_dependencies: ["anchor-scroll"],
           }
         ],
         predicates_to_test: [
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index bb3f318..ca98fe4 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1264,9 +1264,6 @@
     }
   }
 
-  if (accessibility_mode.has_mode(ui::AXMode::kScreenReader))
-    SerializeScreenReaderAttributes(node_data);
-
   SerializeUnignoredAttributes(node_data, accessibility_mode);
 
   if (accessibility_mode.has_mode(ui::AXMode::kPDF)) {
@@ -1605,7 +1602,87 @@
       node_data, ax::mojom::blink::StringAttribute::kPlaceholder, placeholder);
 }
 
-void AXObject::SerializeScreenReaderAttributes(ui::AXNodeData* node_data) {
+// Helper function that searches in the subtree of |obj| to a max
+// depth of |max_depth| for an image.
+//
+// Returns true on success, or false if it finds more than one image,
+// or any node with a name, or anything deeper than |max_depth|.
+static AXObject* SearchForExactlyOneInnerImage(AXObject* obj,
+                                               AXObject* inner_image,
+                                               int max_depth) {
+  // If it's the first image, set |inner_image|. If we already
+  // found an image, fail.
+  if (ui::IsImage(obj->RoleValue())) {
+    if (inner_image)
+      return nullptr;
+    inner_image = obj;
+  } else {
+    // If we found something else with a name, fail.
+    if (!ui::IsPlatformDocument(obj->RoleValue()) &&
+        !ui::IsLink(obj->RoleValue())) {
+      ax::mojom::blink::NameFrom name_from;
+      HeapVector<Member<AXObject>> name_objects;
+      String name = obj->GetName(name_from, &name_objects);
+
+      if (!name.StripWhiteSpace().IsEmpty())
+        return nullptr;
+    }
+  }
+
+  // Fail if we recursed to |max_depth| and there's more of a subtree.
+  if (max_depth == 0 && obj->ChildCountIncludingIgnored())
+    return nullptr;
+
+  // Don't count ignored nodes toward depth.
+  int next_depth = obj->AccessibilityIsIgnored() ? max_depth : max_depth - 1;
+
+  // Recurse.
+  for (int i = 0; i < obj->ChildCountIncludingIgnored(); i++) {
+    inner_image = SearchForExactlyOneInnerImage(obj->ChildAtIncludingIgnored(i),
+                                                inner_image, next_depth);
+    if (!inner_image)
+      return nullptr;
+  }
+
+  return inner_image;
+}
+
+// Return true if the subtree of |obj|, to a max depth of 3, contains
+// exactly one image. Return that image in |inner_image|.
+static AXObject* FindExactlyOneInnerImageInMaxDepthThree(
+    AXObject& obj,
+    AXObject* inner_image) {
+  return SearchForExactlyOneInnerImage(&obj, inner_image, /* max_depth = */ 3);
+}
+
+String AXObject::KeyboardShortcut() const {
+  const AtomicString& access_key = AccessKey();
+  if (access_key.IsNull())
+    return String();
+
+  DEFINE_STATIC_LOCAL(String, modifier_string, ([] {
+                        unsigned modifiers =
+                            KeyboardEventManager::kAccessKeyModifiers;
+                        // Follow the same order as Mozilla MSAA implementation:
+                        // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard
+                        // shortcut strings should not be localized and defines
+                        // the separator as "+".
+                        StringBuilder modifier_string_builder;
+                        if (modifiers & WebInputEvent::kControlKey)
+                          modifier_string_builder.Append("Ctrl+");
+                        if (modifiers & WebInputEvent::kAltKey)
+                          modifier_string_builder.Append("Alt+");
+                        if (modifiers & WebInputEvent::kShiftKey)
+                          modifier_string_builder.Append("Shift+");
+                        if (modifiers & WebInputEvent::kMetaKey)
+                          modifier_string_builder.Append("Win+");
+                        return modifier_string_builder.ToString();
+                      }()));
+
+  return String(modifier_string + access_key);
+}
+
+void AXObject::SerializeOtherScreenReaderAttributes(ui::AXNodeData* node_data) {
   String display_style;
   Node* node = GetNode();
   if (node && !node->IsDocumentNode()) {
@@ -1637,6 +1714,21 @@
         active_descendant->AXObjectID());
   }
 
+  if (ui::IsImage(node_data->role))
+    AXObjectCache().AddImageAnnotations(this, node_data);
+
+  // If a link or web area isn't otherwise labeled and contains exactly one
+  // image (searching only to a max depth of 2), and the link doesn't have
+  // accessible text from an attribute like aria-label, then annotate the
+  // link/web area with the image's annotation, too.
+  if ((ui::IsLink(node_data->role) ||
+       ui::IsPlatformDocument(node_data->role)) &&
+      node_data->GetNameFrom() != ax::mojom::blink::NameFrom::kAttribute) {
+    if (AXObject* inner_image =
+            FindExactlyOneInnerImageInMaxDepthThree(*this, nullptr))
+      AXObjectCache().AddImageAnnotations(inner_image, node_data);
+  }
+
   if (Node* node = GetNode()) {
     if (node->IsElementNode()) {
       Element* element = To<Element>(node);
@@ -1648,36 +1740,7 @@
       }
     }
   }
-}
 
-String AXObject::KeyboardShortcut() const {
-  const AtomicString& access_key = AccessKey();
-  if (access_key.IsNull())
-    return String();
-
-  DEFINE_STATIC_LOCAL(String, modifier_string, ());
-  if (modifier_string.IsNull()) {
-    unsigned modifiers = KeyboardEventManager::kAccessKeyModifiers;
-    // Follow the same order as Mozilla MSAA implementation:
-    // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
-    // should not be localized and defines the separator as "+".
-    StringBuilder modifier_string_builder;
-    if (modifiers & WebInputEvent::kControlKey)
-      modifier_string_builder.Append("Ctrl+");
-    if (modifiers & WebInputEvent::kAltKey)
-      modifier_string_builder.Append("Alt+");
-    if (modifiers & WebInputEvent::kShiftKey)
-      modifier_string_builder.Append("Shift+");
-    if (modifiers & WebInputEvent::kMetaKey)
-      modifier_string_builder.Append("Win+");
-    modifier_string = modifier_string_builder.ToString();
-  }
-
-  return String(modifier_string + access_key);
-}
-
-void AXObject::SerializeOtherScreenReaderAttributes(
-    ui::AXNodeData* node_data) const {
   DCHECK_NE(node_data->role, ax::mojom::blink::Role::kUnknown);
   DCHECK_NE(node_data->role, ax::mojom::blink::Role::kNone);
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index 5f0e915..50a64df 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -1415,7 +1415,7 @@
   void SerializeLiveRegionAttributes(ui::AXNodeData* node_data) const;
   void SerializeNameAndDescriptionAttributes(ui::AXMode accessibility_mode,
                                              ui::AXNodeData* node_data) const;
-  void SerializeOtherScreenReaderAttributes(ui::AXNodeData* node_data) const;
+  void SerializeOtherScreenReaderAttributes(ui::AXNodeData* node_data);
   void SerializeScreenReaderAttributes(ui::AXNodeData* node_data);
   void SerializeScrollAttributes(ui::AXNodeData* node_data);
   void SerializeSparseAttributes(ui::AXNodeData* node_data);
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 4cf9eb95..01dbc43 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
@@ -3511,6 +3511,16 @@
   MarkAXObjectDirtyWithCleanLayoutHelper(obj, true);
 }
 
+void AXObjectCacheImpl::AddImageAnnotations(AXObject* obj,
+                                            ui::AXNodeData* node_data) {
+  WebLocalFrameImpl* webframe = WebLocalFrameImpl::FromFrame(
+      obj->GetDocument()->AXObjectCacheOwner().GetFrame());
+  if (webframe && webframe->Client()) {
+    WebAXObject web_object(obj);
+    webframe->Client()->AddImageAnnotations(web_object, node_data);
+  }
+}
+
 void AXObjectCacheImpl::MarkAXObjectDirty(AXObject* obj) {
   if (!obj)
     return;
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 b5621d0..3fe254b 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
@@ -256,6 +256,8 @@
   void MarkAXObjectDirtyWithCleanLayout(AXObject*);
   void MarkAXSubtreeDirtyWithCleanLayout(AXObject*);
 
+  void AddImageAnnotations(AXObject*, ui::AXNodeData*);
+
   // Set the parent of |child|. If no parent is possible, this means the child
   // can no longer be in the AXTree, so remove the child.
   AXObject* RestoreParentOrPrune(AXObject* child);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
index 32cddab..0d9c9be5 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -142,6 +142,7 @@
   if (is_mappable) {
     GPU* gpu = device->adapter()->gpu();
     gpu->TrackMappableBuffer(buffer);
+    device->TrackMappableBuffer(buffer);
     buffer->mappable_buffer_handles_ = gpu->mappable_buffer_handles();
   }
 
@@ -205,6 +206,7 @@
   GetProcs().bufferDestroy(GetHandle());
   // Destroyed, so it can never be mapped again. Stop tracking.
   device_->adapter()->gpu()->UntrackMappableBuffer(this);
+  device_->UntrackMappableBuffer(this);
   // Drop the reference to the mapped buffer handles. No longer
   // need to remove the WGPUBuffer from this set in ~GPUBuffer.
   mappable_buffer_handles_ = nullptr;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
index cf60e3d..fa33a58 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -261,6 +261,15 @@
       texture_->GetHandle(), swap_buffers_->Size(), resource_provider);
 }
 
+bool GPUCanvasContext::CopyRenderingResultsToVideoFrame(
+    WebGraphicsContext3DVideoFramePool* frame_pool,
+    SourceDrawingBuffer src_buffer,
+    const gfx::ColorSpace& dst_color_space,
+    VideoFrameCopyCompletedCallback callback) {
+  return swap_buffers_->CopyToVideoFrame(frame_pool, src_buffer,
+                                         dst_color_space, std::move(callback));
+}
+
 void GPUCanvasContext::SetFilterQuality(
     cc::PaintFlags::FilterQuality filter_quality) {
   if (filter_quality != filter_quality_) {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
index 9e6755e..7118c98 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -31,7 +31,6 @@
 
  public:
   class Factory : public CanvasRenderingContextFactory {
-
    public:
     Factory() = default;
 
@@ -69,6 +68,11 @@
   // be webgpu compatible. Returns true on success.
   bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
                                              SourceDrawingBuffer) final;
+  bool CopyRenderingResultsToVideoFrame(
+      WebGraphicsContext3DVideoFramePool* frame_pool,
+      SourceDrawingBuffer src_buffer,
+      const gfx::ColorSpace& dst_color_space,
+      VideoFrameCopyCompletedCallback callback) override;
   void SetIsInHiddenPage(bool) override {}
   void SetIsBeingDisplayed(bool) override {}
   bool isContextLost() const override { return false; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
index 55bfe79..3bc933f 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/modules/webgpu/gpu_validation_error.h"
 #include "third_party/blink/renderer/modules/webgpu/string_utils.h"
 #include "third_party/blink/renderer/platform/bindings/microtask.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
 
 namespace blink {
 
@@ -383,9 +384,10 @@
   return queue_;
 }
 
-void GPUDevice::destroy() {
+void GPUDevice::destroy(ScriptState* script_state) {
   destroyed_ = true;
   DestroyAllExternalTextures();
+  UnmapAllMappableBuffers(script_state);
   GetProcs().deviceDestroy(GetHandle());
   FlushNow();
 }
@@ -596,6 +598,7 @@
   visitor->Trace(queue_);
   visitor->Trace(lost_property_);
   visitor->Trace(active_external_textures_);
+  visitor->Trace(mappable_buffers_);
   ExecutionContextClient::Trace(visitor);
   EventTargetWithInlineData::Trace(visitor);
 }
@@ -613,6 +616,20 @@
   active_external_textures_.clear();
 }
 
+void GPUDevice::UnmapAllMappableBuffers(ScriptState* script_state) {
+  for (GPUBuffer* buffer : mappable_buffers_) {
+    buffer->unmap(script_state);
+  }
+}
+
+void GPUDevice::TrackMappableBuffer(GPUBuffer* buffer) {
+  mappable_buffers_.insert(buffer);
+}
+
+void GPUDevice::UntrackMappableBuffer(GPUBuffer* buffer) {
+  mappable_buffers_.erase(buffer);
+}
+
 void GPUDevice::AddActiveExternalTexture(GPUExternalTexture* external_texture) {
   DCHECK(external_texture);
   active_external_textures_.insert(external_texture);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.h b/third_party/blink/renderer/modules/webgpu/gpu_device.h
index d9a5d0e..2fbe809 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_device.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -55,7 +55,6 @@
 class ScriptPromiseResolver;
 class ScriptState;
 class V8GPUErrorFilter;
-
 class GPUDevice final : public EventTargetWithInlineData,
                         public ExecutionContextClient,
                         public DawnObject<WGPUDevice> {
@@ -84,7 +83,7 @@
 
   GPUQueue* queue();
 
-  void destroy();
+  void destroy(ScriptState* script_state);
 
   GPUBuffer* createBuffer(const GPUBufferDescriptor* descriptor);
   GPUTexture* createTexture(const GPUTextureDescriptor* descriptor,
@@ -149,6 +148,13 @@
                                   ExceptionState& exception_state);
   std::string formattedLabel() const;
 
+  // Store the buffer in a weak hash set so we can unmap it when the
+  // device is destroyed.
+  void TrackMappableBuffer(GPUBuffer* buffer);
+  // Untrack the GPUBuffer. This is called eagerly when the buffer is
+  // destroyed.
+  void UntrackMappableBuffer(GPUBuffer* buffer);
+
  private:
   using LostProperty =
       ScriptPromiseProperty<Member<GPUDeviceLostInfo>, ToV8UndefinedGenerator>;
@@ -158,6 +164,8 @@
 
   void DestroyAllExternalTextures();
 
+  void UnmapAllMappableBuffers(ScriptState* script_state);
+
   void OnUncapturedError(WGPUErrorType errorType, const char* message);
   void OnLogging(WGPULoggingType loggingType, const char* message);
   void OnDeviceLostError(WGPUDeviceLostReason, const char* message);
@@ -205,6 +213,8 @@
   // when the device is destroyed (via .destroy) to free the memory.
   HeapHashSet<WeakMember<GPUExternalTexture>> active_external_textures_;
 
+  HeapHashSet<WeakMember<GPUBuffer>> mappable_buffers_;
+
   // This attribute records that whether GPUDevice is destroyed (via destroy()).
   bool destroyed_ = false;
 };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
index f692582a..fef9e48 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_device.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -15,7 +15,7 @@
 
     [SameObject] readonly attribute GPUQueue queue;
 
-    void destroy();
+    [CallWith=ScriptState] void destroy();
 
     GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
     [RaisesException] GPUTexture createTexture(GPUTextureDescriptor descriptor);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index fce85ab..0965def 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1872,13 +1872,16 @@
         additional_usage_flags = gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
       }
 
-      gpu_memory_buffer = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
-          size, buffer_format, buffer_usage, gpu::kNullSurfaceHandle, nullptr);
-
-      if (gpu_memory_buffer) {
-        back_buffer_mailbox = sii->CreateSharedImage(
-            gpu_memory_buffer.get(), gpu_memory_buffer_manager, color_space_,
-            origin, kPremul_SkAlphaType, usage | additional_usage_flags);
+      if (gpu::IsImageFromGpuMemoryBufferFormatSupported(
+              buffer_format, ContextProvider()->GetCapabilities())) {
+        gpu_memory_buffer = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
+            size, buffer_format, buffer_usage, gpu::kNullSurfaceHandle,
+            nullptr);
+        if (gpu_memory_buffer) {
+          back_buffer_mailbox = sii->CreateSharedImage(
+              gpu_memory_buffer.get(), gpu_memory_buffer_manager, color_space_,
+              origin, kPremul_SkAlphaType, usage | additional_usage_flags);
+        }
       }
     }
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index d3e2ebe..b10f599 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -6,6 +6,7 @@
 
 #include "build/build_config.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/client/webgpu_interface.h"
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
@@ -27,6 +28,7 @@
       return viz::RGBA_8888;
   }
 }
+
 }  // namespace
 
 WebGPUSwapBufferProvider::WebGPUSwapBufferProvider(
@@ -94,7 +96,33 @@
   }
 }
 
-void WebGPUSwapBufferProvider::DiscardCurrentSwapBuffer() {
+std::tuple<uint32_t, bool>
+WebGPUSwapBufferProvider::GetTextureTargetAndOverlayCandidacy() const {
+// On macOS, shared images are backed by IOSurfaces that can only be used with
+// OpenGL via the rectangle texture target and are overlay candidates. Every
+// other shared image implementation is implemented on OpenGL via some form of
+// eglSurface and eglBindTexImage (on ANGLE or system drivers) so they use the
+// 2D texture target and cannot always be overlay candidates.
+#if BUILDFLAG(IS_MAC)
+  const uint32_t texture_target = gpu::GetPlatformSpecificTextureTarget();
+  const bool is_overlay_candidate = true;
+#else
+  const uint32_t texture_target = GL_TEXTURE_2D;
+  const bool is_overlay_candidate = false;
+#endif
+
+  return std::make_tuple(texture_target, is_overlay_candidate);
+}
+
+uint32_t WebGPUSwapBufferProvider::GetTextureTarget() const {
+  return std::get<0>(GetTextureTargetAndOverlayCandidacy());
+}
+bool WebGPUSwapBufferProvider::IsOverlayCandidate() const {
+  return std::get<1>(GetTextureTargetAndOverlayCandidacy());
+}
+
+void WebGPUSwapBufferProvider::ReleaseWGPUTextureAccessIfNeeded(
+    bool for_transfer) {
   if (current_swap_buffer_) {
     if (auto context_provider = GetContextProviderWeakPtr()) {
       gpu::webgpu::WebGPUInterface* webgpu =
@@ -102,8 +130,17 @@
 
       // Dissociate mailbox to avoid memory leaks.
       if (wire_device_id_ && wire_texture_id_) {
-        webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
+        if (for_transfer) {
+          // Give client a chance to do something before the dissociation.
+          DCHECK(client_);
+          client_->OnTextureTransferred();
 
+          webgpu->DissociateMailboxForPresent(
+              wire_device_id_, wire_device_generation_, wire_texture_id_,
+              wire_texture_generation_);
+        } else {
+          webgpu->DissociateMailbox(wire_texture_id_, wire_texture_generation_);
+        }
         wire_device_id_ = 0;
         wire_device_generation_ = 0;
         wire_texture_id_ = 0;
@@ -115,10 +152,14 @@
       webgpu->GenUnverifiedSyncTokenCHROMIUM(
           current_swap_buffer_->access_finished_token.GetData());
     }
-    current_swap_buffer_ = nullptr;
   }
 }
 
+void WebGPUSwapBufferProvider::DiscardCurrentSwapBuffer() {
+  ReleaseWGPUTextureAccessIfNeeded(/*for_transfer=*/false);
+  current_swap_buffer_ = nullptr;
+}
+
 void WebGPUSwapBufferProvider::Neuter() {
   if (neutered_) {
     return;
@@ -182,7 +223,7 @@
 
 WGPUTexture WebGPUSwapBufferProvider::GetNewTexture(const gfx::Size& size,
                                                     SkAlphaType alpha_mode) {
-  DCHECK(!current_swap_buffer_);
+  DCHECK(!wire_texture_id_);
   auto context_provider = GetContextProviderWeakPtr();
   if (!context_provider) {
     return nullptr;
@@ -257,41 +298,13 @@
     return false;
   }
 
-  DCHECK(client_);
-  client_->OnTextureTransferred();
+  ReleaseWGPUTextureAccessIfNeeded(/*for_transfer=*/true);
 
-  // Make Dawn relinquish access to the texture so it can be used by the
-  // compositor. This will call wgpu::Texture::Destroy so that further accesses
-  // to the texture are errors.
-  gpu::webgpu::WebGPUInterface* webgpu =
-      GetContextProviderWeakPtr()->ContextProvider()->WebGPUInterface();
-  DCHECK_NE(wire_device_id_, 0u);
-  DCHECK_NE(wire_texture_id_, 0u);
-  webgpu->DissociateMailboxForPresent(wire_device_id_, wire_device_generation_,
-                                      wire_texture_id_,
-                                      wire_texture_generation_);
-
-  // Make the compositor wait on previous Dawn commands.
-  webgpu->GenUnverifiedSyncTokenCHROMIUM(
-      current_swap_buffer_->access_finished_token.GetData());
-
-  // On macOS, shared images are backed by IOSurfaces that can only be used with
-  // OpenGL via the rectangle texture target and are overlay candidates. Every
-  // other shared image implementation is implemented on OpenGL via some form of
-  // eglSurface and eglBindTexImage (on ANGLE or system drivers) so they use the
-  // 2D texture target and cannot always be overlay candidates.
-#if BUILDFLAG(IS_MAC)
-  const uint32_t texture_target = gpu::GetPlatformSpecificTextureTarget();
-  const bool is_overlay_candidate = true;
-#else
-  const uint32_t texture_target = GL_TEXTURE_2D;
-  const bool is_overlay_candidate = false;
-#endif
   // Populate the output resource
   *out_resource = viz::TransferableResource::MakeGL(
-      current_swap_buffer_->mailbox, GL_LINEAR, texture_target,
+      current_swap_buffer_->mailbox, GL_LINEAR, GetTextureTarget(),
       current_swap_buffer_->access_finished_token, current_swap_buffer_->size,
-      is_overlay_candidate);
+      IsOverlayCandidate());
   out_resource->color_space = gfx::ColorSpace::CreateSRGB();
   out_resource->format = Format();
 
@@ -302,14 +315,49 @@
                 scoped_refptr<WebGPUSwapBufferProvider>(this),
                 std::move(current_swap_buffer_));
 
-  wire_device_id_ = 0;
-  wire_device_generation_ = 0;
-  wire_texture_id_ = 0;
-  wire_texture_generation_ = 0;
-
   return true;
 }
 
+bool WebGPUSwapBufferProvider::CopyToVideoFrame(
+    WebGraphicsContext3DVideoFramePool* frame_pool,
+    SourceDrawingBuffer src_buffer,
+    const gfx::ColorSpace& dst_color_space,
+    WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback) {
+  DCHECK(!neutered_);
+  if (neutered_ || !GetContextProviderWeakPtr()) {
+    return false;
+  }
+
+  DCHECK(frame_pool);
+
+  auto* frame_pool_ri = frame_pool->GetRasterInterface();
+  DCHECK(frame_pool_ri);
+
+  // Copy kFrontBuffer to a video frame is not supported
+  DCHECK_EQ(src_buffer, kBackBuffer);
+
+  // For a conversion from swap buffer's texture to video frame, we do it
+  // using WebGraphicsContext3DVideoFramePool's graphics context. Thus, we
+  // need to release WebGPU/Dawn's context's access to the texture.
+  ReleaseWGPUTextureAccessIfNeeded(/*for_transfer=*/true);
+
+  gpu::MailboxHolder mailbox_holder(current_swap_buffer_->mailbox,
+                                    current_swap_buffer_->access_finished_token,
+                                    GetTextureTarget());
+
+  auto success = frame_pool->CopyRGBATextureToVideoFrame(
+      Format(), current_swap_buffer_->size, gfx::ColorSpace::CreateSRGB(),
+      kTopLeft_GrSurfaceOrigin, mailbox_holder, dst_color_space,
+      std::move(callback));
+
+  // Subsequent access to this swap buffer (either webgpu or compositor) must
+  // wait for the copy operation to finish.
+  frame_pool_ri->GenUnverifiedSyncTokenCHROMIUM(
+      current_swap_buffer_->access_finished_token.GetData());
+
+  return success;
+}
+
 void WebGPUSwapBufferProvider::MailboxReleased(
     std::unique_ptr<SwapBuffer> swap_buffer,
     const gpu::SyncToken& sync_token,
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
index c69ec7d5..2556c01 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -11,6 +11,8 @@
 #include "gpu/command_buffer/common/sync_token.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_types_3d.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -29,7 +31,7 @@
   class Client {
    public:
     // Called to make the WebGPU/Dawn stop accessing the texture prior to its
-    // transfer to the compositor.
+    // transfer to the compositor/video frame
     virtual void OnTextureTransferred() = 0;
   };
 
@@ -49,6 +51,32 @@
   void DiscardCurrentSwapBuffer();
   WGPUTexture GetNewTexture(const gfx::Size& size, SkAlphaType alpha_type);
 
+  // Copy swapchain's texture to a video frame.
+  // This happens at the end of an animation frame. Dawn's access to the
+  // texture will be released in order for the texture to be processed by
+  // WebGraphicsContext3DVideoFramePool context. Attempting to use the texture
+  // via WebGPU/Dawn API in JS after this point won't work.
+  //
+  // These are typical sequential steps of an animation frame:
+  // 1. start frame:
+  //     - WebGPUSwapBufferProvider::GetNewTexture()
+  // 2. client draws to the swap chain's texture using WebGPU APIs.
+  // 3. finalize frame:
+  //    (if client uses canvas.captureStream())
+  //     - WebGPUSwapBufferProvider::CopyToVideoFrame()
+  //         - ReleaseWGPUTextureAccessIfNeeded()
+  //         - copy swap chain's texture to a video frame using another graphics
+  //         context.
+  // 4. TextureLayer::Update()
+  //     - WebGPUSwapBufferProvider::PrepareTransferableResource()
+  //         - ReleaseWGPUTextureAccessIfNeeded() (if not already done)
+  //         - current_swap_buffer_'s ownership is transferred to caller.
+  bool CopyToVideoFrame(
+      WebGraphicsContext3DVideoFramePool* frame_pool,
+      SourceDrawingBuffer src_buffer,
+      const gfx::ColorSpace& dst_color_space,
+      WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback);
+
   struct WebGPUMailboxTextureAndSize {
     scoped_refptr<WebGPUMailboxTexture> mailbox_texture;
     gfx::Size size;
@@ -95,6 +123,10 @@
     gpu::SyncToken access_finished_token;
   };
 
+  std::tuple<uint32_t, bool> GetTextureTargetAndOverlayCandidacy() const;
+  uint32_t GetTextureTarget() const;
+  bool IsOverlayCandidate() const;
+
   std::unique_ptr<WebGPUSwapBufferProvider::SwapBuffer> NewOrRecycledSwapBuffer(
       gpu::SharedImageInterface* sii,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
@@ -107,6 +139,13 @@
                        const gpu::SyncToken& sync_token,
                        bool lost_resource);
 
+  // This method will dissociate current Dawn Texture (produced by
+  // GetNewTexture()) from the mailbox so that the mailbox can be used by other
+  // components (Compositor/Skia).
+  // After this method returns, Dawn won't be able to access the mailbox
+  // anymore.
+  void ReleaseWGPUTextureAccessIfNeeded(bool for_transfer);
+
   scoped_refptr<DawnControlClientHolder> dawn_control_client_;
   Client* client_;
   WGPUDevice device_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index c8995c1..10636682 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -47,7 +47,7 @@
       options_(std::move(world)),
       speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
       defer_(kNoDefer),
-      image_request_behavior_(kNone) {}
+      image_request_behavior_(ImageRequestBehavior::kNone) {}
 
 FetchParameters::FetchParameters(ResourceRequest resource_request,
                                  const ResourceLoaderOptions& options)
@@ -56,7 +56,7 @@
       options_(options),
       speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
       defer_(kNoDefer),
-      image_request_behavior_(kNone) {}
+      image_request_behavior_(ImageRequestBehavior::kNone) {}
 
 FetchParameters::FetchParameters(FetchParameters&&) = default;
 
@@ -121,13 +121,13 @@
 }
 
 void FetchParameters::SetLazyImageDeferred() {
-  DCHECK_EQ(kNone, image_request_behavior_);
-  image_request_behavior_ = kDeferImageLoad;
+  DCHECK_EQ(ImageRequestBehavior::kNone, image_request_behavior_);
+  image_request_behavior_ = ImageRequestBehavior::kDeferImageLoad;
 }
 
 void FetchParameters::SetLazyImageNonBlocking() {
   // TODO(domfarolino): [Before merging]: can we DCHECK here.
-  image_request_behavior_ = kNonBlockingImage;
+  image_request_behavior_ = ImageRequestBehavior::kNonBlockingImage;
 }
 
 void FetchParameters::SetModuleScript() {
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 0e8ff59..be68305 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -60,13 +60,13 @@
     kInDocument,  // The request was discovered in the main document
     kInserted     // The request was discovered in a document.write()
   };
-  enum ImageRequestBehavior {
-    kNone = 0,          // No optimization.
-    kDeferImageLoad,    // Defer loading the image from network. Full image
-                        // might still load if the request is already-loaded or
-                        // in memory cache.
-    kNonBlockingImage   // The image load may continue, but must be placed in
-                        // ResourceFetcher::non_blocking_loaders_.
+  enum class ImageRequestBehavior {
+    kNone = 0,         // No optimization.
+    kDeferImageLoad,   // Defer loading the image from network. Full image
+                       // might still load if the request is already-loaded or
+                       // in memory cache.
+    kNonBlockingImage  // The image load may continue, but must be placed in
+                       // ResourceFetcher::non_blocking_loaders_.
   };
 
   struct ResourceWidth {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 2bce260..38a2c33 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -591,7 +591,8 @@
   // - instructed to defer loading images from network
   if (resource->GetType() == ResourceType::kImage &&
       (ShouldDeferImageLoad(resource->Url()) ||
-       params.GetImageRequestBehavior() == FetchParameters::kDeferImageLoad)) {
+       params.GetImageRequestBehavior() ==
+           FetchParameters::ImageRequestBehavior::kDeferImageLoad)) {
     return false;
   }
   return policy != RevalidationPolicy::kUse || resource->StillNeedsLoad();
@@ -1207,7 +1208,7 @@
     image_resources_.insert(resource);
     not_loaded_image_resources_.insert(resource);
     if (params.GetImageRequestBehavior() ==
-        FetchParameters::kNonBlockingImage) {
+        FetchParameters::ImageRequestBehavior::kNonBlockingImage) {
       load_blocking_policy = ImageLoadBlockingPolicy::kForceNonBlockingLoad;
     }
   }
diff --git a/third_party/blink/tools/.coveragerc b/third_party/blink/tools/.coveragerc
new file mode 100644
index 0000000..77a66c58
--- /dev/null
+++ b/third_party/blink/tools/.coveragerc
@@ -0,0 +1,7 @@
+[run]
+branch = True
+
+[report]
+fail_under = 70
+precision = 1
+skip_empty = True
diff --git a/third_party/blink/tools/blink_tool.py b/third_party/blink/tools/blink_tool.py
index 2cb2ba0..09517e0 100755
--- a/third_party/blink/tools/blink_tool.py
+++ b/third_party/blink/tools/blink_tool.py
@@ -35,6 +35,7 @@
 import os
 import signal
 import sys
+import six
 
 from blinkpy.common.system.log_utils import configure_logging
 from blinkpy.tool.blink_tool import BlinkTool
@@ -62,7 +63,9 @@
 # contain unicode strings (as with some peoples' names) we need to apply
 # the utf-8 codec to prevent throwing and exception.
 # Not having this was the cause of https://bugs.webkit.org/show_bug.cgi?id=63452.
-sys.stdout = ForgivingUTF8Writer(sys.stdout)
+# In PY3 default encoding is utf-8. Hence we don't need this.
+if six.PY2:
+    sys.stdout = ForgivingUTF8Writer(sys.stdout)
 
 
 def main():
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index b5acecc..a984a10 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -673,6 +673,8 @@
             'ui::IsDialog',
             'ui::IsHeading',
             'ui::IsLandmark',
+            'ui::IsLink',
+            'ui::IsImage',
             'ui::IsPlatformDocument',
             'ui::IsPresentational',
             'ui::IsSelectRequiredOrImplicit',
diff --git a/third_party/blink/tools/blinkpy/tool/commands/abstract_local_server_command.py b/third_party/blink/tools/blinkpy/tool/commands/abstract_local_server_command.py
index 5f0afff..8a9e3f65 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/abstract_local_server_command.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/abstract_local_server_command.py
@@ -57,8 +57,10 @@
 
         server_url = 'http://localhost:%d%s' % (options.httpd_port,
                                                 self.launch_path)
-        print 'Starting server at %s' % server_url
-        print "Use the 'Exit' link in the UI, %squitquitquit or Ctrl-C to stop" % server_url
+        print('Starting server at %s' % server_url)
+        print(
+            "Use the 'Exit' link in the UI, %squitquitquit or Ctrl-C to stop" %
+            server_url)
 
         if options.show_results:
             # FIXME: This seems racy.
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_server.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_server.py
index c96ba17..a708ae2 100644
--- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_server.py
+++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_server.py
@@ -83,7 +83,7 @@
         results_directory = args[0]
         host = Host()
 
-        print 'Parsing full_results.json...'
+        print('Parsing full_results.json...')
         results_json_path = host.filesystem.join(results_directory,
                                                  'full_results.json')
         results_json = json_results_generator.load_json(
@@ -96,7 +96,7 @@
         self._test_config = TestConfig(port, web_tests_directory,
                                        results_directory, platforms, host)
 
-        print 'Gathering current baselines...'
+        print('Gathering current baselines...')
         self._gather_baselines(results_json)
 
         return {
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 ad9c6eab..ffa8909 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
@@ -178,8 +178,13 @@
             if component:
                 tests = {component: tests}
         results['tests'] = tests
-        test_names = self._extract_artifacts(results['tests'],
-                                             delim=results['path_delimiter'])
+        metadata = results.get('metadata') or {}
+        test_names = self._extract_artifacts(
+            results['tests'],
+            delim=results['path_delimiter'],
+            # Unlike the "external/wpt" prefix, 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))
 
         results_serialized = json.dumps(results)
@@ -199,7 +204,11 @@
             json.dump(results, dest)
             dest.write(');')
 
-    def _extract_artifacts(self, current_node, current_path='', delim='/'):
+    def _extract_artifacts(self,
+                           current_node,
+                           current_path='',
+                           delim='/',
+                           test_name_prefix=''):
         """Recursively extract artifacts from the test results trie.
 
         The JSON results represent tests as the leaves of a trie (nested
@@ -215,10 +224,14 @@
                 root directory.
             delim (str): Delimiter between components in test names. In
                 practice, the value is the POSIX directory separator.
+            test_name_prefix (str): Test name prefix to prepend to the generated
+                path when uploading results.
 
         Returns:
             list[str]: 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.
             if 'artifacts' not in current_node:
@@ -234,7 +247,8 @@
             # Required by fast/harness/results.html to show stderr.
             if 'stderr' in artifacts:
                 current_node['has_stderr'] = True
-            self._add_result_to_sink(current_node, current_path)
+            self._add_result_to_sink(current_node, current_path,
+                                     test_name_prefix)
             _log.debug('Extracted artifacts for %s: %s', current_path,
                        ', '.join(artifacts) if artifacts else '(none)')
             return [current_path]
@@ -247,7 +261,8 @@
                     # At the web test root, do not include a leading slash.
                     child_path = component
                 test_names.extend(
-                    self._extract_artifacts(child_node, child_path, delim))
+                    self._extract_artifacts(child_node, child_path, delim,
+                                            test_name_prefix))
             return test_names
 
     def _locate_expected_text(self, test_name, extension='.ini'):
@@ -351,7 +366,8 @@
         if not screenshots:
             return
         for screenshot in screenshots:
-            url, printable_image = screenshot.split(':')[:2]
+            url, printable_image = screenshot.rsplit(':', 1)
+
             # The URL produced by wptrunner will have a leading "/", which we
             # trim away for easier comparison to the WPT name below.
             if url.startswith('/'):
@@ -380,18 +396,18 @@
 
         diff_bytes, _, error = self.port.diff_image(expected_image_bytes,
                                                     actual_image_bytes)
-        if diff_bytes and not error:
+        if error:
+            _log.error(
+                'Error creating diff image for %s '
+                '(error: %s, diff_bytes is None: %s)', test_name, error,
+                diff_bytes is None)
+        elif diff_bytes:
             diff_subpath = self._write_png_artifact(
                 diff_bytes,
                 test_name,
                 test_failures.FILENAME_SUFFIX_DIFF,
             )
             artifacts['image_diff'] = [diff_subpath]
-        else:
-            _log.error(
-                'Error creating diff image for %s '
-                '(error: %s, diff_bytes is None: %s)', test_name, error,
-                diff_bytes is None)
 
     def _maybe_write_logs(self, artifacts, test_name):
         """Write WPT logs to disk, if possible."""
@@ -460,7 +476,7 @@
         index = test_name.rfind('?')
         return test_name if index == -1 else test_name[:index]
 
-    def _add_result_to_sink(self, node, test_name):
+    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
@@ -502,9 +518,12 @@
                 # upload the same artifacts multiple times.
                 artifacts=(artifacts.artifacts if iteration == 0 else {}),
             )
-            self.sink.report_individual_test_result(test_name, result,
-                                                    self.results_dir, None,
-                                                    test_path)
+            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 _trim_to_regressions(self, current_node):
         """Recursively remove non-regressions from the test results trie.
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 94675da..4025ffb 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
@@ -25,15 +25,15 @@
         self.invocation_level_artifacts = {}
         self.host = TypFakeHost()
 
-    def report_individual_test_result(self, test_name, result,
-                                      artifacts_sub_dir, expectation,
-                                      test_path):
-        del artifacts_sub_dir
-        assert not expectation, 'expectation parameter should always be None'
+    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': test_name,
-            'test_path': test_path,
+            'test_name_prefix': test_name_prefix,
+            'test_path': test_file_location,
             'result': {
+                'name': result.name,
                 'actual': result.actual,
                 'expected': result.expected,
                 'unexpected': result.unexpected,
@@ -155,20 +155,22 @@
         path_from_out_dir = self.fs.join('layout-test-results', 'external',
                                          'wpt', 'fail',
                                          'test_variant1-actual.txt')
-        self.assertEqual(self.processor.sink.sink_requests, [{
-            'test': test_name,
-            'test_path': test_abs_path,
-            'result': {
-                'actual': 'FAIL',
-                'expected': {'PASS', 'FAIL'},
-                'unexpected': False,
-                'took': 0,
-                'flaky': False,
-                'artifacts': {
-                    'actual_text': [path_from_out_dir],
-                },
-            },
-        }])
+        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],
+                                 },
+                             },
+                         }])
 
     def test_result_sink_for_test_variant(self):
         json_dict = {
@@ -196,20 +198,74 @@
         path_from_out_dir = self.fs.join('layout-test-results', 'external',
                                          'wpt', 'fail',
                                          'test_variant1-actual.txt')
-        self.assertEqual(self.processor.sink.sink_requests, [{
-            'test': test_name,
-            'test_path': test_abs_path,
-            'result': {
-                'actual': 'FAIL',
-                'expected': {'PASS'},
-                'unexpected': True,
-                'took': 0,
-                'flaky': False,
-                'artifacts': {
-                    'actual_text': [path_from_out_dir],
+        self.assertEqual(self.processor.sink.sink_requests,
+                         [{
+                             'test_name_prefix': '',
+                             '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],
+                                 },
+                             },
+                         }])
+
+    def test_result_sink_with_prefix_through_metadata(self):
+        """Verify that the sink uploads results with a test name prefix.
+
+        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.
+
+        See Also:
+            https://source.chromium.org/chromium/_/chromium/catapult.git/+/0c6b8d6722cc0e4a35b51d5104374b8cf9cc264e:third_party/typ/typ/runner.py;l=243-244
+        """
+        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.processor.process_wpt_results(OUTPUT_JSON_FILENAME)
+        test_name = self.fs.join('external', 'wpt', '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', 'external',
+                                         'wpt', '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],
+                                 },
+                             },
+                         }])
 
     def test_result_sink_for_multiple_runs(self):
         json_dict = {
@@ -231,29 +287,32 @@
         test_name = self.fs.join('external', 'wpt', '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': test_name,
-            'test_path': test_abs_path,
-            'result': {
-                'actual': 'PASS',
-                'expected': {'PASS'},
-                'unexpected': False,
-                'took': 2,
-                'flaky': True,
-                'artifacts': {},
-            },
-        }, {
-            'test': test_name,
-            'test_path': test_abs_path,
-            'result': {
-                'actual': 'FAIL',
-                'expected': {'PASS'},
-                'unexpected': True,
-                'took': 3,
-                'flaky': True,
-                'artifacts': {},
-            },
-        }])
+        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': {},
+                             },
+                         }])
 
     def test_result_sink_artifacts(self):
         json_dict = {
@@ -279,11 +338,12 @@
         path_from_out_dir = self.fs.join('layout-test-results', 'external',
                                          'wpt', 'fail', 'test-actual.txt')
         self.assertEqual(
-            self.processor.sink.sink_requests,
-            [{
-                'test': self.fs.join('external', 'wpt', 'fail', 'test.html'),
+            self.processor.sink.sink_requests, [{
+                'test_name_prefix': '',
                 'test_path': test_abs_path,
                 'result': {
+                    'name': self.fs.join('external', 'wpt', 'fail',
+                                         'test.html'),
                     'actual': 'FAIL',
                     'expected': {'PASS'},
                     'unexpected': True,
diff --git a/third_party/blink/tools/blinkpy/web_tests/bisect_test_ordering.py b/third_party/blink/tools/blinkpy/web_tests/bisect_test_ordering.py
index c60f6248..89b6cf9 100644
--- a/third_party/blink/tools/blinkpy/web_tests/bisect_test_ordering.py
+++ b/third_party/blink/tools/blinkpy/web_tests/bisect_test_ordering.py
@@ -57,7 +57,7 @@
     def bisect(self):
         if self.test_fails_in_isolation():
             self.buckets = [Bucket([self.expected_failure])]
-            print '%s fails when run in isolation.' % self.expected_failure
+            print('%s fails when run in isolation.' % self.expected_failure)
             self.print_result()
             return 0
         if not self.test_fails(self.tests):
@@ -81,26 +81,26 @@
         return self.test_bucket_list_fails([Bucket([self.expected_failure])])
 
     def verify_non_flaky(self):
-        print 'Verifying the failure is not flaky by running 10 times.'
+        print('Verifying the failure is not flaky by running 10 times.')
         count_failures = 0
         for _ in range(0, 10):
             if self.test_bucket_list_fails(self.buckets):
                 count_failures += 1
-        print 'Failed %d/10 times' % count_failures
+        print('Failed %d/10 times' % count_failures)
 
     def print_progress(self):
         count = 0
         for bucket in self.buckets:
             count += len(bucket.tests)
-        print '%d tests left, %d buckets' % (count, len(self.buckets))
+        print('%d tests left, %d buckets' % (count, len(self.buckets)))
 
     def print_result(self):
         tests = []
         for bucket in self.buckets:
             tests += bucket.tests
         extra_args = ' --debug' if self.is_debug else ''
-        print 'run_web_tests.py%s --jobs=1 --order=none %s' % (extra_args,
-                                                               ' '.join(tests))
+        print('run_web_tests.py%s --jobs=1 --order=none %s' %
+              (extra_args, ' '.join(tests)))
 
     def is_done(self):
         for bucket in self.buckets:
diff --git a/third_party/blink/tools/blinkpy/web_tests/web_tests_history.py b/third_party/blink/tools/blinkpy/web_tests/web_tests_history.py
index dde4520d..cae136c 100644
--- a/third_party/blink/tools/blinkpy/web_tests/web_tests_history.py
+++ b/third_party/blink/tools/blinkpy/web_tests/web_tests_history.py
@@ -97,7 +97,7 @@
 
     def _process_single(self, path):
         _init(self)
-        print _run(path)
+        print(_run(path))
         return 0
 
     def _process_many(self, paths):
@@ -125,7 +125,7 @@
                 if isinstance(res, BaseException):
                     # Traceback is already printed in the worker; exit directly.
                     raise SystemExit
-                print res
+                print(res)
             pool.close()
         except Exception:
             # A user exception was raised from the manager (main) process.
diff --git a/third_party/blink/tools/run_blinkpy_tests.py b/third_party/blink/tools/run_blinkpy_tests.py
index 43d341f..8e0b3b9 100755
--- a/third_party/blink/tools/run_blinkpy_tests.py
+++ b/third_party/blink/tools/run_blinkpy_tests.py
@@ -32,16 +32,34 @@
 import sys
 
 from blinkpy.common import path_finder
+from blinkpy.common.system.filesystem import FileSystem
 path_finder.add_typ_dir_to_sys_path()
 
 import typ
 
 
 def main():
+    finder = path_finder.PathFinder(FileSystem())
+    os.environ['COVERAGE_RCFILE'] = finder.path_from_blink_tools('.coveragerc')
     return typ.main(
+        coverage_source=[
+            # Do not measure coverage of executables under `blink/tools`.
+            finder.path_from_blink_tools('blinkpy'),
+        ],
+        coverage_omit=[
+            '*/blinkpy/third_party/*',
+            # Exclude non-production code.
+            '*/PRESUBMIT.py',
+            '*/blinkpy/web_tests/lint_test_expectations_presubmit.py',
+            '*_unittest.py',
+            '*mock*.py',
+            # Temporarily exclude python2 code that Coverage.py cannot import in
+            # python3.
+            '*/blinkpy/style/*',
+        ],
         top_level_dirs=[
             path_finder.get_blink_tools_dir(),
-            os.path.join(path_finder.get_source_dir(), 'build', 'scripts')
+            path_finder.get_build_scripts_dir(),
         ],
         path=[path_finder.get_blinkpy_thirdparty_dir()])
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index e10cf933..aa52550 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -56,6 +56,7 @@
 crbug.com/1204961 [ Mac10.14 ] external/wpt/websockets/stream/tentative/constructor.any.sharedworker.html?wpt_flags=h2 [ Failure Pass ]
 # Flaking on WebKit Linux MSAN
 crbug.com/1207373 [ Linux ] external/wpt/uievents/order-of-events/mouse-events/mousemove-across.html [ Failure Pass ]
+crbug.com/1339285 [ Linux ] fast/loader/iframe-window-open-stealing-focus.html [ Failure Timeout Pass ]
 
 # WPT Test harness doesn't deal with finding an about:blank ref test
 crbug.com/1066130 external/wpt/infrastructure/assumptions/blank.html [ Failure ]
@@ -5663,8 +5664,8 @@
 crbug.com/1180227 [ Mac ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ Crash Failure Pass ]
 crbug.com/1180227 [ Linux ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ Failure Pass ]
 
-crbug.com/1180274 crbug.com/1046784 [ Win ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Failure Pass ]
-crbug.com/1180274 crbug.com/1046784 [ Linux ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Failure Pass ]
+crbug.com/1180274 crbug.com/1046784 [ Win ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Failure Timeout Pass ]
+crbug.com/1180274 crbug.com/1046784 [ Linux ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Failure Timeout Pass ]
 crbug.com/1341227 [ Mac ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Skip ]
 
 # Sheriff 2021-02-21
@@ -6260,11 +6261,13 @@
 crbug.com/1249176 [ Mac12 ] virtual/basic-card-enabled/payments/payment-request-interface.html [ Failure Pass ]
 crbug.com/1249176 [ Mac12-arm64 ] external/wpt/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub.html [ Failure Pass ]
 crbug.com/1249176 [ Mac12-arm64 ] fast/js/instanceof-test.html [ Failure Pass ]
-crbug.com/1249176 [ Mac12-arm64 ] http/tests/devtools/elements/styles-2/nested-pseudo-elements.js [ Failure Pass ]
 crbug.com/1249176 [ Mac12-arm64 ] media/controls/overflow-menu-focus.html [ Failure Pass ]
 # Sheriff 2022-07-04
 crbug.com/1341689 [ Linux ] media/controls/overflow-menu-focus.html [ Failure Pass ]
 
+# crbug.com/1344983
+crbug.com/1344983 [ Mac11 ] fast/js/instanceof-test.html [ Failure Pass ]
+
 # Following tests timeout on mac11-arm64
 crbug.com/1249176 [ Mac11-arm64 ] http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Failure Timeout ]
 
@@ -6330,6 +6333,8 @@
 crbug.com/1249176 [ Mac12-arm64 ] external/wpt/largest-contentful-paint/multiple-redirects-TAO.html [ Failure Pass ]
 crbug.com/1249176 [ Mac11-arm64 ] virtual/background-svg-in-lcp/external/wpt/largest-contentful-paint/multiple-redirects-TAO.html [ Failure Pass ]
 crbug.com/1249176 [ Mac12-arm64 ] virtual/background-svg-in-lcp/external/wpt/largest-contentful-paint/multiple-redirects-TAO.html [ Failure Pass ]
+crbug.com/1249176 [ Mac12-arm64 ] http/tests/devtools/elements/styles-2/nested-pseudo-elements.js [ Failure Pass ]
+crbug.com/1249176 [ Mac11-arm64 ] http/tests/devtools/elements/styles-2/nested-pseudo-elements.js [ Failure Pass ]
 
 # mac-arm CI 10-01-2021
 crbug.com/1249176 [ Mac11-arm64 ] http/tests/security/opened-document-security-origin-resets-on-navigation.html [ Timeout ]
@@ -6352,6 +6357,9 @@
 crbug.com/1249176 [ Mac11-arm64 ] media/autoplay/webaudio-audio-context-init.html [ Crash Pass ]
 crbug.com/1249176 [ Mac12-arm64 ] media/autoplay/webaudio-audio-context-init.html [ Crash Pass ]
 
+#devtool flaky test crbug.com/1046784
+crbug.com/1046784 [ Mac12 ] http/tests/devtools/oopif/oopif-presentation-console-messages.js [ Failure Pass ]
+
 # Sheriff 2021-09-16
 crbug.com/1250457 [ Mac ] virtual/scroll-unification/plugins/plugin-map-data-to-src.html [ Failure ]
 crbug.com/1250457 [ Mac ] storage/websql/open-database-set-empty-version.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-hoverpopup-attribute.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-hoverpopup-attribute.tentative.html
index 51e026d..3f1ce38 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-hoverpopup-attribute.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-hoverpopup-attribute.tentative.html
@@ -83,11 +83,6 @@
     .send();
 }
 function msSinceMouseOver() {
-  // The hover delay is kept low to avoid this test taking too long,
-  // but that means that sometimes on a slow bot, the hover delay can
-  // elapse before we check the pop-up status. That makes this test
-  // flaky. Use the time returned by this function to just skip checks
-  // in that case.
   return performance.now() - mouseOverStarted;
 }
 async function waitForHoverTime() {
@@ -95,6 +90,14 @@
   await waitForRender();
 };
 
+// NOTE about testing methodology:
+// This test checks whether pop-ups are triggered *after* the appropriate hover
+// delay. The delay used for testing is kept low, to avoid this test taking too
+// long, but that means that sometimes on a slow bot/client, the hover delay can
+// elapse before we are able to check the pop-up status. And that can make this
+// test flaky. To avoid that, the msSinceMouseOver() function is used to check
+// that not-too-much time has passed, and if it has, the test is simply skipped.
+
 ["auto","hint","manual"].forEach(type => {
   ["plain","nested","nested-offset"].forEach(invokerType => {
     promise_test(async (t) => {
@@ -102,6 +105,7 @@
       assert_false(popUp.matches(':top-layer'));
       await mouseOver(invoker);
       let showing = popUp.matches(':top-layer');
+      // See NOTE above.
       if (msSinceMouseOver() < hoverPopUpDelay)
         assert_false(showing,'pop-up should not show immediately');
       await waitForHoverTime();
@@ -116,6 +120,7 @@
       const {popUp,invoker} = await makePopUpAndInvoker(t,type,invokerType,longerHoverDelay);
       await mouseOver(invoker);
       let showing = popUp.matches(':top-layer');
+      // See NOTE above.
       if (msSinceMouseOver() >= longerHoverDelay)
         return; // The WPT runner was too slow.
       assert_false(showing,'pop-up should not show immediately');
@@ -142,6 +147,7 @@
       await mouseOver(invoker);
       let showing = popUp.matches(':top-layer');
       popUp.remove();
+      // See NOTE above.
       if (msSinceMouseOver() >= hoverPopUpDelay)
         return; // The WPT runner was too slow.
       assert_false(showing,'pop-up should not show immediately');
@@ -161,6 +167,7 @@
       await mouseOver(invoker);
       let eitherShowing = popUp.matches(':top-layer') || popUp2.matches(':top-layer');
       reassignPopupFn(popUp2);
+      // See NOTE above.
       if (msSinceMouseOver() >= hoverPopUpDelay)
         return; // The WPT runner was too slow.
       assert_false(eitherShowing,'pop-up should not show immediately');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-sharedworker.html
deleted file mode 100644
index 9bfe5a1..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-sharedworker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-1-nothrow-worker-setup.js");
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker-setup.js
deleted file mode 100644
index 88fc22b..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker-setup.js
+++ /dev/null
@@ -1,4 +0,0 @@
-importScripts("/resources/testharness.js");
-importScripts("module/evaluation-order-setup.mjs");
-importScripts("module/evaluation-order-1-nothrow-worker.mjs");
-importScripts("module/evaluation-order-1-nothrow.mjs");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker.html
deleted file mode 100644
index 4ddfb61d..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow-worker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-1-nothrow-worker-setup.js");
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow.html
deleted file mode 100644
index b08372e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-nothrow.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="module/evaluation-order-setup.mjs"></script>
-<script>
-  window.addEventListener("load", ev => globalThis.testDone());
-  globalThis.expectedLog = [
-    "step-1-1", "step-1-2",
-    "microtask",
-    "script-load",
-    "global-load",
-  ];
-</script>
-
-<script src="module/evaluation-order-1-nothrow.mjs"
-    onerror="globalThis.unreachable()"
-    onload="globalThis.log.push('script-load')"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-sharedworker.html
deleted file mode 100644
index 0ad18a8..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-sharedworker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-1-worker-setup.js");
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker-setup.js
deleted file mode 100644
index 5ac90a23..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker-setup.js
+++ /dev/null
@@ -1,4 +0,0 @@
-importScripts("/resources/testharness.js");
-importScripts("module/evaluation-order-setup.mjs");
-importScripts("evaluation-order-1-worker.js");
-importScripts("module/evaluation-order-1.mjs");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.html
deleted file mode 100644
index 7760e08..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-1-worker-setup.js");
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.js
deleted file mode 100644
index b583bf1..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1-worker.js
+++ /dev/null
@@ -1,9 +0,0 @@
-globalThis.expectedLog = [
-  "step-1-1", "step-1-2",
-  "global-error", "error",
-  "microtask",
-];
-
-globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
-
-done();
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1.html
deleted file mode 100644
index 7bf71320..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/evaluation-order-1.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="module/evaluation-order-setup.mjs"></script>
-<script>
-  window.addEventListener("load", event => globalThis.testDone());
-  globalThis.expectedLog = [
-    "step-1-1", "step-1-2",
-    "global-error", "error",
-    "microtask",
-    "script-load",
-    "global-load"
-  ];
-</script>
-
-<script src="module/evaluation-order-1.mjs"
-    onerror="unreachable()" onload="log.push('script-load')"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js
new file mode 100644
index 0000000..bacfc9f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js
@@ -0,0 +1,11 @@
+// META: global=dedicatedworker,sharedworker
+// META: script=./resources/evaluation-order-setup.js
+
+// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
+// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope
+setupTest("importScripts() queueing a microtask then throwing an exception", [
+  "body",
+  "microtask",
+]);
+
+importScripts('./resources/evaluation-order-1-nothrow.js');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js
new file mode 100644
index 0000000..006eab7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js
@@ -0,0 +1,5 @@
+// META: global=dedicatedworker-module,sharedworker-module
+// META: script=./resources/evaluation-order-setup.js
+
+import './resources/evaluation-order-1-nothrow-setup.js';
+import './resources/evaluation-order-1-nothrow.js';
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js
new file mode 100644
index 0000000..0b42ea1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js
@@ -0,0 +1,22 @@
+// META: global=dedicatedworker,sharedworker
+// META: script=./resources/evaluation-order-setup.js
+
+// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
+// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope
+setupTest("importScripts() queueing a microtask then throwing an exception", [
+  // Step 6 of #run-a-classic-script.
+  "body",
+
+  // Step 7.1.1 ("Clean up after running script") is no-op because JavaScript
+  // execution context stack is still non-empty immediately after
+  // importScripts() as the outer script is still executing.
+
+  // Step 7.1.2 (Rethrowing an exception) causes worker onerror.
+  "global-error",
+
+  // Microtask checkpoint is performed later, perhaps
+  // "Clean up after running script" after the outer script is finished.
+  "microtask",
+]);
+
+importScripts('./resources/evaluation-order-1-throw.js');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js
new file mode 100644
index 0000000..f6cc427c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js
@@ -0,0 +1,5 @@
+// META: global=dedicatedworker-module,sharedworker-module
+// META: script=./resources/evaluation-order-setup.js
+
+import './resources/evaluation-order-1-throw-setup.js';
+import './resources/evaluation-order-1-throw.js';
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html
new file mode 100644
index 0000000..4800ef8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/evaluation-order-setup.js"></script>
+
+<script>
+// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
+setupTest("Classic script queueing a microtask then throwing an exception", [
+  "body",         // Step 6.
+  "global-error", // "Report the exception" at Step 7.3.
+  "microtask",    // "Clean up after running script" at Step 7.2.
+  ]);
+</script>
+<script src="resources/evaluation-order-1-throw.js"
+    onerror="unreachable()" onload="testDone()"></script>
+
+<script>
+// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script
+setupTest("Classic script queueing a microtask", [
+  "body",         // Step 6.
+  "microtask",    // "Clean up after running script" at Step 7.2.
+  ]);
+</script>
+<script src="resources/evaluation-order-1-nothrow.js"
+    onerror="unreachable()" onload="testDone()"></script>
+
+
+<script type="module" src="resources/evaluation-order-1-throw-setup.js"></script>
+<script type="module" src="resources/evaluation-order-1-throw.js"
+    onerror="unreachable()" onload="testDone()"></script>
+
+<script type="module" src="resources/evaluation-order-1-nothrow-setup.js"></script>
+<script type="module" src="resources/evaluation-order-1-nothrow.js"
+    onerror="unreachable()" onload="testDone()"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js
new file mode 100644
index 0000000..bbc64748
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js
@@ -0,0 +1,5 @@
+// META: global=dedicatedworker-module,sharedworker-module
+// META: script=./resources/evaluation-order-setup.js
+
+import './resources/evaluation-order-2-setup.js';
+import './resources/evaluation-order-2.1.mjs';
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html
new file mode 100644
index 0000000..e55c2ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/evaluation-order-setup.js"></script>
+
+<script type="module" src="resources/evaluation-order-2-setup.js"></script>
+<script type="module" src="resources/evaluation-order-2.1.mjs"
+    onerror="unreachable()" onload="testDone()"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js
new file mode 100644
index 0000000..19e9471
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js
@@ -0,0 +1,5 @@
+// META: global=dedicatedworker-module,sharedworker-module
+// META: script=./resources/evaluation-order-setup.js
+
+import './resources/evaluation-order-3-setup.js';
+import './resources/evaluation-order-3.1.mjs';
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html
new file mode 100644
index 0000000..ef351acd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/evaluation-order-setup.js"></script>
+
+<script type="module" src="resources/evaluation-order-3-setup.js"></script>
+<script type="module" src="resources/evaluation-order-3.1.mjs"
+    onerror="unreachable()"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html
new file mode 100644
index 0000000..f276784
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/evaluation-order-setup.js"></script>
+
+<script>
+// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
+setupTest("Module script queueing a microtask then top-level await", [
+  "step-4.1-1", "step-4.1-2",
+  "microtask-4.1",
+  "script-load",
+  "step-4.2-1", "step-4.2-2",
+  "microtask-4.2",
+]);
+window.onerror = testDone;
+</script>
+<script type="module" src="resources/evaluation-order-4.1.mjs"
+    onerror="unreachable()" onload="log.push('script-load')"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js
new file mode 100644
index 0000000..1b42e995
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js
@@ -0,0 +1,5 @@
+// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
+setupTest("Module script queueing a microtask", [
+  "body",         // Step 6.
+  "microtask",    // "Clean up after running script" at Step 8.
+]);
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js
new file mode 100644
index 0000000..e19d9b1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js
@@ -0,0 +1,2 @@
+queueMicrotask(() => globalThis.log.push("microtask"));
+globalThis.log.push("body");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js
new file mode 100644
index 0000000..651a494
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js
@@ -0,0 +1,10 @@
+// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
+setupTest("Module script queueing a microtask then throwing an exception", [
+  "body",         // Step 6.
+  "microtask",    // "Clean up after running script" at Step 8.
+  "global-error", // "Clean up after running script" at Step 8, because
+    // `evaluationPromise` is synchronously rejected and the rejection is
+    // processed in the microtask checkpoint here (See also Step 7).
+    // As `evaluationPromise` is rejected after the microtask queued during
+    // evaluation, "global-error" occurs after "microtask".
+]);
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js
new file mode 100644
index 0000000..2451df1c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js
@@ -0,0 +1,4 @@
+queueMicrotask(() => globalThis.log.push("microtask"));
+globalThis.log.push("body");
+
+throw new Error("error");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js
new file mode 100644
index 0000000..46f735453
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js
@@ -0,0 +1,10 @@
+// Spec: https://html.spec.whatwg.org/C/#run-a-module-script
+setupTest("Module script queueing a microtask then throwing an exception", [
+  "step-2.2-1", "step-2.2-2", // Step 6.
+  "microtask-2.2",            // "Clean up after running script" at Step 8.
+  "global-error",             // "Clean up after running script" at Step 8,
+    // because `evaluationPromise` is synchronously rejected and the rejection
+    // is processed in the microtask checkpoint here (See also Step 7).
+    // As `evaluationPromise` is rejected after the microtask queued during
+    // evaluation, "global-error" occurs after "microtask".
+]);
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2.1.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.1.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2.1.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.1.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2.2.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.2.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2.2.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.2.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js
similarity index 62%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js
index 79dabab..edc0469 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.mjs
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js
@@ -1,8 +1,7 @@
-globalThis.expectedLog = [
+setupTest("Module script queueing a microtask then throwing an exception", [
   "step-3.1-1", "step-3.1-2", "step-3.1-3",
   "microtask-3.1",
   "step-3.2-1", "step-3.2-2",
   "microtask-3.2",
   "import-catch", "error",
-];
-done();
\ No newline at end of file
+]);
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3.1.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.1.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3.1.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.1.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3.2.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.2.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3.2.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.2.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4.1.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.1.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4.1.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.1.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4.2.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.2.mjs
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4.2.mjs
rename to third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.2.mjs
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js
new file mode 100644
index 0000000..d2e28935
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js
@@ -0,0 +1,30 @@
+globalThis.setup({allow_uncaught_exception: true});
+
+// Must be called after previous tests are completed.
+globalThis.setupTest = (description, expectedLog) => {
+  globalThis.log = [];
+  globalThis.onerror = message => {
+      globalThis.log.push("global-error");
+      return true;
+  };
+  globalThis.onunhandledrejection =
+      () => globalThis.log.push('unhandled-promise-rejection');
+
+  globalThis.unreachable = () => globalThis.log.push("unreachable");
+
+  globalThis.test_load = async_test(description);
+  globalThis.testDone = globalThis.test_load.step_func_done(() => {
+    assert_array_equals(globalThis.log, expectedLog);
+  });
+
+  if (!('Window' in globalThis && globalThis instanceof Window)) {
+    // In workers, there are no <script> load event, so scheduling `testDone()`
+    // here, assuming the target script is loaded and evaluated soon.
+    globalThis.test_load.step_timeout(() => globalThis.testDone(), 1000);
+
+    // In workers, call `done()` here because the auto-generated `done()` calls
+    // by `any.js` etc. are at the end of main script and thus are not
+    // evaluated when the target script throws an exception.
+    done();
+  }
+};
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-sharedworker.html
deleted file mode 100644
index 77ece9e4..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-sharedworker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-1-nothrow-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker-setup.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker-setup.mjs
deleted file mode 100644
index 24cccd4..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker-setup.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import "/resources/testharness.js";
-import "./evaluation-order-setup.mjs";
-
-import "./evaluation-order-1-nothrow-worker.mjs";
-
-import "./evaluation-order-1-nothrow.mjs";
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.html
deleted file mode 100644
index 1b7ea09e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-1-nothrow-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.mjs
deleted file mode 100644
index 4d3cf31a..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow-worker.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-globalThis.expectedLog = [
-  "step-1-1", "step-1-2",
-  "microtask",
-];
-
-globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
-done();
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.html
deleted file mode 100644
index 080f5ac..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script type="module">
-  import "./evaluation-order-setup.mjs";
-  window.addEventListener("load", ev => globalThis.testDone());
-  globalThis.expectedLog = [
-    "step-1-1", "step-1-2",
-    "microtask",
-    "script-load",
-    "global-load",
-  ];
-</script>
-
-<script type="module" src="evaluation-order-1-nothrow.mjs"
-    onerror="globalThis.unreachable()"
-    onload="globalThis.log.push('script-load')"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.mjs
deleted file mode 100644
index c1d35beb..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-nothrow.mjs
+++ /dev/null
@@ -1,3 +0,0 @@
-globalThis.log.push("step-1-1");
-queueMicrotask(() => globalThis.log.push("microtask"));
-globalThis.log.push("step-1-2");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-sharedworker.html
deleted file mode 100644
index cc7f030..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-sharedworker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-1-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker-setup.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker-setup.mjs
deleted file mode 100644
index 3971461d..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker-setup.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import "/resources/testharness.js";
-import "./evaluation-order-setup.mjs";
-
-import "./evaluation-order-1-worker.mjs";
-
-import "./evaluation-order-1.mjs";
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.html
deleted file mode 100644
index 0325bb2..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-1-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.mjs
deleted file mode 100644
index 9be87c7..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1-worker.mjs
+++ /dev/null
@@ -1,9 +0,0 @@
-globalThis.expectedLog = [
-  "step-1-1", "step-1-2",
-  "microtask",
-  "global-error", "error",
-];
-
-globalThis.test_load.step_timeout(() => globalThis.testDone(), 0);
-
-done();
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.html
deleted file mode 100644
index 728aded..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script type="module">
-  import "./evaluation-order-setup.mjs";
-  window.addEventListener("load", event => globalThis.testDone());
-  globalThis.expectedLog = [
-    "step-1-1", "step-1-2",
-    "microtask",
-    "global-error", "error",
-    "script-load",
-    "global-load"
-  ];
-</script>
-
-<script type="module" src="evaluation-order-1.mjs"
-    onerror="unreachable()" onload="log.push('script-load')"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.mjs
deleted file mode 100644
index 7a43726..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-1.mjs
+++ /dev/null
@@ -1,5 +0,0 @@
-globalThis.log.push("step-1-1");
-queueMicrotask(() => log.push("microtask"));
-globalThis.log.push("step-1-2");
-
-throw new Error("error");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-sharedworker.html
deleted file mode 100644
index 0645639..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-sharedworker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-2-import-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker-setup.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker-setup.mjs
deleted file mode 100644
index 0cfdca6..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker-setup.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import "/resources/testharness.js";
-import "./evaluation-order-setup.mjs";
-
-import "./evaluation-order-2-import-worker.mjs";
-
-import "./evaluation-order-2.1.mjs";
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.html
deleted file mode 100644
index 8307019..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-2-import-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.mjs
deleted file mode 100644
index 3d9c9bb7..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import-worker.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-globalThis.expectedLog = [
-  "step-2.2-1", "step-2.2-2",
-  "microtask-2.2",
-  "global-error", "error",
-];
-
-done();
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import.html
deleted file mode 100644
index 1db333c..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-2-import.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script type="module">
-  import "./evaluation-order-setup.mjs";
-  globalThis.expectedLog = [
-    "step-2.2-1", "step-2.2-2",
-    "microtask-2.2",
-    "global-error", "error",
-    "script-load",
-    "global-load",
-  ];
-</script>
-
-<script type="module" src="evaluation-order-2.1.mjs"
-    onerror="globalThis.unreachable()"
-    onload="globalThis.log.push('script-load')">
- </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-sharedworker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-sharedworker.html
deleted file mode 100644
index cd1f5ed..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-sharedworker.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new SharedWorker(
-      "evaluation-order-3-dynamic-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker-setup.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker-setup.mjs
deleted file mode 100644
index f202cff..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker-setup.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import "/resources/testharness.js";
-import "./evaluation-order-setup.mjs";
-
-import "./evaluation-order-3-dynamic-worker.mjs";
-
-import "./evaluation-order-3.1.mjs";
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.html
deleted file mode 100644
index 49731bd..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic-worker.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  const worker = new Worker(
-      "evaluation-order-3-dynamic-worker-setup.mjs", {type:"module"});
-  fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic.html
deleted file mode 100644
index 6306c0b..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-3-dynamic.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script type="module">
-  import "./evaluation-order-setup.mjs";
-  globalThis.expectedLog = [
-    "step-3.1-1", "step-3.1-2", "step-3.1-3", "microtask-3.1",
-    "script-load",
-    "step-3.2-1", "step-3.2-2", "microtask-3.2",
-    "import-catch", "error"
-  ];
-</script>
-
-<script type="module" src="evaluation-order-3.1.mjs"
-    onerror="globalThis.unreachable()"
-    onload="globalThis.log.push('script-load')">
- </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4-tla.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4-tla.html
deleted file mode 100644
index da07faf4..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4-tla.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<title>Testing evaluation order</title>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-    setup({allow_uncaught_exception: true});
-
-    window.log = [];
-
-    window.addEventListener("error", ev => testDone());
-    window.addEventListener("onunhandledrejection", unreachable);
-
-    const test_load = async_test("Test evaluation order of modules");
-
-    window.addEventListener("load", ev => log.push("window-load"));
-
-    function unreachable() { log.push("unexpected"); }
-    function testDone() {
-      test_load.step(() => {
-        assert_array_equals(log, [
-             "step-4.1-1", "step-4.1-2", "microtask-4.1",
-             "script-load", "window-load",
-             "step-4.2-1", "step-4.2-2", "microtask-4.2",
-            ]);
-      });
-      test_load.done();
-    }
-</script>
-
-<script type="module" src="evaluation-order-4.1.mjs"
-    onerror="unreachable()" onload="log.push('script-load')">
- </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-setup.mjs b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-setup.mjs
deleted file mode 100644
index d3f22e9e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-setup.mjs
+++ /dev/null
@@ -1,19 +0,0 @@
-globalThis.setup({allow_uncaught_exception: true});
-
-globalThis.log = [];
-
-globalThis.addEventListener("error",
-    event => globalThis.log.push("global-error", event.error.message));
-globalThis.addEventListener("onunhandledrejection",
-    event => globalThis.log.push('unhandled-promise-rejection'));
-globalThis.addEventListener("load",
-    event => globalThis.log.push("global-load"));
-
-globalThis.unreachable = function() {
-    globalThis.log.push("unreachable");
-}
-
-globalThis.test_load = async_test("Test evaluation order of modules");
-globalThis.testDone = globalThis.test_load.step_func_done(() => {
-  assert_array_equals(globalThis.log, globalThis.expectedLog);
-});
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-001.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-001.html
new file mode 100644
index 0000000..ea40937
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-001.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Basic of anchor-scroll: anchored elements should keep "pinned" to the anchor during anchor scroll updates</title>
+<link rel="author" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/">
+<link rel="match" href="reference/anchor-scroll-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+body {
+  font: 20px/1 Ahem;
+  margin: 0;
+}
+
+#scroll-container {
+  width: 400px;
+  height: 400px;
+  overflow: scroll;
+}
+
+#scroll-contents {
+  width: 1000px;
+  height: 1000px;
+  position: relative;
+}
+
+#placefiller-above-anchor {
+  height: 500px;
+}
+
+#placefiller-before-anchor {
+  display: inline-block;
+  width: 500px;
+}
+
+#anchor {
+  anchor-name: --anchor;
+}
+
+#inner-anchored {
+  color: green;
+  position: absolute;
+  left: anchor(--anchor left);
+  bottom: anchor(--anchor top);
+  anchor-scroll: --anchor;
+}
+
+#outer-anchored {
+  color: yellow;
+  position: absolute;
+  left: anchor(--anchor left);
+  top: anchor(--anchor bottom);
+  anchor-scroll: --anchor;
+}
+</style>
+
+<div style="position: relative">
+  <div id="scroll-container">
+    <div id="scroll-contents">
+      <div id="placefiller-above-anchor"></div>
+      <div id="placefiller-before-anchor"></div>
+      <span id="anchor">anchor</span>
+      <div id="inner-anchored">inner-anchored</div>
+    </div>
+  </div>
+  <div id="outer-anchored">outer-anchored</div>
+</div>
+
+<script>
+function raf() {
+  return new Promise(resolve => requestAnimationFrame(resolve));
+}
+
+async function runTest() {
+  await raf();
+  await raf();
+  const scroller = document.getElementById('scroll-container');
+  scroller.scrollTop = 300;
+  scroller.scrollLeft = 450;
+  document.documentElement.classList.remove('reftest-wait');
+}
+runTest();
+</script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-002.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-002.html
new file mode 100644
index 0000000..3344b86c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-scroll-update-002.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Basic of anchor-scroll: anchored elements should update location on `anchor-scroll` property changes</title>
+<link rel="author" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/">
+<link rel="match" href="reference/anchor-scroll-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+body {
+  font: 20px/1 Ahem;
+  margin: 0;
+}
+
+#scroll-container {
+  width: 400px;
+  height: 400px;
+  overflow: scroll;
+}
+
+#scroll-contents {
+  width: 1000px;
+  height: 1000px;
+  position: relative;
+}
+
+#placefiller-above-anchor {
+  height: 500px;
+}
+
+#placefiller-before-anchor {
+  display: inline-block;
+  width: 500px;
+}
+
+#anchor {
+  anchor-name: --anchor;
+}
+
+#inner-anchored {
+  color: green;
+  position: absolute;
+  left: anchor(--anchor left);
+  bottom: anchor(--anchor top);
+}
+
+#outer-anchored {
+  color: yellow;
+  position: absolute;
+  left: anchor(--anchor left);
+  top: anchor(--anchor bottom);
+}
+</style>
+
+<div style="position: relative">
+  <div id="scroll-container">
+    <div id="scroll-contents">
+      <div id="placefiller-above-anchor"></div>
+      <div id="placefiller-before-anchor"></div>
+      <span id="anchor">anchor</span>
+      <div id="inner-anchored">inner-anchored</div>
+    </div>
+  </div>
+  <div id="outer-anchored">outer-anchored</div>
+</div>
+
+<script>
+const scroller = document.getElementById('scroll-container');
+scroller.scrollTop = 300;
+scroller.scrollLeft = 450;
+
+function raf() {
+  return new Promise(resolve => requestAnimationFrame(resolve));
+}
+
+async function runTest() {
+  await raf();
+  await raf();
+  document.getElementById('inner-anchored').style.anchorScroll = '--anchor';
+  document.getElementById('outer-anchored').style.anchorScroll = '--anchor';
+  document.documentElement.classList.remove('reftest-wait');
+}
+runTest();
+</script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-size-minmax-001.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-size-minmax-001.html
new file mode 100644
index 0000000..f84fc37
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-size-minmax-001.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/#propdef-anchor-name">
+<link rel="author" href="mailto:kojii@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<style>
+.container {
+  position: relative;
+  height: 10px;
+}
+.anchor1 {
+  anchor-name: --a1;
+  width: 5px;
+  height: 7px;
+  background: orange;
+}
+.target {
+  position: absolute;
+}
+</style>
+<body onload="checkLayout('.target')">
+  <div class="container">
+    <div class="anchor1"></div>
+
+    <div class="target"
+      style="min-width: anchor-size(--a1 width)"
+      data-expected-width=5></div>
+
+    <div class="target"
+      style="max-width: anchor-size(--a1 width)"
+      data-expected-width=5>
+      <div style="width: 100px"></div>
+    </div>
+  </div>
+</body>
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index 04a98f7..e0b93a4 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -255,7 +255,6 @@
   "src/crypto/x509v3/internal.h",
   "src/crypto/x509v3/pcy_cache.c",
   "src/crypto/x509v3/pcy_data.c",
-  "src/crypto/x509v3/pcy_lib.c",
   "src/crypto/x509v3/pcy_map.c",
   "src/crypto/x509v3/pcy_node.c",
   "src/crypto/x509v3/pcy_tree.c",
diff --git a/third_party/closure_compiler/externs/bluetooth.js b/third_party/closure_compiler/externs/bluetooth.js
index 86e7ba4..44d2de8 100644
--- a/third_party/closure_compiler/externs/bluetooth.js
+++ b/third_party/closure_compiler/externs/bluetooth.js
@@ -1,4 +1,4 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -7,7 +7,7 @@
 // NOTE: The format of types has changed. 'FooType' is now
 //   'chrome.bluetooth.FooType'.
 // Please run the closure compiler before committing changes.
-// See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md
+// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
 /** @fileoverview Externs generated from namespace: bluetooth */
 
diff --git a/third_party/libaom/options.gni b/third_party/libaom/options.gni
index b72b0cb..40db01b 100644
--- a/third_party/libaom/options.gni
+++ b/third_party/libaom/options.gni
@@ -4,7 +4,7 @@
 
 declare_args() {
   # Enable encoding and decoding AV1 video files.
-  enable_libaom = !is_chromeos_lacros && !is_android && !is_castos
+  enable_libaom = !is_android && !is_castos
 
   # To be deprecated soon.
   enable_libaom_decoder = false
diff --git a/third_party/libvpx/BUILD.gn b/third_party/libvpx/BUILD.gn
index a972e1f1..3125138d9 100644
--- a/third_party/libvpx/BUILD.gn
+++ b/third_party/libvpx/BUILD.gn
@@ -19,7 +19,7 @@
     cpu_arch_full = "x64"
   }
 } else if (current_cpu == "arm") {
-  if (is_chromeos_ash) {
+  if (is_chromeos) {
     # ChromeOS gets highbd vp9 but other arm targets do not.
     cpu_arch_full = "arm-neon-highbd"
   } else if (arm_use_neon) {
@@ -30,7 +30,7 @@
     cpu_arch_full = "arm"
   }
 } else if (current_cpu == "arm64") {
-  if (is_chromeos_ash || is_mac) {
+  if (is_chromeos || is_mac) {
     cpu_arch_full = "arm64-highbd"
   } else {
     cpu_arch_full = current_cpu
@@ -378,7 +378,7 @@
     sources = libvpx_srcs_mips
     public_deps = [ ":libvpx_mips_headers" ]
   } else if (current_cpu == "arm") {
-    if (is_chromeos_ash) {
+    if (is_chromeos) {
       sources = libvpx_srcs_arm_neon_highbd
       public_deps = [ ":libvpx_arm_neon_highbd_headers" ]
     } else if (arm_use_neon) {
@@ -392,7 +392,7 @@
       public_deps = [ ":libvpx_arm_headers" ]
     }
   } else if (current_cpu == "arm64") {
-    if (is_chromeos_ash || is_win || is_mac) {
+    if (is_chromeos || is_win || is_mac) {
       sources = libvpx_srcs_arm64_highbd
       public_deps = [ ":libvpx_arm64_highbd_headers" ]
     } else {
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index f2543c8..70c5134c 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -283,7 +283,7 @@
     "META": {"sizes": {"includes": [500],}},
     "includes": [1960],
   },
-  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd": {
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/signin/profile_picker/resources.grd": {
     "META": {"sizes": {"includes": [50],}},
     "includes": [1980],
   },
@@ -404,7 +404,7 @@
     "META": {"sizes": {"includes": [10]}},
     "includes": [2500],
   },
-  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/webui_js_error/webui_js_error_resources.grd": {
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/webui_js_error/resources.grd": {
    "META": {"sizes": {"includes": [10],}},
    "includes": [2520],
   },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 698c75c6..97ee0ba 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9584,9 +9584,9 @@
 </enum>
 
 <enum name="AutofillVirtualCardDialogLinkClicked">
-  <int value="0" label="Education text link"/>
-  <int value="1" label="Google legal message link"/>
-  <int value="2" label="Issuer legal message link"/>
+  <int value="0" label="Google legal message link"/>
+  <int value="1" label="Issuer legal message link"/>
+  <int value="2" label="Education text link"/>
 </enum>
 
 <enum name="AutofillVirtualCardEnrollBubbleResult">
@@ -27555,6 +27555,7 @@
   <int value="13" label="show_default_folder"/>
   <int value="14" label="set_shelf_enabled"/>
   <int value="15" label="determine_filename"/>
+  <int value="16" label="set_ui_options"/>
 </enum>
 
 <enum name="DownloadImageType">
@@ -35168,6 +35169,7 @@
   <int value="1687" label="SIDEPANEL_SETOPTIONS"/>
   <int value="1688" label="ENTERPRISEREPORTINGPRIVATE_GETFILESYSTEMINFO"/>
   <int value="1689" label="FILEMANAGERPRIVATE_GETDRIVEQUOTAMETADATA"/>
+  <int value="1690" label="DOWNLOADS_SETUIOPTIONS"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -35799,6 +35801,7 @@
   <int value="239" label="kEnterpriseRemoteApps"/>
   <int value="240" label="kOffscreen"/>
   <int value="241" label="kSidePanel"/>
+  <int value="242" label="kDownloadsUi"/>
 </enum>
 
 <enum name="ExtensionPointEnableState">
@@ -51216,6 +51219,7 @@
   <int value="2" label="Return to Recent Tab tile"/>
   <int value="3" label="Feed Card"/>
   <int value="4" label="Fake Omnibox"/>
+  <int value="5" label="Trending Queries"/>
 </enum>
 
 <enum name="iOSCredentialIdentityStoreErrorForReporting">
@@ -55515,6 +55519,7 @@
       label="EnableBackForwardCacheForScreenReader:enabled"/>
   <int value="-2043331707" label="PasswordScriptsFetching:disabled"/>
   <int value="-2043128632" label="enable-tab-switcher-in-document-mode"/>
+  <int value="-2043095449" label="DXGIWaitableSwapChain:enabled"/>
   <int value="-2042278511" label="SmartSuggestionForLargeDownloads:disabled"/>
   <int value="-2041281386" label="MultiPaste:disabled"/>
   <int value="-2040471724" label="CrOSComponent:disabled"/>
@@ -61525,6 +61530,7 @@
   <int value="1799521026" label="LegacyTLSEnforced:disabled"/>
   <int value="1799526742" label="PreemptiveLinkToTextGeneration:disabled"/>
   <int value="1800509458" label="DriveFsChromeNetworking:disabled"/>
+  <int value="1800603694" label="DXGIWaitableSwapChain:disabled"/>
   <int value="1801585504" label="ContextMenuShopWithGoogleLens:enabled"/>
   <int value="1802874714" label="QueryTilesEnableQueryEditing:disabled"/>
   <int value="1803465156" label="enable-zero-suggest-most-visited"/>
@@ -65273,6 +65279,7 @@
   <int value="22" label="TestMessage"/>
   <int value="23" label="TailoredSecurityEnabled"/>
   <int value="24" label="VrServicesUpgrade"/>
+  <int value="25" label="TailoredSecurityDisabled"/>
   <int value="26" label="ArCoreUpgrade"/>
   <int value="27" label="InstantApps"/>
   <int value="28" label="AboutThisSite"/>
@@ -71939,6 +71946,9 @@
 </enum>
 
 <enum name="OmniboxZeroSuggestRequests">
+  <obsolete>
+    Obsolete as of M105.
+  </obsolete>
   <int value="1" label="requests sent">Suggest requests that were sent.</int>
   <int value="2" label="requests invalidated">
     Suggest requests that were invalidated, e.g., due to user starting to type.
@@ -80011,6 +80021,8 @@
   <int value="2" label="Open SafeBrowsing Enhanced Protection"/>
   <int value="3" label="Open Chrome feedback form"/>
   <int value="4" label="Open Privacy Guide"/>
+  <int value="5" label="Start Tab Group Tutorial"/>
+  <int value="6" label="Open Password Manager"/>
 </enum>
 
 <enum name="ProtectorError">
@@ -95680,6 +95692,18 @@
              translated"/>
 </enum>
 
+<enum name="TrendingQueryIndex">
+  <summary>
+    Index of a trending query view on the new tab page. This is only an enum so
+    that the dashboard won't produce misleading statistics like averages.
+  </summary>
+  <int value="0" label="0"/>
+  <int value="1" label="1"/>
+  <int value="2" label="2"/>
+  <int value="3" label="3"/>
+  <int value="4" label="kMaxValue"/>
+</enum>
+
 <enum name="TrendingTileEvent">
   <int value="0" label="Tile was shown"/>
   <int value="1" label="Tile was removed"/>
@@ -104341,6 +104365,25 @@
   </int>
 </enum>
 
+<enum name="ZeroSuggestProviderEvent">
+  <int value="0" label="cached response converted to results">
+    Cached response was synchronously converted to displayed matches.
+  </int>
+  <int value="1" label="request sent">Remote request was sent.</int>
+  <int value="2" label="request invalidated">
+    Remote request was invalidated (due to user starting to type or another
+    zero-suggest request).
+  </int>
+  <int value="3" label="response received">
+    Remote response was received asynchronously.
+  </int>
+  <int value="4" label="response cached">Remote response was cached.</int>
+  <int value="5" label="response converted to results">
+    Remote response ended up being converted to displayed matches. This may
+    happen due to an empty displayed result set or an empty remote result set.
+  </int>
+</enum>
+
 <enum name="ZipFileCreator.Result">
   <int value="0" label="Success"/>
   <int value="1" label="Cancelled"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 303106c..7a0b873d 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -111,6 +111,7 @@
   <variant name=".SendTabToSelf"/>
   <variant name=".SharedHighlighting"/>
   <variant name=".SyncError"/>
+  <variant name=".TailoredSecurityDisabled"/>
   <variant name=".TailoredSecurityEnabled"/>
   <variant name=".Translate"/>
   <variant name=".UpdatePassword"/>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index e52121d..4fd0d39 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -2694,6 +2694,40 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.Tokenizer.MainDocument.ATypicalStates" units="bitmask"
+    expires_after="2022-09-01">
+  <owner>sky@chromium.org</owner>
+  <owner>swarm-team@google.com</owner>
+  <summary>
+    This metric is reported for the main document when tokenizing of the input
+    completes. The histogram is a bitmask of values capturing how often
+    non-typical states are encountered. A value of 0 means none were
+    encountered. Bitmask values are:
+
+    Bit 1: Set if document.write() is encountered.
+
+    Bit 2: Set if the tokenizer state as determined by HTMLTreeBuilder does not
+    match the speculative state from HTMLTokenizer.
+
+    Bit 3: Set if the input contains a null character.
+
+    Bit 4: Set if input contains CDATA.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Tokenizer.MainDocument.LocationOfFirstATypicalState"
+    units="location" expires_after="2022-09-01">
+  <owner>sky@chromium.org</owner>
+  <owner>swarm-team@google.com</owner>
+  <summary>
+    This metric is reported for the main document when tokenizing of the input
+    completes. This is emitted if a non-typical tokenization state is
+    encountered (see Blink.Tokenizer.MainDocument.ATypicalStates for more
+    details). The value is the location in the input stream of the first
+    non-typical state.
+  </summary>
+</histogram>
+
 <histogram name="Blink.UpdateViewportIntersection.UpdateTime"
     units="microseconds" expires_after="2022-12-11">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 1141c24..957470a 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -1222,6 +1222,36 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.PasswordManager.Favicons.Count" units="count"
+    expires_after="2023-07-01">
+  <owner>veronguyen@google.com</owner>
+  <owner>tmartino@chromium.org</owner>
+  <summary>
+    The number of favicons loaded (image, not monogram string) in the Password
+    Manager recorded when the view will disappear.
+  </summary>
+</histogram>
+
+<histogram name="IOS.PasswordManager.Favicons.Percentage" units="%"
+    expires_after="2023-07-01">
+  <owner>veronguyen@google.com</owner>
+  <owner>tmartino@chromium.org</owner>
+  <summary>
+    The percentage of passwords that have a favicon that is an image in the
+    Password Manager recorded when the view will disappear.
+  </summary>
+</histogram>
+
+<histogram name="IOS.PasswordManager.PasswordsWithFavicons.Count" units="count"
+    expires_after="2023-07-01">
+  <owner>veronguyen@google.com</owner>
+  <owner>tmartino@chromium.org</owner>
+  <summary>
+    The number of passwords with a favicon loaded in the Password Manager
+    recorded when the view will disappear.
+  </summary>
+</histogram>
+
 <histogram name="IOS.PasswordsInOtherApps.AutoFillStatusChange"
     enum="PasswordAutoFillEnrollmentStatus" expires_after="2022-12-11">
   <owner>ginnyhuang@chromium.org</owner>
@@ -1720,6 +1750,16 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.TrendingQueries" enum="TrendingQueryIndex"
+    expires_after="2023-07-24">
+  <owner>thegreenfrog@chromium.org</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>
+    Logs a user tapping on a trending query and the index position of that query
+    in the module.
+  </summary>
+</histogram>
+
 <histogram name="IOS.WarmStartBackgroundTime" units="msec"
     expires_after="2023-04-27">
   <obsolete>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index d9630d8..5cec36a 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -2278,8 +2278,32 @@
   </summary>
 </histogram>
 
+<histogram name="Omnibox.ZeroSuggestProvider.{ResultType}.{RequestType}"
+    enum="ZeroSuggestProviderEvent" expires_after="2022-12-11">
+  <owner>mahmadi@chromium.org</owner>
+  <owner>chrome-omnibox-team@google.com</owner>
+  <summary>
+    Enumerates the events in the ZeroSuggestProvider as a result of
+    {RequestType} for {ResultType} (i.e., suggestions shown when the user has
+    focused or cleared the omnibox but has not typed in yet).
+  </summary>
+  <token key="ResultType">
+    <variant name="NoURL"
+        summary="zero-prefix suggestions not based on the current page URL"/>
+    <variant name="URLBased"
+        summary="zero-prefix suggestions based on the current page URL"/>
+  </token>
+  <token key="RequestType">
+    <variant name="NonPrefetch" summary="user-initiated requests"/>
+    <variant name="Prefetch" summary="non-user-initiated proactive requests"/>
+  </token>
+</histogram>
+
 <histogram name="Omnibox.ZeroSuggestRequests.NonPrefetch"
     enum="OmniboxZeroSuggestRequests" expires_after="2022-12-11">
+  <obsolete>
+    Obsolete as of M105.
+  </obsolete>
   <owner>mahmadi@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -2308,6 +2332,9 @@
 
 <histogram name="Omnibox.ZeroSuggestRequests.Prefetch"
     enum="OmniboxZeroSuggestRequests" expires_after="2022-12-11">
+  <obsolete>
+    Obsolete as of M105.
+  </obsolete>
   <owner>mahmadi@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index db6a3bd..8fb7eb2f 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -909,17 +909,6 @@
   </summary>
 </histogram>
 
-<histogram name="Webapp.Update.ManifestUpdateResult.DefaultApp"
-    enum="WebAppManifestUpdateResult" expires_after="M102">
-  <owner>alancutter@chromium.org</owner>
-  <owner>tsergeant@chromium.org</owner>
-  <owner>desktop-pwas-team@google.com</owner>
-  <summary>
-    Identical to Webapp.Update.ManifestUpdateResult but restricted to just
-    default installed web apps.
-  </summary>
-</histogram>
-
 <histogram name="WebApp.UrlHandling.DialogState"
     enum="WebAppUrlHandlingDialogState" expires_after="2022-06-25">
   <owner>mek@chromium.org</owner>
diff --git a/tools/polymer/css_to_wrapper.py b/tools/polymer/css_to_wrapper.py
index 1ab64d37..62d30bdf6 100644
--- a/tools/polymer/css_to_wrapper.py
+++ b/tools/polymer/css_to_wrapper.py
@@ -57,10 +57,11 @@
 
 
 def _parse_style_line(line, metadata):
-  if not metadata['include']:
-    include_match = re.search(_INCLUDE_REGEX, line)
-    if include_match:
-      metadata['include'] = line[include_match.end():]
+  include_match = re.search(_INCLUDE_REGEX, line)
+  if include_match:
+    assert not metadata[
+        'include'], f'Found multiple "{_INCLUDE_REGEX}" lines. Only one should exist.'
+    metadata['include'] = line[include_match.end():]
 
   import_match = re.search(_IMPORT_REGEX, line)
   if import_match:
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 01eba7f..22483104 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -79,17 +79,29 @@
     "ax_tree_update_forward.h",
   ]
 
+  if (!is_chromeos_ash) {
+    sources += [
+      "ax_enum_localization_util.cc",
+      "ax_enum_localization_util.h",
+    ]
+  }
+
   public_deps = [
     ":ax_constants_mojo",
     ":ax_enums_mojo",
     "//base",
-    "//base:i18n",
-    "//ui/base",
     "//ui/gfx",
     "//ui/gfx/geometry",
-    "//ui/strings",
   ]
 
+  if (!is_chromeos_ash) {
+    public_deps += [
+      "//base:i18n",
+      "//ui/base",
+      "//ui/strings",
+    ]
+  }
+
   deps = [ "//build:chromeos_buildflags" ]
 
   if (is_chromeos_ash) {
diff --git a/ui/accessibility/ax_enum_localization_util.cc b/ui/accessibility/ax_enum_localization_util.cc
new file mode 100644
index 0000000..ee31b0f
--- /dev/null
+++ b/ui/accessibility/ax_enum_localization_util.cc
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_enum_localization_util.h"
+
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/strings/grit/ax_strings.h"
+
+namespace ui {
+
+std::string ToLocalizedString(ax::mojom::DefaultActionVerb action_verb) {
+  switch (action_verb) {
+    case ax::mojom::DefaultActionVerb::kNone:
+      return "";
+    case ax::mojom::DefaultActionVerb::kActivate:
+      return l10n_util::GetStringUTF8(IDS_AX_ACTIVATE_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kCheck:
+      return l10n_util::GetStringUTF8(IDS_AX_CHECK_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kClick:
+      return l10n_util::GetStringUTF8(IDS_AX_CLICK_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kClickAncestor:
+      return l10n_util::GetStringUTF8(IDS_AX_CLICK_ANCESTOR_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kJump:
+      return l10n_util::GetStringUTF8(IDS_AX_JUMP_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kOpen:
+      return l10n_util::GetStringUTF8(IDS_AX_OPEN_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kPress:
+      return l10n_util::GetStringUTF8(IDS_AX_PRESS_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kSelect:
+      return l10n_util::GetStringUTF8(IDS_AX_SELECT_ACTION_VERB);
+    case ax::mojom::DefaultActionVerb::kUncheck:
+      return l10n_util::GetStringUTF8(IDS_AX_UNCHECK_ACTION_VERB);
+  }
+
+  return "";
+}
+
+}  // namespace ui
diff --git a/ui/accessibility/ax_enum_localization_util.h b/ui/accessibility/ax_enum_localization_util.h
new file mode 100644
index 0000000..fce548b
--- /dev/null
+++ b/ui/accessibility/ax_enum_localization_util.h
@@ -0,0 +1,21 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_ENUM_LOCALIZATION_UTIL_H_
+#define UI_ACCESSIBILITY_AX_ENUM_LOCALIZATION_UTIL_H_
+
+#include <string>
+
+#include "ui/accessibility/ax_base_export.h"
+#include "ui/accessibility/ax_enums.mojom-forward.h"
+
+namespace ui {
+
+// Returns a localized string that corresponds to the name of the given action.
+AX_BASE_EXPORT std::string ToLocalizedString(
+    ax::mojom::DefaultActionVerb action_verb);
+
+}  // namespace ui
+
+#endif  // UI_ACCESSIBILITY_AX_ENUM_LOCALIZATION_UTIL_H_
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index ccb6b45e..aee128d71 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -6,9 +6,6 @@
 
 #include "ui/accessibility/ax_enums.mojom.h"
 
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/strings/grit/ax_strings.h"
-
 namespace ui {
 
 const char* ToString(ax::mojom::Event event) {
@@ -750,33 +747,6 @@
   return "";
 }
 
-std::string ToLocalizedString(ax::mojom::DefaultActionVerb action_verb) {
-  switch (action_verb) {
-    case ax::mojom::DefaultActionVerb::kNone:
-      return "";
-    case ax::mojom::DefaultActionVerb::kActivate:
-      return l10n_util::GetStringUTF8(IDS_AX_ACTIVATE_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kCheck:
-      return l10n_util::GetStringUTF8(IDS_AX_CHECK_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kClick:
-      return l10n_util::GetStringUTF8(IDS_AX_CLICK_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kClickAncestor:
-      return l10n_util::GetStringUTF8(IDS_AX_CLICK_ANCESTOR_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kJump:
-      return l10n_util::GetStringUTF8(IDS_AX_JUMP_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kOpen:
-      return l10n_util::GetStringUTF8(IDS_AX_OPEN_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kPress:
-      return l10n_util::GetStringUTF8(IDS_AX_PRESS_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kSelect:
-      return l10n_util::GetStringUTF8(IDS_AX_SELECT_ACTION_VERB);
-    case ax::mojom::DefaultActionVerb::kUncheck:
-      return l10n_util::GetStringUTF8(IDS_AX_UNCHECK_ACTION_VERB);
-  }
-
-  return "";
-}
-
 const char* ToString(ax::mojom::Mutation mutation) {
   switch (mutation) {
     case ax::mojom::Mutation::kNone:
diff --git a/ui/accessibility/ax_enum_util.h b/ui/accessibility/ax_enum_util.h
index f3c4605e..0bc02e0 100644
--- a/ui/accessibility/ax_enum_util.h
+++ b/ui/accessibility/ax_enum_util.h
@@ -36,10 +36,6 @@
 AX_BASE_EXPORT const char* ToString(
     ax::mojom::DefaultActionVerb default_action_verb);
 
-// Returns a localized string that corresponds to the name of the given action.
-AX_BASE_EXPORT std::string ToLocalizedString(
-    ax::mojom::DefaultActionVerb action_verb);
-
 // ax::mojom::Mutation
 AX_BASE_EXPORT const char* ToString(ax::mojom::Mutation mutation);
 
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index ad5b32d..fbf6c07 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -159,8 +159,7 @@
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (parent_)
     return parent_;
-  const AXTreeManager* manager =
-      AXTreeManagerMap::GetInstance().GetManager(tree_->GetAXTreeID());
+  const AXTreeManager* manager = GetManager();
   if (manager)
     return manager->GetParentNodeFromParentTreeAsAXNode();
   return nullptr;
@@ -196,8 +195,7 @@
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   AXNode* unignored_parent = GetUnignoredParent();
   if (!unignored_parent) {
-    const AXTreeManager* manager =
-        AXTreeManagerMap::GetInstance().GetManager(tree_->GetAXTreeID());
+    const AXTreeManager* manager = GetManager();
     if (manager)
       unignored_parent = manager->GetParentNodeFromParentTreeAsAXNode();
   }
@@ -288,48 +286,104 @@
     return nullptr;
 
   AXNode* deepest_child = GetFirstChild();
+  DCHECK(deepest_child);
   while (deepest_child->GetChildCount())
     deepest_child = deepest_child->GetFirstChild();
 
   return deepest_child;
 }
 
+AXNode* AXNode::GetDeepestFirstChildCrossingTreeBoundary() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
+  if (!GetChildCountCrossingTreeBoundary())
+    return nullptr;
+
+  AXNode* deepest_child = GetFirstChildCrossingTreeBoundary();
+  DCHECK(deepest_child);
+  while (deepest_child->GetChildCountCrossingTreeBoundary())
+    deepest_child = deepest_child->GetFirstChildCrossingTreeBoundary();
+
+  return deepest_child;
+}
+
 AXNode* AXNode::GetDeepestFirstUnignoredChild() const {
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (!GetUnignoredChildCount())
     return nullptr;
 
   AXNode* deepest_child = GetFirstUnignoredChild();
+  DCHECK(deepest_child);
   while (deepest_child->GetUnignoredChildCount())
     deepest_child = deepest_child->GetFirstUnignoredChild();
 
   return deepest_child;
 }
 
+AXNode* AXNode::GetDeepestFirstUnignoredChildCrossingTreeBoundary() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
+  if (!GetUnignoredChildCountCrossingTreeBoundary())
+    return nullptr;
+
+  AXNode* deepest_child = GetFirstUnignoredChildCrossingTreeBoundary();
+  DCHECK(deepest_child);
+  while (deepest_child->GetUnignoredChildCountCrossingTreeBoundary())
+    deepest_child = deepest_child->GetFirstUnignoredChildCrossingTreeBoundary();
+
+  return deepest_child;
+}
+
 AXNode* AXNode::GetDeepestLastChild() const {
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (!GetChildCount())
     return nullptr;
 
   AXNode* deepest_child = GetLastChild();
+  DCHECK(deepest_child);
   while (deepest_child->GetChildCount())
     deepest_child = deepest_child->GetLastChild();
 
   return deepest_child;
 }
 
+AXNode* AXNode::GetDeepestLastChildCrossingTreeBoundary() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
+  if (!GetChildCountCrossingTreeBoundary())
+    return nullptr;
+
+  AXNode* deepest_child = GetLastChildCrossingTreeBoundary();
+  DCHECK(deepest_child);
+  while (deepest_child->GetChildCountCrossingTreeBoundary())
+    deepest_child = deepest_child->GetLastChildCrossingTreeBoundary();
+
+  return deepest_child;
+}
+
 AXNode* AXNode::GetDeepestLastUnignoredChild() const {
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (!GetUnignoredChildCount())
     return nullptr;
 
   AXNode* deepest_child = GetLastUnignoredChild();
+  DCHECK(deepest_child);
   while (deepest_child->GetUnignoredChildCount())
     deepest_child = deepest_child->GetLastUnignoredChild();
 
   return deepest_child;
 }
 
+AXNode* AXNode::GetDeepestLastUnignoredChildCrossingTreeBoundary() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
+  if (!GetUnignoredChildCountCrossingTreeBoundary())
+    return nullptr;
+
+  AXNode* deepest_child = GetLastUnignoredChildCrossingTreeBoundary();
+  DCHECK(deepest_child);
+  while (deepest_child->GetUnignoredChildCountCrossingTreeBoundary())
+    deepest_child = deepest_child->GetLastUnignoredChildCrossingTreeBoundary();
+
+  return deepest_child;
+}
+
 AXNode* AXNode::GetNextSibling() const {
   DCHECK(!tree_->GetTreeUpdateInProgressState());
   AXNode* parent = GetParent();
@@ -602,6 +656,11 @@
   return UnignoredChildCrossingTreeBoundaryIterator(this, nullptr);
 }
 
+bool AXNode::CanFireEvents() const {
+  // TODO(nektar): Cache the `IsChildOfLeaf` state in `AXComputedNodeData`.
+  return !IsChildOfLeaf();
+}
+
 absl::optional<int> AXNode::CompareTo(const AXNode& other) const {
   if (this == &other)
     return 0;
@@ -737,6 +796,10 @@
   return color;
 }
 
+AXTreeManager* AXNode::GetManager() const {
+  return AXTreeManagerMap::GetInstance().GetManager(tree_->GetAXTreeID());
+}
+
 bool AXNode::HasStringAttribute(ax::mojom::StringAttribute attribute) const {
   return GetComputedNodeData().HasOrCanComputeAttribute(attribute);
 }
@@ -1688,6 +1751,7 @@
 }
 
 bool AXNode::IsChildOfLeaf() const {
+  // TODO(nektar): Cache this state in `AXComputedNodeData`.
   for (const AXNode* ancestor = GetUnignoredParent(); ancestor;
        ancestor = ancestor->GetUnignoredParent()) {
     if (ancestor->IsLeaf())
@@ -1929,6 +1993,51 @@
   return nullptr;
 }
 
+AXNode* AXNode::GetTextFieldInnerEditorElement() const {
+  if (!data().IsAtomicTextField() || !GetUnignoredChildCount())
+    return nullptr;
+
+  // Text fields wrap their static text and inline text boxes in generic
+  // containers, and some, like <input type="search">, wrap the wrapper as well.
+  // There are several incarnations of this structure.
+  // 1. An empty atomic text field:
+  // -- Generic container <-- there can be any number of these in a chain.
+  //    However, some empty text fields have the below structure, with empty
+  //    text boxes.
+  // 2. A single line, an atomic text field with some text in it:
+  // -- Generic container <-- there can be any number of these in a chain.
+  // ---- Static text
+  // ------ Inline text box children (zero or more)
+  // ---- Line Break (optional,  a placeholder break element if the text data
+  //                    ends with '\n' or '\r')
+  // 3. A multiline textarea with some text in it:
+  //    Similar to #2, but can repeat the static text, line break children
+  //    multiple times.
+
+  AXNode* text_container = GetDeepestFirstUnignoredChild();
+  DCHECK(text_container) << "Unable to retrieve deepest unignored child on\n"
+                         << *this;
+  // Non-empty text fields expose a set of static text objects with one or more
+  // inline text boxes each. On some platforms, such as Android, we don't enable
+  // inline text boxes, and only the static text objects are exposed.
+  if (text_container->GetRole() == ax::mojom::Role::kInlineTextBox)
+    text_container = text_container->GetUnignoredParent();
+
+  // Get the parent of the static text or the line break, if any; a line break
+  // is possible when the field contains a line break as its first character.
+  if (text_container->GetRole() == ax::mojom::Role::kStaticText ||
+      text_container->GetRole() == ax::mojom::Role::kLineBreak) {
+    text_container = text_container->GetUnignoredParent();
+  }
+
+  DCHECK(text_container) << "Unexpected unignored parent while computing text "
+                            "field inner editor element on\n"
+                         << *this;
+  if (text_container->GetRole() == ax::mojom::Role::kGenericContainer)
+    return text_container;
+  return nullptr;
+}
+
 AXNode* AXNode::GetSelectionContainer() const {
   for (AXNode* ancestor = const_cast<AXNode*>(this); ancestor;
        ancestor = ancestor->GetUnignoredParent()) {
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h
index b8d49b73..676ee2e 100644
--- a/ui/accessibility/ax_node.h
+++ b/ui/accessibility/ax_node.h
@@ -29,6 +29,8 @@
 
 class AXComputedNodeData;
 class AXTableInfo;
+class AXTreeManager;
+
 struct AXLanguageInfo;
 struct AXTreeData;
 
@@ -167,10 +169,18 @@
   AXNode* GetLastChildCrossingTreeBoundary() const;
   AXNode* GetLastUnignoredChild() const;
   AXNode* GetLastUnignoredChildCrossingTreeBoundary() const;
+
+  // TODO(accessibility): Consider renaming all "GetDeepest...Child" methods to
+  // "GetDeepest...Descendant".
   AXNode* GetDeepestFirstChild() const;
+  AXNode* GetDeepestFirstChildCrossingTreeBoundary() const;
   AXNode* GetDeepestFirstUnignoredChild() const;
+  AXNode* GetDeepestFirstUnignoredChildCrossingTreeBoundary() const;
   AXNode* GetDeepestLastChild() const;
+  AXNode* GetDeepestLastChildCrossingTreeBoundary() const;
   AXNode* GetDeepestLastUnignoredChild() const;
+  AXNode* GetDeepestLastUnignoredChildCrossingTreeBoundary() const;
+
   AXNode* GetNextSibling() const;
   AXNode* GetNextUnignoredSibling() const;
   AXNode* GetPreviousSibling() const;
@@ -231,6 +241,12 @@
   UnignoredChildCrossingTreeBoundaryIterator
   UnignoredChildrenCrossingTreeBoundaryEnd() const;
 
+  // Returns true if this is a node on which accessibility events make sense to
+  // be fired. Events are not needed on nodes that will, for example, never
+  // appear in a tree that is visible to assistive software, as there will be no
+  // software to handle the event on the other end.
+  bool CanFireEvents() const;
+
   // Returns an optional integer indicating the logical order of this node
   // compared to another node, or returns an empty optional if the nodes are not
   // comparable. Nodes are not comparable if they do not share a common
@@ -292,6 +308,8 @@
   SkColor ComputeColor() const;
   SkColor ComputeBackgroundColor() const;
 
+  AXTreeManager* GetManager() const;
+
   //
   // Methods for accessing accessibility attributes including attributes that
   // are computed on the browser side. (See `AXNodeData` and
@@ -687,6 +705,11 @@
   // contenteditable without the role, (see `AXNodeData::IsTextField()`).
   AXNode* GetTextFieldAncestor() const;
 
+  // Get the native text field's deepest container; the lowest descendant that
+  // contains all its text. Returns nullptr if the text field is empty, or if it
+  // is not an atomic text field, (e.g., <input> or <textarea>).
+  AXNode* GetTextFieldInnerEditorElement() const;
+
   // If this node is within a container (or widget) that supports either single
   // or multiple selection, returns the node that represents the container.
   AXNode* GetSelectionContainer() const;
diff --git a/ui/accessibility/platform/BUILD.gn b/ui/accessibility/platform/BUILD.gn
index 052fb4b..c9cef1a 100644
--- a/ui/accessibility/platform/BUILD.gn
+++ b/ui/accessibility/platform/BUILD.gn
@@ -87,6 +87,7 @@
 
   public_deps = [
     "//ui/accessibility:ax_base",
+    "//ui/base:buildflags",
     "//ui/display",
   ]
 
diff --git a/ui/accessibility/platform/ax_platform_atk_hyperlink.cc b/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
index 889f749..c3a0bfeb 100644
--- a/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
+++ b/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 
+#include "ui/accessibility/ax_enum_localization_util.h"
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/platform/ax_platform_node_auralinux.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 6b2d71e..76c3c61 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -40,6 +40,7 @@
 #include "ui/accessibility/ax_action_handler_registry.h"
 #include "ui/accessibility/ax_active_popup.h"
 #include "ui/accessibility/ax_constants.mojom.h"
+#include "ui/accessibility/ax_enum_localization_util.h"
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_mode_observer.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/base/cocoa/nsmenuitem_additions_unittest.mm b/ui/base/cocoa/nsmenuitem_additions_unittest.mm
index aad2f1e..f382715 100644
--- a/ui/base/cocoa/nsmenuitem_additions_unittest.mm
+++ b/ui/base/cocoa/nsmenuitem_additions_unittest.mm
@@ -516,6 +516,61 @@
   CFRelease(list);
 }
 
+// Tests that ModifierMaskForKeyEvent() works correctly for "flags changed"
+// events.
+TEST(NSMenuItemAdditionsTest, MMFKEHandlesFlagsChangedEvents) {
+  NSEventModifierFlags modifiers = NSEventModifierFlagCommand;
+  NSEvent* flags_changed_event =
+      [NSEvent keyEventWithType:NSEventTypeFlagsChanged
+                             location:NSZeroPoint
+                        modifierFlags:modifiers
+                            timestamp:0.0
+                         windowNumber:0
+                              context:nil
+                           characters:@""
+          charactersIgnoringModifiers:@""
+                            isARepeat:NO
+                              keyCode:0];
+
+  NSEventModifierFlags expected_flags =
+      NSEventModifierFlagCommand | NSEventModifierFlagControl |
+      NSEventModifierFlagOption | NSEventModifierFlagShift;
+  // Flags changed events don't have characters. Make sure we don't make the
+  // mistake of of assuming the event contains characters.
+  EXPECT_EQ(expected_flags, ModifierMaskForKeyEvent(flags_changed_event));
+
+  modifiers = NSEventModifierFlagFunction;
+  flags_changed_event = [NSEvent keyEventWithType:NSEventTypeFlagsChanged
+                                         location:NSZeroPoint
+                                    modifierFlags:modifiers
+                                        timestamp:0.0
+                                     windowNumber:0
+                                          context:nil
+                                       characters:@""
+                      charactersIgnoringModifiers:@""
+                                        isARepeat:NO
+                                          keyCode:0];
+
+  // Make sure, in particular, we handle flags changed for the function key.
+  // See https://crbug.com/1340934 .
+  EXPECT_EQ(expected_flags, ModifierMaskForKeyEvent(flags_changed_event));
+
+  modifiers = NSEventModifierFlagOption;
+  NSEvent* key_up_event = [NSEvent keyEventWithType:NSEventTypeKeyUp
+                                           location:NSZeroPoint
+                                      modifierFlags:modifiers
+                                          timestamp:0.0
+                                       windowNumber:0
+                                            context:nil
+                                         characters:@"a"
+                        charactersIgnoringModifiers:@"a"
+                                          isARepeat:NO
+                                            keyCode:0];
+
+  // Check that there are no issues with key up events.
+  EXPECT_EQ(expected_flags, ModifierMaskForKeyEvent(key_up_event));
+}
+
 }  // namespace
 }  // namespace cocoa
 }  // namespace ui
diff --git a/ui/base/ime/linux/input_method_auralinux_unittest.cc b/ui/base/ime/linux/input_method_auralinux_unittest.cc
index dd2a9d8..b0269b5 100644
--- a/ui/base/ime/linux/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -16,7 +16,6 @@
 #include "ui/base/ime/dummy_text_input_client.h"
 #include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/linux/fake_input_method_context.h"
 #include "ui/base/ime/linux/linux_input_method_context_factory.h"
 #include "ui/base/ime/virtual_keyboard_controller_stub.h"
 #include "ui/events/event.h"
diff --git a/ui/base/models/dialog_model_field.cc b/ui/base/models/dialog_model_field.cc
index 884eb18..9cd3a52 100644
--- a/ui/base/models/dialog_model_field.cc
+++ b/ui/base/models/dialog_model_field.cc
@@ -241,7 +241,7 @@
 DialogModelCombobox::~DialogModelCombobox() = default;
 
 void DialogModelCombobox::OnSelectedIndexChanged(base::PassKey<DialogModelHost>,
-                                                 int selected_index) {
+                                                 size_t selected_index) {
   selected_index_ = selected_index;
 }
 
diff --git a/ui/base/models/dialog_model_field.h b/ui/base/models/dialog_model_field.h
index 9d7097e..37bded46 100644
--- a/ui/base/models/dialog_model_field.h
+++ b/ui/base/models/dialog_model_field.h
@@ -338,7 +338,7 @@
   DialogModelCombobox& operator=(const DialogModelCombobox&) = delete;
   ~DialogModelCombobox() override;
 
-  int selected_index() const { return selected_index_; }
+  size_t selected_index() const { return selected_index_; }
   ui::ComboboxModel* combobox_model() { return combobox_model_.get(); }
 
   // Methods with base::PassKey<DialogModelHost> are only intended to be called
@@ -350,7 +350,7 @@
     return accessible_name_;
   }
   void OnSelectedIndexChanged(base::PassKey<DialogModelHost>,
-                              int selected_index);
+                              size_t selected_index);
   void OnPerformAction(base::PassKey<DialogModelHost>);
 
  private:
@@ -358,7 +358,7 @@
 
   const std::u16string label_;
   const std::u16string accessible_name_;
-  int selected_index_;
+  size_t selected_index_;
   std::unique_ptr<ui::ComboboxModel> combobox_model_;
   base::RepeatingClosure callback_;
 };
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index 8bdb9fa..961b730 100644
--- a/ui/gfx/mac/io_surface.cc
+++ b/ui/gfx/mac/io_surface.cc
@@ -53,6 +53,7 @@
     case gfx::BufferFormat::BGRA_8888:
     case gfx::BufferFormat::BGRX_8888:
     case gfx::BufferFormat::RGBA_8888:
+    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::BGRA_1010102:
       DCHECK_EQ(plane, 0);
       return 4;
@@ -71,7 +72,6 @@
     }
     case gfx::BufferFormat::BGR_565:
     case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_1010102:
     case gfx::BufferFormat::YVU_420:
       NOTREACHED();
@@ -99,6 +99,7 @@
     case gfx::BufferFormat::BGRA_8888:
     case gfx::BufferFormat::BGRX_8888:
     case gfx::BufferFormat::RGBA_8888:
+    case gfx::BufferFormat::RGBX_8888:
       return 'BGRA';
     case gfx::BufferFormat::RGBA_F16:
       return 'RGhA';
@@ -108,7 +109,6 @@
       return 'x420';
     case gfx::BufferFormat::BGR_565:
     case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_1010102:
     // Technically RGBA_1010102 should be accepted as 'R10k', but then it won't
     // be supported by CGLTexImageIOSurface2D(), so it's best to reject it here.
diff --git a/ui/gl/direct_composition_child_surface_win.cc b/ui/gl/direct_composition_child_surface_win.cc
index 377a7cd..823b96d 100644
--- a/ui/gl/direct_composition_child_surface_win.cc
+++ b/ui/gl/direct_composition_child_surface_win.cc
@@ -64,6 +64,17 @@
       features::kDirectCompositionVerifyDrawOffset);
 }
 
+bool IsWaitableSwapChainEnabled() {
+  // Waitable swap chains were first enabled in Win 8.1/DXGI 1.3
+  return (base::win::GetVersion() >= base::win::Version::WIN8_1) &&
+         base::FeatureList::IsEnabled(features::kDXGIWaitableSwapChain);
+}
+
+UINT GetMaxWaitableQueuedFrames() {
+  return static_cast<UINT>(
+      features::kDXGIWaitableSwapChainMaxQueuedFrames.Get());
+}
+
 }  // namespace
 
 DirectCompositionChildSurfaceWin::PendingFrame::PendingFrame(
@@ -430,6 +441,9 @@
     desc.Flags = DirectCompositionSurfaceWin::AllowTearing()
                      ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING
                      : 0;
+    desc.Flags |= IsWaitableSwapChainEnabled()
+                      ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
+                      : 0;
     HRESULT hr = dxgi_factory->CreateSwapChainForComposition(
         d3d11_device_.Get(), &desc, nullptr, &swap_chain_);
     first_swap_ = true;
@@ -458,6 +472,11 @@
           gfx::ColorSpaceWin::GetDXGIColorSpace(color_space_));
       DCHECK(SUCCEEDED(hr))
           << "SetColorSpace1 failed with error " << std::hex << hr;
+      if (IsWaitableSwapChainEnabled()) {
+        hr = swap_chain->SetMaximumFrameLatency(GetMaxWaitableQueuedFrames());
+        DCHECK(SUCCEEDED(hr))
+            << "SetMaximumFrameLatency failed with error " << std::hex << hr;
+      }
     }
   }
 
@@ -568,6 +587,9 @@
     UINT flags = DirectCompositionSurfaceWin::AllowTearing()
                      ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING
                      : 0;
+    flags |= IsWaitableSwapChainEnabled()
+                 ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
+                 : 0;
     HRESULT hr = swap_chain_->ResizeBuffers(buffer_count, size.width(),
                                             size.height(), format, flags);
     UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapChainResizeResult",
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm
index 85e68d17..180a2bbe 100644
--- a/ui/gl/gl_image_io_surface.mm
+++ b/ui/gl/gl_image_io_surface.mm
@@ -71,6 +71,7 @@
     case gfx::BufferFormat::BGRA_8888:
     case gfx::BufferFormat::BGRX_8888:  // See https://crbug.com/595948.
     case gfx::BufferFormat::RGBA_8888:
+    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_F16:
     case gfx::BufferFormat::BGRA_1010102:
       return GL_RGBA;
@@ -80,7 +81,6 @@
       return GL_RGB_YCBCR_P010_CHROMIUM;
     case gfx::BufferFormat::BGR_565:
     case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_1010102:
     case gfx::BufferFormat::YVU_420:
       NOTREACHED() << gfx::BufferFormatToString(format);
@@ -522,6 +522,7 @@
     case gfx::BufferFormat::BGRA_8888:
     case gfx::BufferFormat::BGRX_8888:
     case gfx::BufferFormat::RGBA_8888:
+    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_F16:
     case gfx::BufferFormat::BGRA_1010102:
     case gfx::BufferFormat::YUV_420_BIPLANAR:
@@ -529,7 +530,6 @@
       return true;
     case gfx::BufferFormat::BGR_565:
     case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_1010102:
     case gfx::BufferFormat::YVU_420:
       return false;
diff --git a/ui/gl/gl_image_io_surface_egl.mm b/ui/gl/gl_image_io_surface_egl.mm
index 254c58f..411d686 100644
--- a/ui/gl/gl_image_io_surface_egl.mm
+++ b/ui/gl/gl_image_io_surface_egl.mm
@@ -45,6 +45,7 @@
     case gfx::BufferFormat::RG_1616:
       return {GL_RG, GL_UNSIGNED_SHORT};
     case gfx::BufferFormat::BGRX_8888:
+    case gfx::BufferFormat::RGBX_8888:
       return {GL_RGB, GL_UNSIGNED_BYTE};
     case gfx::BufferFormat::BGRA_8888:
     case gfx::BufferFormat::RGBA_8888:
@@ -55,7 +56,6 @@
       return {GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV};
     case gfx::BufferFormat::BGR_565:
     case gfx::BufferFormat::RGBA_4444:
-    case gfx::BufferFormat::RGBX_8888:
     case gfx::BufferFormat::RGBA_1010102:
     case gfx::BufferFormat::YVU_420:
     case gfx::BufferFormat::YUV_420_BIPLANAR:
@@ -126,7 +126,7 @@
   EGLBoolean result =
       eglChooseConfig(display_, nullptr, &dummy_config_, 1, &numConfigs);
   DCHECK(result == EGL_TRUE);
-  DCHECK(numConfigs = 1);
+  DCHECK_EQ(numConfigs, 1);
   DCHECK(dummy_config_ != nullptr);
   const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
   if (GLSurface::ExtensionsContain(extensions,
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 2125948..825810a 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -268,4 +268,12 @@
   return base::FeatureList::IsEnabled(kDefaultANGLEVulkan);
 }
 
+// Use waitable swap chain on Windows to reduce display latency.
+const base::Feature kDXGIWaitableSwapChain{"DXGIWaitableSwapChain",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
+// If using waitable swap chain, specify the maximum number of queued frames.
+const base::FeatureParam<int> kDXGIWaitableSwapChainMaxQueuedFrames{
+    &kDXGIWaitableSwapChain, "DXGIWaitableSwapChainMaxQueuedFrames", 2};
+
 }  // namespace features
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index 466650f6..d0ab7ad4 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -107,6 +107,9 @@
 GL_EXPORT extern const base::Feature kDefaultANGLEVulkan;
 GL_EXPORT extern const base::Feature kTrackCurrentShaders;
 GL_EXPORT extern const base::Feature kVulkanFromANGLE;
+GL_EXPORT extern const base::Feature kDXGIWaitableSwapChain;
+GL_EXPORT extern const base::FeatureParam<int>
+    kDXGIWaitableSwapChainMaxQueuedFrames;
 
 GL_EXPORT bool IsDefaultANGLEVulkan();
 
diff --git a/ui/gtk/BUILD.gn b/ui/gtk/BUILD.gn
index 734f3ff..0088321 100644
--- a/ui/gtk/BUILD.gn
+++ b/ui/gtk/BUILD.gn
@@ -137,7 +137,7 @@
     "//ui/gfx",
     "//ui/gfx:native_widget_types",
     "//ui/gfx/geometry",
-    "//ui/linux:linux_ui",
+    "//ui/linux:linux_ui_impl",
     "//ui/native_theme",
     "//ui/shell_dialogs",
     "//ui/strings",
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
index 383080e..b410534 100644
--- a/ui/gtk/gtk_ui.cc
+++ b/ui/gtk/gtk_ui.cc
@@ -590,7 +590,7 @@
   return size;
 }
 
-ui::NativeTheme* GtkUi::GetNativeTheme() const {
+ui::NativeTheme* GtkUi::GetNativeThemeImpl() const {
   return native_theme_;
 }
 
diff --git a/ui/gtk/gtk_ui.h b/ui/gtk/gtk_ui.h
index 5f0cdf3d..1137f17 100644
--- a/ui/gtk/gtk_ui.h
+++ b/ui/gtk/gtk_ui.h
@@ -15,7 +15,7 @@
 #include "ui/base/glib/glib_signal.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gtk/gtk_ui_platform.h"
-#include "ui/linux/linux_ui.h"
+#include "ui/linux/linux_ui_base.h"
 #include "ui/linux/window_frame_provider.h"
 #include "ui/views/window/frame_buttons.h"
 
@@ -36,7 +36,7 @@
 class SettingsProvider;
 
 // Interface to GTK desktop features.
-class GtkUi : public ui::LinuxUi {
+class GtkUi : public ui::LinuxUiBase {
  public:
   GtkUi();
 
@@ -97,7 +97,7 @@
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
   std::string GetCursorThemeName() override;
   int GetCursorThemeSize() override;
-  ui::NativeTheme* GetNativeTheme() const override;
+  ui::NativeTheme* GetNativeThemeImpl() const override;
 
   // ui::TextEditKeybindingDelegate:
   bool GetTextEditCommandsForEvent(
diff --git a/ui/linux/BUILD.gn b/ui/linux/BUILD.gn
index f290fe3a..fa3e8d33 100644
--- a/ui/linux/BUILD.gn
+++ b/ui/linux/BUILD.gn
@@ -31,7 +31,6 @@
     "//build:chromecast_buildflags",
     "//ui/gfx",
     "//ui/gfx/animation",
-    "//ui/native_theme",
   ]
   public_deps = [
     "//printing/buildflags",
@@ -39,6 +38,17 @@
   ]
 }
 
+source_set("linux_ui_impl") {
+  public = [ "linux_ui_base.h" ]
+  sources = [ "linux_ui_base.cc" ]
+  public_deps = [ ":linux_ui" ]
+  deps = [
+    "//base",
+    "//ui/gfx",
+    "//ui/native_theme",
+  ]
+}
+
 source_set("linux_ui_factory") {
   sources = [
     "linux_ui_factory.cc",
@@ -66,7 +76,7 @@
   public = [ "fake_linux_ui.h" ]
   sources = [ "fake_linux_ui.cc" ]
 
-  public_deps = [ ":linux_ui" ]
+  public_deps = [ ":linux_ui_impl" ]
   deps = [
     "//base",
     "//skia",
diff --git a/ui/linux/fake_linux_ui.cc b/ui/linux/fake_linux_ui.cc
index beb120e4..5dfb564 100644
--- a/ui/linux/fake_linux_ui.cc
+++ b/ui/linux/fake_linux_ui.cc
@@ -6,6 +6,7 @@
 
 #include "base/time/time.h"
 #include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 
@@ -119,7 +120,7 @@
   return 0;
 }
 
-ui::NativeTheme* FakeLinuxUi::GetNativeTheme() const {
+ui::NativeTheme* FakeLinuxUi::GetNativeThemeImpl() const {
   return nullptr;
 }
 
diff --git a/ui/linux/fake_linux_ui.h b/ui/linux/fake_linux_ui.h
index 52cc79e..7e3228c 100644
--- a/ui/linux/fake_linux_ui.h
+++ b/ui/linux/fake_linux_ui.h
@@ -5,14 +5,14 @@
 #ifndef UI_LINUX_FAKE_LINUX_UI_H_
 #define UI_LINUX_FAKE_LINUX_UI_H_
 
-#include "ui/linux/linux_ui.h"
+#include "ui/linux/linux_ui_base.h"
 
 namespace ui {
 
 // This class is meant to be overridden by tests.  It's provided as a
 // convenience so that tests don't have to stub lots of methods just to override
 // a single one.
-class COMPONENT_EXPORT(LINUX_UI) FakeLinuxUi : public LinuxUi {
+class FakeLinuxUi : public LinuxUiBase {
  public:
   FakeLinuxUi();
   ~FakeLinuxUi() override;
@@ -51,7 +51,7 @@
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
   std::string GetCursorThemeName() override;
   int GetCursorThemeSize() override;
-  ui::NativeTheme* GetNativeTheme() const override;
+  ui::NativeTheme* GetNativeThemeImpl() const override;
   bool GetTextEditCommandsForEvent(
       const ui::Event& event,
       std::vector<ui::TextEditCommandAuraLinux>* commands) override;
diff --git a/ui/linux/linux_ui.cc b/ui/linux/linux_ui.cc
index 2021188..5e9ec12 100644
--- a/ui/linux/linux_ui.cc
+++ b/ui/linux/linux_ui.cc
@@ -13,7 +13,6 @@
 #include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "ui/linux/cursor_theme_manager_observer.h"
-#include "ui/native_theme/native_theme.h"
 
 namespace {
 
@@ -91,11 +90,6 @@
                         use_system_theme_callback_.Run(window));
 }
 
-ui::NativeTheme* LinuxUi::GetNativeTheme(bool use_system_theme) const {
-  return use_system_theme ? GetNativeTheme()
-                          : ui::NativeTheme::GetInstanceForNativeUi();
-}
-
 void LinuxUi::SetUseSystemThemeCallback(UseSystemThemeCallback callback) {
   use_system_theme_callback_ = std::move(callback);
 }
diff --git a/ui/linux/linux_ui.h b/ui/linux/linux_ui.h
index 401ac46..41b2bb0 100644
--- a/ui/linux/linux_ui.h
+++ b/ui/linux/linux_ui.h
@@ -35,7 +35,8 @@
 
 namespace gfx {
 class Image;
-}
+class Size;
+}  // namespace gfx
 
 namespace printing {
 class PrintingContextLinux;
@@ -124,7 +125,7 @@
   ui::NativeTheme* GetNativeTheme(aura::Window* window) const;
 
   // Returns the classic or system NativeTheme depending on `use_system_theme`.
-  ui::NativeTheme* GetNativeTheme(bool use_system_theme) const;
+  virtual ui::NativeTheme* GetNativeTheme(bool use_system_theme) const = 0;
 
   // Sets a callback that determines whether to use the system theme.
   void SetUseSystemThemeCallback(UseSystemThemeCallback callback);
@@ -253,7 +254,7 @@
     return cursor_theme_observer_list_;
   }
 
-  virtual ui::NativeTheme* GetNativeTheme() const = 0;
+  virtual ui::NativeTheme* GetNativeThemeImpl() const = 0;
 
  private:
   // Used to determine whether the system theme should be used for a window.  If
diff --git a/ui/linux/linux_ui_base.cc b/ui/linux/linux_ui_base.cc
new file mode 100644
index 0000000..c588e2c
--- /dev/null
+++ b/ui/linux/linux_ui_base.cc
@@ -0,0 +1,20 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/linux/linux_ui_base.h"
+
+#include "ui/native_theme/native_theme.h"
+
+namespace ui {
+
+LinuxUiBase::LinuxUiBase() = default;
+
+LinuxUiBase::~LinuxUiBase() = default;
+
+ui::NativeTheme* LinuxUiBase::GetNativeTheme(bool use_system_theme) const {
+  return use_system_theme ? GetNativeThemeImpl()
+                          : ui::NativeTheme::GetInstanceForNativeUi();
+}
+
+}  // namespace ui
diff --git a/ui/linux/linux_ui_base.h b/ui/linux/linux_ui_base.h
new file mode 100644
index 0000000..c3fb93c8
--- /dev/null
+++ b/ui/linux/linux_ui_base.h
@@ -0,0 +1,23 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_LINUX_LINUX_UI_BASE_H_
+#define UI_LINUX_LINUX_UI_BASE_H_
+
+#include "ui/linux/linux_ui.h"
+
+namespace ui {
+
+class LinuxUiBase : public LinuxUi {
+ public:
+  LinuxUiBase();
+  ~LinuxUiBase() override;
+
+  // LinuxUi:
+  ui::NativeTheme* GetNativeTheme(bool use_system_theme) const override;
+};
+
+}  // namespace ui
+
+#endif  // UI_LINUX_LINUX_UI_BASE_H_
diff --git a/ui/linux/linux_ui_delegate.h b/ui/linux/linux_ui_delegate.h
index d3cc75c..6df1fdb 100644
--- a/ui/linux/linux_ui_delegate.h
+++ b/ui/linux/linux_ui_delegate.h
@@ -10,7 +10,10 @@
 
 #include "base/callback_forward.h"
 #include "base/component_export.h"
-#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+using AcceleratedWidget = uint32_t;
+}
 
 namespace ui {
 
diff --git a/ui/qt/BUILD.gn b/ui/qt/BUILD.gn
index af3dc60..913f8b8 100644
--- a/ui/qt/BUILD.gn
+++ b/ui/qt/BUILD.gn
@@ -94,7 +94,7 @@
     "//ui/color",
     "//ui/color:mixers",
     "//ui/gfx",
-    "//ui/linux:linux_ui",
+    "//ui/linux:linux_ui_impl",
     "//ui/native_theme",
     "//ui/shell_dialogs",
     "//ui/views",
diff --git a/ui/qt/qt_ui.cc b/ui/qt/qt_ui.cc
index e70d2e4c..a44ed93b 100644
--- a/ui/qt/qt_ui.cc
+++ b/ui/qt/qt_ui.cc
@@ -298,7 +298,7 @@
   return 0;
 }
 
-ui::NativeTheme* QtUi::GetNativeTheme() const {
+ui::NativeTheme* QtUi::GetNativeThemeImpl() const {
   return native_theme_.get();
 }
 
diff --git a/ui/qt/qt_ui.h b/ui/qt/qt_ui.h
index 5f3748b7..179b0b3 100644
--- a/ui/qt/qt_ui.h
+++ b/ui/qt/qt_ui.h
@@ -12,7 +12,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/color/color_provider.h"
 #include "ui/color/color_provider_manager.h"
-#include "ui/linux/linux_ui.h"
+#include "ui/linux/linux_ui_base.h"
 #include "ui/qt/qt_interface.h"
 
 #if BUILDFLAG(ENABLE_PRINTING)
@@ -24,9 +24,9 @@
 class QtNativeTheme;
 
 // Interface to QT desktop features.
-class QtUi : public ui::LinuxUi, QtInterface::Delegate {
+class QtUi : public ui::LinuxUiBase, QtInterface::Delegate {
  public:
-  explicit QtUi(std::unique_ptr<ui::LinuxUi> fallback_linux_uik);
+  explicit QtUi(std::unique_ptr<ui::LinuxUi> fallback_linux_ui);
 
   QtUi(const QtUi&) = delete;
   QtUi& operator=(const QtUi&) = delete;
@@ -74,7 +74,7 @@
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
   std::string GetCursorThemeName() override;
   int GetCursorThemeSize() override;
-  ui::NativeTheme* GetNativeTheme() const override;
+  ui::NativeTheme* GetNativeThemeImpl() const override;
 
   // ui::TextEditKeybindingDelegate:
   bool GetTextEditCommandsForEvent(
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index b6792b3..0e8edf9 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -679,10 +679,13 @@
   // TODO(sammiequon): Investigate if we can remove |anchor_widget_| and just
   // replace its calls with GetAnchorView()->GetWidget().
   DCHECK_EQ(anchor_widget_, GetAnchorView()->GetWidget());
-  gfx::Transform transform =
-      anchor_widget_->GetNativeWindow()->layer()->GetTargetTransform();
-  if (!transform.IsIdentity())
-    anchor_rect_->Offset(-gfx::ToRoundedVector2d(transform.To2dTranslation()));
+  if (anchor_widget_) {
+    gfx::Transform transform =
+        anchor_widget_->GetNativeWindow()->layer()->GetTargetTransform();
+    if (!transform.IsIdentity())
+      anchor_rect_->Offset(
+          -gfx::ToRoundedVector2d(transform.To2dTranslation()));
+  }
 #endif
 
   return anchor_rect_.value();
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 4a78cdd..63c8429c 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -640,7 +640,7 @@
   NotifyAccessibilityEvent(ax::mojom::Event::kExpandedChanged, true);
 }
 
-void Combobox::MenuSelectionAt(int index) {
+void Combobox::MenuSelectionAt(size_t index) {
   if (!menu_selection_at_callback_ || !menu_selection_at_callback_.Run(index)) {
     SetSelectedIndex(index);
     OnPerformAction();
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
index 006721b..0515b2aa 100644
--- a/ui/views/controls/combobox/combobox.h
+++ b/ui/views/controls/combobox/combobox.h
@@ -44,7 +44,7 @@
  public:
   METADATA_HEADER(Combobox);
 
-  using MenuSelectionAtCallback = base::RepeatingCallback<bool(int index)>;
+  using MenuSelectionAtCallback = base::RepeatingCallback<bool(size_t index)>;
 
   static constexpr int kDefaultComboboxTextContext = style::CONTEXT_BUTTON;
   static constexpr int kDefaultComboboxTextStyle = style::STYLE_PRIMARY;
@@ -84,7 +84,7 @@
       views::PropertyChangedCallback callback);
 
   // Called when there has been a selection from the menu.
-  void MenuSelectionAt(int index);
+  void MenuSelectionAt(size_t index);
 
   // Looks for the first occurrence of |value| in |model()|. If found, selects
   // the found index and returns true. Otherwise simply noops and returns false.
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 1f1ea9e..146a825f 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -317,7 +317,8 @@
       window_y = pt.y;
     }
 
-    WPARAM target = client_area ? event->native_event().wParam : nc_hit_result;
+    WPARAM target = client_area ? event->native_event().wParam
+                                : static_cast<WPARAM>(nc_hit_result);
     LPARAM window_coords = MAKELPARAM(window_x, window_y);
     PostMessage(target_window, event_type, target, window_coords);
     return;
@@ -434,18 +435,18 @@
   SelectByCharDetails() = default;
 
   // Index of the first menu with the specified mnemonic.
-  int first_match = -1;
+  absl::optional<size_t> first_match;
 
   // If true there are multiple menu items with the same mnemonic.
   bool has_multiple = false;
 
-  // Index of the selected item; may remain -1.
-  int index_of_item = -1;
+  // Index of the selected item; may remain nullopt.
+  absl::optional<size_t> index_of_item;
 
   // If there are multiple matches this is the index of the item after the
-  // currently selected item whose mnemonic matches. This may remain -1 even
-  // though there are matches.
-  int next_match = -1;
+  // currently selected item whose mnemonic matches. This may remain nullopt
+  // even though there are matches.
+  absl::optional<size_t> next_match;
 };
 
 // MenuController:State ------------------------------------------------------
@@ -2059,14 +2060,14 @@
   state_ = pending_state_;
   state_.open_leading.swap(pending_open_direction);
 
-  int menu_depth = MenuDepth(state_.item);
+  size_t menu_depth = MenuDepth(state_.item);
   if (menu_depth == 0) {
     state_.open_leading.clear();
   } else {
-    int cached_size = static_cast<int>(state_.open_leading.size());
-    DCHECK_GE(menu_depth, 0);
-    while (cached_size-- >= menu_depth)
+    for (size_t cached_size = state_.open_leading.size();
+         cached_size >= menu_depth; --cached_size) {
       state_.open_leading.pop_back();
+    }
   }
 
   if (!state_.item) {
@@ -2256,10 +2257,10 @@
   BuildMenuItemPath(old_item, old_path);
   BuildMenuItemPath(new_item, new_path);
 
-  *first_diff_at = std::distance(
+  *first_diff_at = static_cast<size_t>(std::distance(
       old_path->cbegin(), std::mismatch(old_path->cbegin(), old_path->cend(),
                                         new_path->cbegin(), new_path->cend())
-                              .first);
+                              .first));
 }
 
 void MenuController::BuildMenuItemPath(MenuItemView* item,
@@ -2752,8 +2753,8 @@
 }
 
 // static
-int MenuController::MenuDepth(MenuItemView* item) {
-  return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : 0;
+size_t MenuController::MenuDepth(MenuItemView* item) {
+  return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : size_t{0};
 }
 
 void MenuController::IncrementSelection(
@@ -2813,9 +2814,11 @@
   if (ordering.empty())
     return;
 
-  const int set_size = ordering.size();
-  for (int i = 0; i < set_size; ++i)
-    ordering[i]->GetViewAccessibility().OverridePosInSet(i + 1, set_size);
+  const size_t set_size = ordering.size();
+  for (size_t i = 0; i < set_size; ++i) {
+    ordering[i]->GetViewAccessibility().OverridePosInSet(
+        static_cast<int>(i + 1), static_cast<int>(set_size));
+  }
 }
 
 void MenuController::MoveSelectionToFirstOrLastItem(
@@ -2842,38 +2845,20 @@
 MenuItemView* MenuController::FindInitialSelectableMenuItem(
     MenuItemView* parent,
     SelectionIncrementDirectionType direction) {
-  return FindNextSelectableMenuItem(
-      parent, direction == INCREMENT_SELECTION_DOWN ? -1 : 0, direction, true);
-}
-
-MenuItemView* MenuController::FindNextSelectableMenuItem(
-    MenuItemView* parent,
-    int index,
-    SelectionIncrementDirectionType direction,
-    bool is_initial) {
-  int parent_count =
-      static_cast<int>(parent->GetSubmenu()->GetMenuItems().size());
-  int stop_index = (index + parent_count) % parent_count;
-  bool include_all_items =
-      (index == -1 && direction == INCREMENT_SELECTION_DOWN) ||
-      (index == 0 && direction == INCREMENT_SELECTION_UP);
-  int delta = direction == INCREMENT_SELECTION_UP ? -1 : 1;
-  // Loop through the menu items skipping any invisible menus. The loop stops
-  // when we wrap or find a visible and enabled child.
-  do {
-    if (!MenuConfig::instance().arrow_key_selection_wraps && !is_initial) {
-      if (index == 0 && direction == INCREMENT_SELECTION_UP)
-        return nullptr;
-      if (index == parent_count - 1 && direction == INCREMENT_SELECTION_DOWN)
-        return nullptr;
+  const size_t parent_count = parent->GetSubmenu()->GetMenuItems().size();
+  if (direction == INCREMENT_SELECTION_DOWN) {
+    for (size_t index = 0; index < parent_count; ++index) {
+      MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index);
+      if (child->IsTraversableByKeyboard())
+        return child;
     }
-    index = (index + delta + parent_count) % parent_count;
-    if (index == stop_index && !include_all_items)
-      return nullptr;
-    MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index);
-    if (child->IsTraversableByKeyboard())
-      return child;
-  } while (index != stop_index);
+  } else {
+    for (size_t index = parent_count; index > 0; --index) {
+      MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index - 1);
+      if (child->IsTraversableByKeyboard())
+        return child;
+    }
+  }
   return nullptr;
 }
 
@@ -2920,15 +2905,16 @@
     MenuItemView* child = menu_items[i];
     if (child->GetEnabled() && child->GetVisible()) {
       if (child == pending_state_.item)
-        details.index_of_item = static_cast<int>(i);
+        details.index_of_item = i;
       if (match_function(child, key)) {
-        if (details.first_match == -1)
-          details.first_match = static_cast<int>(i);
-        else
+        if (!details.first_match.has_value()) {
+          details.first_match = i;
+        } else {
           details.has_multiple = true;
-        if (details.next_match == -1 && details.index_of_item != -1 &&
-            static_cast<int>(i) > details.index_of_item)
-          details.next_match = static_cast<int>(i);
+        }
+        if (!details.next_match.has_value() &&
+            details.index_of_item.has_value() && i > details.index_of_item)
+          details.next_match = i;
       }
     }
   }
@@ -2938,23 +2924,25 @@
 void MenuController::AcceptOrSelect(MenuItemView* parent,
                                     const SelectByCharDetails& details) {
   // This should only be invoked if there is a match.
-  DCHECK_NE(details.first_match, -1);
+  DCHECK(details.first_match.has_value());
   DCHECK(parent->HasSubmenu());
   SubmenuView* submenu = parent->GetSubmenu();
   DCHECK(submenu);
   if (!details.has_multiple) {
     // There's only one match, activate it (or open if it has a submenu).
-    if (submenu->GetMenuItemAt(details.first_match)->HasSubmenu()) {
-      SetSelection(submenu->GetMenuItemAt(details.first_match),
+    if (submenu->GetMenuItemAt(details.first_match.value())->HasSubmenu()) {
+      SetSelection(submenu->GetMenuItemAt(details.first_match.value()),
                    SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
     } else {
-      Accept(submenu->GetMenuItemAt(details.first_match), 0);
+      Accept(submenu->GetMenuItemAt(details.first_match.value()), 0);
     }
-  } else if (details.index_of_item == -1 || details.next_match == -1) {
-    SetSelection(submenu->GetMenuItemAt(details.first_match),
+  } else if (!details.index_of_item.has_value() ||
+             !details.next_match.has_value()) {
+    SetSelection(submenu->GetMenuItemAt(details.first_match.value()),
                  SELECTION_DEFAULT);
   } else {
-    SetSelection(submenu->GetMenuItemAt(details.next_match), SELECTION_DEFAULT);
+    SetSelection(submenu->GetMenuItemAt(details.next_match.value()),
+                 SELECTION_DEFAULT);
   }
 }
 
@@ -2979,7 +2967,7 @@
   // Look for matches based on mnemonic first.
   SelectByCharDetails details =
       FindChildForMnemonic(item, key, &MatchesMnemonic);
-  if (details.first_match != -1) {
+  if (details.first_match.has_value()) {
     AcceptOrSelect(item, details);
     return;
   }
@@ -2992,7 +2980,7 @@
   } else {
     // If no mnemonics found, look at first character of titles.
     details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
-    if (details.first_match != -1)
+    if (details.first_match.has_value())
       AcceptOrSelect(item, details);
   }
 }
@@ -3317,13 +3305,33 @@
   if (!parent)
     return;
   const auto menu_items = parent->GetSubmenu()->GetMenuItems();
-  if (menu_items.size() <= 1)
+  const size_t num_menu_items = menu_items.size();
+  if (num_menu_items <= 1)
     return;
   const auto i = std::find(menu_items.cbegin(), menu_items.cend(), item);
   DCHECK(i != menu_items.cend());
-  MenuItemView* to_select = FindNextSelectableMenuItem(
-      parent, std::distance(menu_items.cbegin(), i), direction, false);
-  SetInitialHotTrackedView(to_select, direction);
+  auto index = static_cast<size_t>(std::distance(menu_items.cbegin(), i));
+
+  // Loop through the menu items in the desired direction.  Assume we can wrap
+  // all the way back to this item.
+  size_t stop_index = index;
+  if (!MenuConfig::instance().arrow_key_selection_wraps) {
+    // Don't want to allow wrapping, so stop as soon as it happens.
+    stop_index = direction == INCREMENT_SELECTION_UP ? (num_menu_items - 1) : 0;
+  }
+  const size_t delta =
+      direction == INCREMENT_SELECTION_UP ? (num_menu_items - 1) : 1;
+  while (true) {
+    index = (index + delta) % num_menu_items;
+    if (index == stop_index)
+      return;
+    // Stop on the next keyboard-traversable item.
+    MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index);
+    if (child->IsTraversableByKeyboard()) {
+      SetInitialHotTrackedView(child, direction);
+      return;
+    }
+  }
 }
 
 void MenuController::SetHotTrackedButton(Button* new_hot_button) {
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h
index a4958eb..ed374ea 100644
--- a/ui/views/controls/menu/menu_controller.h
+++ b/ui/views/controls/menu/menu_controller.h
@@ -521,7 +521,7 @@
                                       ui::OwnedWindowAnchor* anchor);
 
   // Returns the depth of the menu.
-  static int MenuDepth(MenuItemView* item);
+  static size_t MenuDepth(MenuItemView* item);
 
   // Selects the next or previous (depending on |direction|) menu item.
   void IncrementSelection(SelectionIncrementDirectionType direction);
@@ -545,15 +545,6 @@
       MenuItemView* parent,
       SelectionIncrementDirectionType direction);
 
-  // Returns the next or previous selectable child menu item of |parent|
-  // starting at |index| and incrementing or decrementing index by 1 depending
-  // on |direction|. If there are no more selectable items NULL is returned.
-  MenuItemView* FindNextSelectableMenuItem(
-      MenuItemView* parent,
-      int index,
-      SelectionIncrementDirectionType direction,
-      bool is_initial);
-
   // If the selected item has a submenu and it isn't currently open, the
   // the selection is changed such that the menu opens immediately.
   void OpenSubmenuChangeSelectionIfCan();
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 0b68148..67dc750 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -721,17 +721,6 @@
         parent, MenuController::INCREMENT_SELECTION_UP);
   }
 
-  MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent, int index) {
-    return menu_controller_->FindNextSelectableMenuItem(
-        parent, index, MenuController::INCREMENT_SELECTION_DOWN, false);
-  }
-
-  MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent,
-                                               int index) {
-    return menu_controller_->FindNextSelectableMenuItem(
-        parent, index, MenuController::INCREMENT_SELECTION_UP, false);
-  }
-
   internal::MenuControllerDelegate* GetCurrentDelegate() {
     return menu_controller_->delegate_;
   }
@@ -1065,11 +1054,6 @@
   ASSERT_NE(nullptr, last_selectable);
   EXPECT_EQ(2, last_selectable->GetCommand());
 
-  // There should be no next or previous selectable item since there is only a
-  // single enabled item in the menu.
-  EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item(), 1));
-  EXPECT_EQ(nullptr, FindPreviousSelectableMenuItem(menu_item(), 1));
-
   // Clear references in menu controller to the menu item that is going away.
   ResetSelection();
 }
diff --git a/ui/views/controls/menu/menu_insertion_delegate_win.h b/ui/views/controls/menu/menu_insertion_delegate_win.h
index 461620c5..235c34e 100644
--- a/ui/views/controls/menu/menu_insertion_delegate_win.h
+++ b/ui/views/controls/menu/menu_insertion_delegate_win.h
@@ -12,7 +12,7 @@
 class MenuInsertionDelegateWin {
  public:
   // Returns the index to insert items into the menu at.
-  virtual int GetInsertionIndex(HMENU native_menu) = 0;
+  virtual size_t GetInsertionIndex(HMENU native_menu) = 0;
 
  protected:
   virtual ~MenuInsertionDelegateWin() = default;
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index f5a714b..8543989 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -352,7 +352,7 @@
 }
 
 MenuItemView* MenuItemView::AddMenuItemAt(
-    int index,
+    size_t index,
     int item_id,
     const std::u16string& label,
     const std::u16string& secondary_label,
@@ -362,10 +362,9 @@
     Type type,
     ui::MenuSeparatorType separator_style) {
   DCHECK_NE(type, Type::kEmpty);
-  DCHECK_GE(index, 0);
   if (!submenu_)
     CreateSubmenu();
-  DCHECK_LE(static_cast<size_t>(index), submenu_->children().size());
+  DCHECK_LE(index, submenu_->children().size());
   if (type == Type::kSeparator) {
     submenu_->AddChildViewAt(std::make_unique<MenuSeparator>(separator_style),
                              index);
@@ -425,7 +424,7 @@
   AppendMenuItemImpl(0, std::u16string(), ui::ImageModel(), Type::kSeparator);
 }
 
-void MenuItemView::AddSeparatorAt(int index) {
+void MenuItemView::AddSeparatorAt(size_t index) {
   AddMenuItemAt(index, /*item_id=*/0, /*label=*/std::u16string(),
                 /*secondary_label=*/std::u16string(),
                 /*minor_text=*/std::u16string(),
@@ -439,8 +438,7 @@
                                                const std::u16string& label,
                                                const ui::ImageModel& icon,
                                                Type type) {
-  const int index =
-      submenu_ ? static_cast<int>(submenu_->children().size()) : 0;
+  const size_t index = submenu_ ? submenu_->children().size() : size_t{0};
   return AddMenuItemAt(index, item_id, label, std::u16string(),
                        std::u16string(), ui::ImageModel(), icon, type,
                        ui::NORMAL_SEPARATOR);
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h
index c0ed9e1..6bf95a2 100644
--- a/ui/views/controls/menu/menu_item_view.h
+++ b/ui/views/controls/menu/menu_item_view.h
@@ -154,7 +154,7 @@
 
   // Add an item to the menu at a specified index.  ChildrenChanged() should
   // called after adding menu items if the menu may be active.
-  MenuItemView* AddMenuItemAt(int index,
+  MenuItemView* AddMenuItemAt(size_t index,
                               int item_id,
                               const std::u16string& label,
                               const std::u16string& secondary_label,
@@ -194,7 +194,7 @@
   void AppendSeparator();
 
   // Adds a separator to this menu at the specified position.
-  void AddSeparatorAt(int index);
+  void AddSeparatorAt(size_t index);
 
   // All the AppendXXX methods funnel into this.
   MenuItemView* AppendMenuItemImpl(int item_id,
diff --git a/ui/views/controls/menu/menu_model_adapter.cc b/ui/views/controls/menu/menu_model_adapter.cc
index 45b0ba5..285e4a8 100644
--- a/ui/views/controls/menu/menu_model_adapter.cc
+++ b/ui/views/controls/menu/menu_model_adapter.cc
@@ -68,9 +68,9 @@
 
 // Static.
 MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model,
-                                                       int model_index,
+                                                       size_t model_index,
                                                        MenuItemView* menu,
-                                                       int menu_index,
+                                                       size_t menu_index,
                                                        int item_id) {
   absl::optional<MenuItemView::Type> type;
   ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index);
@@ -133,19 +133,17 @@
 
 // Static.
 MenuItemView* MenuModelAdapter::AppendMenuItemFromModel(ui::MenuModel* model,
-                                                        int model_index,
+                                                        size_t model_index,
                                                         MenuItemView* menu,
                                                         int item_id) {
-  const int menu_index =
-      menu->HasSubmenu()
-          ? static_cast<int>(menu->GetSubmenu()->children().size())
-          : 0;
+  const size_t menu_index =
+      menu->HasSubmenu() ? menu->GetSubmenu()->children().size() : size_t{0};
   return AddMenuItemFromModelAt(model, model_index, menu, menu_index, item_id);
 }
 
 MenuItemView* MenuModelAdapter::AppendMenuItem(MenuItemView* menu,
                                                ui::MenuModel* model,
-                                               int index) {
+                                               size_t index) {
   return AppendMenuItemFromModel(model, index, menu,
                                  model->GetCommandIdAt(index));
 }
diff --git a/ui/views/controls/menu/menu_model_adapter.h b/ui/views/controls/menu/menu_model_adapter.h
index b7c7474..ebbc36a3 100644
--- a/ui/views/controls/menu/menu_model_adapter.h
+++ b/ui/views/controls/menu/menu_model_adapter.h
@@ -53,15 +53,15 @@
   // Creates a menu item for the specified entry in the model and adds it as
   // a child to |menu| at the specified |menu_index|.
   static MenuItemView* AddMenuItemFromModelAt(ui::MenuModel* model,
-                                              int model_index,
+                                              size_t model_index,
                                               MenuItemView* menu,
-                                              int menu_index,
+                                              size_t menu_index,
                                               int item_id);
 
   // Creates a menu item for the specified entry in the model and appends it as
   // a child to |menu|.
   static MenuItemView* AppendMenuItemFromModel(ui::MenuModel* model,
-                                               int model_index,
+                                               size_t model_index,
                                                MenuItemView* menu,
                                                int item_id);
 
@@ -76,7 +76,7 @@
   // menu.
   virtual MenuItemView* AppendMenuItem(MenuItemView* menu,
                                        ui::MenuModel* model,
-                                       int index);
+                                       size_t index);
 
   // views::MenuDelegate implementation.
   void ExecuteCommand(int id) override;
diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc
index ca62ed3..3a5fdba 100644
--- a/ui/views/controls/menu/native_menu_win.cc
+++ b/ui/views/controls/menu/native_menu_win.cc
@@ -31,7 +31,7 @@
   raw_ptr<NativeMenuWin> native_menu_win;
 
   // The index of the item within the menu's model.
-  int model_index;
+  size_t model_index;
 };
 
 // Returns the NativeMenuWin for a particular HMENU.
@@ -68,7 +68,7 @@
   items_.clear();
 
   owner_draw_ = model_->HasIcons() || owner_draw_;
-  first_item_index_ = delegate ? delegate->GetInsertionIndex(menu_) : 0;
+  first_item_index_ = delegate ? delegate->GetInsertionIndex(menu_) : size_t{0};
   for (size_t model_index = 0; model_index < model_->GetItemCount();
        ++model_index) {
     size_t menu_index = model_index + first_item_index_;
@@ -81,7 +81,7 @@
 
 void NativeMenuWin::UpdateStates() {
   // A depth-first walk of the menu items, updating states.
-  int model_index = 0;
+  size_t model_index = 0;
   for (const auto& item : items_) {
     size_t menu_index = model_index + first_item_index_;
     SetMenuItemState(menu_index, model_->IsEnabledAt(model_index),
@@ -101,7 +101,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // NativeMenuWin, private:
 
-bool NativeMenuWin::IsSeparatorItemAt(int menu_index) const {
+bool NativeMenuWin::IsSeparatorItemAt(size_t menu_index) const {
   MENUITEMINFO mii = {0};
   mii.cbSize = sizeof(mii);
   mii.fMask = MIIM_FTYPE;
@@ -109,7 +109,7 @@
   return !!(mii.fType & MF_SEPARATOR);
 }
 
-void NativeMenuWin::AddMenuItemAt(int menu_index, int model_index) {
+void NativeMenuWin::AddMenuItemAt(size_t menu_index, size_t model_index) {
   MENUITEMINFO mii = {0};
   mii.cbSize = sizeof(mii);
   mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA;
@@ -131,29 +131,31 @@
   } else {
     if (type == ui::MenuModel::TYPE_RADIO)
       mii.fType |= MFT_RADIOCHECK;
-    mii.wID = model_->GetCommandIdAt(model_index);
+    mii.wID = static_cast<UINT>(model_->GetCommandIdAt(model_index));
   }
   item_data->native_menu_win = this;
   item_data->model_index = model_index;
   mii.dwItemData = reinterpret_cast<ULONG_PTR>(item_data.get());
-  items_.insert(items_.begin() + model_index, std::move(item_data));
+  items_.insert(items_.begin() + static_cast<ptrdiff_t>(model_index),
+                std::move(item_data));
   UpdateMenuItemInfoForString(&mii, model_index,
                               model_->GetLabelAt(model_index));
   InsertMenuItem(menu_, menu_index, TRUE, &mii);
 }
 
-void NativeMenuWin::AddSeparatorItemAt(int menu_index, int model_index) {
+void NativeMenuWin::AddSeparatorItemAt(size_t menu_index, size_t model_index) {
   MENUITEMINFO mii = {0};
   mii.cbSize = sizeof(mii);
   mii.fMask = MIIM_FTYPE;
   mii.fType = MFT_SEPARATOR;
   // Insert a dummy entry into our label list so we can index directly into it
   // using item indices if need be.
-  items_.insert(items_.begin() + model_index, std::make_unique<ItemData>());
-  InsertMenuItem(menu_, menu_index, TRUE, &mii);
+  items_.insert(items_.begin() + static_cast<ptrdiff_t>(model_index),
+                std::make_unique<ItemData>());
+  InsertMenuItem(menu_, static_cast<UINT>(menu_index), TRUE, &mii);
 }
 
-void NativeMenuWin::SetMenuItemState(int menu_index,
+void NativeMenuWin::SetMenuItemState(size_t menu_index,
                                      bool enabled,
                                      bool checked,
                                      bool is_default) {
@@ -170,11 +172,11 @@
   mii.cbSize = sizeof(mii);
   mii.fMask = MIIM_STATE;
   mii.fState = state;
-  SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii);
+  SetMenuItemInfo(menu_, static_cast<UINT>(menu_index), MF_BYPOSITION, &mii);
 }
 
-void NativeMenuWin::SetMenuItemLabel(int menu_index,
-                                     int model_index,
+void NativeMenuWin::SetMenuItemLabel(size_t menu_index,
+                                     size_t model_index,
                                      const std::u16string& label) {
   if (IsSeparatorItemAt(menu_index))
     return;
@@ -182,11 +184,11 @@
   MENUITEMINFO mii = {0};
   mii.cbSize = sizeof(mii);
   UpdateMenuItemInfoForString(&mii, model_index, label);
-  SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii);
+  SetMenuItemInfo(menu_, static_cast<UINT>(menu_index), MF_BYPOSITION, &mii);
 }
 
 void NativeMenuWin::UpdateMenuItemInfoForString(MENUITEMINFO* mii,
-                                                int model_index,
+                                                size_t model_index,
                                                 const std::u16string& label) {
   std::u16string formatted = label;
   ui::MenuModel::ItemType type = model_->GetTypeAt(model_index);
diff --git a/ui/views/controls/menu/native_menu_win.h b/ui/views/controls/menu/native_menu_win.h
index bfd6503..89f78b8 100644
--- a/ui/views/controls/menu/native_menu_win.h
+++ b/ui/views/controls/menu/native_menu_win.h
@@ -51,21 +51,21 @@
   //            code in the functions in this class.
 
   // Returns true if the item at the specified index is a separator.
-  bool IsSeparatorItemAt(int menu_index) const;
+  bool IsSeparatorItemAt(size_t menu_index) const;
 
   // Add items. See note above about indices.
-  void AddMenuItemAt(int menu_index, int model_index);
-  void AddSeparatorItemAt(int menu_index, int model_index);
+  void AddMenuItemAt(size_t menu_index, size_t model_index);
+  void AddSeparatorItemAt(size_t menu_index, size_t model_index);
 
   // Sets the state of the item at the specified index.
-  void SetMenuItemState(int menu_index,
+  void SetMenuItemState(size_t menu_index,
                         bool enabled,
                         bool checked,
                         bool is_default);
 
   // Sets the label of the item at the specified index.
-  void SetMenuItemLabel(int menu_index,
-                        int model_index,
+  void SetMenuItemLabel(size_t menu_index,
+                        size_t model_index,
                         const std::u16string& label);
 
   // Updates the local data structure with the correctly formatted version of
@@ -73,7 +73,7 @@
   // the menu is not owner-draw. That's a mouthful. This function exists because
   // of the peculiarities of the Windows menu API.
   void UpdateMenuItemInfoForString(MENUITEMINFO* mii,
-                                   int model_index,
+                                   size_t model_index,
                                    const std::u16string& label);
 
   // Resets the native menu stored in |menu_| by destroying any old menu then
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 88597c05..64046a5 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -1575,7 +1575,7 @@
     return;
   }
 
-  size_t index = i - accelerators_->begin();
+  auto index = static_cast<size_t>(i - accelerators_->begin());
   accelerators_->erase(i);
   if (index >= registered_accelerator_count_) {
     // The accelerator is not registered to FocusManager.
@@ -2556,10 +2556,9 @@
 
 // Tree operations -------------------------------------------------------------
 
-void View::AddChildViewAtImpl(View* view, int index) {
+void View::AddChildViewAtImpl(View* view, size_t index) {
   CHECK_NE(view, this) << "You cannot add a view as its own child";
-  DCHECK_GE(index, 0);
-  DCHECK_LE(static_cast<size_t>(index), children_.size());
+  DCHECK_LE(index, children_.size());
 
   // TODO(https://crbug.com/942298): Should just DCHECK(!view->parent_);.
   View* parent = view->parent_;
@@ -2578,7 +2577,8 @@
 #if DCHECK_IS_ON()
   DCHECK(!iterating_);
 #endif
-  const auto pos = children_.insert(std::next(children_.cbegin(), index), view);
+  const auto pos = children_.insert(
+      std::next(children_.cbegin(), static_cast<ptrdiff_t>(index)), view);
 
   view->RemoveFromFocusList();
   SetFocusSiblings(view, pos);
@@ -3142,8 +3142,9 @@
     NOTREACHED();
     return;
   }
-  for (std::vector<ui::Accelerator>::const_iterator i(
-           accelerators_->begin() + registered_accelerator_count_);
+  for (std::vector<ui::Accelerator>::const_iterator i =
+           accelerators_->begin() +
+           static_cast<ptrdiff_t>(registered_accelerator_count_);
        i != accelerators_->end(); ++i) {
     accelerator_focus_manager_->RegisterAccelerator(
         *i, ui::AcceleratorManager::kNormalPriority, this);
diff --git a/ui/views/view.h b/ui/views/view.h
index 29b0bed4..f80f61f 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -413,7 +413,7 @@
     return AddChildView<T>(view.release());
   }
   template <typename T>
-  T* AddChildViewAt(std::unique_ptr<T> view, int index) {
+  T* AddChildViewAt(std::unique_ptr<T> view, size_t index) {
     DCHECK(!view->owned_by_client())
         << "This should only be called if the client is passing ownership of "
            "|view| to the parent View.";
@@ -424,17 +424,19 @@
   // for new code.
   template <typename T>
   T* AddChildView(T* view) {
-    AddChildViewAtImpl(view, static_cast<int>(children_.size()));
+    AddChildViewAtImpl(view, children_.size());
     return view;
   }
   template <typename T>
-  T* AddChildViewAt(T* view, int index) {
+  T* AddChildViewAt(T* view, size_t index) {
     AddChildViewAtImpl(view, index);
     return view;
   }
 
   // Moves |view| to the specified |index|. A negative value for |index| moves
   // the view at the end.
+  // TODO(crbug.com/1292951): Change `index` to size_t and remove negative
+  // indexing behavior.
   void ReorderChildView(View* view, int index);
 
   // Removes |view| from this view. The view's parent will change to null.
@@ -1755,7 +1757,7 @@
   // Tree operations -----------------------------------------------------------
 
   // Adds |view| as a child of this view at |index|.
-  void AddChildViewAtImpl(View* view, int index);
+  void AddChildViewAtImpl(View* view, size_t index);
 
   // Removes |view| from the hierarchy tree. If |update_tool_tip| is
   // true, the tooltip is updated. If |delete_removed_view| is true, the
diff --git a/ui/webui/resources/js/browser_command/browser_command.mojom b/ui/webui/resources/js/browser_command/browser_command.mojom
index e4677c4..a0cc369 100644
--- a/ui/webui/resources/js/browser_command/browser_command.mojom
+++ b/ui/webui/resources/js/browser_command/browser_command.mojom
@@ -20,6 +20,8 @@
   kOpenSafeBrowsingEnhancedProtectionSettings = 2,
   kOpenFeedbackForm = 3,
   kOpenPrivacyGuide = 4,
+  kStartTabGroupTutorial = 5,
+  kOpenPasswordManager = 6,
 };
 
 // Click information needed to determine user's desired window disposition using
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc
index 5046b82..65149ff 100644
--- a/weblayer/renderer/content_renderer_client_impl.cc
+++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -172,7 +172,8 @@
   }
 }
 
-void ContentRendererClientImpl::WebViewCreated(blink::WebView* web_view) {
+void ContentRendererClientImpl::WebViewCreated(blink::WebView* web_view,
+                                               bool was_created_by_renderer) {
   new prerender::NoStatePrefetchClient(web_view);
 }
 
diff --git a/weblayer/renderer/content_renderer_client_impl.h b/weblayer/renderer/content_renderer_client_impl.h
index c5318ec..d4ed15b 100644
--- a/weblayer/renderer/content_renderer_client_impl.h
+++ b/weblayer/renderer/content_renderer_client_impl.h
@@ -36,7 +36,8 @@
   // content::ContentRendererClient:
   void RenderThreadStarted() override;
   void RenderFrameCreated(content::RenderFrame* render_frame) override;
-  void WebViewCreated(blink::WebView* web_view) override;
+  void WebViewCreated(blink::WebView* web_view,
+                      bool was_created_by_renderer) override;
   SkBitmap* GetSadPluginBitmap() override;
   SkBitmap* GetSadWebViewBitmap() override;
   void PrepareErrorPage(content::RenderFrame* render_frame,