diff --git a/DEPS b/DEPS
index db318c6c..2bf3f2fa 100644
--- a/DEPS
+++ b/DEPS
@@ -280,7 +280,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': 'b4613bade556fa6e5e8264712b2ee8ccf303a959',
+  'skia_revision': 'cb18e028c403caba0f1189583d281ef72b5a4a2b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -396,7 +396,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': '28858cfac0b9028bc69a27e17c0bb85cf01441f1',
+  'dawn_revision': '3f908f3907e532481e4c91d3b814b46869405fe8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -496,11 +496,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'llvm_libc_revision':    '362f0421a0b01997d04a0950be2af6dbdfb10443',
+  'llvm_libc_revision':    'd7c6dddc045ba4080880d43c34a2d9c2ce5c600f',
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       'cd5c0d7a12c69adc579a64c8e75001489f36c800',
+  'libcxx_revision':       '1f7db7501cf902d5d3ad5fd9b31bea33bb8bf9da',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:c97a86a72105f3328a540f5a5ab17d11989ab7dd',
@@ -1439,7 +1439,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '2b25944cc5da43fee0c2cc41e60165bbe51f6a93',
+    '61ca08e978df2e55fe40731b7c5c1ed333480e42',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1598,7 +1598,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'HjCnM63aOnbhvGp0nj6JuOymC5wZPp7Hsz5dmUhRaBIC',
+          'version': 'R1-nD-_Tg8Aa4iBdGNF1S-cmJxWGMTeiDCjAHq37rYgC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -2943,7 +2943,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'kW1jpVDreWg6VhmuRwdpu30o3pP2KBgUSPuDM_OpoM0C',
+        'version': '0PhIc72kc4JXyHzVzku5VY89N8EwcqyCyaOmMkqohIUC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -2954,7 +2954,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '6HCn6wybY_ktBgqOduq_93aFTzf_xvK8Ma6I3vNKC3wC',
+        'version': 'QIjYxtpMp-UQZZA7MhROCwqx5ELMrOcqkCwmqjk_sT8C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -2987,7 +2987,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'lFpG8Z5K480lkmtZyADnZlXZFD0LAMVFPDgrFZjHk3sC',
+        'version': 'pXOtcKeVya83_m-iFsRtje-hKCqSrAZksbpSTNNKkjYC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4446,7 +4446,7 @@
     'packages' : [
       {
         'package': 'chromeos_internal/inputs/orca',
-        'version': 'nHZAB6k_K5IIS-x4cuGYQWvKRu_O6TT9WmmwT2jer4YC'
+        'version': 'Wzh-xjWvzQ4sxJ83qNnnr0RIF5dy95fqpG-is0Y_aRQC'
       }
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4634,7 +4634,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '4886ed2c5e084e5ac85cb2b822c16214c0e38337',
+        '5d0e91884d86fd282c91ecf82a87a83192703707',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/ash/quick_insert/views/quick_insert_gif_view.cc b/ash/quick_insert/views/quick_insert_gif_view.cc
index a446982f..0a00168 100644
--- a/ash/quick_insert/views/quick_insert_gif_view.cc
+++ b/ash/quick_insert/views/quick_insert_gif_view.cc
@@ -72,7 +72,11 @@
 
 void QuickInsertGifView::UpdateFrame() {
   CHECK(next_frame_index_ < frames_.size());
-  SetImage(ui::ImageModel::FromImageSkia(frames_[next_frame_index_].image));
+  // Don't update the frame image if the view is not visible, but keep the timer
+  // going.
+  if (!GetVisibleBounds().IsEmpty()) {
+    SetImage(ui::ImageModel::FromImageSkia(frames_[next_frame_index_].image));
+  }
 
   // Schedule next frame update.
   update_frame_timer_.Start(FROM_HERE, frames_[next_frame_index_].duration,
diff --git a/ash/quick_insert/views/quick_insert_gif_view_unittest.cc b/ash/quick_insert/views/quick_insert_gif_view_unittest.cc
index c966726..e55f925 100644
--- a/ash/quick_insert/views/quick_insert_gif_view_unittest.cc
+++ b/ash/quick_insert/views/quick_insert_gif_view_unittest.cc
@@ -8,6 +8,8 @@
 #include <vector>
 
 #include "ash/public/cpp/image_util.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/test_widget_builder.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
@@ -16,6 +18,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/view_class_properties.h"
 
 namespace ash {
 namespace {
@@ -68,7 +71,13 @@
       preview_image_fetched_callback_;
 };
 
-TEST(QuickInsertGifViewTest, CorrectSizeBeforePreviewFetched) {
+class QuickInsertGifViewTest : public AshTestBase {
+ public:
+  QuickInsertGifViewTest()
+      : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+};
+
+TEST_F(QuickInsertGifViewTest, CorrectSizeBeforePreviewFetched) {
   GifAssetFetcher asset_fetcher;
   QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
                               asset_fetcher.GetPreviewImageFetcher(),
@@ -77,9 +86,7 @@
   EXPECT_EQ(gif_view.GetImageModel().Size(), kImageSize);
 }
 
-TEST(QuickInsertGifViewTest, ShowsPreviewImageWhenFramesNotFetched) {
-  base::test::SingleThreadTaskEnvironment task_environment;
-
+TEST_F(QuickInsertGifViewTest, ShowsPreviewImageWhenFramesNotFetched) {
   GifAssetFetcher asset_fetcher;
   QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
                               asset_fetcher.GetPreviewImageFetcher(),
@@ -92,13 +99,16 @@
   EXPECT_EQ(gif_view.GetImageModel().Size(), kImageSize);
 }
 
-TEST(QuickInsertGifViewTest, ShowsGifFrameAfterFramesAreFetched) {
-  base::test::SingleThreadTaskEnvironment task_environment;
-
+TEST_F(QuickInsertGifViewTest, ShowsGifFrameAfterFramesAreFetched) {
   GifAssetFetcher asset_fetcher;
-  QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
-                              asset_fetcher.GetPreviewImageFetcher(),
-                              kImageSize);
+  auto widget =
+      TestWidgetBuilder()
+          .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)
+          .SetBounds({10, 10, 100, 100})
+          .BuildClientOwnsWidget();
+  auto* gif_view = widget->SetContentsView(std::make_unique<QuickInsertGifView>(
+      asset_fetcher.GetFramesFetcher(), asset_fetcher.GetPreviewImageFetcher(),
+      kImageSize));
 
   asset_fetcher.CompleteFetchPreviewImage(
       image_util::CreateEmptyImage(kImageSize));
@@ -107,39 +117,44 @@
       CreateGifFrame(base::Milliseconds(40))};
   asset_fetcher.CompleteFetchFrames(frames);
 
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
-  EXPECT_EQ(gif_view.GetImageModel().Size(), kImageSize);
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
+  EXPECT_EQ(gif_view->GetImageModel().Size(), kImageSize);
 }
 
-TEST(QuickInsertGifViewTest, ShowsGifFrameIfPreviewAndFramesBothFetched) {
-  base::test::SingleThreadTaskEnvironment task_environment;
-
+TEST_F(QuickInsertGifViewTest, ShowsGifFrameIfPreviewAndFramesBothFetched) {
   GifAssetFetcher asset_fetcher;
-  QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
-                              asset_fetcher.GetPreviewImageFetcher(),
-                              kImageSize);
+  auto widget =
+      TestWidgetBuilder()
+          .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)
+          .SetBounds({0, 0, 100, 100})
+          .BuildClientOwnsWidget();
+  auto* gif_view = widget->SetContentsView(std::make_unique<QuickInsertGifView>(
+      asset_fetcher.GetFramesFetcher(), asset_fetcher.GetPreviewImageFetcher(),
+      kImageSize));
 
   const std::vector<image_util::AnimationFrame> frames = {
       CreateGifFrame(base::Milliseconds(30)),
       CreateGifFrame(base::Milliseconds(40))};
   asset_fetcher.CompleteFetchFrames(frames);
 
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 
   asset_fetcher.CompleteFetchPreviewImage(
       image_util::CreateEmptyImage(kImageSize));
 
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 }
 
-TEST(QuickInsertGifViewTest, FrameDurations) {
-  base::test::SingleThreadTaskEnvironment task_environment(
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
-
+TEST_F(QuickInsertGifViewTest, FrameDurations) {
   GifAssetFetcher asset_fetcher;
-  QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
-                              asset_fetcher.GetPreviewImageFetcher(),
-                              kImageSize);
+  auto widget =
+      TestWidgetBuilder()
+          .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)
+          .SetBounds({0, 0, 100, 100})
+          .BuildClientOwnsWidget();
+  auto* gif_view = widget->SetContentsView(std::make_unique<QuickInsertGifView>(
+      asset_fetcher.GetFramesFetcher(), asset_fetcher.GetPreviewImageFetcher(),
+      kImageSize));
 
   const std::vector<image_util::AnimationFrame> frames = {
       CreateGifFrame(base::Milliseconds(30)),
@@ -147,26 +162,28 @@
       CreateGifFrame(base::Milliseconds(50))};
   asset_fetcher.CompleteFetchFrames(frames);
 
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 
-  task_environment.FastForwardBy(frames[0].duration);
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[1].image));
+  task_environment()->FastForwardBy(frames[0].duration);
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[1].image));
 
-  task_environment.FastForwardBy(frames[1].duration);
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[2].image));
+  task_environment()->FastForwardBy(frames[1].duration);
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[2].image));
 
-  task_environment.FastForwardBy(frames[2].duration);
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  task_environment()->FastForwardBy(frames[2].duration);
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 }
 
-TEST(QuickInsertGifViewTest, AdjustsShortFrameDurations) {
-  base::test::SingleThreadTaskEnvironment task_environment(
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
-
+TEST_F(QuickInsertGifViewTest, AdjustsShortFrameDurations) {
   GifAssetFetcher asset_fetcher;
-  QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
-                              asset_fetcher.GetPreviewImageFetcher(),
-                              kImageSize);
+  auto widget =
+      TestWidgetBuilder()
+          .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)
+          .SetBounds({0, 0, 100, 100})
+          .BuildClientOwnsWidget();
+  auto* gif_view = widget->SetContentsView(std::make_unique<QuickInsertGifView>(
+      asset_fetcher.GetFramesFetcher(), asset_fetcher.GetPreviewImageFetcher(),
+      kImageSize));
 
   const std::vector<image_util::AnimationFrame> frames = {
       CreateGifFrame(base::Milliseconds(0)),
@@ -175,28 +192,26 @@
 
   // We use a duration of 100ms for frames that specify a duration of <= 10ms
   // (to follow the behavior of blink).
-  task_environment.FastForwardBy(base::Milliseconds(20));
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  task_environment()->FastForwardBy(base::Milliseconds(20));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 
-  task_environment.FastForwardBy(base::Milliseconds(20));
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[0].image));
+  task_environment()->FastForwardBy(base::Milliseconds(20));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[0].image));
 
-  task_environment.FastForwardBy(base::Milliseconds(60));
-  EXPECT_TRUE(GetImage(gif_view).BackedBySameObjectAs(frames[1].image));
+  task_environment()->FastForwardBy(base::Milliseconds(60));
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(frames[1].image));
 }
 
-TEST(QuickInsertGifViewTest, RecordsTimeToFirstFrameWhenGifIsFetchedFirst) {
-  base::test::SingleThreadTaskEnvironment task_environment(
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+TEST_F(QuickInsertGifViewTest, RecordsTimeToFirstFrameWhenGifIsFetchedFirst) {
   base::HistogramTester histogram_tester;
   GifAssetFetcher asset_fetcher;
   QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
                               asset_fetcher.GetPreviewImageFetcher(),
                               kImageSize);
 
-  task_environment.FastForwardBy(base::Milliseconds(100));
+  task_environment()->FastForwardBy(base::Milliseconds(100));
   asset_fetcher.CompleteFetchFrames({CreateGifFrame(base::Milliseconds(0))});
-  task_environment.FastForwardBy(base::Milliseconds(200));
+  task_environment()->FastForwardBy(base::Milliseconds(200));
   asset_fetcher.CompleteFetchPreviewImage(
       image_util::CreateEmptyImage(kImageSize));
 
@@ -205,19 +220,18 @@
                                           base::Milliseconds(100), 1);
 }
 
-TEST(QuickInsertGifViewTest, RecordsTimeToFirstFrameWhenPreviewIsFetchedFirst) {
-  base::test::SingleThreadTaskEnvironment task_environment(
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+TEST_F(QuickInsertGifViewTest,
+       RecordsTimeToFirstFrameWhenPreviewIsFetchedFirst) {
   base::HistogramTester histogram_tester;
   GifAssetFetcher asset_fetcher;
   QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
                               asset_fetcher.GetPreviewImageFetcher(),
                               kImageSize);
 
-  task_environment.FastForwardBy(base::Milliseconds(100));
+  task_environment()->FastForwardBy(base::Milliseconds(100));
   asset_fetcher.CompleteFetchPreviewImage(
       image_util::CreateEmptyImage(kImageSize));
-  task_environment.FastForwardBy(base::Milliseconds(200));
+  task_environment()->FastForwardBy(base::Milliseconds(200));
   asset_fetcher.CompleteFetchFrames({CreateGifFrame(base::Milliseconds(0))});
 
   histogram_tester.ExpectTotalCount("Ash.Picker.TimeToFirstGifFrame", 1);
@@ -225,23 +239,44 @@
                                           base::Milliseconds(100), 1);
 }
 
-TEST(QuickInsertGifViewTest,
-     DoesNotRecordTimeToFirstFrameForInvalidGifsOrPreviews) {
-  base::test::SingleThreadTaskEnvironment task_environment(
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+TEST_F(QuickInsertGifViewTest,
+       DoesNotRecordTimeToFirstFrameForInvalidGifsOrPreviews) {
   base::HistogramTester histogram_tester;
   GifAssetFetcher asset_fetcher;
   QuickInsertGifView gif_view(asset_fetcher.GetFramesFetcher(),
                               asset_fetcher.GetPreviewImageFetcher(),
                               kImageSize);
 
-  task_environment.FastForwardBy(base::Milliseconds(100));
+  task_environment()->FastForwardBy(base::Milliseconds(100));
   asset_fetcher.CompleteFetchPreviewImage(gfx::ImageSkia());
-  task_environment.FastForwardBy(base::Milliseconds(200));
+  task_environment()->FastForwardBy(base::Milliseconds(200));
   asset_fetcher.CompleteFetchFrames({});
 
   histogram_tester.ExpectTotalCount("Ash.Picker.TimeToFirstGifFrame", 0);
 }
 
+TEST_F(QuickInsertGifViewTest, DoesNotShowGifFrameIfNotVisible) {
+  GifAssetFetcher asset_fetcher;
+  auto widget =
+      TestWidgetBuilder()
+          .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS)
+          .SetBounds({0, 0, 100, 100})
+          .BuildClientOwnsWidget();
+  auto* gif_view = widget->SetContentsView(std::make_unique<QuickInsertGifView>(
+      asset_fetcher.GetFramesFetcher(), asset_fetcher.GetPreviewImageFetcher(),
+      kImageSize));
+  gif_view->SetVisible(false);
+  asset_fetcher.CompleteFetchPreviewImage(
+      image_util::CreateEmptyImage(kImageSize));
+
+  const gfx::ImageSkia preview_image = GetImage(*gif_view);
+  const std::vector<image_util::AnimationFrame> frames = {
+      CreateGifFrame(base::Milliseconds(30)),
+      CreateGifFrame(base::Milliseconds(40))};
+  asset_fetcher.CompleteFetchFrames(frames);
+
+  EXPECT_TRUE(GetImage(*gif_view).BackedBySameObjectAs(preview_image));
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts b/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts
index 26cfe21..c9cad90 100644
--- a/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts
+++ b/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertDeepEquals, assertEquals, assertGE, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals, assertGE, assertLE, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
 
 import {assertFilenamesToBe, assertFilesLoaded, assertFilesToBe, assertMatch, assertSingleFileLaunch, createMockTestDirectory, FakeFileSystemFileHandle, fileToFileHandle, getFileErrors, getLoadedFiles, GuestDriver, launchWithFiles, launchWithFocusFile, launchWithHandles, loadFilesWithoutSendingToGuest, runTestInGuest, sendTestMessage, simulateLosingAccessToDirectory} from './driver.js';
 import {FileSnapshot} from './driver_api.js';
@@ -940,9 +940,14 @@
   let testResponse = await sendTestMessage({simple: 'getAllFiles'});
   let clientFiles: FileSnapshot[] = testResponse.testQueryResultData;
 
+  // Using a range instead of exact equality to avoid depending
+  // on the exact PNG encoder implementation.
+  const IMAGE_FILE_MIN_SIZE = 1000;
+  const IMAGE_FILE_MAX_SIZE = 3000;
+
   // Second file should be a placeholder with zero size.
-  const IMAGE_FILE_SIZE = 1605;
-  assertEquals(clientFiles[0]!.size, IMAGE_FILE_SIZE);
+  assertLE(IMAGE_FILE_MIN_SIZE, clientFiles[0]!.size);
+  assertLE(clientFiles[0]!.size, IMAGE_FILE_MAX_SIZE);
   assertEquals(clientFiles[1]!.size, 0);
 
   testResponse = await sendTestMessage(
@@ -953,8 +958,10 @@
   clientFiles = testResponse.testQueryResultData;
 
   // Second file should now be opened and have a valid size.
-  assertEquals(clientFiles[0]!.size, IMAGE_FILE_SIZE);
-  assertEquals(clientFiles[1]!.size, IMAGE_FILE_SIZE);
+  assertLE(IMAGE_FILE_MIN_SIZE, clientFiles[0]!.size);
+  assertLE(clientFiles[0]!.size, IMAGE_FILE_MAX_SIZE);
+  assertLE(IMAGE_FILE_MIN_SIZE, clientFiles[1]!.size);
+  assertLE(clientFiles[1]!.size, IMAGE_FILE_MAX_SIZE);
 };
 
 // Tests the IPC behind the loadNext and loadPrev functions on the received file
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index dc1e033..a7d53e89 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision var in //DEPS.
-  libcxx_revision = "cd5c0d7a12c69adc579a64c8e75001489f36c800"
+  libcxx_revision = "1f7db7501cf902d5d3ad5fd9b31bea33bb8bf9da"
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 4a784db..b4a9f814 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=133
 MINOR=0
-BUILD=6940
+BUILD=6942
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
index 2f11744d..5809857 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -26,6 +26,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.shared_preferences.SharedPreferencesManager;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
@@ -62,6 +63,7 @@
 import org.chromium.components.embedder_support.contextmenu.ContextMenuNativeDelegate;
 import org.chromium.components.embedder_support.contextmenu.ContextMenuParams;
 import org.chromium.components.embedder_support.contextmenu.ContextMenuPopulator;
+import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.externalauth.ExternalAuthUtils;
 import org.chromium.components.feature_engagement.FeatureConstants;
@@ -209,6 +211,67 @@
         }
     }
 
+    // Used to record the UMA histogram Android.CustomTabs.ContextMenu.UrlScheme. These don't
+    // need to be a comprehensive list of schemes since what we are interested in is the relative
+    // volume of data scheme.
+    // Since these values are persisted to logs, they should never be renumbered or reused.
+    // LINT.IfChange(UrlScheme)
+    @VisibleForTesting
+    @IntDef({
+        UrlScheme.UNKNOWN_SCHEME,
+        UrlScheme.HTTP_SCHEME,
+        UrlScheme.HTTPS_SCHEME,
+        UrlScheme.FILE_SCHEME,
+        UrlScheme.FTP_SCHEME,
+        UrlScheme.DATA_SCHEME,
+        UrlScheme.JAVASCRIPT_SCHEME,
+        UrlScheme.CHROME_SCHEME,
+        UrlScheme.BLOB_SCHEME,
+        UrlScheme.CONTENT_SCHEME,
+        UrlScheme.INTENT_SCHEME,
+    })
+    public @interface UrlScheme {
+        int UNKNOWN_SCHEME = 0;
+        int HTTP_SCHEME = 1;
+        int HTTPS_SCHEME = 2;
+        int FILE_SCHEME = 3;
+        int FTP_SCHEME = 4;
+        int DATA_SCHEME = 5;
+        int JAVASCRIPT_SCHEME = 6;
+        int CHROME_SCHEME = 7;
+        int BLOB_SCHEME = 8;
+        int CONTENT_SCHEME = 9;
+        int INTENT_SCHEME = 10;
+        int COUNT = 11;
+    }
+
+    // LINT.ThenChange(/tools/metrics/histograms/metadata/custom_tabs/enums.xml:CustomTabsUrlScheme)
+
+    private static @UrlScheme int schemeForUrl(String scheme) {
+        if (scheme.equals(UrlConstants.HTTP_SCHEME)) {
+            return UrlScheme.HTTP_SCHEME;
+        } else if (scheme.equals(UrlConstants.HTTPS_SCHEME)) {
+            return UrlScheme.HTTPS_SCHEME;
+        } else if (scheme.equals(UrlConstants.FILE_SCHEME)) {
+            return UrlScheme.FILE_SCHEME;
+        } else if (scheme.equals(UrlConstants.FTP_SCHEME)) {
+            return UrlScheme.FTP_SCHEME;
+        } else if (scheme.equals(UrlConstants.DATA_SCHEME)) {
+            return UrlScheme.DATA_SCHEME;
+        } else if (scheme.equals(UrlConstants.JAVASCRIPT_SCHEME)) {
+            return UrlScheme.JAVASCRIPT_SCHEME;
+        } else if (scheme.equals(UrlConstants.CHROME_SCHEME)) {
+            return UrlScheme.CHROME_SCHEME;
+        } else if (scheme.equals(UrlConstants.BLOB_SCHEME)) {
+            return UrlScheme.BLOB_SCHEME;
+        } else if (scheme.equals(UrlConstants.CONTENT_SCHEME)) {
+            return UrlScheme.CONTENT_SCHEME;
+        } else if (scheme.equals(UrlConstants.INTENT_SCHEME)) {
+            return UrlScheme.INTENT_SCHEME;
+        }
+        return UrlScheme.UNKNOWN_SCHEME;
+    }
+
     /**
      * Builds a {@link ChromeContextMenuPopulator}.
      *
@@ -288,6 +351,12 @@
                 if ((mMode == ContextMenuMode.NORMAL || mMode == ContextMenuMode.CUSTOM_TAB)
                         && EphemeralTabCoordinator.isSupported()) {
                     mShowEphemeralTabNewLabel = shouldTriggerEphemeralTabHelpUi();
+                    if (mMode == ContextMenuMode.CUSTOM_TAB) {
+                        @UrlScheme int enumScheme = schemeForUrl(mParams.getUrl().getScheme());
+                        RecordHistogram.recordEnumeratedHistogram(
+                                "CustomTabs.ContextMenu.UrlScheme", enumScheme, UrlScheme.COUNT);
+                    }
+
                     linkGroup.add(
                             createListItem(Item.OPEN_IN_EPHEMERAL_TAB, mShowEphemeralTabNewLabel));
                 }
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 10fcdad5..07a046f9 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -6600,7 +6600,7 @@
 <translation id="5646558797914161501">Forretningsmand</translation>
 <translation id="5646994841348250879">Vælg en konto for at logge ind på <ph name="SITE_ETLD_PLUS_ONE" /></translation>
 <translation id="5648021990716966815">Stik til mikrofon</translation>
-<translation id="5648166631817621825">De seneste syv dage</translation>
+<translation id="5648166631817621825">De seneste 7 dage</translation>
 <translation id="5651308944918885595">Synlighed for Deling tæt på</translation>
 <translation id="5653154844073528838">Du har <ph name="PRINTER_COUNT" /> gemte printere.</translation>
 <translation id="5654669866168491665">Få flere oplysninger om websites, der muligvis ikke fungerer, når tredjepartscookies blokeres</translation>
diff --git a/chrome/app/resources/generated_resources_fr-CA.xtb b/chrome/app/resources/generated_resources_fr-CA.xtb
index 0078bb29..6c723a6 100644
--- a/chrome/app/resources/generated_resources_fr-CA.xtb
+++ b/chrome/app/resources/generated_resources_fr-CA.xtb
@@ -6698,7 +6698,7 @@
 <translation id="5740328398383587084">Partage à proximité</translation>
 <translation id="5740709157181662145">prise en charge et stabilité du matériel de <ph name="DEVICE_OS" /></translation>
 <translation id="574104302965107104">Duplication d'écran</translation>
-<translation id="574209121243317957">Timbre de la voix</translation>
+<translation id="574209121243317957">Ton</translation>
 <translation id="5742787970423162234">Applications Web regroupées avec des fonctionnalités améliorées. <ph name="BEGIN_LINK_LEARN_MORE" />En savoir plus<ph name="END_LINK_LEARN_MORE" /></translation>
 <translation id="5743501966138291117">L'utilisation du déverrouillage automatique nécessite un NIP de 12 chiffres ou moins</translation>
 <translation id="5746169159649715125">Enregistrer au format PDF</translation>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 006d5c33..52838cd7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2800,13 +2800,6 @@
     {"Force disabled", media::switches::kAutoFramingOverride,
      media::switches::kAutoFramingForceDisabled}};
 
-const FeatureEntry::Choice kCameraSuperResOverrideChoices[] = {
-    {"Default", "", ""},
-    {"Enabled", media::switches::kCameraSuperResOverride,
-     media::switches::kCameraSuperResForceEnabled},
-    {"Disabled", media::switches::kCameraSuperResOverride,
-     media::switches::kCameraSuperResForceDisabled}};
-
 const FeatureEntry::Choice kFaceRetouchOverrideChoices[] = {
     {"Default", "", ""},
     {"Enabled with relighting", media::switches::kFaceRetouchOverride,
@@ -6180,10 +6173,6 @@
     {"auto-framing-override", flag_descriptions::kAutoFramingOverrideName,
      flag_descriptions::kAutoFramingOverrideDescription, kOsCrOS,
      MULTI_VALUE_TYPE(kAutoFramingOverrideChoices)},
-    {"camera-super-res-override",
-     flag_descriptions::kCameraSuperResOverrideName,
-     flag_descriptions::kCameraSuperResOverrideDescription, kOsCrOS,
-     MULTI_VALUE_TYPE(kCameraSuperResOverrideChoices)},
     {"face-retouch-override", flag_descriptions::kFaceRetouchOverrideName,
      flag_descriptions::kFaceRetouchOverrideDescription, kOsCrOS,
      MULTI_VALUE_TYPE(kFaceRetouchOverrideChoices)},
diff --git a/chrome/browser/ash/app_list/search/BUILD.gn b/chrome/browser/ash/app_list/search/BUILD.gn
index 77f6aec85..144d240 100644
--- a/chrome/browser/ash/app_list/search/BUILD.gn
+++ b/chrome/browser/ash/app_list/search/BUILD.gn
@@ -63,8 +63,6 @@
     "search_provider.h",
     "search_session_metrics_manager.cc",
     "search_session_metrics_manager.h",
-    "sparky_event_rewriter.cc",
-    "sparky_event_rewriter.h",
     "types.cc",
     "types.h",
   ]
diff --git a/chrome/browser/ash/app_list/search/search_controller.cc b/chrome/browser/ash/app_list/search/search_controller.cc
index 324dcd8..2a0ef48 100644
--- a/chrome/browser/ash/app_list/search/search_controller.cc
+++ b/chrome/browser/ash/app_list/search/search_controller.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ash/app_list/search/search_controller.h"
 
 #include <algorithm>
-#include <memory>
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
@@ -13,7 +12,6 @@
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_metrics.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
-#include "ash/public/cpp/window_tree_host_lookup.h"
 #include "ash/system/federated/federated_service_controller_impl.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_forward.h"
@@ -39,41 +37,18 @@
 #include "chrome/browser/ash/app_list/search/search_metrics_manager.h"
 #include "chrome/browser/ash/app_list/search/search_provider.h"
 #include "chrome/browser/ash/app_list/search/search_session_metrics_manager.h"
-#include "chrome/browser/ash/app_list/search/sparky_event_rewriter.h"
 #include "chrome/browser/ash/app_list/search/types.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/metrics/structured/event_logging_features.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/components/mahi/public/cpp/mahi_manager.h"
-#include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "ui/aura/window_tree_host.h"
 #include "ui/display/screen.h"
 
 namespace app_list {
 namespace {
 
-// Constants for sparky panel position.
-inline constexpr int kPanelBoundsPadding = 8;
-inline constexpr int kPanelDefaultWidth = 360;
-inline constexpr int kPanelDefaultHeight = 492;
-
-void OpenSparkyPanel() {
-  chromeos::MahiManager* sparky_manager = chromeos::MahiManager::Get();
-  if (sparky_manager && sparky_manager->IsEnabled()) {
-    auto display = display::Screen::GetScreen()->GetPrimaryDisplay();
-    // Opens the panel in the bottom right of the screen. It's the same
-    // position before the panel position becomes dynamic.
-    sparky_manager->OpenMahiPanel(
-        display.id(), gfx::Rect(display.work_area().bottom_right().x() -
-                                    kPanelDefaultWidth - kPanelBoundsPadding,
-                                display.work_area().bottom_right().y() -
-                                    kPanelDefaultHeight - kPanelBoundsPadding,
-                                kPanelDefaultWidth, kPanelDefaultHeight));
-  }
-}
 
 void ClearNonZeroStateResults(ResultsMap& results) {
   for (auto it = results.begin(); it != results.end();) {
@@ -94,18 +69,10 @@
     Profile* profile,
     ash::federated::FederatedServiceController* federated_service_controller)
     : profile_(profile),
-      sparky_event_rewriter_(std::make_unique<SparkyEventRewriter>()),
       model_updater_(model_updater),
       list_controller_(list_controller),
       notifier_(notifier),
       federated_service_controller_(federated_service_controller) {
-  if (chromeos::features::IsSparkyEnabled()) {
-    // Get the window tree host for the primary display.
-    const auto& display = display::Screen::GetScreen()->GetPrimaryDisplay();
-    auto* host = ash::GetWindowTreeHostForDisplay(display.id());
-    CHECK(host);
-    host->GetEventSource()->AddEventRewriter(sparky_event_rewriter_.get());
-  }
 }
 
 SearchController::~SearchController() = default;
@@ -231,15 +198,6 @@
 
 void SearchController::StartZeroState(base::OnceClosure on_done,
                                       base::TimeDelta timeout) {
-  // Opens launcher will open sparky UI instead if flag is enabled and shift
-  // key is pressed, and it prevents the launcher panel from opening. This code
-  // is used for experiment only and should never go to production.
-  if (chromeos::features::IsSparkyEnabled() &&
-      sparky_event_rewriter_->is_shift_pressed()) {
-    OpenSparkyPanel();
-    return;
-  }
-
   // Clear all results - zero state search request is made when the app list
   // gets first shown, which would indicate that search is not currently active.
   results_.clear();
diff --git a/chrome/browser/ash/app_list/search/search_controller.h b/chrome/browser/ash/app_list/search/search_controller.h
index 0fd8cea..3661e05 100644
--- a/chrome/browser/ash/app_list/search/search_controller.h
+++ b/chrome/browser/ash/app_list/search/search_controller.h
@@ -48,7 +48,6 @@
 class SearchSessionMetricsManager;
 class SearchProvider;
 class SearchEngine;
-class SparkyEventRewriter;
 
 // Long queries will be truncated down to this length.
 constexpr int kMaxAllowedQueryLength = 500;
@@ -235,7 +234,6 @@
   std::unique_ptr<SearchEngine> search_engine_;
 
   std::unique_ptr<SearchFileScanner> search_file_scanner_;
-  std::unique_ptr<SparkyEventRewriter> sparky_event_rewriter_;
 
   const raw_ptr<AppListModelUpdater> model_updater_;
   const raw_ptr<AppListControllerDelegate> list_controller_;
diff --git a/chrome/browser/ash/app_list/search/sparky_event_rewriter.cc b/chrome/browser/ash/app_list/search/sparky_event_rewriter.cc
deleted file mode 100644
index ff3bc124..0000000
--- a/chrome/browser/ash/app_list/search/sparky_event_rewriter.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ash/app_list/search/sparky_event_rewriter.h"
-
-#include "ui/events/keycodes/keyboard_codes_posix.h"
-#include "ui/events/types/event_type.h"
-
-namespace app_list {
-
-ui::EventDispatchDetails SparkyEventRewriter::RewriteEvent(
-    const ui::Event& event,
-    const Continuation continuation) {
-  // Observe control key press and control key release action.
-  if (event.type() == ui::EventType::kKeyPressed &&
-      event.AsKeyEvent()->key_code() == ui::VKEY_SHIFT) {
-    shift_pressed_ = true;
-  } else if (event.type() == ui::EventType::kKeyReleased &&
-             event.AsKeyEvent()->key_code() == ui::VKEY_SHIFT) {
-    shift_pressed_ = false;
-  }
-
-  // Accepts the supplied event without change.
-  return SendEvent(continuation, &event);
-}
-
-}  // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/sparky_event_rewriter.h b/chrome/browser/ash/app_list/search/sparky_event_rewriter.h
deleted file mode 100644
index ca8e7143..0000000
--- a/chrome/browser/ash/app_list/search/sparky_event_rewriter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_SPARKY_EVENT_REWRITER_H_
-#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_SPARKY_EVENT_REWRITER_H_
-
-#include "ui/events/event_rewriter.h"
-
-namespace app_list {
-
-class SparkyEventRewriter : public ui::EventRewriter {
- public:
-  SparkyEventRewriter() = default;
-
-  SparkyEventRewriter(const SparkyEventRewriter&) = delete;
-  SparkyEventRewriter& operator=(const SparkyEventRewriter&) = delete;
-
-  ~SparkyEventRewriter() override = default;
-
-  bool is_shift_pressed() { return shift_pressed_; }
-
-  // ui::EventRewriter
-  ui::EventDispatchDetails RewriteEvent(
-      const ui::Event& event,
-      const Continuation continuation) override;
-
- private:
-  bool shift_pressed_ = false;
-};
-
-}  // namespace app_list
-
-#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_SPARKY_EVENT_REWRITER_H_
diff --git a/chrome/browser/ash/input_method/BUILD.gn b/chrome/browser/ash/input_method/BUILD.gn
index 5fe38e8d..39d45f5b 100644
--- a/chrome/browser/ash/input_method/BUILD.gn
+++ b/chrome/browser/ash/input_method/BUILD.gn
@@ -213,6 +213,7 @@
     "//chromeos/ash/components/file_manager:constants",
     "//chromeos/ash/components/language_preferences",
     "//chromeos/ash/components/settings",
+    "//chromeos/ash/components/specialized_features",
     "//chromeos/ash/services/federated/public/mojom",
     "//chromeos/ash/services/ime:constants",
     "//chromeos/components/editor_menu/public/cpp",
@@ -224,6 +225,7 @@
     "//chromeos/strings",
     "//components/account_id",
     "//components/exo",
+    "//components/feedback",
     "//components/feedback/redaction_tool",
     "//components/language/core/browser",
     "//components/language/core/common",
diff --git a/chrome/browser/ash/input_method/editor_feedback.cc b/chrome/browser/ash/input_method/editor_feedback.cc
index 7950d04..5be4a8f 100644
--- a/chrome/browser/ash/input_method/editor_feedback.cc
+++ b/chrome/browser/ash/input_method/editor_feedback.cc
@@ -2,77 +2,32 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/constants/ash_features.h"
-#include "base/system/sys_info.h"
-#include "base/task/thread_pool.h"
-#include "chrome/browser/feedback/feedback_uploader_chrome.h"
+#include "chrome/browser/ash/input_method/editor_feedback.h"
+
+#include <string>
+#include <string_view>
+
+#include "chrome/browser/feedback/feedback_uploader_chrome.h"  // IWYU pragma: keep - Required for pointer cast.
 #include "chrome/browser/feedback/feedback_uploader_factory_chrome.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/channel_info.h"
+#include "chromeos/ash/components/specialized_features/feedback.h"
 #include "components/feedback/feedback_constants.h"
-#include "components/feedback/feedback_data.h"
-#include "components/feedback/redaction_tool/redaction_tool.h"
-#include "content/public/browser/browser_context.h"
-#include "google_apis/gaia/gaia_auth_util.h"
 
 namespace ash::input_method {
-namespace {
-
-base::WeakPtr<feedback::FeedbackUploader> GetFeedbackUploaderFromContext(
-    content::BrowserContext* context) {
-  feedback::FeedbackUploader* uploader =
-      static_cast<feedback::FeedbackUploader*>(
-          feedback::FeedbackUploaderFactoryChrome::GetForBrowserContext(
-              context));
-  // Can be a nullptr value in unit tests.
-  if (!uploader) {
-    return nullptr;
-  }
-
-  return uploader->AsWeakPtr();
-}
-
-std::string GetChromeVersion() {
-  return chrome::GetVersionString(chrome::WithExtendedStable(true));
-}
-
-std::string GetOsVersion() {
-  std::string version;
-  base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_VERSION", &version);
-  return version;
-}
-
-scoped_refptr<feedback::FeedbackData> RedactFeedbackData(
-    scoped_refptr<feedback::FeedbackData> feedback_data) {
-  redaction::RedactionTool redactor(nullptr);
-  redactor.EnableCreditCardRedaction(true);
-  feedback_data->RedactDescription(redactor);
-  return feedback_data;
-}
-
-void SendFeedback(scoped_refptr<feedback::FeedbackData> feedback_data) {
-  feedback_data->OnFeedbackPageDataComplete();
-}
-
-void RedactThenSendFeedback(
-    scoped_refptr<feedback::FeedbackData> feedback_data) {
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::TaskPriority::BEST_EFFORT},
-      base::BindOnce(&RedactFeedbackData, feedback_data),
-      base::BindOnce(&SendFeedback));
-}
-
-}  // namespace
 
 bool SendEditorFeedback(Profile* profile, std::string_view description) {
-  auto feedback_data = base::MakeRefCounted<feedback::FeedbackData>(
-      GetFeedbackUploaderFromContext(profile), nullptr);
-  feedback_data->set_product_id(feedback::kOrcaFeedbackProductId);
-  feedback_data->set_include_chrome_platform(false);
-  feedback_data->set_description(std::string(description));
-  feedback_data->AddLog("CHROME VERSION", GetChromeVersion());
-  feedback_data->AddLog("CHROMEOS_RELEASE_VERSION", GetOsVersion());
-  RedactThenSendFeedback(feedback_data);
+  // NOTE: `FeedbackUploaderFactoryChrome` (in //chrome/browser/feedback/)
+  // returns different instances to `FeedbackUploaderFactory` (in
+  // //components/feedback/content). The correct instance should be obtained
+  // from `FeedbackUploaderFactoryChrome`.
+  feedback::FeedbackUploader* uploader =
+      feedback::FeedbackUploaderFactoryChrome::GetForBrowserContext(profile);
+  if (!uploader) {
+    return false;
+  }
+
+  specialized_features::SendFeedback(
+      *uploader, feedback::kOrcaFeedbackProductId, std::string(description));
   return true;
 }
 }  // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/editor_feedback.h b/chrome/browser/ash/input_method/editor_feedback.h
index 0925bdab..e160ebc 100644
--- a/chrome/browser/ash/input_method/editor_feedback.h
+++ b/chrome/browser/ash/input_method/editor_feedback.h
@@ -5,8 +5,9 @@
 #ifndef CHROME_BROWSER_ASH_INPUT_METHOD_EDITOR_FEEDBACK_H_
 #define CHROME_BROWSER_ASH_INPUT_METHOD_EDITOR_FEEDBACK_H_
 
-#include "chrome/browser/profiles/profile.h"
-#include "components/feedback/feedback_uploader.h"
+#include <string_view>
+
+class Profile;
 
 namespace ash::input_method {
 
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
index 9b47a92..633288d 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -450,6 +450,28 @@
       return mojom::NamedDomKey::kF11;
     case ui::DomKey::F12:
       return mojom::NamedDomKey::kF12;
+    case ui::DomKey::BROWSER_BACK:
+      return mojom::NamedDomKey::kBrowserBack;
+    case ui::DomKey::BROWSER_FORWARD:
+      return mojom::NamedDomKey::kBrowserForward;
+    case ui::DomKey::BROWSER_REFRESH:
+      return mojom::NamedDomKey::kBrowserRefresh;
+    case ui::DomKey::ZOOM_TOGGLE:
+      // This the DomKey for the "full screen" key.
+      return mojom::NamedDomKey::kZoomToggle;
+    case ui::DomKey::LAUNCH_MY_COMPUTER:
+      // This the DomKey for the "Show all open windows" key.
+      return mojom::NamedDomKey::kLaunchMyComputer;
+    case ui::DomKey::BRIGHTNESS_DOWN:
+      return mojom::NamedDomKey::kBrightnessDown;
+    case ui::DomKey::BRIGHTNESS_UP:
+      return mojom::NamedDomKey::kBrightnessUp;
+    case ui::DomKey::AUDIO_VOLUME_MUTE:
+      return mojom::NamedDomKey::kAudioVolumeMute;
+    case ui::DomKey::AUDIO_VOLUME_DOWN:
+      return mojom::NamedDomKey::kAudioVolumeDown;
+    case ui::DomKey::AUDIO_VOLUME_UP:
+      return mojom::NamedDomKey::kAudioVolumeUp;
     default:
       return std::nullopt;
   }
diff --git a/chrome/browser/ash/lobster/BUILD.gn b/chrome/browser/ash/lobster/BUILD.gn
index 491a30d2..f21b6742 100644
--- a/chrome/browser/ash/lobster/BUILD.gn
+++ b/chrome/browser/ash/lobster/BUILD.gn
@@ -44,7 +44,8 @@
     "//chrome/browser/profiles:profile",
     "//chrome/browser/resources/chromeos/mako:resources",
     "//chrome/browser/ui/webui/ash/lobster:lobster",
-    "//components/feedback/redaction_tool",
+    "//chromeos/ash/components/specialized_features",
+    "//components/feedback",
     "//components/keyed_service/core",
     "//components/manta",
     "//components/variations/service",
diff --git a/chrome/browser/ash/lobster/lobster_feedback.cc b/chrome/browser/ash/lobster/lobster_feedback.cc
index e4b63d9a2..517f70b 100644
--- a/chrome/browser/ash/lobster/lobster_feedback.cc
+++ b/chrome/browser/ash/lobster/lobster_feedback.cc
@@ -2,63 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ash/lobster/lobster_feedback.h"
+
+#include <string>
+#include <string_view>
+
 #include "base/strings/stringprintf.h"
-#include "base/system/sys_info.h"
-#include "base/task/thread_pool.h"
-#include "chrome/browser/feedback/feedback_uploader_chrome.h"
+#include "chrome/browser/feedback/feedback_uploader_chrome.h"  // IWYU pragma: keep - Required for pointer cast.
 #include "chrome/browser/feedback/feedback_uploader_factory_chrome.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/channel_info.h"
+#include "chromeos/ash/components/specialized_features/feedback.h"
 #include "components/feedback/feedback_constants.h"
-#include "components/feedback/feedback_data.h"
-#include "components/feedback/redaction_tool/redaction_tool.h"
 
 namespace {
 
-base::WeakPtr<feedback::FeedbackUploader> GetFeedbackUploaderFromContext(
-    content::BrowserContext* context) {
-  feedback::FeedbackUploader* uploader =
-      static_cast<feedback::FeedbackUploader*>(
-          feedback::FeedbackUploaderFactoryChrome::GetForBrowserContext(
-              context));
-  // Can be a nullptr value in unit tests.
-  if (!uploader) {
-    return nullptr;
-  }
-
-  return uploader->AsWeakPtr();
-}
-
-std::string GetChromeVersion() {
-  return chrome::GetVersionString(chrome::WithExtendedStable(true));
-}
-
-std::string GetOsVersion() {
-  std::string version;
-  base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_VERSION", &version);
-  return version;
-}
-
-scoped_refptr<feedback::FeedbackData> RedactFeedbackData(
-    scoped_refptr<feedback::FeedbackData> feedback_data) {
-  redaction::RedactionTool redactor(nullptr);
-  redactor.EnableCreditCardRedaction(true);
-  feedback_data->RedactDescription(redactor);
-  return feedback_data;
-}
-
-void SendFeedback(scoped_refptr<feedback::FeedbackData> feedback_data) {
-  feedback_data->OnFeedbackPageDataComplete();
-}
-
-void RedactThenSendFeedback(
-    scoped_refptr<feedback::FeedbackData> feedback_data) {
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::TaskPriority::BEST_EFFORT},
-      base::BindOnce(&RedactFeedbackData, feedback_data),
-      base::BindOnce(&SendFeedback));
-}
-
 std::string BuildFeedbackDescription(std::string_view query,
                                      std::string_view model_version,
                                      std::string_view user_description) {
@@ -74,18 +31,19 @@
                          std::string_view model_version,
                          std::string_view user_description,
                          std::string_view image_bytes) {
-  auto feedback_data = base::MakeRefCounted<feedback::FeedbackData>(
-      GetFeedbackUploaderFromContext(profile), nullptr);
+  // NOTE: `FeedbackUploaderFactoryChrome` (in //chrome/browser/feedback/)
+  // returns different instances to `FeedbackUploaderFactory` (in
+  // //components/feedback/content). The correct instance should be obtained
+  // from `FeedbackUploaderFactoryChrome`.
+  feedback::FeedbackUploader* uploader =
+      feedback::FeedbackUploaderFactoryChrome::GetForBrowserContext(profile);
+  if (!uploader) {
+    return false;
+  }
 
-  feedback_data->set_product_id(feedback::kLobsterFeedbackProductId);
-  feedback_data->set_include_chrome_platform(false);
-  feedback_data->set_description(
-      BuildFeedbackDescription(query, model_version, user_description));
-  feedback_data->set_image(image_bytes.data());
-  feedback_data->AddLog("CHROME VERSION", GetChromeVersion());
-  feedback_data->AddLog("CHROMEOS_RELEASE_VERSION", GetOsVersion());
-
-  RedactThenSendFeedback(feedback_data);
-
+  specialized_features::SendFeedback(
+      *uploader, feedback::kLobsterFeedbackProductId,
+      BuildFeedbackDescription(query, model_version, user_description),
+      std::string(image_bytes));
   return true;
 }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 95470a98..efa4a41 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1175,14 +1175,6 @@
     "expiry_milestone": 140
   },
   {
-    "name": "camera-super-res-override",
-    "owners": [
-      "julianachang@chromium.org",
-      "chromeos-camera-eng@google.com"
-    ],
-    "expiry_milestone": 140
-  },
-  {
     "name": "campaigns-test-tag",
     "owners": [ "llin@google.com", "cros-growth@google.com" ],
     "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8fc2bd8f..3b3308e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -6177,12 +6177,6 @@
 const char kCameraAngleBackendDescription[] =
     "When enabled, uses ANGLE as the GL driver in the camera service.";
 
-const char kCameraSuperResOverrideName[] =
-    "Camera super resolution control override";
-const char kCameraSuperResOverrideDescription[] =
-    "Overrides the default to enable or disable the single frame super "
-    "resolution feature.";
-
 const char kChromeboxUsbPassthroughRestrictionsName[] =
     "Limit primary mice/keyboards from USB passthrough on chromeboxes";
 const char kChromeboxUsbPassthroughRestrictionsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 4e298eb..ae1fe5f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3596,9 +3596,6 @@
 extern const char kCameraAngleBackendName[];
 extern const char kCameraAngleBackendDescription[];
 
-extern const char kCameraSuperResOverrideName[];
-extern const char kCameraSuperResOverrideDescription[];
-
 extern const char kDisableBruschettaInstallChecksName[];
 extern const char kDisableBruschettaInstallChecksDescription[];
 
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
index 58f0f4ea..994d296 100644
--- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
+++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_fr-CA.xtb
@@ -674,7 +674,7 @@
 <translation id="5308380583665731573">Connecter</translation>
 <translation id="5310788376443009632">Éléments supprimés :</translation>
 <translation id="5316825363044614340">passer à la ligne suivante</translation>
-<translation id="5320727453979144100">Mode rémanent activé</translation>
+<translation id="5320727453979144100">Mode Rémanent activé</translation>
 <translation id="5321085947096604457">{COUNT,plural, =1{virgule}one{# virgule}other{# virgules}}</translation>
 <translation id="532485153932049746">Formatage du texte
     <ph name="FONT_SIZE_STRING" />
@@ -834,7 +834,7 @@
 <translation id="6322856989298155004">Sons</translation>
 <translation id="6324551002951139333">Erreur grammaticale détectée</translation>
 <translation id="6325241889020214828">copier <ph name="TEXT" />.</translation>
-<translation id="6348657800373377022">Zone de liste déroulante</translation>
+<translation id="6348657800373377022">Zone de liste ou de texte</translation>
 <translation id="6348869651006731065">Gris clair</translation>
 <translation id="6350358010104919766">{COUNT,plural, =1{puce}one{# puce}other{# puces}}</translation>
 <translation id="6357433033180746873">Aucune cellule à droite</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
index b897b4e..31cefa4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
@@ -1009,7 +1009,7 @@
 <translation id="5628604359369369630">Ulæst – Tilgængelig offline</translation>
 <translation id="5631483240431073854">Administrer åbne faner</translation>
 <translation id="5641456720590409793"><ph name="BEGIN_LINK1" />Søgehistorikken<ph name="END_LINK1" /> og <ph name="BEGIN_LINK2" />andre former for aktivitet<ph name="END_LINK2" /> gemmes muligvis på din Google-konto</translation>
-<translation id="5648166631817621825">De seneste syv dage</translation>
+<translation id="5648166631817621825">De seneste 7 dage</translation>
 <translation id="5655963694829536461">Søg i dine downloads</translation>
 <translation id="5657871969392618475">Dine oplysninger er beskyttet af en profillås</translation>
 <translation id="5659593005791499971">Mail</translation>
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc
index 5fa4fa1..a929ef72 100644
--- a/chrome/browser/ui/views/find_bar_view.cc
+++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -126,19 +126,8 @@
     UpdateAccessibleName();
 
     if (last_result_->final_update()) {
-      ui::AXNodeData node_data;
-      // This is a temporary fix that mimics what's done in
-      // `ViewAccessibility::GetAccessibleNodeData`. We must set the cached role
-      // on the local AXNodeData to pass the check that ensures the role is set
-      // before the accessible name. This is now necessary because the role is
-      // now set in the cache directly instead of in `GetAccessibleNodeData`.
-      //
-      // TODO(crbug.com/325137417): Remove this once we get the name from the
-      // cache directly.
-      node_data.role = GetViewAccessibility().GetCachedRole();
-      GetAccessibleNodeData(&node_data);
       GetViewAccessibility().AnnouncePolitely(
-          node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
+          GetViewAccessibility().GetCachedName());
     }
   }
 
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 85a8fa5e..2a6e1f59 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1736055242-eb981e477a0eef26f28f9feebf7540f5516cf868-13407c41dd759a2f9f7eaacafa2fa9937d55edeb.profdata
+chrome-android32-main-1736121387-8751dfc419c6202923916413867178215066cb95-3f7a0664838c4800231a7ac65ddeae542de0f4c2.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 4b8c0ea..41affdf4 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1736053901-f82134902e3611d2f2ea64343cb301478b6ee327-bf29a6e1232c16d394a547b227ab0758ffb15d81.profdata
+chrome-android64-main-1736134916-b2df95d437c0ad9a9cc400278b9bd079386b4425-d1b3471f0def2a33b14c2ff994c9dd732f665b27.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 3ace06d..ee18135f 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1736035008-1e787edf30410677cefdb4f9a6a786e0c0b48cf9-f9c454499611e8196d32a0a0d5b85ed61966cd42.profdata
+chrome-linux-main-1736121387-cddeb30d029927c1a144289d8673b424a481006e-3f7a0664838c4800231a7ac65ddeae542de0f4c2.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 0b4bc7a..13f56d4c 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1736055242-8f657ef55c0701665c5d390be368061f4d26a757-13407c41dd759a2f9f7eaacafa2fa9937d55edeb.profdata
+chrome-mac-arm-main-1736135741-b251be4942bbabcf6662b7616242ce2996af8147-f4955f3c3b8bc3f3f3c15b39da05d9d7063d9aeb.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 5898dfad..d8c2085 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1736035008-aeafd41d7e7ea7d780d02057b00a11addc0070bc-f9c454499611e8196d32a0a0d5b85ed61966cd42.profdata
+chrome-mac-main-1736098906-09b9dd61082e7600356f4bec99b62ebd1c848c23-33373bb9b02131e92a14dea7a5719eff4bd2d253.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index f4b624de..bcb979c 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1736035008-02a7316a117d5f7dc078ec8d957cf02243c63d19-f9c454499611e8196d32a0a0d5b85ed61966cd42.profdata
+chrome-win-arm64-main-1736121387-effff0437ebf306721ebeecfae3987ca6a497b3a-3f7a0664838c4800231a7ac65ddeae542de0f4c2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index e37f89c..945055d6 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1736044336-4feb22e1fc1bb1722db53e121ff9d1071189e6e8-2a0c41c318db96f51fbe39a09c31e11b0955536b.profdata
+chrome-win32-main-1736098906-778c3036db29030f9eb01174fd19d073df88fb0e-33373bb9b02131e92a14dea7a5719eff4bd2d253.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index bdc30c6..8640ad92 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1736035008-3c2c37144b6197efb9cfb79dec67c04efcaa99dc-f9c454499611e8196d32a0a0d5b85ed61966cd42.profdata
+chrome-win64-main-1736110736-c9a065ed12aeef7ca7fc2f498c4ab9fff40af67c-788208e24fea880703644b5bcd36e5a49407f115.profdata
diff --git a/chrome/test/data/controlled_frame/webrequest_event_handlers.window.js b/chrome/test/data/controlled_frame/webrequest_event_handlers.window.js
index d5e9a7e..ce3683cf 100644
--- a/chrome/test/data/controlled_frame/webrequest_event_handlers.window.js
+++ b/chrome/test/data/controlled_frame/webrequest_event_handlers.window.js
@@ -24,9 +24,6 @@
   const controlledframe = await createControlledFrame('/simple.html');
   controlledframe.stop();
 
-  const targetUrl = new URL(controlledframe.src);
-  targetUrl.pathname = '/handbag.png';
-
   for (const singleEvent of WebRequestEvents) {
     const eventName = singleEvent.name;
     window['count' + eventName] = 0;
@@ -35,7 +32,7 @@
     };
 
     controlledframe.request[eventName].addListener(
-        eventCounter.bind({name: eventName}), {urls: [targetUrl.toString()]});
+        eventCounter.bind({name: eventName}), {urls: ['<all_urls>']});
   }
 
   // Temporarily add special case for onErrorOccurred here to monitor it being
@@ -44,23 +41,15 @@
   window['occurredErrors'] = [];
   controlledframe.request.onErrorOccurred.addListener(function(details) {
     window['occurredErrors'].push(details.error);
-  }, {urls: [targetUrl.toString()]});
+  }, {urls: ['<all_urls>']});
+
+  const targetUrl = new URL(controlledframe.src);
+  targetUrl.pathname = '/handbag.png';
 
   const script = `(async() => {await fetch('${
       targetUrl.toString()}', {method:'GET'});})();`;
   await executeAsyncScript(controlledframe, script);
 
-  // Temporarily add special case for onErrorOccurred here to monitor it being
-  // triggered in the CI.
-  // TODO(crbug.com/386380410): clean up.
-  assert_true(
-      window['occurredErrors'].length === 0,
-      `\nonErrorOccurred triggered ${
-          window['occurredErrors'].length} times, errors are:\n${
-          window['occurredErrors']
-              .map((item, index) => `${index + 1}. ${item}`)
-              .join('\n')}\n`);
-
   for (singleEvent of WebRequestEvents) {
     const eventName = singleEvent.name;
     console.log(
@@ -78,4 +67,15 @@
               window['count' + eventName]} time(s).`);
     }
   }
+
+  // Temporarily add special case for onErrorOccurred here to monitor it being
+  // triggered in the CI.
+  // TODO(crbug.com/386380410): clean up.
+  assert_true(
+      window['occurredErrors'].length === 0,
+      `\nonErrorOccurred triggered ${
+          window['occurredErrors'].length} times, errors are:\n${
+          window['occurredErrors']
+              .map((item, index) => `${index + 1}. ${item}`)
+              .join('\n')}\n`);
 }, 'WebRequest Event Handlers');
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 454a475e..9c6679a7 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-16149.0.0-1065874
\ No newline at end of file
+16150.0.0-1065890
\ No newline at end of file
diff --git a/chromeos/ash/components/specialized_features/BUILD.gn b/chromeos/ash/components/specialized_features/BUILD.gn
index 483fe5f..99d458c7e 100644
--- a/chromeos/ash/components/specialized_features/BUILD.gn
+++ b/chromeos/ash/components/specialized_features/BUILD.gn
@@ -11,9 +11,16 @@
   sources = [
     "feature_access_checker.cc",
     "feature_access_checker.h",
+    "feedback.cc",
+    "feedback.h",
   ]
+
   deps = [
     "//base",
+    "//base/version_info:version_string",
+    "//chromeos/ash/components/channel",
+    "//components/feedback",
+    "//components/feedback/redaction_tool",
     "//components/prefs",
     "//components/signin/public/identity_manager",
     "//components/variations/service",
@@ -22,9 +29,15 @@
 
 source_set("unit_tests") {
   testonly = true
+  sources = [
+    "feature_access_checker_unittest.cc",
+    "feedback_unittest.cc",
+  ]
   deps = [
     ":specialized_features",
     "//base/test:test_support",
+    "//components/feedback",
+    "//components/feedback/proto",
     "//components/metrics",
     "//components/metrics:test_support",
     "//components/prefs",
@@ -32,7 +45,7 @@
     "//components/signin/public/identity_manager",
     "//components/signin/public/identity_manager:test_support",
     "//components/variations:test_support",
+    "//services/network:test_support",
     "//testing/gtest",
   ]
-  sources = [ "feature_access_checker_unittest.cc" ]
 }
diff --git a/chromeos/ash/components/specialized_features/DEPS b/chromeos/ash/components/specialized_features/DEPS
index f2ff3a8..f118b11 100644
--- a/chromeos/ash/components/specialized_features/DEPS
+++ b/chromeos/ash/components/specialized_features/DEPS
@@ -1,4 +1,6 @@
 include_rules = [
+  "+chromeos/ash/components/channel",
+  "+components/feedback",
   "+components/metrics/metrics_state_manager.h",
   "+components/signin/public",
   "+components/variations/service",
diff --git a/chromeos/ash/components/specialized_features/feedback.cc b/chromeos/ash/components/specialized_features/feedback.cc
new file mode 100644
index 0000000..858469a8
--- /dev/null
+++ b/chromeos/ash/components/specialized_features/feedback.cc
@@ -0,0 +1,88 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/ash/components/specialized_features/feedback.h"
+
+#include <optional>
+#include <string>
+#include <utility>
+
+#include "base/functional/bind.h"
+#include "base/location.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/system/sys_info.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/version_info/version_string.h"
+#include "chromeos/ash/components/channel/channel_info.h"
+#include "components/feedback/feedback_data.h"
+#include "components/feedback/redaction_tool/redaction_tool.h"
+
+namespace specialized_features {
+
+namespace {
+
+// Gets the current Chrome version as a string.
+// Equivalent to `chrome::GetVersionString()`, without needing to use //chrome
+// dependencies.
+std::string GetChromeVersion() {
+  return version_info::GetVersionStringWithModifier(ash::GetChannelName());
+}
+
+// Gets `CHROMEOS_RELEASE_VERSION` as a string.
+std::string GetOsVersion() {
+  std::string version;
+  base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_VERSION", &version);
+  return version;
+}
+
+// Redacts the description of the provided feedback data and returns it.
+scoped_refptr<feedback::FeedbackData> RedactFeedbackData(
+    scoped_refptr<feedback::FeedbackData> feedback_data) {
+  redaction::RedactionTool redactor(/*first_party_extension_ids=*/nullptr);
+  redactor.EnableCreditCardRedaction(true);
+  feedback_data->RedactDescription(redactor);
+  return feedback_data;
+}
+
+// Queues a feedback report for the provided feedback data.
+void SendFeedback(scoped_refptr<feedback::FeedbackData> feedback_data) {
+  feedback_data->OnFeedbackPageDataComplete();
+}
+
+// Redacts the description, then sends the provided feedback data.
+void RedactThenSendFeedback(
+    scoped_refptr<feedback::FeedbackData> feedback_data) {
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::TaskPriority::BEST_EFFORT},
+      base::BindOnce(&RedactFeedbackData, std::move(feedback_data)),
+      base::BindOnce(&SendFeedback));
+}
+
+}  // namespace
+
+void SendFeedback(feedback::FeedbackUploader& uploader,
+                  int product_id,
+                  std::string description,
+                  std::optional<std::string> image,
+                  std::optional<std::string> image_mime_type) {
+  auto feedback_data = base::MakeRefCounted<feedback::FeedbackData>(
+      uploader.AsWeakPtr(), /*tracing_manager=*/nullptr);
+
+  feedback_data->set_product_id(product_id);
+  feedback_data->set_include_chrome_platform(false);
+  feedback_data->set_description(std::move(description));
+  if (image.has_value()) {
+    feedback_data->set_image(std::move(*image));
+  }
+  if (image_mime_type.has_value()) {
+    feedback_data->set_image_mime_type(std::move(*image_mime_type));
+  }
+  feedback_data->AddLog("CHROME VERSION", GetChromeVersion());
+  feedback_data->AddLog("CHROMEOS_RELEASE_VERSION", GetOsVersion());
+
+  RedactThenSendFeedback(feedback_data);
+}
+
+}  // namespace specialized_features
diff --git a/chromeos/ash/components/specialized_features/feedback.h b/chromeos/ash/components/specialized_features/feedback.h
new file mode 100644
index 0000000..99dcd6c
--- /dev/null
+++ b/chromeos/ash/components/specialized_features/feedback.h
@@ -0,0 +1,35 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_ASH_COMPONENTS_SPECIALIZED_FEATURES_FEEDBACK_H_
+#define CHROMEOS_ASH_COMPONENTS_SPECIALIZED_FEATURES_FEEDBACK_H_
+
+#include <optional>
+#include <string>
+
+#include "base/component_export.h"
+
+namespace feedback {
+class FeedbackUploader;
+}
+
+namespace specialized_features {
+
+// Uploads feedback about a specialized feature after redacting the given
+// description.
+// WARNING: The start and end of `description` may not be redacted correctly due
+// to limitations in `feedback::RedactionTool`. To work around this, prepend
+// exactly two spaces (for credit cards WITHOUT triggering the three space hash
+// exception) and append a new line (for credit cards).
+// TODO: b/367882164 - Fix this in `feedback::RedactionTool`, or work around it.
+COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_SPECIALIZED_FEATURES)
+void SendFeedback(feedback::FeedbackUploader& uploader,
+                  int product_id,
+                  std::string description,
+                  std::optional<std::string> image = std::nullopt,
+                  std::optional<std::string> image_mime_type = std::nullopt);
+
+}  // namespace specialized_features
+
+#endif  // CHROMEOS_ASH_COMPONENTS_SPECIALIZED_FEATURES_FEEDBACK_H_
diff --git a/chromeos/ash/components/specialized_features/feedback_unittest.cc b/chromeos/ash/components/specialized_features/feedback_unittest.cc
new file mode 100644
index 0000000..022f5d0
--- /dev/null
+++ b/chromeos/ash/components/specialized_features/feedback_unittest.cc
@@ -0,0 +1,220 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/ash/components/specialized_features/feedback.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/check.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "components/feedback/feedback_uploader.h"
+#include "components/feedback/proto/extension.pb.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace specialized_features {
+namespace {
+
+using ::base::test::InvokeFuture;
+using ::testing::_;
+using ::testing::HasSubstr;
+using ::testing::Not;
+using ::testing::WithArg;
+using ::testing::WithoutArgs;
+
+constexpr int kFakeProductId = 1;
+
+class MockFeedbackUploader : public feedback::FeedbackUploader {
+ public:
+  MockFeedbackUploader(
+      const base::FilePath& state_path,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+      : FeedbackUploader(/*is_off_the_record=*/false,
+                         state_path,
+                         std::move(url_loader_factory)) {}
+
+  // feedback::FeedbackUploader:
+  MOCK_METHOD(void,
+              QueueReport,
+              (std::unique_ptr<std::string> data,
+               bool has_email,
+               int product_id),
+              (override));
+
+  base::WeakPtr<FeedbackUploader> AsWeakPtr() override {
+    return weak_ptr_factory_.GetWeakPtr();
+  }
+
+ private:
+  base::WeakPtrFactory<MockFeedbackUploader> weak_ptr_factory_{this};
+};
+
+// A `base::ScopedTempDir` which automatically creates itself upon construction.
+// Required to use `MockFeedbackUploader` in `SpecializedFeaturesFeedbackTest`.
+class ScopedAutocreatingTempDir {
+ public:
+  ScopedAutocreatingTempDir() { CHECK(scoped_temp_dir_.CreateUniqueTempDir()); }
+
+  const base::FilePath& GetPath() const LIFETIME_BOUND {
+    return scoped_temp_dir_.GetPath();
+  }
+
+ private:
+  base::ScopedTempDir scoped_temp_dir_;
+};
+
+class SpecializedFeaturesFeedbackTest : public testing::Test {
+ public:
+  SpecializedFeaturesFeedbackTest()
+      : uploader_(
+            scoped_autocreating_temp_dir_.GetPath(),
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &url_loader_factory_)) {}
+
+  MockFeedbackUploader& uploader() LIFETIME_BOUND { return uploader_; }
+
+ private:
+  base::test::TaskEnvironment task_environment_;
+  network::TestURLLoaderFactory url_loader_factory_;
+  ScopedAutocreatingTempDir scoped_autocreating_temp_dir_;
+  MockFeedbackUploader uploader_;
+};
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackUsesProductId) {
+  base::test::TestFuture<void> report_future;
+  EXPECT_CALL(uploader(), QueueReport(_, _, kFakeProductId))
+      .WillOnce(WithoutArgs(InvokeFuture(report_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description");
+  EXPECT_TRUE(report_future.Wait());
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackSendsDescription) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_EQ(feedback_data.common_data().description(), "test description");
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackRedactsDescriptionStart) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  // This test fails without two leading spaces in the description due to a
+  // limitation in `feedback::RedactionTool`.
+  // TODO: b/367882164 - Fix this test by either fixing
+  // `feedback::RedactionTool`, or working around it.
+  SendFeedback(uploader(), kFakeProductId,
+               "  4242 4242 4242 4242 is my credit card number");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_THAT(feedback_data.common_data().description(),
+              Not(HasSubstr("4242 4242 4242 4242")));
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackRedactsDescriptionEnd) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  // This test fails without a trailing new line in the description due to a
+  // limitation in `feedback::RedactionTool`.
+  // TODO: b/367882164 - Fix this test by either fixing
+  // `feedback::RedactionTool`, or working around it.
+  SendFeedback(uploader(), kFakeProductId,
+               "My credit card number is 4242 4242 4242 4242\n");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_THAT(feedback_data.common_data().description(),
+              Not(HasSubstr("4242 4242 4242 4242")));
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest,
+       SendFeedbackDoesNotIncludeScreenshotByDefault) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_FALSE(feedback_data.screenshot().has_binary_content());
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackSendsScreenshot) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description",
+               "screenshotbytes");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_EQ(feedback_data.screenshot().binary_content(), "screenshotbytes");
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest,
+       SendFeedbackUsesDefaultScreenshotMimeType) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description",
+               "screenshotbytes");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_EQ(feedback_data.screenshot().mime_type(), "image/png");
+}
+
+TEST_F(SpecializedFeaturesFeedbackTest, SendFeedbackSendsScreenshotMimeType) {
+  base::test::TestFuture<std::unique_ptr<std::string>> feedback_string_future;
+  EXPECT_CALL(uploader(), QueueReport)
+      .WillOnce(WithArg<0>(InvokeFuture(feedback_string_future)));
+
+  SendFeedback(uploader(), kFakeProductId, "test description",
+               "screenshotbytes", "image/jpeg");
+
+  std::unique_ptr<std::string> feedback_string = feedback_string_future.Take();
+  ASSERT_TRUE(feedback_string);
+  userfeedback::ExtensionSubmit feedback_data;
+  feedback_data.ParseFromString(*feedback_string);
+  EXPECT_EQ(feedback_data.screenshot().mime_type(), "image/jpeg");
+}
+
+}  // namespace
+}  // namespace specialized_features
diff --git a/chromeos/ash/services/ime/public/mojom/input_method.mojom b/chromeos/ash/services/ime/public/mojom/input_method.mojom
index 102be92..9c903187 100644
--- a/chromeos/ash/services/ime/public/mojom/input_method.mojom
+++ b/chromeos/ash/services/ime/public/mojom/input_method.mojom
@@ -6,7 +6,7 @@
 // the Chromium repo. This file should be updated first, before syncing in the
 // other repos.
 
-// Next MinVersion: 23
+// Next MinVersion: 24
 
 module ash.ime.mojom;
 
@@ -25,7 +25,7 @@
 // If a key is not listed here, then it means that the Chrome OS first-party
 // IMEs do not handle it and it is safe for the OS to handle the key itself.
 //
-// Next ordinal: 18
+// Next ordinal: 40
 [Stable, Extensible, RenamedFrom="chromeos.ime.mojom.NamedDomKey"]
 enum NamedDomKey {
   [Default] kOther = 0,
@@ -61,6 +61,19 @@
   [MinVersion=16] kF10 = 27,
   [MinVersion=16] kF11 = 28,
   [MinVersion=16] kF12 = 29,
+  // Chrome action keys (top row keys)
+  [MinVersion=23] kBrowserBack = 30,
+  [MinVersion=23] kBrowserForward = 31,
+  [MinVersion=23] kBrowserRefresh = 32,
+  // ZoomToggle corresponds to the "full screen" action.
+  [MinVersion=23] kZoomToggle = 33,
+  // LaunchMyComputer corresponds to "Show all open windows" action.
+  [MinVersion=23] kLaunchMyComputer = 34,
+  [MinVersion=23] kBrightnessDown = 35,
+  [MinVersion=23] kBrightnessUp = 36,
+  [MinVersion=23] kAudioVolumeMute = 37,
+  [MinVersion=23] kAudioVolumeDown = 38,
+  [MinVersion=23] kAudioVolumeUp = 39,
 };
 
 // Represents a key pressed by the user, taking into account aspects like
diff --git a/clank b/clank
index 2b25944..61ca08e 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 2b25944cc5da43fee0c2cc41e60165bbe51f6a93
+Subproject commit 61ca08e978df2e55fe40731b7c5c1ed333480e42
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 10ecbab..4b9c046a 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "50.59",
-  "log_list_timestamp": "2025-01-04T12:55:26Z",
+  "version": "50.60",
+  "log_list_timestamp": "2025-01-05T12:53:50Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/feedback/feedback_common.cc b/components/feedback/feedback_common.cc
index 9b04227..7d69567 100644
--- a/components/feedback/feedback_common.cc
+++ b/components/feedback/feedback_common.cc
@@ -185,7 +185,11 @@
 
   if (image().size()) {
     userfeedback::PostedScreenshot screenshot;
-    screenshot.set_mime_type(kPngMimeType);
+    if (image_mime_type().empty()) {
+      screenshot.set_mime_type(kPngMimeType);
+    } else {
+      screenshot.set_mime_type(image_mime_type());
+    }
 
     // Set that we 'have' dimensions of the screenshot. These dimensions are
     // ignored by the server but are a 'required' field in the protobuf.
diff --git a/components/feedback/feedback_common.h b/components/feedback/feedback_common.h
index be6e574..967f8a26 100644
--- a/components/feedback/feedback_common.h
+++ b/components/feedback/feedback_common.h
@@ -76,6 +76,7 @@
   const std::string& description() const { return description_; }
   const std::string& user_email() const { return user_email_; }
   const std::string& image() const { return image_; }
+  const std::string& image_mime_type() const { return image_mime_type_; }
   const SystemLogsMap* sys_info() const { return &logs_; }
   int32_t product_id() const { return product_id_; }
   std::string user_agent() const { return user_agent_; }
@@ -105,6 +106,9 @@
     user_email_ = user_email;
   }
   void set_image(std::string image) { image_ = std::move(image); }
+  void set_image_mime_type(std::string image_mime_type) {
+    image_mime_type_ = std::move(image_mime_type);
+  }
   void set_product_id(int32_t product_id) { product_id_ = product_id; }
   void set_user_agent(const std::string& user_agent) {
     user_agent_ = user_agent;
@@ -159,6 +163,8 @@
   std::string ai_metadata_;
 
   std::string image_;
+  // If empty, assumed to be PNG.
+  std::string image_mime_type_;
 
   // It is possible that multiple attachment add calls are running in
   // parallel, so synchronize access.
diff --git a/components/feedback/feedback_common_unittest.cc b/components/feedback/feedback_common_unittest.cc
index a71a856..95709a7 100644
--- a/components/feedback/feedback_common_unittest.cc
+++ b/components/feedback/feedback_common_unittest.cc
@@ -4,6 +4,11 @@
 
 #include "components/feedback/feedback_common.h"
 
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+#include "base/containers/span.h"
 #include "base/functional/bind.h"
 #include "components/feedback/feedback_report.h"
 #include "components/feedback/proto/common.pb.h"
@@ -21,6 +26,12 @@
 constexpr char kLongLog[] = TEN_LINES TEN_LINES TEN_LINES TEN_LINES TEN_LINES;
 constexpr char kLogsAttachmentName[] = "system_logs.zip";
 constexpr int kTestProductId = 3490;
+constexpr uint8_t kPngBytes[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A,
+                                 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D,
+                                 0x49, 0x48, 0x44, 0x52};
+constexpr uint8_t kJpegBytes[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10,
+                                  0x4A, 0x46, 0x49, 0x46, 0x00, 0x01,
+                                  0x01, 0x00, 0x00, 0x01};
 
 #if BUILDFLAG(IS_CHROMEOS)
 constexpr int kDefaultProductId = 208;  // ChromeOS default product ID.
@@ -146,3 +157,25 @@
   EXPECT_EQ("log_id", report_.web_data().product_specific_data(0).key());
   EXPECT_EQ("TEST_ID", report_.web_data().product_specific_data(0).value());
 }
+
+TEST_F(FeedbackCommonTest, ImageMimeTypeNoImage) {
+  feedback_->PrepareReport(&report_);
+
+  EXPECT_FALSE(report_.screenshot().has_mime_type());
+}
+
+TEST_F(FeedbackCommonTest, ImageMimeTypeNotSpecified) {
+  feedback_->set_image(std::string(base::as_string_view(kPngBytes)));
+  feedback_->PrepareReport(&report_);
+
+  EXPECT_EQ(report_.screenshot().mime_type(), "image/png");
+}
+
+TEST_F(FeedbackCommonTest, ImageMimeTypeSpecified) {
+  constexpr std::string_view kMimeType = "image/jpeg";
+  feedback_->set_image(std::string(base::as_string_view(kJpegBytes)));
+  feedback_->set_image_mime_type(std::string(kMimeType));
+  feedback_->PrepareReport(&report_);
+
+  EXPECT_EQ(report_.screenshot().mime_type(), kMimeType);
+}
diff --git a/components/manta/BUILD.gn b/components/manta/BUILD.gn
index ffdcd77..20959ccc 100644
--- a/components/manta/BUILD.gn
+++ b/components/manta/BUILD.gn
@@ -46,16 +46,6 @@
       "scanner_provider.h",
       "snapper_provider.cc",
       "snapper_provider.h",
-      "sparky/sparky_context.cc",
-      "sparky/sparky_context.h",
-      "sparky/sparky_delegate.cc",
-      "sparky/sparky_delegate.h",
-      "sparky/sparky_provider.cc",
-      "sparky/sparky_provider.h",
-      "sparky/sparky_util.cc",
-      "sparky/sparky_util.h",
-      "sparky/system_info_delegate.cc",
-      "sparky/system_info_delegate.h",
       "walrus_provider.cc",
       "walrus_provider.h",
     ]
@@ -76,8 +66,6 @@
       "orca_provider_unittest.cc",
       "scanner_provider_unittest.cc",
       "snapper_provider_unittest.cc",
-      "sparky/sparky_provider_unittest.cc",
-      "sparky/sparky_util_unittest.cc",
       "walrus_provider_unittest.cc",
     ]
   }
diff --git a/components/manta/manta_service.cc b/components/manta/manta_service.cc
index 467f663..8be646d 100644
--- a/components/manta/manta_service.cc
+++ b/components/manta/manta_service.cc
@@ -12,7 +12,6 @@
 #include "components/account_id/account_id.h"
 #include "components/manta/anchovy/anchovy_provider.h"
 #include "components/manta/provider_params.h"
-#include "components/manta/sparky/system_info_delegate.h"
 #include "components/signin/public/identity_manager/account_capabilities.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/tribool.h"
@@ -24,7 +23,6 @@
 #include "components/manta/orca_provider.h"
 #include "components/manta/scanner_provider.h"
 #include "components/manta/snapper_provider.h"
-#include "components/manta/sparky/sparky_provider.h"
 #include "components/manta/walrus_provider.h"
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
@@ -144,19 +142,6 @@
                                         identity_manager_, provider_params);
 }
 
-std::unique_ptr<SparkyProvider> MantaService::CreateSparkyProvider(
-    std::unique_ptr<SparkyDelegate> sparky_delegate,
-    std::unique_ptr<SystemInfoDelegate> system_info_delegate) {
-  if (!identity_manager_ || !sparky_delegate || !system_info_delegate) {
-    return nullptr;
-  }
-  const ProviderParams provider_params = {
-      /*use_api_key=*/is_demo_mode_, chrome_version_, chrome_channel_, locale_};
-  return std::make_unique<SparkyProvider>(
-      shared_url_loader_factory_, identity_manager_, provider_params,
-      std::move(sparky_delegate), std::move(system_info_delegate));
-}
-
 std::unique_ptr<WalrusProvider> MantaService::CreateWalrusProvider() {
   if (!identity_manager_) {
     return nullptr;
diff --git a/components/manta/manta_service.h b/components/manta/manta_service.h
index 247b53f6d..34d1daa2 100644
--- a/components/manta/manta_service.h
+++ b/components/manta/manta_service.h
@@ -13,8 +13,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/version_info/channel.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/system_info_delegate.h"
 
 namespace signin {
 class IdentityManager;
@@ -36,7 +34,6 @@
 class OrcaProvider;
 class ScannerProvider;
 class SnapperProvider;
-class SparkyProvider;
 class WalrusProvider;
 
 // The MantaService class is a KeyedService for the Chrome/ChromeOS Manta
@@ -74,9 +71,6 @@
   std::unique_ptr<OrcaProvider> CreateOrcaProvider();
   std::unique_ptr<ScannerProvider> CreateScannerProvider();
   virtual std::unique_ptr<SnapperProvider> CreateSnapperProvider();
-  std::unique_ptr<SparkyProvider> CreateSparkyProvider(
-      std::unique_ptr<SparkyDelegate> sparky_delegate,
-      std::unique_ptr<SystemInfoDelegate> system_info_delegate);
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Determines whether the profile for this KeyedService support Orca feature.
diff --git a/components/manta/manta_service_callbacks.cc b/components/manta/manta_service_callbacks.cc
index 17c4d8ec..a518ef4 100644
--- a/components/manta/manta_service_callbacks.cc
+++ b/components/manta/manta_service_callbacks.cc
@@ -88,10 +88,6 @@
       base::UmaHistogramTimes("Ash.MantaService.MahiProvider.QA.TimeCost",
                               time_cost);
       break;
-    case manta::MantaMetricType::kSparky:
-      base::UmaHistogramTimes("Ash.MantaService.SparkyProvider.TimeCost",
-                              time_cost);
-      break;
     case MantaMetricType::kAnchovy:
       base::UmaHistogramTimes("Ash.MantaService.AnchovyProvider.TimeCost",
                               time_cost);
@@ -130,10 +126,6 @@
       base::UmaHistogramEnumeration(
           "Ash.MantaService.MahiProvider.QA.StatusCode", status_code);
       break;
-    case manta::MantaMetricType::kSparky:
-      base::UmaHistogramEnumeration(
-          "Ash.MantaService.SparkyProvider.StatusCode", status_code);
-      break;
     case MantaMetricType::kAnchovy:
       base::UmaHistogramEnumeration(
           "Ash.MantaService.AnchovyProvider.StatusCode", status_code);
diff --git a/components/manta/manta_service_callbacks.h b/components/manta/manta_service_callbacks.h
index 9cbdc94..3747bf41 100644
--- a/components/manta/manta_service_callbacks.h
+++ b/components/manta/manta_service_callbacks.h
@@ -29,7 +29,6 @@
   kMahiSummary,
   kMahiElucidation,
   kMahiQA,
-  kSparky,
   kWalrus,
 };
 
diff --git a/components/manta/proto/BUILD.gn b/components/manta/proto/BUILD.gn
index c2fa767..da19eec 100644
--- a/components/manta/proto/BUILD.gn
+++ b/components/manta/proto/BUILD.gn
@@ -16,7 +16,6 @@
     "manta.proto",
     "rpc_status.proto",
     "scanner.proto",
-    "sparky.proto",
   ]
 
   if (allow_internal) {
diff --git a/components/manta/proto/manta.proto b/components/manta/proto/manta.proto
index ed95cc5d..cd6ec75 100644
--- a/components/manta/proto/manta.proto
+++ b/components/manta/proto/manta.proto
@@ -6,7 +6,6 @@
 option optimize_for = LITE_RUNTIME;
 
 import "components/manta/proto/common.proto";
-import "components/manta/proto/sparky.proto";
 
 package manta.proto;
 
@@ -19,7 +18,6 @@
   CHROMEOS_READER_SUMMARY = 303;
   CHROMEOS_READER_TOC = 312;
   CHROMEOS_READER_Q_AND_A = 313;
-  CHROMEOS_SPARKY = 314;
   CHROMEOS_LOBSTER = 315;
   CHROMEOS_SCANNER = 316;
   CHROMEOS_READER_ELUCIDATION = 317;
@@ -111,7 +109,6 @@
     string text = 1;
     Image image = 2;
     Proto3Any custom = 3;
-    SparkyContextData sparky_context_data = 5;
   }
   optional string tag = 4;
 }
@@ -129,7 +126,6 @@
     string text = 1;
     Image image = 2;
     Proto3Any custom = 3;
-    SparkyResponse sparky_response = 7;
   }
 
   optional float score = 5;
diff --git a/components/manta/proto/sparky.proto b/components/manta/proto/sparky.proto
deleted file mode 100644
index 8a9b48b..0000000
--- a/components/manta/proto/sparky.proto
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-
-import "components/manta/proto/common.proto";
-
-package manta.proto;
-
-enum Task {
-  reserved 3, 4;
-
-  TASK_UNSPECIFIED = 0;
-  TASK_SETTINGS = 1;
-  TASK_DIAGNOSTICS = 2;
-  TASK_GENERIC = 5;
-  TASK_PLANNER = 6;
-}
-
-enum Diagnostics {
-  DIAGNOSTICS_UNSPECIFIED = 0;
-  DIAGNOSTICS_MEMORY = 1;
-  DIAGNOSTICS_CPU = 2;
-  DIAGNOSTICS_BATTERY = 3;
-  DIAGNOSTICS_STORAGE = 4;
-}
-
-enum SettingType {
-  SETTING_TYPE_UNSPECIFIED = 0;
-  SETTING_TYPE_BOOL = 1;
-  SETTING_TYPE_STRING = 2;
-  SETTING_TYPE_DOUBLE = 3;
-  SETTING_TYPE_INTEGER = 4;
-}
-
-enum Role {
-  ROLE_UNSPECIFIED = 0;
-  ROLE_USER = 1;
-  ROLE_ASSISTANT = 2;
-}
-
-message BatteryData {
-  optional int32 battery_health = 1;
-  optional int32 cycle_count = 2;
-  optional string battery_time = 3;
-  optional int32 battery_charge_percentage = 4;
-}
-
-message StorageData {
-  optional string free_storage = 1;
-  optional string total_storage = 2;
-}
-
-message CPUData {
-  optional int32 cpu_usage_snapshot = 1;
-  optional int32 temperature = 2;
-  optional double clock_speed_ghz = 3;
-}
-
-message MemoryData {
-  optional double free_ram_gb = 1;
-  optional double total_ram_gb = 2;
-}
-
-message DiagnosticsData {
-  optional BatteryData battery = 1;
-  optional StorageData storage = 2;
-  optional CPUData cpu = 3;
-  optional MemoryData memory = 4;
-}
-
-message ServerConfig {
-  optional string server_url = 1;
-}
-
-message SettingsValue {
-  oneof settings_value {
-    bool bool_val = 1;
-    string text_val = 2;
-    double double_val = 3;
-    int32 int_val = 4;
-  }
-}
-
-message Setting {
-  string settings_id = 1;
-  SettingsValue value = 2;
-  SettingType type = 3;
-}
-
-message SettingsData {
-  repeated Setting setting = 1;
-}
-
-message App {
-  string id = 1;
-  string name = 2;
-  repeated string searchable_term = 3;
-}
-
-message AppsData {
-  repeated App app = 1;
-}
-
-message TextEntry {
-  optional string text = 1;
-}
-
-message KeyPress {
-  optional string key = 1;
-
-  optional bool control = 2;
-  optional bool alt = 3;
-  optional bool shift = 4;
-}
-
-message Click {
-  enum Button {
-    UNSPECIFIED = 0;
-    LEFT = 1;
-    RIGHT = 2;
-    MIDDLE = 3;
-  }
-
-  optional int32 x_pos = 1;
-  optional int32 y_pos = 2;
-  optional Button button = 3;
-}
-
-message Scroll {
-  enum Direction {
-    UNSPECIFIED = 0;
-    UP = 1;
-    DOWN = 2;
-    LEFT = 3;
-    RIGHT = 4;
-  }
-
-  optional Direction direction = 1;
-  optional int32 distance = 2;
-}
-
-message LaunchFile {
-  optional string launch_file_path = 1;
-}
-
-message WriteFile {
-  optional string name = 1;
-  optional string file_bytes = 2;
-}
-
-message Action {
-  oneof action {
-    Setting update_setting = 1;
-    string launch_app_id = 2;
-    Click click = 3;
-    TextEntry text_entry = 4;
-    bool all_done = 5;
-    LaunchFile launch_file = 6;
-    KeyPress key_press = 7;
-    Scroll scroll = 8;
-    WriteFile write_file = 9;
-  }
-}
-
-message DiagnosticsRequest {
-  repeated Diagnostics diagnostics = 1;
-}
-
-message SettingsDataRequest {}
-
-message FileRequest {
-  repeated string paths = 1;
-}
-
-message File {
-  optional string path = 1;
-  optional string name = 2;
-  optional int64 size_in_bytes = 3;
-  // Returns a relative date if the file date was yesterday or today
-  //`Today 11:44` or it returns the date in the format of `22 July 2024, 13:38`.
-  optional string date_modified = 4;
-  optional bytes serialized_bytes = 5;
-  optional string summary = 6;
-}
-
-message FilesData {
-  repeated File files = 1;
-}
-
-message Update {
-  optional FilesData files_with_summary = 1;
-}
-
-message ContextRequest {
-  optional DiagnosticsRequest diagnostics = 1;
-  optional FileRequest files = 2;
-  optional SettingsDataRequest settings = 3;
-}
-
-message Turn {
-  optional string message = 1;
-  optional Role role = 2;
-  repeated Action action = 3;
-  optional Image screenshot = 4;
-}
-
-message SparkyResponse {
-  optional ContextRequest context_request = 1;
-  optional Turn latest_reply = 2;
-  optional Update update = 3;
-}
-
-message WebContent {
-  optional string page_contents = 1;
-  optional string page_url = 2;
-}
-
-message SparkyContextData {
-  optional Task task = 1;
-  optional DiagnosticsData diagnostics_data = 2;
-  optional SettingsData settings_data = 3;
-  repeated Turn conversation = 4;
-  optional Image screenshot = 5;
-  optional AppsData apps_data = 6;
-  optional WebContent web_contents = 7;
-  optional FilesData files_data = 8;
-  optional ServerConfig server_config = 9;
-}
diff --git a/components/manta/sparky/sparky_context.cc b/components/manta/sparky/sparky_context.cc
deleted file mode 100644
index f8d102c1..0000000
--- a/components/manta/sparky/sparky_context.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/sparky_context.h"
-
-#include "components/manta/proto/sparky.pb.h"
-
-namespace manta {
-
-SparkyContext::SparkyContext(const proto::Turn& latest_turn)
-    : latest_turn(latest_turn) {}
-
-SparkyContext::SparkyContext(const proto::Turn& latest_turn,
-                             const std::string& page_content)
-    : latest_turn(latest_turn), page_content(page_content) {}
-
-SparkyContext::~SparkyContext() = default;
-
-SparkyContext::SparkyContext(const SparkyContext&) = default;
-SparkyContext& SparkyContext::operator=(const SparkyContext&) = default;
-
-}  // namespace manta
diff --git a/components/manta/sparky/sparky_context.h b/components/manta/sparky/sparky_context.h
deleted file mode 100644
index 39fe795..0000000
--- a/components/manta/sparky/sparky_context.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MANTA_SPARKY_SPARKY_CONTEXT_H_
-#define COMPONENTS_MANTA_SPARKY_SPARKY_CONTEXT_H_
-
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/sparky_util.h"
-
-namespace manta {
-
-// Stores the input Sparky data to be included into the Sparky Provider.
-struct COMPONENT_EXPORT(MANTA) SparkyContext {
-  explicit SparkyContext(const proto::Turn& latest_turn);
-
-  SparkyContext(const proto::Turn& latest_turn,
-                const std::string& page_content);
-
-  ~SparkyContext();
-
-  SparkyContext(const SparkyContext&);
-  SparkyContext& operator=(const SparkyContext&);
-
-  proto::Turn latest_turn;
-  std::optional<DiagnosticsData> diagnostics_data;
-  std::optional<std::string> page_content;
-  std::optional<std::string> page_url;
-  std::optional<std::string> server_url;
-  std::vector<FileData> files;
-  bool collect_settings{true};
-  proto::Task task{proto::Task::TASK_PLANNER};
-};
-
-}  // namespace manta
-
-#endif  // COMPONENTS_MANTA_SPARKY_SPARKY_CONTEXT_H_
diff --git a/components/manta/sparky/sparky_delegate.cc b/components/manta/sparky/sparky_delegate.cc
deleted file mode 100644
index 6830d20..0000000
--- a/components/manta/sparky/sparky_delegate.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/sparky_delegate.h"
-
-#include <memory>
-#include <optional>
-
-#include "base/values.h"
-
-namespace manta {
-
-SettingsData::SettingsData(const std::string& pref_name,
-                           const PrefType& pref_type,
-                           std::optional<base::Value> value)
-    : pref_name(pref_name), pref_type(pref_type) {
-  switch (pref_type) {
-    case PrefType::kBoolean:
-      bool_val = value->GetBool();
-      val_set = true;
-      break;
-    case PrefType::kInt:
-      int_val = value->GetInt();
-      val_set = true;
-      break;
-    case PrefType::kDouble:
-      double_val = value->GetDouble();
-      val_set = true;
-      break;
-    case PrefType::kString:
-      string_val = value->GetString();
-      val_set = true;
-      break;
-    default:
-      // TODO add in error message.
-      break;
-  }
-}
-
-SettingsData::~SettingsData() = default;
-
-SettingsData::SettingsData(const SettingsData&) = default;
-SettingsData& SettingsData::operator=(const SettingsData&) = default;
-
-std::optional<base::Value> SettingsData::GetValue() const {
-  if (!val_set) {
-    return std::nullopt;
-  }
-  switch (pref_type) {
-    case PrefType::kBoolean:
-      return std::make_optional<base::Value>(bool_val);
-    case PrefType::kInt:
-      return std::make_optional<base::Value>(int_val);
-    case PrefType::kDouble:
-      return std::make_optional<base::Value>(double_val);
-    case PrefType::kString:
-      return std::make_optional<base::Value>(string_val);
-    default:
-      return std::nullopt;
-  }
-}
-
-AppsData::AppsData(const std::string& name, const std::string& id)
-    : name(name), id(id) {}
-
-AppsData::~AppsData() = default;
-
-AppsData::AppsData(AppsData&& other) = default;
-AppsData& AppsData::operator=(AppsData&& other) = default;
-
-void AppsData::AddSearchableText(const std::string& new_searchable_text) {
-  searchable_text.push_back(new_searchable_text);
-}
-FileData::FileData(const std::string& path,
-                   const std::string& name,
-                   const std::string& date_modified)
-    : path(path), name(name), date_modified(date_modified) {}
-
-FileData::~FileData() = default;
-
-FileData::FileData(const FileData&) = default;
-FileData& FileData::operator=(const FileData&) = default;
-
-SparkyDelegate::SparkyDelegate() = default;
-SparkyDelegate::~SparkyDelegate() = default;
-
-}  // namespace manta
diff --git a/components/manta/sparky/sparky_delegate.h b/components/manta/sparky/sparky_delegate.h
deleted file mode 100644
index 6c200d77..0000000
--- a/components/manta/sparky/sparky_delegate.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MANTA_SPARKY_SPARKY_DELEGATE_H_
-#define COMPONENTS_MANTA_SPARKY_SPARKY_DELEGATE_H_
-
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <optional>
-#include <set>
-#include <string>
-
-#include "base/component_export.h"
-#include "base/functional/callback.h"
-#include "base/functional/callback_forward.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/values.h"
-#include "components/manta/sparky/system_info_delegate.h"
-
-namespace manta {
-
-enum class PrefType {
-  kNone = 0,
-  kBoolean,
-  kInt,
-  kDouble,
-  kString,
-  kList,
-  kDictionary,
-  kMaxValue = kDictionary,
-};
-
-// Stores the setting data for the current or wanted state of a Pref.
-struct COMPONENT_EXPORT(MANTA) SettingsData {
-  SettingsData(const std::string& pref_name,
-               const PrefType& pref_type,
-               std::optional<base::Value> value);
-
-  ~SettingsData();
-
-  SettingsData(const SettingsData&);
-  SettingsData& operator=(const SettingsData&);
-
-  std::optional<base::Value> GetValue() const;
-
-  std::string pref_name;
-  PrefType pref_type;
-  bool val_set{false};
-  bool bool_val;
-  int int_val;
-  std::string string_val;
-  double double_val;
-};
-
-struct COMPONENT_EXPORT(MANTA) FileData {
-  FileData(const std::string& path,
-           const std::string& name,
-           const std::string& date_modified);
-
-  ~FileData();
-
-  FileData(const FileData&);
-  FileData& operator=(const FileData&);
-
-  std::string path;
-  std::string name;
-  std::optional<std::vector<uint8_t>> bytes;
-  int64_t size_in_bytes;
-  std::string date_modified;
-  std::string summary;
-};
-
-using ScreenshotDataCallback =
-    base::OnceCallback<void(scoped_refptr<base::RefCountedMemory>)>;
-
-struct COMPONENT_EXPORT(MANTA) AppsData {
-  AppsData(const std::string& name, const std::string& id);
-
-  ~AppsData();
-
-  AppsData(AppsData&& other);
-  AppsData& operator=(AppsData&& other);
-
-  void AddSearchableText(const std::string& new_searchable_text);
-
-  std::string name;
-  std::string id;
-  std::vector<std::string> searchable_text;
-};
-using StorageDataCallback =
-    base::OnceCallback<void(std::unique_ptr<StorageData>)>;
-
-using FilesDataCallback = base::OnceCallback<void(std::vector<FileData>)>;
-
-// Virtual class to handle the information requests and actions taken within
-// Sparky Provider which have a Chrome dependency.
-class COMPONENT_EXPORT(MANTA) SparkyDelegate {
- public:
-  using SettingsDataList = std::map<std::string, std::unique_ptr<SettingsData>>;
-  SparkyDelegate();
-  SparkyDelegate(const SparkyDelegate&) = delete;
-  SparkyDelegate& operator=(const SparkyDelegate&) = delete;
-
-  virtual ~SparkyDelegate();
-
-  virtual bool SetSettings(std::unique_ptr<SettingsData> settings_data) = 0;
-  virtual SettingsDataList* GetSettingsList() = 0;
-  virtual std::optional<base::Value> GetSettingValue(
-      const std::string& setting_id) = 0;
-  virtual void GetScreenshot(ScreenshotDataCallback callback) = 0;
-  virtual std::vector<AppsData> GetAppsList() = 0;
-  virtual void LaunchApp(const std::string& app_id) = 0;
-  virtual void ObtainStorageInfo(StorageDataCallback storage_callback) = 0;
-  virtual void Click(int x, int y) = 0;
-  virtual void KeyboardEntry(std::string text) = 0;
-  virtual void KeyPress(const std::string& key,
-                        bool control,
-                        bool alt,
-                        bool shift) = 0;
-  virtual void GetMyFiles(FilesDataCallback callback,
-                          bool obtain_bytes,
-                          std::set<std::string> allowed_file_paths) = 0;
-  virtual void LaunchFile(const std::string& file_path) = 0;
-  virtual void WriteFile(const std::string& name, const std::string& bytes) = 0;
-  virtual void UpdateFileSummaries(
-      const std::vector<manta::FileData>& files_with_summary) = 0;
-  virtual std::vector<manta::FileData> GetFileSummaries() = 0;
-};
-
-}  // namespace manta
-
-#endif  // COMPONENTS_MANTA_SPARKY_SPARKY_DELEGATE_H_
diff --git a/components/manta/sparky/sparky_provider.cc b/components/manta/sparky/sparky_provider.cc
deleted file mode 100644
index 51d28c78..0000000
--- a/components/manta/sparky/sparky_provider.cc
+++ /dev/null
@@ -1,427 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "components/manta/sparky/sparky_provider.h"
-
-#include <memory>
-#include <optional>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/check.h"
-#include "base/containers/fixed_flat_map.h"
-#include "base/functional/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "components/endpoint_fetcher/endpoint_fetcher.h"
-#include "components/manta/base_provider.h"
-#include "components/manta/manta_service.h"
-#include "components/manta/manta_service_callbacks.h"
-#include "components/manta/manta_status.h"
-#include "components/manta/proto/manta.pb.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/sparky_util.h"
-#include "components/manta/sparky/system_info_delegate.h"
-#include "components/signin/public/base/consent_level.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-namespace manta {
-
-namespace {
-
-// TODO (b/336703051) Update with new Oauth.
-constexpr char kOauthConsumerName[] = "manta_sparky";
-constexpr base::TimeDelta kTimeout = base::Seconds(75);
-
-// Handles the QA response from the server.
-void OnQAServerResponseOrErrorReceived(
-    SparkyProvider::SparkyProtoResponseCallback callback,
-    std::unique_ptr<proto::Response> manta_response,
-    MantaStatus manta_status) {
-  if (manta_status.status_code != MantaStatusCode::kOk) {
-    CHECK(manta_response == nullptr);
-    std::move(callback).Run(nullptr, std::move(manta_status));
-    return;
-  }
-
-  CHECK(manta_response != nullptr);
-  if (manta_response->output_data_size() < 1 ||
-      !manta_response->output_data(0).has_sparky_response()) {
-    std::string message = std::string();
-
-    // Tries to find more information from filtered_data
-    if (manta_response->filtered_data_size() > 0 &&
-        manta_response->filtered_data(0).is_output_data()) {
-      message = base::StringPrintf(
-          "filtered output for: %s",
-          proto::FilteredReason_Name(manta_response->filtered_data(0).reason())
-              .c_str());
-    }
-    std::move(callback).Run(std::make_unique<proto::SparkyResponse>(),
-                            {MantaStatusCode::kBlockedOutputs, message});
-    return;
-  }
-
-  std::move(callback).Run(std::make_unique<proto::SparkyResponse>(
-                              manta_response->output_data(0).sparky_response()),
-                          std::move(manta_status));
-}
-
-}  // namespace
-
-SparkyProvider::SparkyProvider(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    signin::IdentityManager* identity_manager,
-    const ProviderParams& provider_params,
-    std::unique_ptr<SparkyDelegate> sparky_delegate,
-    std::unique_ptr<SystemInfoDelegate> system_info_delegate)
-    : BaseProvider(url_loader_factory, identity_manager, provider_params),
-      sparky_delegate_(std::move(sparky_delegate)),
-      system_info_delegate_(std::move(system_info_delegate)) {}
-
-SparkyProvider::SparkyProvider(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    signin::IdentityManager* identity_manager,
-    std::unique_ptr<SparkyDelegate> sparky_delegate,
-    std::unique_ptr<SystemInfoDelegate> system_info_delegate)
-    : BaseProvider(url_loader_factory, identity_manager),
-      sparky_delegate_(std::move(sparky_delegate)),
-      system_info_delegate_(std::move(system_info_delegate)) {}
-
-SparkyProvider::~SparkyProvider() = default;
-
-std::vector<manta::FileData> SparkyProvider::GetFilesSummary() {
-  return sparky_delegate_->GetFileSummaries();
-}
-
-void SparkyProvider::ClearDialog() {
-  request_.Clear();
-  consecutive_assistant_turn_count_ = 0;
-  is_additional_call_expected_ = false;
-}
-
-void SparkyProvider::MarkLastActionAllDone() {
-  if (request_.input_data_size() == 0) {
-    return;
-  }
-  auto* sparky_context_data =
-      request_.mutable_input_data(request_.input_data_size() - 1)
-          ->mutable_sparky_context_data();
-
-  if (sparky_context_data->conversation_size() == 0) {
-    return;
-  }
-  auto* last_conversation = sparky_context_data->mutable_conversation(
-      sparky_context_data->conversation_size() - 1);
-
-  // Keeps the last action. Adds a new `all_done` action at the end instead.
-  auto* last_action = last_conversation->add_action();
-  last_action->set_all_done(true);
-  is_additional_call_expected_ = false;
-}
-
-void SparkyProvider::QuestionAndAnswer(
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback) {
-  sparky_delegate_->GetScreenshot(base::BindOnce(
-      &SparkyProvider::OnScreenshotObtained, weak_ptr_factory_.GetWeakPtr(),
-      std::move(sparky_context), std::move(done_callback)));
-}
-
-void SparkyProvider::OnScreenshotObtained(
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback,
-    scoped_refptr<base::RefCountedMemory> png_screenshot) {
-  request_.set_feature_name(proto::FeatureName::CHROMEOS_SPARKY);
-
-  proto::InputData* input_data;
-  if (request_.input_data_size() > 0) {
-    input_data = request_.mutable_input_data(request_.input_data_size() - 1);
-  } else {
-    input_data = request_.add_input_data();
-  }
-  input_data->set_tag("sparky_context");
-
-  auto* sparky_context_data = input_data->mutable_sparky_context_data();
-
-  // Only adds the latest turn to the request if it is from the user. If the
-  // turn comes from the assistant, it has been added when the response is
-  // received from the assistant.
-  if (sparky_context->latest_turn.role() == proto::ROLE_USER) {
-    *sparky_context_data->add_conversation() = sparky_context->latest_turn;
-    consecutive_assistant_turn_count_ = 0;
-  }
-
-  sparky_context_data->set_task(sparky_context->task);
-  if (sparky_context->page_url.has_value()) {
-    auto* web_contents = sparky_context_data->mutable_web_contents();
-    web_contents->set_page_url(sparky_context->page_url.value());
-    if (sparky_context->page_content.has_value()) {
-      web_contents->set_page_contents(sparky_context->page_content.value());
-    }
-  }
-
-  if (png_screenshot) {
-    proto::Image* image_proto = sparky_context_data->mutable_screenshot();
-    image_proto->set_serialized_bytes(
-        std::string(base::as_string_view(*png_screenshot)));
-  }
-  auto* apps_data = sparky_context_data->mutable_apps_data();
-  AddAppsData(sparky_delegate_->GetAppsList(), apps_data);
-
-  if (sparky_context->collect_settings) {
-    auto* settings_list = sparky_delegate_->GetSettingsList();
-    if (settings_list) {
-      auto* settings_data = sparky_context_data->mutable_settings_data();
-      AddSettingsProto(*settings_list, settings_data);
-    }
-  }
-  if (sparky_context->diagnostics_data) {
-    auto* diagnostics_proto = sparky_context_data->mutable_diagnostics_data();
-    AddDiagnosticsProto(sparky_context->diagnostics_data, diagnostics_proto);
-  }
-  if (!sparky_context->files.empty()) {
-    auto* files_proto = sparky_context_data->mutable_files_data();
-    AddFilesData(sparky_context->files, files_proto);
-  }
-
-  // This parameter contains the address of one of the backends which the
-  // request is passed through to once it is pushed up in a manta request.
-  if (sparky_context->server_url) {
-    proto::ServerConfig* server_config =
-        sparky_context_data->mutable_server_config();
-    server_config->set_server_url(sparky_context->server_url.value());
-  }
-
-  MantaProtoResponseCallback internal_callback = base::BindOnce(
-      &OnQAServerResponseOrErrorReceived,
-      base::BindOnce(&SparkyProvider::OnResponseReceived,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(done_callback),
-                     std::move(sparky_context)));
-
-  // TODO(b:338501686): MISSING_TRAFFIC_ANNOTATION should be resolved before
-  // launch.
-  RequestInternal(GURL{GetProviderEndpoint(false)}, kOauthConsumerName,
-                  MISSING_TRAFFIC_ANNOTATION, request_,
-                  MantaMetricType::kSparky, std::move(internal_callback),
-                  kTimeout);
-}
-
-void SparkyProvider::OnResponseReceived(
-    SparkyShowAnswerCallback done_callback,
-    std::unique_ptr<SparkyContext> sparky_context,
-    std::unique_ptr<proto::SparkyResponse> sparky_response,
-    manta::MantaStatus status) {
-  if (status.status_code != manta::MantaStatusCode::kOk) {
-    std::move(done_callback).Run(status, nullptr);
-    return;
-  }
-
-  if (sparky_response->has_update()) {
-    if (sparky_response->update().has_files_with_summary()) {
-      auto files_proto = sparky_response->update().files_with_summary();
-      sparky_delegate_->UpdateFileSummaries(GetFileDataFromProto(files_proto));
-    }
-  }
-
-  if (sparky_response->has_context_request()) {
-    RequestAdditionalInformation(sparky_response->context_request(),
-                                 std::move(sparky_context),
-                                 std::move(done_callback), status);
-    return;
-  }
-  if (sparky_response->has_latest_reply()) {
-    OnDialogResponse(std::move(sparky_context), sparky_response->latest_reply(),
-                     std::move(done_callback), status);
-    return;
-  }
-
-  // Occurs if the response cannot be parsed correctly.
-  std::move(done_callback).Run(status, nullptr);
-  return;
-}
-
-void SparkyProvider::RequestAdditionalInformation(
-    proto::ContextRequest context_request,
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback,
-    manta::MantaStatus status) {
-  if (context_request.has_settings()) {
-    if (!sparky_delegate_->GetSettingsList()->empty()) {
-      sparky_context->collect_settings = true;
-      sparky_context->task = proto::TASK_SETTINGS;
-      QuestionAndAnswer(std::move(sparky_context), std::move(done_callback));
-      return;
-    }
-    std::move(done_callback).Run(status, nullptr);
-    return;
-  }
-  if (context_request.has_diagnostics()) {
-    auto diagnostics_vector =
-        ObtainDiagnosticsVectorFromProto(context_request.diagnostics());
-    if (!diagnostics_vector.empty()) {
-      if (std::find(diagnostics_vector.begin(), diagnostics_vector.end(),
-                    Diagnostics::kStorage) != diagnostics_vector.end()) {
-        sparky_delegate_->ObtainStorageInfo(base::BindOnce(
-            &SparkyProvider::OnStorageReceived, weak_ptr_factory_.GetWeakPtr(),
-            std::move(sparky_context), std::move(done_callback), status,
-            diagnostics_vector));
-        return;
-      }
-      system_info_delegate_->ObtainDiagnostics(
-          diagnostics_vector,
-          base::BindOnce(&SparkyProvider::OnDiagnosticsReceived,
-                         weak_ptr_factory_.GetWeakPtr(),
-                         std::move(sparky_context), std::move(done_callback),
-                         status, nullptr));
-      return;
-    }
-    std::move(done_callback).Run(status, nullptr);
-    return;
-  }
-  if (context_request.has_files()) {
-    std::set<std::string> files = GetSelectedFilePaths(context_request.files());
-    sparky_delegate_->GetMyFiles(
-        base::BindOnce(
-            &SparkyProvider::OnFilesObtained, weak_ptr_factory_.GetWeakPtr(),
-            std::move(sparky_context), std::move(done_callback), status),
-        /*obtain_bytes=*/true, /*allowed_file_paths=*/files);
-    return;
-  }
-
-  // Occurs if no valid request can be found.
-  std::move(done_callback).Run(status, nullptr);
-}
-
-void SparkyProvider::OnStorageReceived(
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback,
-    manta::MantaStatus status,
-    std::vector<Diagnostics> diagnostics_vector,
-    std::unique_ptr<StorageData> storage_data) {
-  bool get_system_diagnostics = false;
-  for (auto diagnostic : diagnostics_vector) {
-    if (diagnostic == Diagnostics::kBattery ||
-        diagnostic == Diagnostics::kCpu || diagnostic == Diagnostics::kMemory) {
-      get_system_diagnostics = true;
-      break;
-    }
-  }
-  if (get_system_diagnostics) {
-    system_info_delegate_->ObtainDiagnostics(
-        diagnostics_vector,
-        base::BindOnce(&SparkyProvider::OnDiagnosticsReceived,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       std::move(sparky_context), std::move(done_callback),
-                       status, std::move(storage_data)));
-    return;
-  }
-  sparky_context->diagnostics_data = std::make_optional<DiagnosticsData>(
-      std::nullopt, std::nullopt, std::nullopt,
-      std::make_optional(*storage_data));
-  QuestionAndAnswer(std::move(sparky_context), std::move(done_callback));
-}
-
-void SparkyProvider::OnDiagnosticsReceived(
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback,
-    manta::MantaStatus status,
-    std::unique_ptr<StorageData> storage_data,
-    std::unique_ptr<DiagnosticsData> diagnostics_data) {
-  if (diagnostics_data) {
-    diagnostics_data->storage_data = std::make_optional(*storage_data);
-    sparky_context->diagnostics_data = std::make_optional(*diagnostics_data);
-    sparky_context->task = proto::TASK_DIAGNOSTICS;
-    QuestionAndAnswer(std::move(sparky_context), std::move(done_callback));
-    return;
-  }
-  std::move(done_callback).Run(status, nullptr);
-}
-
-void SparkyProvider::OnDialogResponse(std::unique_ptr<SparkyContext>,
-                                      proto::Turn latest_reply,
-                                      SparkyShowAnswerCallback done_callback,
-                                      manta::MantaStatus status) {
-  // If the response does not contain any dialog then return an error.
-  if (!latest_reply.has_message()) {
-    std::move(done_callback).Run(status, nullptr);
-    return;
-  }
-
-  // It is possible that `request_` has been cleared before a new agent response
-  // is received, in which case we should totally drop this agent response.
-  if (request_.input_data_size() == 0) {
-    return;
-  }
-
-  if (latest_reply.action_size() > 0) {
-    auto actions_repeated_field = latest_reply.action();
-    for (const proto::Action& action : actions_repeated_field) {
-      if (action.has_update_setting()) {
-        std::unique_ptr<SettingsData> setting_data =
-            ObtainSettingFromProto(action.update_setting());
-        if (!setting_data) {
-          // Return an error if the setting cannot be converted correctly from
-          // the proto.
-          DVLOG(1) << "Invalid setting action requested.";
-          std::move(done_callback).Run(status, nullptr);
-          return;
-        }
-        sparky_delegate_->SetSettings(std::move(setting_data));
-      }
-      if (action.has_launch_app_id()) {
-        sparky_delegate_->LaunchApp(action.launch_app_id());
-      }
-      if (action.has_click()) {
-        sparky_delegate_->Click(action.click().x_pos(), action.click().y_pos());
-      }
-      if (action.has_text_entry()) {
-        sparky_delegate_->KeyboardEntry(action.text_entry().text());
-      }
-      if (action.has_launch_file()) {
-        sparky_delegate_->LaunchFile(action.launch_file().launch_file_path());
-      }
-      if (action.has_write_file()) {
-        sparky_delegate_->WriteFile(action.write_file().name(),
-                                    action.write_file().file_bytes());
-      }
-    }
-
-    // Checks if additional server call is expected.
-    auto last_action = latest_reply.action(latest_reply.action_size() - 1);
-    if (last_action.has_all_done()) {
-      is_additional_call_expected_ = !last_action.all_done();
-    } else {
-      is_additional_call_expected_ = false;
-    }
-  }
-
-  // Attaches the response to the cache.
-  auto* input_data =
-      request_.mutable_input_data(request_.input_data_size() - 1);
-  auto* sparky_context_data = input_data->mutable_sparky_context_data();
-  *sparky_context_data->add_conversation() = latest_reply;
-  consecutive_assistant_turn_count_++;
-
-  std::move(done_callback).Run(status, &latest_reply);
-}
-
-void SparkyProvider::OnFilesObtained(
-    std::unique_ptr<SparkyContext> sparky_context,
-    SparkyShowAnswerCallback done_callback,
-    manta::MantaStatus status,
-    std::vector<FileData> files_data) {
-  if (!files_data.empty()) {
-    sparky_context->files = std::move(files_data);
-    QuestionAndAnswer(std::move(sparky_context), std::move(done_callback));
-  } else {
-    std::move(done_callback).Run(status, nullptr);
-  }
-}
-
-}  // namespace manta
diff --git a/components/manta/sparky/sparky_provider.h b/components/manta/sparky/sparky_provider.h
deleted file mode 100644
index 32c489ed9..0000000
--- a/components/manta/sparky/sparky_provider.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MANTA_SPARKY_SPARKY_PROVIDER_H_
-#define COMPONENTS_MANTA_SPARKY_SPARKY_PROVIDER_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/functional/callback_forward.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/scoped_observation.h"
-#include "components/endpoint_fetcher/endpoint_fetcher.h"
-#include "components/manta/base_provider.h"
-#include "components/manta/manta_service_callbacks.h"
-#include "components/manta/manta_status.h"
-#include "components/manta/proto/manta.pb.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/provider_params.h"
-#include "components/manta/sparky/sparky_context.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/sparky_util.h"
-#include "components/manta/sparky/system_info_delegate.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "url/gurl.h"
-
-namespace manta {
-
-// The Sparky provider for the Manta project. Provides a method for clients to
-// call the relevant google API, handling OAuth and http fetching.
-// IMPORTANT: This class depends on `IdentityManager`.
-// `SparkyProvider::Call` will return an empty response after `IdentityManager`
-// destruction.
-class COMPONENT_EXPORT(MANTA) SparkyProvider : virtual public BaseProvider {
- public:
-  // Returns a `SparkyProvider` instance tied to the profile of the passed
-  // arguments.
-  SparkyProvider(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      signin::IdentityManager* identity_manager,
-      const ProviderParams& provider_params,
-      std::unique_ptr<SparkyDelegate> sparky_delegate,
-      std::unique_ptr<SystemInfoDelegate> system_info_delegate);
-
-  SparkyProvider(const SparkyProvider&) = delete;
-  SparkyProvider& operator=(const SparkyProvider&) = delete;
-
-  ~SparkyProvider() override;
-
-  using SparkyShowAnswerCallback =
-      base::OnceCallback<void(MantaStatus, proto::Turn*)>;
-
-  using SparkyProtoResponseCallback =
-      base::OnceCallback<void(std::unique_ptr<manta::proto::SparkyResponse>,
-                              MantaStatus)>;
-
-  void QuestionAndAnswer(std::unique_ptr<SparkyContext> sparky_context,
-                         SparkyShowAnswerCallback done_callback);
-
-  std::vector<manta::FileData> GetFilesSummary();
-
-  // Clears the previous dialogs stored in memory.
-  void ClearDialog();
-
-  // Assign the last action as all done to prevent any additional calls to the
-  // server.
-  void MarkLastActionAllDone();
-
-  int consecutive_assistant_turn_count() {
-    return consecutive_assistant_turn_count_;
-  }
-
-  bool is_additional_call_expected() { return is_additional_call_expected_; }
-
- protected:
-  SparkyProvider(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      signin::IdentityManager* identity_manager,
-      std::unique_ptr<SparkyDelegate> sparky_delegate,
-      std::unique_ptr<SystemInfoDelegate> system_info_delegate);
-
- private:
-  friend class FakeSparkyProvider;
-
-  // Called if more information is requested from the client. It will make an
-  // additional call to QuestionAndAnswer.
-  void RequestAdditionalInformation(
-      proto::ContextRequest,
-      std::unique_ptr<SparkyContext> sparky_context,
-      SparkyShowAnswerCallback done_callback,
-      manta::MantaStatus status);
-
-  void OnScreenshotObtained(
-      std::unique_ptr<SparkyContext> sparky_context,
-      SparkyShowAnswerCallback done_callback,
-      scoped_refptr<base::RefCountedMemory> png_screenshot);
-
-  void OnResponseReceived(
-      SparkyShowAnswerCallback done_callback,
-      std::unique_ptr<SparkyContext> sparky_context,
-      std::unique_ptr<proto::SparkyResponse> sparky_response,
-      manta::MantaStatus status);
-
-  // If the response back is a dialog response with a message to show to the
-  // user and potentially actions.
-  void OnDialogResponse(std::unique_ptr<SparkyContext> sparky_context,
-                        proto::Turn latest_reply,
-                        SparkyShowAnswerCallback done_callback,
-                        manta::MantaStatus status);
-
-  void OnStorageReceived(std::unique_ptr<SparkyContext> sparky_context,
-                         SparkyShowAnswerCallback done_callback,
-                         manta::MantaStatus status,
-                         std::vector<Diagnostics> diagnostics_vector,
-                         std::unique_ptr<StorageData> storage_data);
-
-  void OnFilesObtained(std::unique_ptr<SparkyContext> sparky_context,
-                       SparkyShowAnswerCallback done_callback,
-                       manta::MantaStatus status,
-                       std::vector<FileData> files_data);
-
-  void OnDiagnosticsReceived(std::unique_ptr<SparkyContext> sparky_context,
-                             SparkyShowAnswerCallback done_callback,
-                             manta::MantaStatus status,
-                             std::unique_ptr<StorageData> storage_data,
-                             std::unique_ptr<DiagnosticsData> diagnostics_data);
-
-  // Stores the dialog of the question and answers along with any associated
-  // actions.
-  proto::Request request_;
-
-  // Number of consecutive assistant turns at the end of `request_`.
-  int consecutive_assistant_turn_count_ = 0;
-
-  // Boolean indicate if an extra server request is required. It's updated
-  // whenever a new agent response is received, the turn limit is reached or a
-  // new conversation is started.
-  bool is_additional_call_expected_ = false;
-
-  std::unique_ptr<SparkyDelegate> sparky_delegate_;
-  std::unique_ptr<SystemInfoDelegate> system_info_delegate_;
-  base::WeakPtrFactory<SparkyProvider> weak_ptr_factory_{this};
-};
-
-}  // namespace manta
-
-#endif  // COMPONENTS_MANTA_SPARKY_SPARKY_PROVIDER_H_
diff --git a/components/manta/sparky/sparky_provider_unittest.cc b/components/manta/sparky/sparky_provider_unittest.cc
deleted file mode 100644
index 003382d..0000000
--- a/components/manta/sparky/sparky_provider_unittest.cc
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/sparky_provider.h"
-
-#include <memory>
-#include <optional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/strings/stringprintf.h"
-#include "base/test/bind.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/task_environment.h"
-#include "base/time/time.h"
-#include "components/manta/base_provider.h"
-#include "components/manta/base_provider_test_helper.h"
-#include "components/manta/manta_status.h"
-#include "components/manta/proto/manta.pb.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_context.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/sparky_util.h"
-#include "components/manta/sparky/system_info_delegate.h"
-#include "components/signin/public/base/consent_level.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
-#include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_status_code.h"
-#include "net/http/http_util.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace manta {
-
-namespace {
-constexpr char kMockEndpoint[] = "https://my-endpoint.com";
-}  // namespace
-
-class FakeSparkyDelegate : public SparkyDelegate {
- public:
-  FakeSparkyDelegate() {
-    current_prefs_ = SettingsDataList();
-    current_prefs_["ash.dark_mode.enabled"] = std::make_unique<SettingsData>(
-        "ash.dark_mode.enabled", PrefType::kBoolean,
-        std::make_optional<base::Value>(true));
-    current_prefs_["power.adaptive_charging_enabled"] =
-        std::make_unique<SettingsData>("power.adaptive_charging_enabled",
-                                       PrefType::kBoolean,
-                                       std::make_optional<base::Value>(false));
-    current_prefs_["ash.night_light.enabled"] = std::make_unique<SettingsData>(
-        "ash.night_light.enabled", PrefType::kBoolean,
-        std::make_optional<base::Value>(false));
-    current_prefs_["ash.night_light.color_temperature"] =
-        std::make_unique<SettingsData>("ash.night_light.color_temperature",
-                                       PrefType::kDouble,
-                                       std::make_optional<base::Value>(0.1));
-  }
-
-  // manta::SparkyDelegate
-  bool SetSettings(std::unique_ptr<SettingsData> settings_data) override {
-    current_prefs_[settings_data->pref_name] = std::make_unique<SettingsData>(
-        settings_data->pref_name, settings_data->pref_type,
-        settings_data->GetValue());
-    return true;
-  }
-  SettingsDataList* GetSettingsList() override {
-    if (current_prefs_.empty()) {
-      return nullptr;
-    } else {
-      return &current_prefs_;
-    }
-  }
-  std::optional<base::Value> GetSettingValue(
-      const std::string& setting_id) override {
-    if (current_prefs_.contains(setting_id)) {
-      return current_prefs_[setting_id]->GetValue();
-    } else {
-      return std::nullopt;
-    }
-  }
-  void GetScreenshot(ScreenshotDataCallback callback) override {
-    std::move(callback).Run(nullptr);
-  }
-  std::vector<AppsData> GetAppsList() override { return {}; }
-  void LaunchApp(const std::string& app_id) override {}
-  void Click(int x, int y) override {}
-  void KeyboardEntry(std::string text) override {}
-  void KeyPress(const std::string& key,
-                bool control,
-                bool alt,
-                bool shift) override {}
-  void GetMyFiles(FilesDataCallback callback,
-                  bool obtain_bytes,
-                  std::set<std::string> allowed_file_paths) override {}
-  void LaunchFile(const std::string& file_path) override {}
-  void WriteFile(const std::string& name, const std::string& bytes) override {}
-
-  void ObtainStorageInfo(StorageDataCallback storage_callback) override {
-    std::move(storage_callback)
-        .Run(std::make_unique<manta::StorageData>("78 GB", "128 GB"));
-  }
-
-  void UpdateFileSummaries(
-      const std::vector<manta::FileData>& files_with_summary) override {}
-  std::vector<manta::FileData> GetFileSummaries() override {
-    std::vector<manta::FileData> files;
-    return files;
-  }
-
- private:
-  SettingsDataList current_prefs_;
-};
-
-class FakeSystemInfoDelegate : public SystemInfoDelegate {
- public:
-  FakeSystemInfoDelegate() = default;
-
-  // TODO (b:340963863) Build out this fake component.
-  // manta::SystemInfoDelegate
-  void ObtainDiagnostics(
-      const std::vector<manta::Diagnostics>& diagnostics,
-      manta::DiagnosticsDataCallback diagnostics_callback) override {
-    std::move(diagnostics_callback).Run(nullptr);
-  }
-};
-
-class FakeSparkyProvider : public SparkyProvider, public FakeBaseProvider {
- public:
-  FakeSparkyProvider(
-      scoped_refptr<network::SharedURLLoaderFactory> test_url_loader_factory,
-      signin::IdentityManager* identity_manager)
-      : BaseProvider(test_url_loader_factory, identity_manager),
-        SparkyProvider(test_url_loader_factory,
-                       identity_manager,
-                       std::make_unique<FakeSparkyDelegate>(),
-                       std::make_unique<FakeSystemInfoDelegate>()),
-        FakeBaseProvider(test_url_loader_factory, identity_manager) {}
-
-  std::optional<base::Value> CheckSettingValue(const std::string& setting_id) {
-    return sparky_delegate_->GetSettingValue(setting_id)->Clone();
-  }
-};
-
-class SparkyProviderTest : public BaseProviderTest {
- public:
-  SparkyProviderTest() = default;
-
-  SparkyProviderTest(const SparkyProviderTest&) = delete;
-  SparkyProviderTest& operator=(const SparkyProviderTest&) = delete;
-
-  ~SparkyProviderTest() override = default;
-
-  std::unique_ptr<FakeSparkyProvider> CreateSparkyProvider() {
-    return std::make_unique<FakeSparkyProvider>(
-        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-            &test_url_loader_factory_),
-        identity_test_env_->identity_manager());
-  }
-};
-
-// Test that string answer response is correctly passed to the callback.
-TEST_F(SparkyProviderTest, SimpleRequestPayload) {
-  base::HistogramTester histogram_tester;
-  manta::proto::Response response;
-  manta::proto::OutputData& output_data = *response.add_output_data();
-  manta::proto::SparkyResponse& sparky_response =
-      *output_data.mutable_sparky_response();
-  auto* latest_reply = sparky_response.mutable_latest_reply();
-  latest_reply->set_message("text answer");
-  latest_reply->set_role(proto::ROLE_ASSISTANT);
-
-  std::string response_data;
-  response.SerializeToString(&response_data);
-
-  SetEndpointMockResponse(GURL{kMockEndpoint}, response_data, net::HTTP_OK,
-                          net::OK);
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-  auto quit_closure = task_environment_.QuitClosure();
-
-  proto::Turn new_turn = CreateTurn("When is it?", proto::Role::ROLE_USER);
-
-  sparky_provider->QuestionAndAnswer(
-      std::make_unique<SparkyContext>(new_turn, "page content"),
-      base::BindLambdaForTesting(
-          [&quit_closure](MantaStatus manta_status, proto::Turn* latest_turn) {
-            ASSERT_EQ(manta_status.status_code, MantaStatusCode::kOk);
-            ASSERT_EQ("text answer", latest_turn->message());
-            quit_closure.Run();
-          }));
-  task_environment_.RunUntilQuit();
-
-  // Metric is logged when response is successfully parsed.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    1);
-}
-
-// Tests that the return string is empty if the returned proto does not contain
-// a custom sparky response.
-TEST_F(SparkyProviderTest, EmptyResponseIfSparkyDataIsNotSet) {
-  base::HistogramTester histogram_tester;
-  manta::proto::Response response;
-  manta::proto::OutputData& output_data = *response.add_output_data();
-  output_data.set_text("text response");
-
-  std::string response_data;
-  response.SerializeToString(&response_data);
-
-  proto::Turn new_turn = CreateTurn("my question", proto::Role::ROLE_USER);
-
-  SetEndpointMockResponse(GURL{kMockEndpoint}, response_data, net::HTTP_OK,
-                          net::OK);
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-  auto quit_closure = task_environment_.QuitClosure();
-
-  sparky_provider->QuestionAndAnswer(
-      std::make_unique<SparkyContext>(new_turn, "page content"),
-      base::BindLambdaForTesting([&quit_closure](MantaStatus manta_status,
-                                                 proto::Turn* latest_turn) {
-        ASSERT_EQ(manta_status.status_code, MantaStatusCode::kBlockedOutputs);
-        ASSERT_FALSE(latest_turn);
-        quit_closure.Run();
-      }));
-  task_environment_.RunUntilQuit();
-
-  // Metric is logged when response is successfully parsed.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    1);
-}
-
-TEST_F(SparkyProviderTest, EmptyResponseAfterIdentityManagerShutdown) {
-  base::HistogramTester histogram_tester;
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-
-  identity_test_env_.reset();
-
-  proto::Turn new_turn = CreateTurn("my question", proto::Role::ROLE_USER);
-
-  auto quit_closure = task_environment_.QuitClosure();
-
-  sparky_provider->QuestionAndAnswer(
-      std::make_unique<SparkyContext>(new_turn, "page content"),
-      base::BindLambdaForTesting(
-          [&quit_closure](MantaStatus manta_status, proto::Turn* latest_turn) {
-            ASSERT_EQ(manta_status.status_code,
-                      MantaStatusCode::kNoIdentityManager);
-            ASSERT_FALSE(latest_turn);
-            quit_closure.Run();
-          }));
-  task_environment_.RunUntilQuit();
-
-  // No metric logged.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    0);
-}
-
-// Test that setting actions can be executed if requested in the response.
-TEST_F(SparkyProviderTest, SettingAction) {
-  base::HistogramTester histogram_tester;
-  manta::proto::Response response;
-  manta::proto::OutputData& output_data = *response.add_output_data();
-  manta::proto::SparkyResponse& sparky_response =
-      *output_data.mutable_sparky_response();
-
-  auto* latest_reply = sparky_response.mutable_latest_reply();
-  latest_reply->set_message("text answer");
-  latest_reply->set_role(proto::ROLE_ASSISTANT);
-  auto* action = latest_reply->add_action();
-  auto* setting_data = action->mutable_update_setting();
-  setting_data->set_type(proto::SETTING_TYPE_BOOL);
-  setting_data->set_settings_id("power.adaptive_charging_enabled");
-  auto* settings_value = setting_data->mutable_value();
-  settings_value->set_bool_val(true);
-
-  std::string response_data;
-  response.SerializeToString(&response_data);
-
-  proto::Turn new_turn =
-      CreateTurn("Turn on adaptive charging", proto::Role::ROLE_USER);
-
-  SetEndpointMockResponse(GURL{kMockEndpoint}, response_data, net::HTTP_OK,
-                          net::OK);
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-
-  auto quit_closure = task_environment_.QuitClosure();
-
-  ASSERT_EQ(false, sparky_provider
-                       ->CheckSettingValue("power.adaptive_charging_enabled")
-                       ->GetBool());
-
-  auto sparky_context =
-      std::make_unique<SparkyContext>(new_turn, "page content");
-  sparky_context->task = proto::Task::TASK_SETTINGS;
-
-  sparky_provider->QuestionAndAnswer(
-      std::move(sparky_context),
-      base::BindLambdaForTesting(
-          [&quit_closure](MantaStatus manta_status, proto::Turn* latest_turn) {
-            ASSERT_EQ(manta_status.status_code, MantaStatusCode::kOk);
-            ASSERT_EQ("text answer", latest_turn->message());
-            quit_closure.Run();
-          }));
-  task_environment_.RunUntilQuit();
-
-  ASSERT_EQ(true, sparky_provider
-                      ->CheckSettingValue("power.adaptive_charging_enabled")
-                      ->GetBool());
-
-  // Metric is logged when response is successfully parsed.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    1);
-}
-
-// Test that sparky response with multiple actions is correctly executed and the
-// final string is passed to the callback.
-TEST_F(SparkyProviderTest, SettingActionWith2Actions) {
-  base::HistogramTester histogram_tester;
-  manta::proto::Response response;
-  manta::proto::OutputData& output_data = *response.add_output_data();
-  manta::proto::SparkyResponse& sparky_response =
-      *output_data.mutable_sparky_response();
-
-  auto* latest_reply = sparky_response.mutable_latest_reply();
-  latest_reply->set_message("text answer");
-  latest_reply->set_role(proto::ROLE_ASSISTANT);
-  auto* action = latest_reply->add_action();
-  auto* setting_data = action->mutable_update_setting();
-  setting_data->set_type(proto::SETTING_TYPE_BOOL);
-  setting_data->set_settings_id("ash.night_light.enabled");
-  auto* settings_value = setting_data->mutable_value();
-  settings_value->set_bool_val(true);
-  auto* action2 = latest_reply->add_action();
-  auto* double_setting = action2->mutable_update_setting();
-  double_setting->set_type(proto::SETTING_TYPE_DOUBLE);
-  double_setting->set_settings_id("ash.night_light.color_temperature");
-  auto* double_value = double_setting->mutable_value();
-  double_value->set_double_val(0.5);
-
-  std::string response_data;
-  response.SerializeToString(&response_data);
-
-  SetEndpointMockResponse(GURL{kMockEndpoint}, response_data, net::HTTP_OK,
-                          net::OK);
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-
-  proto::Turn new_turn =
-      CreateTurn("Turn on night light", proto::Role::ROLE_USER);
-  auto quit_closure = task_environment_.QuitClosure();
-
-  ASSERT_EQ(
-      false,
-      sparky_provider->CheckSettingValue("ash.night_light.enabled")->GetBool());
-  ASSERT_EQ(0.1, sparky_provider
-                     ->CheckSettingValue("ash.night_light.color_temperature")
-                     ->GetDouble());
-
-  auto sparky_context =
-      std::make_unique<SparkyContext>(new_turn, "page content");
-  sparky_context->task = proto::Task::TASK_SETTINGS;
-
-  sparky_provider->QuestionAndAnswer(
-      std::move(sparky_context),
-      base::BindLambdaForTesting(
-          [&quit_closure](MantaStatus manta_status, proto::Turn* latest_turn) {
-            ASSERT_EQ(manta_status.status_code, MantaStatusCode::kOk);
-            ASSERT_EQ("text answer", latest_turn->message());
-            quit_closure.Run();
-          }));
-  task_environment_.RunUntilQuit();
-
-  ASSERT_EQ(
-      true,
-      sparky_provider->CheckSettingValue("ash.night_light.enabled")->GetBool());
-  ASSERT_EQ(0.5, sparky_provider
-                     ->CheckSettingValue("ash.night_light.color_temperature")
-                     ->GetDouble());
-
-  // Metric is logged when response is successfully parsed.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    1);
-}
-
-// Test that the returned callback is empty if the settings are not defined
-// correctly.
-TEST_F(SparkyProviderTest, SettingActionInvalidProto) {
-  base::HistogramTester histogram_tester;
-  manta::proto::Response response;
-  manta::proto::OutputData& output_data = *response.add_output_data();
-  manta::proto::SparkyResponse& sparky_response =
-      *output_data.mutable_sparky_response();
-
-  auto* latest_reply = sparky_response.mutable_latest_reply();
-  latest_reply->set_message("text answer");
-  latest_reply->set_role(proto::ROLE_ASSISTANT);
-  auto* action = latest_reply->add_action();
-  auto* setting_data = action->mutable_update_setting();
-  setting_data->set_type(proto::SETTING_TYPE_BOOL);
-  setting_data->set_settings_id("power.adaptive_charging_enabled");
-  auto* settings_value = setting_data->mutable_value();
-  // Int value set for setting of type bool.
-  settings_value->set_int_val(3);
-
-  std::string response_data;
-  response.SerializeToString(&response_data);
-
-  proto::Turn new_turn =
-      CreateTurn("Turn on adaptive charging", proto::Role::ROLE_USER);
-
-  SetEndpointMockResponse(GURL{kMockEndpoint}, response_data, net::HTTP_OK,
-                          net::OK);
-  std::unique_ptr<FakeSparkyProvider> sparky_provider = CreateSparkyProvider();
-
-  auto quit_closure = task_environment_.QuitClosure();
-  auto sparky_context =
-      std::make_unique<SparkyContext>(new_turn, "page content");
-  sparky_context->task = proto::Task::TASK_SETTINGS;
-  sparky_provider->QuestionAndAnswer(
-      std::move(sparky_context),
-      base::BindLambdaForTesting(
-          [&quit_closure](MantaStatus manta_status, proto::Turn* latest_turn) {
-            ASSERT_EQ(manta_status.status_code, MantaStatusCode::kOk);
-            ASSERT_FALSE(latest_turn);
-            quit_closure.Run();
-          }));
-  task_environment_.RunUntilQuit();
-
-  // Metric is logged when response is successfully parsed.
-  histogram_tester.ExpectTotalCount("Ash.MantaService.SparkyProvider.TimeCost",
-                                    1);
-}
-
-}  // namespace manta
diff --git a/components/manta/sparky/sparky_util.cc b/components/manta/sparky/sparky_util.cc
deleted file mode 100644
index 5384dc4..0000000
--- a/components/manta/sparky/sparky_util.cc
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/sparky_util.h"
-
-#include <memory>
-#include <optional>
-
-#include "base/containers/fixed_flat_map.h"
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_delegate.h"
-
-namespace manta {
-namespace {
-using SettingType = proto::SettingType;
-
-static constexpr auto pref_to_setting_map =
-    base::MakeFixedFlatMap<PrefType, SettingType>({
-        {PrefType::kBoolean, SettingType::SETTING_TYPE_BOOL},
-        {PrefType::kString, SettingType::SETTING_TYPE_STRING},
-        {PrefType::kDouble, SettingType::SETTING_TYPE_DOUBLE},
-        {PrefType::kInt, SettingType::SETTING_TYPE_INTEGER},
-    });
-
-static constexpr auto setting_to_pref_map =
-    base::MakeFixedFlatMap<SettingType, PrefType>({
-        {SettingType::SETTING_TYPE_BOOL, PrefType::kBoolean},
-        {SettingType::SETTING_TYPE_STRING, PrefType::kString},
-        {SettingType::SETTING_TYPE_DOUBLE, PrefType::kDouble},
-        {SettingType::SETTING_TYPE_INTEGER, PrefType::kInt},
-    });
-
-static constexpr auto role_to_proto_map =
-    base::MakeFixedFlatMap<Role, proto::Role>({
-        {Role::kAssistant, proto::Role::ROLE_ASSISTANT},
-        {Role::kUser, proto::Role::ROLE_USER},
-    });
-
-static constexpr auto diagnostic_map =
-    base::MakeFixedFlatMap<manta::proto::Diagnostics, Diagnostics>(
-        {{manta::proto::Diagnostics::DIAGNOSTICS_BATTERY,
-          Diagnostics::kBattery},
-         {manta::proto::Diagnostics::DIAGNOSTICS_CPU, Diagnostics::kCpu},
-         {manta::proto::Diagnostics::DIAGNOSTICS_STORAGE,
-          Diagnostics::kStorage},
-         {manta::proto::Diagnostics::DIAGNOSTICS_MEMORY,
-          Diagnostics::kMemory}});
-
-// Gets the type of setting into the proto enum. Also verifies that the value is
-// of the type specified.
-std::optional<SettingType> VerifyValueAndConvertPrefTypeToSettingType(
-    PrefType pref_type,
-    std::optional<base::Value> value) {
-  if (!value) {
-    return std::nullopt;
-  }
-  const auto iter = pref_to_setting_map.find(pref_type);
-
-  auto type = iter != pref_to_setting_map.end()
-                  ? std::optional<SettingType>(iter->second)
-                  : std::nullopt;
-  if (!type.has_value()) {
-    return std::nullopt;
-  }
-  if ((pref_type == PrefType::kBoolean && value->is_bool()) ||
-      (pref_type == PrefType::kDouble && value->is_double()) ||
-      (pref_type == PrefType::kInt && value->is_int()) ||
-      (pref_type == PrefType::kString && value->is_string())) {
-    return type;
-  }
-
-  return std::nullopt;
-}
-
-// Converts the setting proto into the pref type. Also verifies that the value
-// is of the type specified.
-std::optional<PrefType> VerifyValueAndConvertSettingTypeToPrefType(
-    SettingType setting_type,
-    const proto::SettingsValue& value) {
-  const auto iter = setting_to_pref_map.find(setting_type);
-
-  auto type = iter != setting_to_pref_map.end()
-                  ? std::optional<PrefType>(iter->second)
-                  : std::nullopt;
-  if (!type.has_value()) {
-    return std::nullopt;
-  }
-  if ((type.value() == PrefType::kBoolean && value.has_bool_val()) ||
-      (type.value() == PrefType::kDouble && value.has_double_val()) ||
-      (type.value() == PrefType::kInt && value.has_int_val()) ||
-      (type.value() == PrefType::kString && value.has_text_val())) {
-    return type;
-  }
-
-  return std::nullopt;
-}
-
-std::optional<base::Value> GetSettingsValue(proto::SettingsValue value,
-                                            const PrefType& pref_type) {
-  if (pref_type == PrefType::kBoolean) {
-    return std::make_optional(base::Value(value.bool_val()));
-  } else if (pref_type == PrefType::kInt) {
-    return std::make_optional(base::Value(value.int_val()));
-  } else if (pref_type == PrefType::kDouble) {
-    return std::make_optional(base::Value(value.double_val()));
-  } else if (pref_type == PrefType::kString) {
-    return std::make_optional(base::Value(value.text_val()));
-  } else {
-    return std::nullopt;
-  }
-}
-
-}  // namespace
-
-LaunchFile::LaunchFile(std::string launch_file_path)
-    : launch_file_path(launch_file_path) {}
-LaunchFile::~LaunchFile() = default;
-
-LaunchFile::LaunchFile(const LaunchFile&) = default;
-LaunchFile& LaunchFile::operator=(const LaunchFile&) = default;
-
-ClickAction::ClickAction(int x_pos, int y_pos) : x_pos(x_pos), y_pos(y_pos) {}
-ClickAction::~ClickAction() = default;
-
-ClickAction::ClickAction(const ClickAction&) = default;
-ClickAction& ClickAction::operator=(const ClickAction&) = default;
-
-Action::Action(SettingsData updated_setting)
-    : updated_setting(std::make_optional(updated_setting)),
-      type(ActionType::kSetting) {}
-Action::Action(bool all_done)
-    : type(ActionType::kAllDone), all_done(all_done) {}
-Action::Action(ClickAction click)
-    : click(std::make_optional(click)), type(ActionType::kClick) {}
-Action::Action(ActionType type) : type(type) {}
-Action::Action(LaunchFile launch_file, ActionType type)
-    : launch_file(std::make_optional(launch_file)), type(type) {}
-Action::~Action() = default;
-
-Action::Action(const Action&) = default;
-Action& Action::operator=(const Action&) = default;
-
-proto::Role GetRole(Role role) {
-  const auto iter = role_to_proto_map.find(role);
-  return iter != role_to_proto_map.end() ? iter->second
-                                         : proto::ROLE_UNSPECIFIED;
-}
-
-void AddSettingProto(const SettingsData& setting,
-                     ::manta::proto::Setting* setting_proto,
-                     SettingType setting_type) {
-  setting_proto->set_type(setting_type);
-  setting_proto->set_settings_id(setting.pref_name);
-  auto* settings_value = setting_proto->mutable_value();
-  if (setting.pref_type == PrefType::kBoolean) {
-    settings_value->set_bool_val(setting.bool_val);
-  } else if (setting.pref_type == PrefType::kDouble) {
-    settings_value->set_double_val(setting.double_val);
-  } else if (setting.pref_type == PrefType::kInt) {
-    settings_value->set_int_val(setting.int_val);
-  } else if (setting.pref_type == PrefType::kString) {
-    settings_value->set_text_val(setting.string_val);
-  }
-}
-
-void AddSettingsProto(const SparkyDelegate::SettingsDataList& settings_list,
-                      ::manta::proto::SettingsData* settings_data) {
-  for (auto const& [pref_name, setting] : settings_list) {
-    auto setting_type = VerifyValueAndConvertPrefTypeToSettingType(
-        setting->pref_type, setting->GetValue());
-    if (setting_type == std::nullopt) {
-      DVLOG(1) << "Invalid setting type for" << setting->pref_name;
-      continue;
-    }
-    auto* setting_data = settings_data->add_setting();
-    AddSettingProto(*setting, setting_data, setting_type.value());
-  }
-}
-
-std::vector<Diagnostics> COMPONENT_EXPORT(MANTA)
-    ObtainDiagnosticsVectorFromProto(
-        const ::manta::proto::DiagnosticsRequest& diagnostics_request) {
-  int number_of_diagnostics_requested = diagnostics_request.diagnostics_size();
-  std::vector<Diagnostics> diagnostics_vector;
-  for (int index = 0; index < number_of_diagnostics_requested; index++) {
-    const auto iter =
-        diagnostic_map.find(diagnostics_request.diagnostics(index));
-
-    auto type = iter != diagnostic_map.end()
-                    ? std::optional<Diagnostics>(iter->second)
-                    : std::nullopt;
-    if (type == std::nullopt) {
-      DVLOG(1) << "Invalid diagnostics type";
-      continue;
-    } else {
-      diagnostics_vector.emplace_back(type.value());
-    }
-  }
-  return diagnostics_vector;
-}
-
-void COMPONENT_EXPORT(MANTA)
-    AddDiagnosticsProto(std::optional<DiagnosticsData> diagnostics_data,
-                        proto::DiagnosticsData* diagnostics_proto) {
-  if (diagnostics_data) {
-    if (diagnostics_data->cpu_data) {
-      auto* cpu_proto = diagnostics_proto->mutable_cpu();
-      cpu_proto->set_temperature(
-          diagnostics_data->cpu_data->average_cpu_temp_celsius);
-      cpu_proto->set_clock_speed_ghz(
-          diagnostics_data->cpu_data->scaling_current_frequency_ghz);
-      cpu_proto->set_cpu_usage_snapshot(
-          diagnostics_data->cpu_data->cpu_usage_percentage_snapshot);
-    }
-    if (diagnostics_data->memory_data) {
-      auto* memory_proto = diagnostics_proto->mutable_memory();
-      memory_proto->set_free_ram_gb(
-          diagnostics_data->memory_data->available_memory_gb);
-      memory_proto->set_total_ram_gb(
-          diagnostics_data->memory_data->total_memory_gb);
-    }
-    if (diagnostics_data->battery_data) {
-      auto* battery_proto = diagnostics_proto->mutable_battery();
-      battery_proto->set_battery_health(
-          diagnostics_data->battery_data->battery_wear_percentage);
-      battery_proto->set_battery_charge_percentage(
-          diagnostics_data->battery_data->battery_percentage);
-      battery_proto->set_cycle_count(
-          diagnostics_data->battery_data->cycle_count);
-      battery_proto->set_battery_time(
-          diagnostics_data->battery_data->power_time);
-    }
-    if (diagnostics_data->storage_data) {
-      auto* storage_proto = diagnostics_proto->mutable_storage();
-      storage_proto->set_free_storage(
-          diagnostics_data->storage_data->free_bytes);
-      storage_proto->set_total_storage(
-          diagnostics_data->storage_data->total_bytes);
-    }
-  }
-}
-
-void AddAppsData(base::span<const AppsData> apps_data,
-                 proto::AppsData* apps_proto) {
-  for (const manta::AppsData& app : apps_data) {
-    proto::App* app_proto = apps_proto->add_app();
-    app_proto->set_id(app.id);
-    app_proto->set_name(app.name);
-    app_proto->mutable_searchable_term()->Add(app.searchable_text.begin(),
-                                              app.searchable_text.end());
-  }
-}
-
-void AddFilesData(base::span<const FileData> files_data,
-                  proto::FilesData* files_proto) {
-  for (const manta::FileData& file : files_data) {
-    proto::File* file_proto = files_proto->add_files();
-    file_proto->set_name(file.name);
-    file_proto->set_path(file.path);
-    file_proto->set_date_modified(file.date_modified);
-    file_proto->set_size_in_bytes(file.size_in_bytes);
-    if (file.bytes.has_value()) {
-      file_proto->set_serialized_bytes(
-          std::string(file.bytes->begin(), file.bytes->end()));
-    }
-    if (!file.summary.empty()) {
-      file_proto->set_summary(file.summary);
-    }
-  }
-}
-
-std::unique_ptr<SettingsData> ObtainSettingFromProto(
-    proto::Setting setting_proto) {
-  auto pref_type = VerifyValueAndConvertSettingTypeToPrefType(
-      setting_proto.type(), setting_proto.value());
-  if (pref_type == std::nullopt) {
-    return nullptr;
-  }
-  return std::make_unique<SettingsData>(
-      setting_proto.settings_id(), *pref_type,
-      GetSettingsValue(setting_proto.value(), *pref_type));
-}
-
-std::set<std::string> COMPONENT_EXPORT(MANTA)
-    GetSelectedFilePaths(const proto::FileRequest& file_request) {
-  std::set<std::string> set_file_paths;
-  int file_size = file_request.paths_size();
-  for (int index = 0; index < file_size; index++) {
-    set_file_paths.emplace(file_request.paths(index));
-  }
-  return set_file_paths;
-}
-
-std::optional<FileData> GetFileFromProto(const proto::File& file_proto) {
-  if (!file_proto.has_name() || !file_proto.has_path() ||
-      !file_proto.has_date_modified() || !file_proto.has_size_in_bytes() ||
-      !file_proto.has_summary()) {
-    return std::nullopt;
-  }
-  auto file = std::make_optional<FileData>(file_proto.path(), file_proto.name(),
-                                           file_proto.date_modified());
-  file->summary = file_proto.summary();
-  file->size_in_bytes = file_proto.size_in_bytes();
-  if (file_proto.has_serialized_bytes()) {
-    file->bytes = std::vector<uint8_t>(file_proto.serialized_bytes().begin(),
-                                       file_proto.serialized_bytes().end());
-  }
-  return file;
-}
-
-std::vector<FileData> GetFileDataFromProto(
-    const proto::FilesData& files_proto) {
-  std::vector<FileData> files_data;
-  int proto_file_count = files_proto.files_size();
-  for (int index = 0; index < proto_file_count; ++index) {
-    auto file = GetFileFromProto(files_proto.files(index));
-    if (file.has_value()) {
-      files_data.emplace_back(std::move(file.value()));
-    }
-  }
-  return files_data;
-}
-
-proto::Turn CreateTurn(const std::string& message, manta::proto::Role role) {
-  manta::proto::Turn turn;
-  turn.set_message(message);
-  turn.set_role(role);
-  return turn;
-}
-
-}  // namespace manta
diff --git a/components/manta/sparky/sparky_util.h b/components/manta/sparky/sparky_util.h
deleted file mode 100644
index 35418ca..0000000
--- a/components/manta/sparky/sparky_util.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MANTA_SPARKY_SPARKY_UTIL_H_
-#define COMPONENTS_MANTA_SPARKY_SPARKY_UTIL_H_
-
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/span.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/system_info_delegate.h"
-
-namespace manta {
-
-enum class Role {
-  kUser = 0,
-  kAssistant = 1,
-  kMaxValue = kAssistant,
-};
-
-// TODO(b/351099209): This file can be removed as SparkyProvider now stores a
-// proto.
-
-enum class ActionType {
-  kSetting = 0,
-  kLaunchApp = 1,
-  kLaunchFile = 2,
-  kTextEntry = 3,
-  kClick = 4,
-  kAllDone = 5,
-  kMaxValue = kAllDone,
-};
-
-struct COMPONENT_EXPORT(MANTA) LaunchFile {
-  explicit LaunchFile(std::string launch_file_path);
-
-  ~LaunchFile();
-  LaunchFile(const LaunchFile&);
-  LaunchFile& operator=(const LaunchFile&);
-
-  std::string launch_file_path;
-};
-
-struct COMPONENT_EXPORT(MANTA) ClickAction {
-  ClickAction(int x_pos, int y_pos);
-
-  ~ClickAction();
-  ClickAction(const ClickAction&);
-  ClickAction& operator=(const ClickAction&);
-
-  int x_pos;
-  int y_pos;
-};
-
-struct COMPONENT_EXPORT(MANTA) Action {
-  explicit Action(SettingsData updated_setting);
-  explicit Action(ClickAction click);
-  Action(LaunchFile launch_file, ActionType type);
-  explicit Action(bool all_done);
-  explicit Action(ActionType type);
-
-  ~Action();
-  Action(const Action&);
-  Action& operator=(const Action&);
-
-  std::string launched_app;
-  std::optional<SettingsData> updated_setting;
-  std::optional<ClickAction> click;
-  std::string text_entry;
-  std::optional<LaunchFile> launch_file;
-  ActionType type;
-  bool all_done;
-};
-
-proto::Role COMPONENT_EXPORT(MANTA) GetRole(Role role);
-
-void COMPONENT_EXPORT(MANTA)
-    AddSettingProto(const SettingsData& setting,
-                    ::manta::proto::Setting* setting_proto,
-                    proto::SettingType setting_type);
-
-void COMPONENT_EXPORT(MANTA)
-    AddSettingsProto(const SparkyDelegate::SettingsDataList& settings_list,
-                     ::manta::proto::SettingsData* settings_data);
-
-std::vector<Diagnostics> COMPONENT_EXPORT(MANTA)
-    ObtainDiagnosticsVectorFromProto(
-        const ::manta::proto::DiagnosticsRequest& diagnostics_request);
-
-void COMPONENT_EXPORT(MANTA)
-    AddDiagnosticsProto(std::optional<DiagnosticsData> diagnostics_data,
-                        proto::DiagnosticsData* diagnostics_proto);
-
-void COMPONENT_EXPORT(MANTA) AddAppsData(base::span<const AppsData> apps_data,
-                                         proto::AppsData* apps_proto);
-
-std::unique_ptr<SettingsData> COMPONENT_EXPORT(MANTA)
-    ObtainSettingFromProto(proto::Setting setting_proto);
-
-void COMPONENT_EXPORT(MANTA) AddFilesData(base::span<const FileData> files_data,
-                                          proto::FilesData* files_proto);
-
-std::set<std::string> COMPONENT_EXPORT(MANTA)
-    GetSelectedFilePaths(const proto::FileRequest& file_request);
-
-std::optional<FileData> COMPONENT_EXPORT(MANTA)
-    GetFileFromProto(const proto::File& files_proto);
-
-std::vector<FileData> COMPONENT_EXPORT(MANTA)
-    GetFileDataFromProto(const proto::FilesData& files_proto);
-
-proto::Turn COMPONENT_EXPORT(MANTA)
-    CreateTurn(const std::string& message, manta::proto::Role role);
-
-}  // namespace manta
-
-#endif  // COMPONENTS_MANTA_SPARKY_SPARKY_UTIL_H_
diff --git a/components/manta/sparky/sparky_util_unittest.cc b/components/manta/sparky/sparky_util_unittest.cc
deleted file mode 100644
index f1a56041..0000000
--- a/components/manta/sparky/sparky_util_unittest.cc
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/sparky_util.h"
-
-#include <memory>
-#include <optional>
-
-#include "base/memory/ptr_util.h"
-#include "base/test/task_environment.h"
-#include "components/manta/proto/sparky.pb.h"
-#include "components/manta/sparky/sparky_delegate.h"
-#include "components/manta/sparky/system_info_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace manta {
-
-class SparkyUtilTest : public testing::Test {
- public:
-  SparkyUtilTest() = default;
-
-  SparkyUtilTest(const SparkyUtilTest&) = delete;
-  SparkyUtilTest& operator=(const SparkyUtilTest&) = delete;
-
-  ~SparkyUtilTest() override = default;
-
- protected:
-  base::test::TaskEnvironment task_environment_;
-
-  bool IsSameSetting(const proto::Setting& proto_setting,
-                     const SettingsData* settings_data) {
-    if (!settings_data->val_set) {
-      return false;
-    }
-    if (proto_setting.settings_id() == settings_data->pref_name &&
-        proto_setting.has_value()) {
-      if (proto_setting.type() == proto::SETTING_TYPE_BOOL) {
-        return (proto_setting.value().has_bool_val() &&
-                proto_setting.value().bool_val() == settings_data->bool_val);
-      } else if (proto_setting.type() == proto::SETTING_TYPE_STRING) {
-        return (
-            proto_setting.value().has_text_val() &&
-            (proto_setting.value().text_val() == settings_data->string_val));
-      } else if (proto_setting.type() == proto::SETTING_TYPE_INTEGER) {
-        return (proto_setting.value().has_int_val() &&
-                (proto_setting.value().int_val() == settings_data->int_val));
-      } else if (proto_setting.type() == proto::SETTING_TYPE_DOUBLE) {
-        EXPECT_DOUBLE_EQ(proto_setting.value().double_val(),
-                         settings_data->double_val);
-        return true;
-      }
-    }
-    return false;  // Settings do not match.
-  }
-
-  bool ContainsSetting(
-      const google::protobuf::RepeatedPtrField<proto::Setting>& repeatedField,
-      SettingsData* settings_data) {
-    for (const proto::Setting& proto_setting : repeatedField) {
-      if (IsSameSetting(proto_setting, settings_data)) {
-        return true;
-      }
-    }
-    return false;  // Did not find the setting.
-  }
-
-  bool ContainsApp(
-      const google::protobuf::RepeatedPtrField<proto::App>& repeated_field,
-      std::string_view name,
-      std::string_view id) {
-    for (const proto::App& proto_app : repeated_field) {
-      if (proto_app.id() == id && proto_app.name() == name) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool ContainsAction(const proto::Action& action_proto,
-                      std::vector<Action>* actions) {
-    for (const Action& action : *actions) {
-      if (action.updated_setting.has_value() &&
-          action_proto.has_update_setting()) {
-        if (IsSameSetting(action_proto.update_setting(),
-                          action.updated_setting.has_value()
-                              ? &action.updated_setting.value()
-                              : nullptr)) {
-          return true;
-        }
-      } else if (action.type == ActionType::kLaunchApp &&
-                 action_proto.has_launch_app_id()) {
-        if (action.launched_app == action_proto.launch_app_id()) {
-          return true;
-        }
-      } else if (action_proto.has_all_done() &&
-                 action.type == ActionType::kAllDone) {
-        return action_proto.all_done() == action.all_done;
-      } else if (action_proto.has_click() && action_proto.click().has_x_pos() &&
-                 action_proto.click().has_y_pos() &&
-                 action.type == ActionType::kClick) {
-        return action_proto.click().x_pos() == action.click->x_pos &&
-               action_proto.click().y_pos() == action.click->y_pos;
-      } else if (action_proto.has_text_entry() &&
-                 action_proto.text_entry().has_text() &&
-                 action.type == ActionType::kTextEntry) {
-        return action_proto.text_entry().text() == action.text_entry;
-      } else if (action_proto.has_launch_file() &&
-                 action_proto.launch_file().has_launch_file_path() &&
-                 action.type == ActionType::kLaunchFile) {
-        return action_proto.launch_file().launch_file_path() ==
-               action.launch_file->launch_file_path;
-      }
-    }
-    return false;
-  }
-
-  bool ContainsDialog(const ::google::protobuf::RepeatedPtrField<
-                          ::manta::proto::Turn>& dialog_repeated,
-                      const std::string& dialog,
-                      Role role,
-                      std::vector<Action>* actions) {
-    for (const proto::Turn& proto_dialog : dialog_repeated) {
-      if (proto_dialog.message() == dialog &&
-          proto_dialog.role() == GetRole(role)) {
-        if (actions) {
-          if ((int)actions->size() != proto_dialog.action_size()) {
-            return false;
-          }
-          auto actions_proto = proto_dialog.action();
-          for (const proto::Action& action_proto : actions_proto) {
-            if (!ContainsAction(action_proto, actions)) {
-              return false;
-            }
-          }
-        }
-        return true;
-      }
-    }
-    return false;
-  }
-
-  std::optional<proto::File> ObtainFileProto(
-      const google::protobuf::RepeatedPtrField<proto::File>& repeated_field,
-      std::string file_path) {
-    for (const proto::File& proto_file : repeated_field) {
-      if (proto_file.path() == file_path) {
-        return std::make_optional(proto_file);
-      }
-    }
-    return std::nullopt;
-  }
-};
-
-TEST_F(SparkyUtilTest, AddSettingsProto) {
-  auto current_prefs = SparkyDelegate::SettingsDataList();
-  current_prefs["ash.dark_mode.enabled"] = std::make_unique<SettingsData>(
-      "ash.dark_mode.enabled", PrefType::kBoolean,
-      std::make_optional<base::Value>(true));
-  current_prefs["string_pref"] = std::make_unique<SettingsData>(
-      "string_pref", PrefType::kString,
-      std::make_optional<base::Value>("my string"));
-  current_prefs["int_pref"] = std::make_unique<SettingsData>(
-      "int_pref", PrefType::kInt, std::make_optional<base::Value>(1));
-  current_prefs["ash.night_light.enabled"] = std::make_unique<SettingsData>(
-      "ash.night_light.enabled", PrefType::kBoolean,
-      std::make_optional<base::Value>(false));
-  current_prefs["ash.night_light.color_temperature"] =
-      std::make_unique<SettingsData>("ash.night_light.color_temperature",
-                                     PrefType::kDouble,
-                                     std::make_optional<base::Value>(0.1));
-  proto::SparkyContextData sparky_context_data;
-  manta::proto::SettingsData* settings_data =
-      sparky_context_data.mutable_settings_data();
-  AddSettingsProto(current_prefs, settings_data);
-  auto settings = settings_data->setting();
-  ASSERT_EQ(settings_data->setting_size(), 5);
-  ASSERT_TRUE(
-      ContainsSetting(settings, current_prefs["ash.dark_mode.enabled"].get()));
-  ASSERT_TRUE(ContainsSetting(settings, current_prefs["string_pref"].get()));
-  ASSERT_TRUE(ContainsSetting(settings,
-                              current_prefs["ash.night_light.enabled"].get()));
-  ASSERT_TRUE(ContainsSetting(
-      settings, current_prefs["ash.night_light.color_temperature"].get()));
-}
-
-TEST_F(SparkyUtilTest, AddDiagnosticsProto) {
-  auto cpu_data = std::make_optional<CpuData>(40, 60, 5.0);
-  auto memory_data = std::make_optional<MemoryData>(4.0, 8.0);
-  auto battery_data =
-      std::make_optional<BatteryData>(158, 76, "36 minutes until full", 80);
-  auto storage_data = std::make_optional<manta::StorageData>("78 GB", "128 GB");
-  std::optional<DiagnosticsData> diagnostics_data =
-      std::make_optional<DiagnosticsData>(
-          std::move(battery_data), std::move(cpu_data), std::move(memory_data),
-          std::move(storage_data));
-  proto::SparkyContextData sparky_context_data;
-  auto* diagnostics_proto = sparky_context_data.mutable_diagnostics_data();
-  AddDiagnosticsProto(std::move(diagnostics_data), diagnostics_proto);
-  ASSERT_TRUE(diagnostics_proto->has_battery());
-  ASSERT_TRUE(diagnostics_proto->has_cpu());
-  ASSERT_TRUE(diagnostics_proto->has_memory());
-  ASSERT_TRUE(diagnostics_proto->has_storage());
-
-  ASSERT_DOUBLE_EQ(diagnostics_proto->cpu().clock_speed_ghz(), 5.0);
-  ASSERT_EQ(diagnostics_proto->cpu().cpu_usage_snapshot(), 40);
-  ASSERT_EQ(diagnostics_proto->cpu().temperature(), 60);
-  ASSERT_DOUBLE_EQ(diagnostics_proto->memory().free_ram_gb(), 4.0);
-  ASSERT_DOUBLE_EQ(diagnostics_proto->memory().total_ram_gb(), 8.0);
-  ASSERT_EQ(diagnostics_proto->battery().battery_health(), 76);
-  ASSERT_EQ(diagnostics_proto->battery().battery_charge_percentage(), 80);
-  ASSERT_EQ(diagnostics_proto->battery().cycle_count(), 158);
-  ASSERT_EQ(diagnostics_proto->battery().battery_time(),
-            "36 minutes until full");
-  ASSERT_EQ(diagnostics_proto->storage().free_storage(), "78 GB");
-  ASSERT_EQ(diagnostics_proto->storage().total_storage(), "128 GB");
-}
-
-TEST_F(SparkyUtilTest, AddAppsData) {
-  std::vector<manta::AppsData> apps_data;
-  manta::AppsData app1 = AppsData("name1", "id1");
-  apps_data.emplace_back(std::move(app1));
-  manta::AppsData app2 = AppsData("name2", "id2");
-  app2.AddSearchableText("search_term1");
-  app2.AddSearchableText("search_term2");
-  apps_data.emplace_back(std::move(app2));
-
-  proto::SparkyContextData sparky_context_data;
-  manta::proto::AppsData* apps_proto = sparky_context_data.mutable_apps_data();
-  AddAppsData(std::move(apps_data), apps_proto);
-  auto apps = apps_proto->app();
-  ASSERT_EQ(apps_proto->app_size(), 2);
-  ASSERT_TRUE(ContainsApp(apps, "name2", "id2"));
-  ASSERT_TRUE(ContainsApp(apps, "name1", "id1"));
-}
-
-TEST_F(SparkyUtilTest, ObtainSettingFromProto) {
-  proto::Setting bool_setting_proto;
-  bool_setting_proto.set_type(proto::SETTING_TYPE_BOOL);
-  bool_setting_proto.set_settings_id("power.adaptive_charging_enabled");
-  auto* bool_settings_value = bool_setting_proto.mutable_value();
-  bool_settings_value->set_bool_val(true);
-  std::unique_ptr<SettingsData> bool_settings_data =
-      ObtainSettingFromProto(bool_setting_proto);
-  ASSERT_TRUE(IsSameSetting(bool_setting_proto, bool_settings_data.get()));
-
-  proto::Setting int_setting_proto;
-  int_setting_proto.set_type(proto::SETTING_TYPE_INTEGER);
-  int_setting_proto.set_settings_id("ash.int.setting");
-  auto* int_settings_value = int_setting_proto.mutable_value();
-  int_settings_value->set_int_val(2);
-  std::unique_ptr<SettingsData> int_settings_data =
-      ObtainSettingFromProto(int_setting_proto);
-  ASSERT_TRUE(IsSameSetting(int_setting_proto, int_settings_data.get()));
-
-  proto::Setting double_setting_proto;
-  double_setting_proto.set_type(proto::SETTING_TYPE_DOUBLE);
-  double_setting_proto.set_settings_id("ash.night_light.color_temperature");
-  auto* double_settings_value = double_setting_proto.mutable_value();
-  double_settings_value->set_double_val(0.5);
-  std::unique_ptr<SettingsData> double_settings_data =
-      ObtainSettingFromProto(double_setting_proto);
-  ASSERT_TRUE(IsSameSetting(double_setting_proto, double_settings_data.get()));
-
-  proto::Setting string_setting_proto;
-  string_setting_proto.set_type(proto::SETTING_TYPE_STRING);
-  string_setting_proto.set_settings_id("ash.string.setting");
-  auto* string_settings_value = string_setting_proto.mutable_value();
-  string_settings_value->set_text_val("my string");
-  std::unique_ptr<SettingsData> string_settings_data =
-      ObtainSettingFromProto(string_setting_proto);
-  ASSERT_TRUE(IsSameSetting(string_setting_proto, string_settings_data.get()));
-}
-
-TEST_F(SparkyUtilTest, AddFilesData) {
-  std::vector<manta::FileData> files_data;
-  auto file_1 = FileData("path1", "name1", "2024");
-  file_1.summary = "file 1 summary";
-  file_1.bytes =
-      std::make_optional(std::vector<uint8_t>({2, 4, 6, 7, 4, 7, 2, 8}));
-  file_1.size_in_bytes = 8L;
-
-  files_data.emplace_back(file_1);
-  files_data.emplace_back("path2", "name2", "2023");
-
-  proto::SparkyContextData sparky_context_data;
-  manta::proto::FilesData* files_proto =
-      sparky_context_data.mutable_files_data();
-  AddFilesData(std::move(files_data), files_proto);
-  auto files = files_proto->files();
-  ASSERT_EQ(files_proto->files_size(), 2);
-  std::optional<proto::File> proto_file_1 = ObtainFileProto(files, "path1");
-  ASSERT_TRUE(proto_file_1.has_value());
-  ASSERT_EQ(proto_file_1->name(), "name1");
-  ASSERT_EQ(proto_file_1->date_modified(), "2024");
-  ASSERT_EQ(proto_file_1->serialized_bytes(), "\x2\x4\x6\a\x4\a\x2\b");
-  ASSERT_EQ(proto_file_1->summary(), "file 1 summary");
-  std::optional<proto::File> proto_file_2 = ObtainFileProto(files, "path2");
-  ASSERT_TRUE(proto_file_2.has_value());
-  ASSERT_EQ(proto_file_2->name(), "name2");
-  ASSERT_EQ(proto_file_2->date_modified(), "2023");
-}
-
-TEST_F(SparkyUtilTest, GetSelectedFilePaths) {
-  proto::FileRequest file_request;
-
-  std::set<std::string> empty_set = GetSelectedFilePaths(file_request);
-  ASSERT_TRUE(empty_set.empty());
-
-  file_request.add_paths("my/file/path");
-  file_request.add_paths("my/second/file/path/");
-  std::set<std::string> file_set = GetSelectedFilePaths(file_request);
-  ASSERT_EQ(file_set.size(), 2u);
-  ASSERT_TRUE(file_set.contains("my/file/path"));
-  ASSERT_TRUE(file_set.contains("my/second/file/path/"));
-}
-
-TEST_F(SparkyUtilTest, GetFileDataFromProto) {
-  manta::proto::FilesData files_proto;
-  std::vector<FileData> empty_files_data = GetFileDataFromProto(files_proto);
-  EXPECT_TRUE(empty_files_data.empty());
-
-  manta::proto::File* file1 = files_proto.add_files();
-  file1->set_name("name1");
-  file1->set_path("my/file/path");
-  file1->set_summary("this file is a picture of a cat");
-  file1->set_date_modified("2024");
-  file1->set_size_in_bytes(823);
-
-  manta::proto::File* file2 = files_proto.add_files();
-  file2->set_name("name2");
-  file2->set_path("my/second/file/path/");
-  file2->set_summary("this file is a poem about a cat");
-  file2->set_date_modified("2023");
-  file2->set_size_in_bytes(94);
-
-  std::vector<FileData> files_data = GetFileDataFromProto(files_proto);
-  ASSERT_EQ(files_data.size(), 2u);
-  auto file1_data = files_data.at(0);
-  ASSERT_EQ(file1_data.name, "name1");
-  ASSERT_EQ(file1_data.path, "my/file/path");
-  ASSERT_EQ(file1_data.summary, "this file is a picture of a cat");
-  ASSERT_EQ(file1_data.date_modified, "2024");
-  ASSERT_EQ(file1_data.size_in_bytes, 823);
-}
-
-}  // namespace manta
diff --git a/components/manta/sparky/system_info_delegate.cc b/components/manta/sparky/system_info_delegate.cc
deleted file mode 100644
index 5f38f70f..0000000
--- a/components/manta/sparky/system_info_delegate.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/manta/sparky/system_info_delegate.h"
-
-#include <memory>
-#include <optional>
-
-namespace manta {
-
-StorageData::StorageData(const std::string& free_bytes,
-                         const std::string& total_bytes)
-    : free_bytes(free_bytes), total_bytes(total_bytes) {}
-
-StorageData::~StorageData() = default;
-StorageData::StorageData(const StorageData&) = default;
-StorageData& StorageData::operator=(const StorageData&) = default;
-
-BatteryData::BatteryData(int cycle_count,
-                         int battery_wear_percentage,
-                         const std::string& power_time,
-                         int battery_percentage)
-    : cycle_count(cycle_count),
-      battery_wear_percentage(battery_wear_percentage),
-      power_time(power_time),
-      battery_percentage(battery_percentage) {}
-
-BatteryData::~BatteryData() = default;
-
-BatteryData::BatteryData(const BatteryData&) = default;
-BatteryData& BatteryData::operator=(const BatteryData&) = default;
-
-CpuData::CpuData(int cpu_usage_percentage_snapshot,
-                 int average_cpu_temp_celsius,
-                 double scaling_current_frequency_ghz)
-    : cpu_usage_percentage_snapshot(cpu_usage_percentage_snapshot),
-      average_cpu_temp_celsius(average_cpu_temp_celsius),
-      scaling_current_frequency_ghz(scaling_current_frequency_ghz) {}
-
-CpuData::~CpuData() = default;
-
-CpuData::CpuData(const CpuData&) = default;
-CpuData& CpuData::operator=(const CpuData&) = default;
-
-MemoryData::MemoryData(double available_memory_gb, double total_memory_gb)
-    : available_memory_gb(available_memory_gb),
-      total_memory_gb(total_memory_gb) {}
-
-MemoryData::~MemoryData() = default;
-
-MemoryData::MemoryData(const MemoryData&) = default;
-MemoryData& MemoryData::operator=(const MemoryData&) = default;
-
-DiagnosticsData::DiagnosticsData(std::optional<BatteryData> battery_data,
-                                 std::optional<CpuData> cpu_data,
-                                 std::optional<MemoryData> memory_data,
-                                 std::optional<StorageData> storage_data)
-    : battery_data(std::move(battery_data)),
-      cpu_data(std::move(cpu_data)),
-      memory_data(std::move(memory_data)),
-      storage_data(std::move(storage_data)) {}
-
-DiagnosticsData::~DiagnosticsData() = default;
-
-DiagnosticsData::DiagnosticsData(const DiagnosticsData&) = default;
-DiagnosticsData& DiagnosticsData::operator=(const DiagnosticsData&) = default;
-
-SystemInfoDelegate::SystemInfoDelegate() = default;
-SystemInfoDelegate::~SystemInfoDelegate() = default;
-
-}  // namespace manta
diff --git a/components/manta/sparky/system_info_delegate.h b/components/manta/sparky/system_info_delegate.h
deleted file mode 100644
index e9a4c1c..0000000
--- a/components/manta/sparky/system_info_delegate.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MANTA_SPARKY_SYSTEM_INFO_DELEGATE_H_
-#define COMPONENTS_MANTA_SPARKY_SYSTEM_INFO_DELEGATE_H_
-
-#include <memory>
-
-#include "base/component_export.h"
-#include "base/functional/callback_forward.h"
-#include "base/observer_list_types.h"
-
-namespace manta {
-
-enum class Diagnostics { kBattery = 0, kCpu = 1, kStorage = 2, kMemory = 3 };
-
-struct COMPONENT_EXPORT(MANTA) StorageData {
-  std::string free_bytes;
-  std::string total_bytes;
-
-  StorageData(const std::string& free_bytes, const std::string& total_bytes);
-  ~StorageData();
-
-  StorageData(const StorageData&);
-  StorageData& operator=(const StorageData&);
-};
-
-struct COMPONENT_EXPORT(MANTA) BatteryData {
-  int cycle_count;
-  int battery_wear_percentage;
-  std::string power_time;
-  int battery_percentage;
-
-  BatteryData(int cycle_count,
-              int battery_wear_percentage,
-              const std::string& power_time,
-              int battery_percentage);
-  ~BatteryData();
-
-  BatteryData(const BatteryData&);
-  BatteryData& operator=(const BatteryData&);
-};
-
-struct COMPONENT_EXPORT(MANTA) CpuData {
-  int cpu_usage_percentage_snapshot;
-  int average_cpu_temp_celsius;
-  double scaling_current_frequency_ghz;
-
-  CpuData(int cpu_usage_percentage_snapshot,
-          int average_cpu_temp_celsius,
-          double scaling_current_frequency_ghz);
-
-  ~CpuData();
-
-  CpuData(const CpuData&);
-  CpuData& operator=(const CpuData&);
-};
-
-struct COMPONENT_EXPORT(MANTA) MemoryData {
-  double available_memory_gb;
-  double total_memory_gb;
-
-  MemoryData(double available_memory_gb, double total_memory_gb);
-
-  ~MemoryData();
-
-  MemoryData(const MemoryData&);
-  MemoryData& operator=(const MemoryData&);
-};
-
-struct COMPONENT_EXPORT(MANTA) DiagnosticsData {
-  std::optional<BatteryData> battery_data;
-  std::optional<CpuData> cpu_data;
-  std::optional<MemoryData> memory_data;
-  std::optional<StorageData> storage_data;
-
-  DiagnosticsData(std::optional<BatteryData> battery_data,
-                  std::optional<CpuData> cpu_data,
-                  std::optional<MemoryData> memory_data,
-                  std::optional<StorageData> storage_data);
-
-  ~DiagnosticsData();
-
-  DiagnosticsData(const DiagnosticsData&);
-  DiagnosticsData& operator=(const DiagnosticsData&);
-};
-
-using DiagnosticsDataCallback =
-    base::OnceCallback<void(std::unique_ptr<DiagnosticsData>)>;
-
-class COMPONENT_EXPORT(MANTA) SystemInfoDelegate {
- public:
-  SystemInfoDelegate();
-  SystemInfoDelegate(const SystemInfoDelegate&) = delete;
-  SystemInfoDelegate& operator=(const SystemInfoDelegate&) = delete;
-
-  virtual ~SystemInfoDelegate();
-
-  virtual void ObtainDiagnostics(
-      const std::vector<Diagnostics>& diagnostics,
-      DiagnosticsDataCallback diagnostics_callback) = 0;
-};
-
-}  // namespace manta
-
-#endif  // COMPONENTS_MANTA_SPARKY_SYSTEM_INFO_DELEGATE_H_
diff --git a/components/strings/components_strings_da.xtb b/components/strings/components_strings_da.xtb
index 4ddd164..97db64dd 100644
--- a/components/strings/components_strings_da.xtb
+++ b/components/strings/components_strings_da.xtb
@@ -2610,7 +2610,7 @@
 <translation id="5645132789250840550">Plast (halvblank)</translation>
 <translation id="5645719697465708351">Fest- og helligdagsartikler</translation>
 <translation id="5645854190134202180">Andet arbejdsskift</translation>
-<translation id="5648166631817621825">De seneste syv dage</translation>
+<translation id="5648166631817621825">De seneste 7 dage</translation>
 <translation id="5649053991847567735">Automatiske downloads</translation>
 <translation id="5651323159439184939">Traktorfremføring</translation>
 <translation id="5654927323611874862">Uploadede nedbrudsrapport-id'et:</translation>
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index a4ae15f..9d420f0b 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -273,6 +273,7 @@
   normal_players_.clear();
   pepper_players_.clear();
   one_shot_players_.clear();
+  ambient_players_.clear();
 
   AbandonSystemAudioFocusIfNeeded();
 
@@ -435,10 +436,13 @@
                                  int player_id) {
   media::MediaContentType media_content_type = observer->GetMediaContentType();
 
-  if (media_content_type == media::MediaContentType::kOneShot)
+  if (media_content_type == media::MediaContentType::kOneShot) {
     return AddOneShotPlayer(observer, player_id);
-  if (media_content_type == media::MediaContentType::kPepper)
+  } else if (media_content_type == media::MediaContentType::kPepper) {
     return AddPepperPlayer(observer, player_id);
+  } else if (media_content_type == media::MediaContentType::kAmbient) {
+    return AddAmbientPlayer(observer, player_id);
+  }
 
   observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
   if (audio_device_id_for_origin_)
@@ -522,6 +526,7 @@
   normal_players_.erase(identifier);
   pepper_players_.erase(identifier);
   one_shot_players_.erase(identifier);
+  ambient_players_.erase(identifier);
   hidden_players_.erase(identifier);
 
   if (guarding_player_id_ && *guarding_player_id_ == identifier)
@@ -536,26 +541,21 @@
 }
 
 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
-  for (auto it = normal_players_.begin(); it != normal_players_.end();) {
-    if (it->first.observer == observer)
-      normal_players_.erase(it++);
-    else
-      ++it;
-  }
+  std::erase_if(normal_players_, [observer](const auto& player) {
+    return player.first.observer == observer;
+  });
 
-  for (auto it = pepper_players_.begin(); it != pepper_players_.end();) {
-    if (it->observer == observer)
-      pepper_players_.erase(it++);
-    else
-      ++it;
-  }
+  base::EraseIf(pepper_players_, [observer](const auto& player) {
+    return player.observer == observer;
+  });
 
-  for (auto it = one_shot_players_.begin(); it != one_shot_players_.end();) {
-    if (it->observer == observer)
-      one_shot_players_.erase(it++);
-    else
-      ++it;
-  }
+  base::EraseIf(one_shot_players_, [observer](const auto& player) {
+    return player.observer == observer;
+  });
+
+  base::EraseIf(ambient_players_, [observer](const auto& player) {
+    return player.observer == observer;
+  });
 
   if (guarding_player_id_ && guarding_player_id_->observer == observer)
     ResetDurationUpdateGuard();
@@ -578,7 +578,8 @@
   PlayerIdentifier identifier(observer, player_id);
   if (!normal_players_.count(identifier) &&
       !pepper_players_.count(identifier) &&
-      !one_shot_players_.count(identifier)) {
+      !one_shot_players_.count(identifier) &&
+      !ambient_players_.count(identifier)) {
     return;
   }
 
@@ -596,6 +597,13 @@
     return;
   }
 
+  // If the player is an ambient player, just remove it since it is not expected
+  // to resume an ambient player via resuming MediaSession.
+  if (ambient_players_.count(identifier)) {
+    RemovePlayer(observer, player_id);
+    return;
+  }
+
   // Otherwise, suspend the session.
   // The session might not have audio focus if it was paused prior to being
   // suspended, which is fine.
@@ -777,8 +785,9 @@
 }
 
 bool MediaSessionImpl::IsControllable() const {
-  if (audio_focus_state_ == State::INACTIVE || HasOnlyOneShotPlayers())
+  if (audio_focus_state_ == State::INACTIVE || HasOnlyOneShotPlayers()) {
     return false;
+  }
 
 #if !BUILDFLAG(IS_ANDROID)
   if (routed_service_ && routed_service_->playback_state() !=
@@ -834,8 +843,13 @@
     it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
   }
 
-  for (const auto& it : pepper_players_)
+  for (const auto& it : pepper_players_) {
     it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
+  }
+
+  for (const auto& it : ambient_players_) {
+    it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
+  }
 }
 
 double MediaSessionImpl::GetVolumeMultiplier() const {
@@ -872,6 +886,7 @@
   normal_players_.clear();
   pepper_players_.clear();
   one_shot_players_.clear();
+  ambient_players_.clear();
   AbandonSystemAudioFocusIfNeeded();
 }
 
@@ -932,8 +947,9 @@
   // UI suspend cannot use State::INACTIVE.
   DCHECK(suspend_type == SuspendType::kSystem || new_state == State::SUSPENDED);
 
-  if (HasOnlyOneShotPlayers())
+  if (HasOnlyOneShotPlayers()) {
     return;
+  }
 
   if (audio_focus_state_ != State::ACTIVE)
     return;
@@ -1189,8 +1205,10 @@
         OnSuspendInternal(SuspendType::kSystem, State::SUSPENDED);
         break;
       case AudioFocusType::kAmbient:
+        // There's nothing to do if an ambient request fails.
+        break;
       case AudioFocusType::kGainTransient:
-        // MediaSessionImpl does not use |kGainTransient| or |kAmbient|.
+        // MediaSessionImpl does not use |kGainTransient|.
         NOTREACHED();
       case AudioFocusType::kGainTransientMayDuck:
         // The focus request failed, we should suspend any players that have
@@ -1403,7 +1421,8 @@
 
 void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
   if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
-      !pepper_players_.empty() || !one_shot_players_.empty()) {
+      !pepper_players_.empty() || !one_shot_players_.empty() ||
+      !ambient_players_.empty()) {
     return;
   }
   delegate_->AbandonAudioFocus();
@@ -1506,6 +1525,32 @@
   return true;
 }
 
+bool MediaSessionImpl::AddAmbientPlayer(MediaSessionPlayerObserver* observer,
+                                        int player_id) {
+#if BUILDFLAG(IS_ANDROID)
+  // Ambient players are completely ignored for Android audio focus.
+  return true;
+#else
+  // If we're currently ducking, ensure the new player is also ducked.
+  observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
+
+  // Request audio focus only if we're entirely inactive (i.e. don't request to
+  // un-suspend for an ambient player).
+  if (audio_focus_state_ == State::INACTIVE) {
+    if (RequestSystemAudioFocus(AudioFocusType::kAmbient) ==
+        AudioFocusDelegate::AudioFocusResult::kFailed) {
+      return false;
+    }
+  }
+
+  // If we have audio focus, then add this to the list of ambient players, but
+  // we don't need to update any info or metadata as they are unaffected by
+  // ambient players.
+  ambient_players_.insert(PlayerIdentifier(observer, player_id));
+  return true;
+#endif  // BUILDFLAG(IS_ANDROID)
+}
+
 // MediaSessionService-related methods
 
 void MediaSessionImpl::OnServiceCreated(MediaSessionServiceImpl* service) {
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h
index d7f345d9..c25588a 100644
--- a/content/browser/media/session/media_session_impl.h
+++ b/content/browser/media/session/media_session_impl.h
@@ -450,6 +450,9 @@
   CONTENT_EXPORT bool AddOneShotPlayer(MediaSessionPlayerObserver* observer,
                                        int player_id);
 
+  CONTENT_EXPORT bool AddAmbientPlayer(MediaSessionPlayerObserver* observer,
+                                       int player_id);
+
   // Returns true if there is at least one player and all the players are
   // one-shot.
   bool HasOnlyOneShotPlayers() const;
@@ -544,14 +547,22 @@
   std::set<media_session::mojom::MediaSessionAction> actions_;
 
   std::unique_ptr<AudioFocusDelegate> delegate_;
+
+  // Standard video playback (e.g. WebMediaPlayerImpl players).
   std::map<PlayerIdentifier, media_session::mojom::AudioFocusType>
       normal_players_;
+
+  // Pepper players (PPAPI players).
   base::flat_set<PlayerIdentifier> pepper_players_;
 
   // Players that are playing in the web contents but we cannot control (e.g.
-  // WebAudio or MediaStream).
+  // MediaStream).
   base::flat_set<PlayerIdentifier> one_shot_players_;
 
+  // Players that we can neither control nor should affect other players in the
+  // audio focus stack (e.g. WebAudio).
+  base::flat_set<PlayerIdentifier> ambient_players_;
+
   // Players that are removed from |normal_players_| temporarily when the page
   // goes to back-forward cache. When the page is restored from the cache, these
   // players are also restored to |normal_players_|.
diff --git a/content/browser/media/session/media_session_impl_browsertest.cc b/content/browser/media/session/media_session_impl_browsertest.cc
index e091696..c6c380823 100644
--- a/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/content/browser/media/session/media_session_impl_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_samples.h"
+#include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -37,6 +38,7 @@
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "media/base/media_content_type.h"
+#include "media/base/media_switches.h"
 #include "net/base/filename_util.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -77,6 +79,9 @@
 
   AudioFocusDelegate::AudioFocusResult RequestAudioFocus(
       AudioFocusType audio_focus_type) override {
+    if (audio_focus_request_waiter_) {
+      audio_focus_request_waiter_->Quit();
+    }
     if (async_mode_) {
       requests_.push_back(audio_focus_type);
       return AudioFocusDelegate::AudioFocusResult::kDelayed;
@@ -115,6 +120,14 @@
     sync_result_ = result;
   }
 
+  void WaitForAudioFocusRequested() {
+    if (audio_focus_type_.has_value() || !requests_.empty()) {
+      return;
+    }
+    audio_focus_request_waiter_ = std::make_unique<base::RunLoop>();
+    audio_focus_request_waiter_->Run();
+  }
+
  private:
   AudioFocusDelegate::AudioFocusResult sync_result_ =
       AudioFocusDelegate::AudioFocusResult::kSuccess;
@@ -122,6 +135,8 @@
   raw_ptr<content::MediaSessionImpl> media_session_ = nullptr;
   const bool async_mode_ = false;
 
+  std::unique_ptr<base::RunLoop> audio_focus_request_waiter_;
+
   std::list<AudioFocusType> requests_;
   std::optional<AudioFocusType> audio_focus_type_;
 };
@@ -210,6 +225,12 @@
     ASSERT_TRUE(media_session_);
   }
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitchASCII(
+        switches::kAutoplayPolicy,
+        switches::autoplay::kNoUserGestureRequiredPolicy);
+  }
+
   void TearDownOnMainThread() override {
     media_session_->RemoveAllPlayersForTest();
     mock_media_session_service_.reset();
@@ -3286,6 +3307,22 @@
   EXPECT_FALSE(waiter.MeetsVisibility());
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+                       WebAudioPlayersAreRegisteredAsAmbientPlayers) {
+  // Start WebAudio playback.
+  EXPECT_TRUE(NavigateToURL(
+      shell(), content::GetTestUrl("media/webaudio/", "playback-test.html")));
+  ASSERT_TRUE(ExecJs(shell()->web_contents(), "gain.gain.value = 1"));
+
+  // The WebAudio playback should request ambient audio focus.
+  mock_audio_focus_delegate()->WaitForAudioFocusRequested();
+  ResolveAudioFocusSuccess();
+  ASSERT_TRUE(GetSessionAudioFocusType().has_value());
+  EXPECT_EQ(AudioFocusType::kAmbient, *GetSessionAudioFocusType());
+}
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 class MediaSessionImplPrerenderingBrowserTest
     : public MediaSessionImplBrowserTest {
  public:
diff --git a/content/browser/media/session/media_session_impl_unittest.cc b/content/browser/media/session/media_session_impl_unittest.cc
index 15c77f3..bb29164 100644
--- a/content/browser/media/session/media_session_impl_unittest.cc
+++ b/content/browser/media/session/media_session_impl_unittest.cc
@@ -56,6 +56,7 @@
 
   AudioFocusResult RequestAudioFocus(AudioFocusType type) override {
     request_audio_focus_count_++;
+    last_requested_focus_type_ = type;
     return AudioFocusResult::kSuccess;
   }
 
@@ -79,8 +80,13 @@
 
   int request_audio_focus_count() const { return request_audio_focus_count_; }
 
+  const std::optional<AudioFocusType>& GetLastRequestedFocusType() {
+    return last_requested_focus_type_;
+  }
+
  private:
   int request_audio_focus_count_ = 0;
+  std::optional<AudioFocusType> last_requested_focus_type_;
 
   MediaSessionInfoPtr session_info_;
 };
@@ -187,8 +193,8 @@
   std::unique_ptr<MockMediaSessionPlayerObserver> player_observer_;
 
   void SetDelegateForTests(MediaSessionImpl* session,
-                           AudioFocusDelegate* delegate) {
-    session->SetDelegateForTests(base::WrapUnique(delegate));
+                           std::unique_ptr<AudioFocusDelegate> delegate) {
+    session->SetDelegateForTests(std::move(delegate));
   }
 
   MockMediaSessionServiceImpl& mock_media_session_service() const {
@@ -290,8 +296,9 @@
 }
 
 TEST_F(MediaSessionImplTest, NotifyDelegateOnStateChange) {
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
 
   RequestAudioFocus(GetMediaSession(), AudioFocusType::kGain);
   base::RunLoop().RunUntilIdle();
@@ -600,8 +607,9 @@
 #if BUILDFLAG(IS_MAC)
 
 TEST_F(MediaSessionImplTest, TabFocusDoesNotCauseAudioFocus) {
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
 
   {
     MockMediaSessionMojoObserver observer(*GetMediaSession());
@@ -618,8 +626,9 @@
 #else  // BUILDFLAG(IS_MAC)
 
 TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Active) {
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
 
   {
     MockMediaSessionMojoObserver observer(*GetMediaSession());
@@ -634,8 +643,9 @@
 }
 
 TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Inactive) {
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
   EXPECT_EQ(MediaSessionInfo::SessionState::kInactive,
             GetState(GetMediaSession()));
 
@@ -645,8 +655,9 @@
 }
 
 TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Suspended) {
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
 
   {
     MockMediaSessionMojoObserver observer(*GetMediaSession());
@@ -876,8 +887,9 @@
 TEST_F(MediaSessionImplTest, PausedPlayersDoNotRequestFocus) {
   // If a player is paused when it's added, it should be controllable but should
   // not request audio focus.
-  MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
-  SetDelegateForTests(GetMediaSession(), delegate);
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
   int player_id = StartNewPlayer();
   EXPECT_TRUE(GetMediaSession()->IsActive());
   EXPECT_TRUE(GetMediaSession()->IsControllable());
@@ -941,6 +953,63 @@
       base::Contains(observer.actions(), MediaSessionAction::kSeekBackward));
 }
 
+TEST_F(MediaSessionImplTest, AmbientPlayerFocusRequest) {
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  MockAudioFocusDelegate* delegate = delegate_unique.get();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
+
+  int player_id = player_observer_->StartNewPlayer();
+
+  player_observer_->SetMediaContentType(media::MediaContentType::kAmbient);
+  MockMediaSessionMojoObserver observer(*GetMediaSession());
+  GetMediaSession()->AddPlayer(player_observer_.get(), player_id);
+
+#if BUILDFLAG(IS_ANDROID)
+  // On Android, ambient players should not request audio focus.
+  observer.WaitForState(MediaSessionInfo::SessionState::kInactive);
+  EXPECT_FALSE(delegate->GetLastRequestedFocusType().has_value());
+#else
+  // On other platforms, an ambient player should request ambient focus.
+  observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+  EXPECT_TRUE(delegate->GetLastRequestedFocusType().has_value());
+  EXPECT_EQ(AudioFocusType::kAmbient, *delegate->GetLastRequestedFocusType());
+
+  // Ambient players should also receive volume multiplier updates.
+  constexpr float kDuckingMultiplier = 0.1;
+  EXPECT_EQ(player_observer_->GetVolumeMultiplier(player_id), 1.0);
+  GetMediaSession()->SetDuckingVolumeMultiplier(kDuckingMultiplier);
+  GetMediaSession()->StartDucking();
+  EXPECT_EQ(player_observer_->GetVolumeMultiplier(player_id),
+            kDuckingMultiplier);
+  GetMediaSession()->StopDucking();
+  EXPECT_EQ(player_observer_->GetVolumeMultiplier(player_id), 1.0);
+#endif  // BUILDFLAG(IS_ANDROID)
+}
+
+TEST_F(MediaSessionImplTest, AmbientPlayerDoesNotRequestFocusWhenSuspended) {
+  auto delegate_unique = std::make_unique<MockAudioFocusDelegate>();
+  SetDelegateForTests(GetMediaSession(), std::move(delegate_unique));
+
+  int persistent_player_id = player_observer_->StartNewPlayer();
+
+  MockMediaSessionPlayerObserver ambient_player_observer(
+      main_rfh(), media::MediaContentType::kAmbient);
+  int ambient_player_id = ambient_player_observer.StartNewPlayer();
+
+  // Add a persistent player to get audio focus.
+  MockMediaSessionMojoObserver observer(*GetMediaSession());
+  GetMediaSession()->AddPlayer(player_observer_.get(), persistent_player_id);
+  observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+
+  // Suspend the persistent player.
+  GetMediaSession()->Suspend(MediaSession::SuspendType::kSystem);
+  observer.WaitForState(MediaSessionInfo::SessionState::kSuspended);
+
+  // Adding an ambient player should not change the audio focus state.
+  GetMediaSession()->AddPlayer(&ambient_player_observer, ambient_player_id);
+  observer.WaitForState(MediaSessionInfo::SessionState::kSuspended);
+}
+
 class MediaSessionImplWithMediaSessionClientTest : public MediaSessionImplTest {
  protected:
   TestMediaSessionClient client_;
diff --git a/ios/chrome/app/strings/resources/ios_strings_da.xtb b/ios/chrome/app/strings/resources/ios_strings_da.xtb
index 03602da..ac57067 100644
--- a/ios/chrome/app/strings/resources/ios_strings_da.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_da.xtb
@@ -1020,7 +1020,7 @@
 <translation id="5646284034397250191">Etiket oprettet. Afventer dato</translation>
 <translation id="5647096944343801045">Stort indgangspunkt</translation>
 <translation id="5647193778876139879">Hold fingeren på en adresse.</translation>
-<translation id="5648166631817621825">De seneste syv dage</translation>
+<translation id="5648166631817621825">De seneste 7 dage</translation>
 <translation id="5652623411397330904">De produkter, hvis pris du holder øje med, vises her.</translation>
 <translation id="5657156137487675418">Tillad alle cookies</translation>
 <translation id="5659593005791499971">Mail</translation>
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
index b0cf4ed..852f7c2fa 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-4594af2cd1c40b05bfb45c67c844a32eecf7b489
\ No newline at end of file
+73e2fea879b6482b85223c6f02c436c4cbdbfff3
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
index 0459c56..dab33baf 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-7e9478d0d8e8b14dcad49a7bb4a3d1be8e68f1fd
\ No newline at end of file
+b771af7c75beea215d6e2e691a5586e50c4310fa
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index 68f36c0..8e1b8e79 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-f82086fc40d36051065d4db6b6e43aa264ab479f
\ No newline at end of file
+d782da510ff360bd8f63f7e05ed7f95bc4ce182f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
index 1aef957..3fd4b6b 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-cec34acf8f934c78d4dba9996eec9bf10bf10bb4
\ No newline at end of file
+1e0613ef0082eb2817a02fafb34d020a9b9e8f01
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index acd0423..8ee9c66 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-2f6cdcef54bca99cc90dfee8439d02779534641f
\ No newline at end of file
+f361b7c84410f3ff50ea6ec87e7d6435398a2187
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
index 1c5b0de..78c11d60 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-8391af86700cb2bed52e2c88e2c726515ed259ce
\ No newline at end of file
+ceb2d311da178c029f214913d7adffb9b59986cd
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
index 6e15e0c..763a58d 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-482ebf8c53a518da416687abbcd2496ba83b0b47
\ No newline at end of file
+48b2daf71d14c8aa2295f3d5f45de8d28ac29aed
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
index e6c18dc..7445aec 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-a9427cd1138ec017cdf1b598b5960db08936b75d
\ No newline at end of file
+b04860a88ca1a38cab9c410354b8dd96efeb11ab
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
index 68dc34a3f..5d08d61 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-6638063f07ce80c3f1d5182c721673eac6e3f716
\ No newline at end of file
+40b512f24523d81d44a31cf0f10d122a483e1ae9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
index c1ff8dc..4482204 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-def53c6b717d15d7aa19bec7fb9564d010aea9e4
\ No newline at end of file
+1988b1d730db6d453a21c4159e89a7ad3dcc4099
\ No newline at end of file
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 e03d361..fafcd3b 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 @@
-4c1bb895d983f1d29b6c16b71c2cd21340ebc3a9
\ No newline at end of file
+a7d2653719bc7ead5ecf0145710ede25c802f704
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
index 9b20d363..cb3f1f7 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-f846e770d8aa1d9d17a561f9d90e9dfba3c2a4ae
\ No newline at end of file
+aad67313853c3c6f71b3a33ffed1e6a0e5a487a8
\ 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 f8a6c4e..3dc7702 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 @@
-67f966176099bf9d072f399f952e15f52d978014
\ No newline at end of file
+272de287eb5cb7ad683ba5ed3ad7b313c25b1fd8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 4d8d8eb99..79940112 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-38f14f3b2b6ddcfc1f000bd83e1f0271e3911ac2
\ No newline at end of file
+43df99c3ae445152cf41137714f2e045a6960d70
\ 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 54edc6d9..86a6602 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 @@
-17c88a88bfed773fb6ae7da7b531da47d2aaf5a8
\ No newline at end of file
+30dac3bc7bbb527cc54f7c11d8e67870a21ae90f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
index e673a1c..2f4de1e 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-ee4d2f2bd2b658715fed667aebf17a05ff18bf89
\ No newline at end of file
+1398b71501e1fce584882d2875c6796bf74a8579
\ 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 3f6dfd25..f0a745a42 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 @@
-02fed42cdf3abe39a0c2f4d757c55810c56c36e8
\ No newline at end of file
+5c7d309b526ee1125f676951e161f8e190fe5373
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 0e4c865..5e2abe8 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-3f83b1a3af77fe97cc2f0794acb058304126bcbd
\ No newline at end of file
+442e8c245d9b84d0b66f3d792abb80ae68250f79
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index b8ccf1d..b630db39 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ba93d5a811832d65229ababaeecee6606eb7a68c
\ No newline at end of file
+1c771913f9c3b54c3f7711e27aa158f34dd68833
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index fb407e5..45521b5 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-7f4ebb56fae7a64d5177d75d526612e2c95a71b3
\ No newline at end of file
+ed2ec9ad273c2e058419316b708cdecb5d671d27
\ 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 1f9650c..3a040aaa 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 @@
-5bde75d0d78dcff0113fed2148f1af75d354b30d
\ No newline at end of file
+92e74ea7255545ef603780cceda71cecc860633e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
index f4fe1dc..10b3accd 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-c0a77612a4140e7712501baf54f1eef6a9c86f6c
\ No newline at end of file
+85727c1cbe017c0877ba88755fcc3f9f73113f6b
\ 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 767f1e608..60f6fb4 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 @@
-18758114a89cc656ec771e71a1e286a1dd992355
\ No newline at end of file
+2420499fd95daf02dbcff2da9865be0decc79cf0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 5e1aeac5..7bd45bf 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-23b3fc2d7aacde620326a087b75c09f1603a880d
\ No newline at end of file
+ea7423292ae5d4b2e96c09b328187508b9c8fef2
\ 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 ff58180b5..33a6914 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 @@
-b493e1b328103312ffd25302be5a1d84f2fc679c
\ No newline at end of file
+5ef4b573244f11893df396ce3017a37c948bfbe8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
index 81134252..e337f6e 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-698e9f7d6c91a4bcea4bd39b339090fd38108b48
\ No newline at end of file
+bf6c78eb7e8a0349e2b6e99a8bdb65f8fdad60ca
\ 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 9a18faa..68707d8 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 @@
-379fe354b0c9cce51b620cba89510010da49f5b4
\ No newline at end of file
+26dcd6ba658e830c770a70e21e83e66bf59a58f5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 5645f35..e600a9c 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-64c0b654b4352c3635ab164c2382e363c704ec64
\ No newline at end of file
+b3f0445d852ada59ee6d28aa8836a571c893fa43
\ No newline at end of file
diff --git a/ios_internal b/ios_internal
index 4886ed2..5d0e918 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 4886ed2c5e084e5ac85cb2b822c16214c0e38337
+Subproject commit 5d0e91884d86fd282c91ecf82a87a83192703707
diff --git a/media/base/audio_bus.cc b/media/base/audio_bus.cc
index 0125084..b917fb9 100644
--- a/media/base/audio_bus.cc
+++ b/media/base/audio_bus.cc
@@ -349,9 +349,11 @@
   DCHECK(!is_bitstream_format_);
   CHECK_EQ(channels(), dest->channels());
   CHECK_LE(frames(), dest->frames());
-  for (int ch = 0; ch < channels(); ++ch) {
-    std::ranges::transform(channel_span(ch), dest->channel_span(ch).begin(),
-                           Float32SampleTypeTraits::FromFloat);
+  for (int i = 0; i < channels(); ++i) {
+    float* dest_ptr = dest->channel(i);
+    const float* source_ptr = channel(i);
+    for (int j = 0; j < frames(); ++j)
+      dest_ptr[j] = Float32SampleTypeTraits::FromFloat(source_ptr[j]);
   }
 }
 
@@ -361,25 +363,23 @@
                                    AudioBus* dest) const {
   DCHECK(!is_bitstream_format_);
   CHECK_EQ(channels(), dest->channels());
-
-  const size_t source_offset = base::checked_cast<size_t>(source_start_frame);
-  const size_t dest_offset = base::checked_cast<size_t>(dest_start_frame);
-  const size_t count = base::checked_cast<size_t>(frame_count);
+  CHECK_LE(source_start_frame + frame_count, frames());
+  CHECK_LE(dest_start_frame + frame_count, dest->frames());
 
   // Since we don't know if the other AudioBus is wrapped or not (and we don't
   // want to care), just copy using the public channel() accessors.
   for (int i = 0; i < channels(); ++i) {
-    ConstChannel src_span = channel_span(i).subspan(source_offset, count);
-    dest->channel_span(i).subspan(dest_offset, count).copy_from(src_span);
+    memcpy(dest->channel(i) + dest_start_frame,
+           channel(i) + source_start_frame,
+           sizeof(*channel(i)) * frame_count);
   }
 }
 
 void AudioBus::Scale(float volume) {
   DCHECK(!is_bitstream_format_);
   if (volume > 0 && volume != 1) {
-    for (auto channel : channel_data_) {
-      vector_math::FMUL(channel.data(), volume, frames(), channel.data());
-    }
+    for (int i = 0; i < channels(); ++i)
+      vector_math::FMUL(channel(i), volume, frames(), channel(i));
   } else if (volume == 0) {
     Zero();
   }
diff --git a/media/base/audio_bus.h b/media/base/audio_bus.h
index be9c9ea..2fa481b4 100644
--- a/media/base/audio_bus.h
+++ b/media/base/audio_bus.h
@@ -355,7 +355,7 @@
     AudioBus* dest) {
   const int channels = dest->channels();
   for (int ch = 0; ch < channels; ++ch) {
-    AudioBus::Channel channel_data = dest->channel_span(ch);
+    float* channel_data = dest->channel(ch);
     for (int target_frame_index = write_offset_in_frames,
              read_pos_in_source = ch;
          target_frame_index < write_offset_in_frames + num_frames_to_write;
@@ -377,7 +377,7 @@
     typename TargetSampleTypeTraits::ValueType* dest_buffer) {
   const int channels = source->channels();
   for (int ch = 0; ch < channels; ++ch) {
-    AudioBus::ConstChannel channel_data = source->channel_span(ch);
+    const float* channel_data = source->channel(ch);
     for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch;
          source_frame_index < read_offset_in_frames + num_frames_to_read;
          ++source_frame_index, write_pos_in_dest += channels) {
diff --git a/media/base/audio_bus_unittest.cc b/media/base/audio_bus_unittest.cc
index 3d793b9..6307be08 100644
--- a/media/base/audio_bus_unittest.cc
+++ b/media/base/audio_bus_unittest.cc
@@ -29,12 +29,10 @@
 
 namespace media {
 
-using AlignedFloatArray = base::AlignedHeapArray<float>;
-
 static const int kChannels = 6;
 static constexpr ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
 // Use a buffer size which is intentionally not a multiple of kChannelAlignment.
-static const size_t kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
+static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
 static const int kSampleRate = 48000;
 
 class AudioBusTest : public testing::Test {
@@ -44,17 +42,19 @@
   AudioBusTest(const AudioBusTest&) = delete;
   AudioBusTest& operator=(const AudioBusTest&) = delete;
 
-  ~AudioBusTest() override = default;
+  ~AudioBusTest() override {
+    for (size_t i = 0; i < data_.size(); ++i)
+      base::AlignedFree(data_[i]);
+  }
 
   void VerifyChannelAndFrameCount(AudioBus* bus) {
     EXPECT_EQ(kChannels, bus->channels());
-    EXPECT_EQ(static_cast<int>(kFrameCount), bus->frames());
+    EXPECT_EQ(kFrameCount, bus->frames());
   }
 
-  void VerifySpanIsFilledWithValue(AudioBus::ConstChannel data, float value) {
-    for (size_t i = 0; i < data.size(); ++i) {
+  void VerifyArrayIsFilledWithValue(const float data[], int size, float value) {
+    for (int i = 0; i < size; ++i)
       ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
-    }
   }
 
   // Verify values for each channel in |result| are within |epsilon| of
@@ -77,11 +77,10 @@
         SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i));
 
         if (epsilon == 0) {
-          ASSERT_FLOAT_EQ(expected->channel_span(ch)[i],
-                          result->channel_span(ch)[i]);
+          ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
         } else {
-          ASSERT_NEAR(expected->channel_span(ch)[i],
-                      result->channel_span(ch)[i], epsilon);
+          ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i],
+                      epsilon);
         }
       }
     }
@@ -96,23 +95,22 @@
   // the Zero() method and verify it does as advertised.  Also test data if data
   // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h).
   void VerifyReadWriteAndAlignment(AudioBus* bus) {
-    int channel_count = 0;
-    for (auto channel : bus->AllChannels()) {
+    for (int i = 0; i < bus->channels(); ++i) {
       // Verify that the address returned by channel(i) is a multiple of
       // AudioBus::kChannelAlignment.
-      ASSERT_TRUE(AudioBus::IsAligned(channel));
+      ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
+          bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
+
       // Write into the channel buffer.
-      std::ranges::fill(channel, channel_count++);
+      std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
     }
 
-    for (int i = 0; i < bus->channels(); ++i) {
-      VerifySpanIsFilledWithValue(bus->channel_span(i), i);
-    }
+    for (int i = 0; i < bus->channels(); ++i)
+      VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), i);
 
     bus->Zero();
-    for (int i = 0; i < bus->channels(); ++i) {
-      VerifySpanIsFilledWithValue(bus->channel_span(i), 0);
-    }
+    for (int i = 0; i < bus->channels(); ++i)
+      VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
   }
 
   // Verify copying to and from |bus1| and |bus2|.
@@ -144,22 +142,12 @@
   void AllocateDataPerChannel() {
     data_.reserve(kChannels);
     for (int i = 0; i < kChannels; ++i) {
-      data_.push_back(
-          base::AlignedUninit<float>(kFrameCount, AudioBus::kChannelAlignment));
+      data_.push_back(static_cast<float*>(base::AlignedAlloc(
+          sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
     }
   }
 
-  // TODO(crbug.com/373960632): remove this when all ctors take spans.
-  std::vector<float*> GetRawPointers(std::vector<AlignedFloatArray>& data) {
-    std::vector<float*> result;
-    result.reserve(data_.size());
-    for (AlignedFloatArray& array : data) {
-      result.push_back(array.as_span().data());
-    }
-    return result;
-  }
-
-  std::vector<AlignedFloatArray> data_;
+  std::vector<float*> data_;
 };
 
 // Verify basic Create(...) method works as advertised.
@@ -186,7 +174,8 @@
   std::unique_ptr<AudioBus> bus = AudioBus::CreateWrapper(kChannels);
   bus->set_frames(kFrameCount);
   for (int i = 0; i < bus->channels(); ++i) {
-    bus->SetChannelData(i, data_[i].as_span());
+    bus->SetChannelData(i,
+                        base::span(data_[i], static_cast<size_t>(kFrameCount)));
   }
 
   bool deleted = false;
@@ -208,8 +197,8 @@
   bus->set_frames(kFrameCount);
   AudioBus::ChannelVector channels;
   int value = 1;
-  for (AlignedFloatArray& data : data_) {
-    AudioBus::Channel channel(data);
+  for (float* data : data_) {
+    AudioBus::Channel channel(data, static_cast<size_t>(kFrameCount));
 
     // Fill each channel with a different value.
     std::ranges::fill(channel, value++);
@@ -237,8 +226,8 @@
   bus->set_frames(kFrameCount);
   AudioBus::ChannelVector channels;
   int value = 1;
-  for (AlignedFloatArray& data : data_) {
-    AudioBus::Channel channel(data);
+  for (float* data : data_) {
+    AudioBus::Channel channel(data, static_cast<size_t>(kFrameCount));
 
     // Fill each sample with a different value.
     for (float& sample : channel) {
@@ -265,17 +254,13 @@
 
 // Verify an AudioBus created via wrapping a vector works as advertised.
 TEST_F(AudioBusTest, WrapVector) {
-  AllocateDataPerChannel();
-
-  std::vector<float*> data_pointers;
-  data_pointers.reserve(kChannels);
-
-  for (AlignedFloatArray& data : data_) {
-    data_pointers.push_back(data.as_span().data());
+  data_.reserve(kChannels);
+  for (int i = 0; i < kChannels; ++i) {
+    data_.push_back(static_cast<float*>(base::AlignedAlloc(
+        sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
   }
 
-  std::unique_ptr<AudioBus> bus =
-      AudioBus::WrapVector(kFrameCount, GetRawPointers(data_));
+  std::unique_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
   VerifyChannelAndFrameCount(bus.get());
   VerifyReadWriteAndAlignment(bus.get());
 }
@@ -285,29 +270,26 @@
   AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                          ChannelLayoutConfig::FromLayout<kChannelLayout>(),
                          kSampleRate, kFrameCount);
-  size_t total_frame_count =
-      AudioBus::CalculateMemorySize(params) / sizeof(float);
-  AlignedFloatArray data = base::AlignedUninit<float>(total_frame_count);
+  size_t data_size = AudioBus::CalculateMemorySize(params);
+  std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
+      base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
 
   // Fill the memory with a test value we can check for after wrapping.
   static const float kTestValue = 3;
-  std::ranges::fill(data, kTestValue);
+  std::fill(data.get(), data.get() + data_size / sizeof(*data.get()),
+            kTestValue);
 
-  std::unique_ptr<AudioBus> bus =
-      AudioBus::WrapMemory(params, data.as_span().data());
+  std::unique_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get());
   // Verify the test value we filled prior to wrapping.
-  for (auto channel : bus->AllChannels()) {
-    VerifySpanIsFilledWithValue(channel, kTestValue);
-  }
+  for (int i = 0; i < bus->channels(); ++i)
+    VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kTestValue);
   VerifyChannelAndFrameCount(bus.get());
   VerifyReadWriteAndAlignment(bus.get());
 
   // Verify the channel vectors lie within the provided memory block.
-  const float* backing_memory_start = data.as_span().data();
-  const float* backing_memory_end = backing_memory_start + total_frame_count;
-  EXPECT_GE(bus->channel_span(0).data(), backing_memory_start);
-  EXPECT_LT(bus->channel_span(bus->channels() - 1).data() + bus->frames(),
-            backing_memory_end);
+  EXPECT_GE(bus->channel(0), data.get());
+  EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
+            data.get() + data_size / sizeof(*data.get()));
 }
 
 // Simulate a shared memory transfer and verify results.
@@ -329,7 +311,7 @@
     // Try a copy to an AudioBus wrapping a vector.
     AllocateDataPerChannel();
 
-    bus2 = AudioBus::WrapVector(kFrameCount, GetRawPointers(data_));
+    bus2 = AudioBus::WrapVector(kFrameCount, data_);
     CopyTest(bus1.get(), bus2.get());
   }
   {
@@ -349,60 +331,50 @@
   std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
 
   // Fill the bus with dummy data.
-  int value = 1;
-  for (auto channel : bus->AllChannels()) {
-    std::ranges::fill(channel, value++);
-  }
+  for (int i = 0; i < bus->channels(); ++i)
+    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
   EXPECT_FALSE(bus->AreFramesZero());
 
   // Zero first half the frames of each channel.
   bus->ZeroFrames(kFrameCount / 2);
-
-  value = 1;
-  for (auto channel : bus->AllChannels()) {
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("First Half Zero");
-    auto [first_half, second_half] = channel.split_at(kFrameCount / 2);
-    VerifySpanIsFilledWithValue(first_half, 0);
-    VerifySpanIsFilledWithValue(second_half, value++);
+    VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, 0);
+    VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2,
+                                 kFrameCount - kFrameCount / 2, i + 1);
   }
   EXPECT_FALSE(bus->AreFramesZero());
 
   // Fill the bus with dummy data.
-  value = 1;
-  for (auto channel : bus->AllChannels()) {
-    std::ranges::fill(channel, value++);
-  }
+  for (int i = 0; i < bus->channels(); ++i)
+    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
 
   // Zero the last half of the frames.
-  static constexpr size_t kRemainingFrames = kFrameCount - kFrameCount / 2;
-  bus->ZeroFramesPartial(kFrameCount / 2, kRemainingFrames);
-  value = 1;
-  for (auto channel : bus->AllChannels()) {
+  bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2);
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("Last Half Zero");
-    auto [first_half, second_half] = channel.split_at(kFrameCount / 2);
-    VerifySpanIsFilledWithValue(first_half, value++);
-    VerifySpanIsFilledWithValue(second_half, 0);
+    VerifyArrayIsFilledWithValue(bus->channel(i) + kFrameCount / 2,
+                                 kFrameCount - kFrameCount / 2, 0);
+    VerifyArrayIsFilledWithValue(bus->channel(i), kFrameCount / 2, i + 1);
   }
   EXPECT_FALSE(bus->AreFramesZero());
 
   // Fill the bus with dummy data.
-  value = 1;
-  for (auto channel : bus->AllChannels()) {
-    std::ranges::fill(channel, value++);
-  }
+  for (int i = 0; i < bus->channels(); ++i)
+    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
 
   // Zero all the frames of each channel.
   bus->Zero();
-  for (auto channel : bus->AllChannels()) {
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("All Zero");
-    VerifySpanIsFilledWithValue(channel, 0);
+    VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
   }
   EXPECT_TRUE(bus->AreFramesZero());
 }
 
 // Each test vector represents two channels of data in the following arbitrary
 // layout: <min, zero, max, min, max / 2, min / 2, zero, max, zero, zero>.
-static constexpr int kTestVectorSize = 10;
+static const int kTestVectorSize = 10;
 static const uint8_t kTestVectorUint8[kTestVectorSize] = {
     0,         -INT8_MIN,          UINT8_MAX,
     0,         INT8_MAX / 2 + 128, INT8_MIN / 2 + 128,
@@ -435,7 +407,7 @@
     -1.0f, 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, -1.0f};
 
 // Expected results.
-static constexpr size_t kTestVectorFrameCount = kTestVectorSize / 2;
+static const int kTestVectorFrameCount = kTestVectorSize / 2;
 static const float kTestVectorResult[][kTestVectorFrameCount] = {
     {-1.0f, 1.0f, 0.5f, 0.0f, 0.0f},
     {0.0f, -1.0f, -0.5f, 1.0f, 0.0f}};
@@ -448,7 +420,8 @@
   std::unique_ptr<AudioBus> expected =
       AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
   for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
-    expected->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
+    memcpy(expected->channel(ch), kTestVectorResult[ch],
+           kTestVectorFrameCount * sizeof(*expected->channel(ch)));
   }
 
   {
@@ -492,8 +465,8 @@
 // Verify FromInterleavedPartial() deinterleaves audio correctly.
 TEST_F(AudioBusTest, FromInterleavedPartial) {
   // Only deinterleave the middle two frames in each channel.
-  static constexpr size_t kPartialStart = 1;
-  static constexpr size_t kPartialFrames = 2;
+  static const int kPartialStart = 1;
+  static const int kPartialFrames = 2;
   ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount);
 
   std::unique_ptr<AudioBus> bus =
@@ -501,11 +474,10 @@
   std::unique_ptr<AudioBus> expected =
       AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
   expected->Zero();
-  int current_channel = 0;
-  for (auto partial_channel :
-       expected->AllChannelsSubspan(kPartialStart, kPartialFrames)) {
-    partial_channel.copy_from(base::span(kTestVectorResult[current_channel++])
-                                  .subspan(kPartialStart, kPartialFrames));
+  for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
+    memcpy(expected->channel(ch) + kPartialStart,
+           kTestVectorResult[ch] + kPartialStart,
+           kPartialFrames * sizeof(*expected->channel(ch)));
   }
 
   {
@@ -524,7 +496,8 @@
       AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
   // Fill the bus with our test vector.
   for (int ch = 0; ch < bus->channels(); ++ch) {
-    bus->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
+    memcpy(bus->channel(ch), kTestVectorResult[ch],
+           kTestVectorFrameCount * sizeof(*bus->channel(ch)));
   }
 
   {
@@ -575,7 +548,7 @@
   bus->FromInterleaved<Float32SampleTypeTraits>(kTestVectorFloat32Invalid,
                                                 bus->frames());
   // Verify FromInterleaved applied no sanity.
-  ASSERT_EQ(bus->channel_span(0)[0], kTestVectorFloat32Invalid[0]);
+  ASSERT_EQ(bus->channel(0)[0], kTestVectorFloat32Invalid[0]);
   float test_array[std::size(kTestVectorFloat32Sanitized)];
   bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array);
   for (size_t i = 0; i < std::size(kTestVectorFloat32Sanitized); ++i)
@@ -603,7 +576,7 @@
       kTestVectorFloat32Sanitized, bus->frames());
 
   // Verify FromInterleaved applied no sanity.
-  ASSERT_EQ(bus->channel_span(0)[0], kTestVectorFloat32Invalid[0]);
+  ASSERT_EQ(bus->channel(0)[0], kTestVectorFloat32Invalid[0]);
 
   std::unique_ptr<AudioBus> copy_to_bus =
       AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
@@ -611,8 +584,7 @@
 
   for (int ch = 0; ch < expected->channels(); ++ch) {
     for (int i = 0; i < expected->frames(); ++i)
-      ASSERT_EQ(copy_to_bus->channel_span(ch)[i],
-                expected->channel_span(ch)[i]);
+      ASSERT_EQ(copy_to_bus->channel(ch)[i], expected->channel(ch)[i]);
   }
 
   ASSERT_EQ(expected->channels(), copy_to_bus->channels());
@@ -624,14 +596,15 @@
 // Verify ToInterleavedPartial() interleaves audio correctly.
 TEST_F(AudioBusTest, ToInterleavedPartial) {
   // Only interleave the middle two frames in each channel.
-  static constexpr size_t kPartialStart = 1;
-  static constexpr size_t kPartialFrames = 2;
+  static const int kPartialStart = 1;
+  static const int kPartialFrames = 2;
   ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrameCount);
 
   std::unique_ptr<AudioBus> expected =
       AudioBus::Create(kTestVectorChannelCount, kTestVectorFrameCount);
   for (int ch = 0; ch < kTestVectorChannelCount; ++ch) {
-    expected->channel_span(ch).copy_from(base::span(kTestVectorResult[ch]));
+    memcpy(expected->channel(ch), kTestVectorResult[ch],
+           kTestVectorFrameCount * sizeof(*expected->channel(ch)));
   }
 
   {
@@ -658,10 +631,11 @@
     // Create a bus and fill each channel with a test pattern of form
     // [1.0, 2.0, 3.0, ...]
     bus_under_test = AudioBus::Create(kChannelCount, kFrameCount);
-    for (auto channel : bus_under_test->AllChannels()) {
-      int value = 1;
-      for (float& sample : channel) {
-        sample = value++;
+    for (int ch = 0; ch < kChannelCount; ++ch) {
+      auto* sample_array_for_current_channel = bus_under_test->channel(ch);
+      for (int frame_index = 0; frame_index < kFrameCount; frame_index++) {
+        sample_array_for_current_channel[frame_index] =
+            static_cast<float>(frame_index + 1);
       }
     }
 
@@ -680,14 +654,13 @@
   test_data.bus_under_test->FromInterleaved<Float32SampleTypeTraits>(
       &test_data.interleaved_dummy_frames[0], test_data.kInterleavedFrameCount);
 
-  const size_t untouched_frame_count =
-      test_data.kFrameCount - test_data.kInterleavedFrameCount;
-
   // Verification
-  for (auto partial_channel : test_data.bus_under_test->AllChannelsSubspan(
-           test_data.kInterleavedFrameCount, untouched_frame_count)) {
-    for (auto sample : partial_channel) {
-      ASSERT_EQ(0.0f, sample);
+  for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
+    auto* sample_array_for_current_channel =
+        test_data.bus_under_test->channel(ch);
+    for (int frame_index = test_data.kInterleavedFrameCount;
+         frame_index < test_data.kFrameCount; frame_index++) {
+      ASSERT_EQ(0.0f, sample_array_for_current_channel[frame_index]);
     }
   }
 }
@@ -706,8 +679,8 @@
 
     // Verification
     for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
-      auto sample_array_for_current_channel =
-          test_data.bus_under_test->channel_span(ch);
+      auto* sample_array_for_current_channel =
+          test_data.bus_under_test->channel(ch);
       for (int frame_index =
                test_data.kInterleavedFrameCount + kWriteOffsetInFrames;
            frame_index < test_data.kFrameCount; frame_index++) {
@@ -729,8 +702,8 @@
 
     // Verification
     for (int ch = 0; ch < test_data.kChannelCount; ++ch) {
-      auto sample_array_for_current_channel =
-          test_data.bus_under_test->channel_span(ch);
+      auto* sample_array_for_current_channel =
+          test_data.bus_under_test->channel(ch);
       // Check untouched frames before write offset
       for (int frame_index = 0; frame_index < kWriteOffsetInFrames;
            frame_index++) {
@@ -752,31 +725,31 @@
   std::unique_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
 
   // Fill the bus with dummy data.
-  static constexpr float kFillValue = 1;
-  for (auto channel : bus->AllChannels()) {
-    std::ranges::fill(channel, kFillValue);
-  }
+  static const float kFillValue = 1;
+  for (int i = 0; i < bus->channels(); ++i)
+    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue);
 
   // Adjust by an invalid volume and ensure volume is unchanged.
   bus->Scale(-1);
-  for (auto channel : bus->AllChannels()) {
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("Invalid Scale");
-    VerifySpanIsFilledWithValue(channel, kFillValue);
+    VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), kFillValue);
   }
 
   // Verify correct volume adjustment.
-  static constexpr float kVolume = 0.5;
+  static const float kVolume = 0.5;
   bus->Scale(kVolume);
-  for (auto channel : bus->AllChannels()) {
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("Half Scale");
-    VerifySpanIsFilledWithValue(channel, kFillValue * kVolume);
+    VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(),
+                                 kFillValue * kVolume);
   }
 
   // Verify zero volume case.
   bus->Scale(0);
-  for (auto channel : bus->AllChannels()) {
+  for (int i = 0; i < bus->channels(); ++i) {
     SCOPED_TRACE("Zero Scale");
-    VerifySpanIsFilledWithValue(channel, 0);
+    VerifyArrayIsFilledWithValue(bus->channel(i), bus->frames(), 0);
   }
 }
 
@@ -794,7 +767,7 @@
 
   EXPECT_EQ(0, bus->GetBitstreamFrames());
   bus->SetBitstreamFrames(kFrameCount);
-  EXPECT_EQ(static_cast<int>(kFrameCount), bus->GetBitstreamFrames());
+  EXPECT_EQ(kFrameCount, bus->GetBitstreamFrames());
 
   std::unique_ptr<AudioBus> bus2 = AudioBus::Create(1, kFrameCount);
   CopyTest(bus.get(), bus2.get());
diff --git a/media/base/media_content_type.h b/media/base/media_content_type.h
index 3010805d..ed1f9ae 100644
--- a/media/base/media_content_type.h
+++ b/media/base/media_content_type.h
@@ -25,8 +25,11 @@
   // audio focus when the player joins but will not let it respond to audio
   // focus changes.
   kOneShot,
+  // Type indicating that a player that can be mixed with other types of audio,
+  // having no effect on other holders of audio focus.
+  kAmbient,
   // The maximum number of media content types.
-  kMax = kOneShot,
+  kMax = kAmbient,
 };
 
 // Utility function for deciding the MediaContentType of a player based on its
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
index a3b9f9e9c..6f6d84c 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
@@ -43,10 +43,6 @@
     "/run/camera/force_enable_effects";
 const base::FilePath::CharType kForceDisableEffectsPath[] =
     "/run/camera/force_disable_effects";
-const base::FilePath::CharType kForceEnableSuperResPath[] =
-    "/run/camera/force_enable_super_res";
-const base::FilePath::CharType kForceDisableSuperResPath[] =
-    "/run/camera/force_disable_super_res";
 const base::FilePath::CharType kEnableRetouchWithRelightPath[] =
     "/run/camera/enable_retouch_with_relight";
 const base::FilePath::CharType kEnableOnlyRetouchPath[] =
@@ -309,13 +305,6 @@
       /*should_enable=*/ash::features::IsVideoConferenceEnabled(),
       /*should_remove_both=*/false);
 
-  CreateEnableDisableFile(
-      kForceEnableSuperResPath, kForceDisableSuperResPath,
-      /*should_enable=*/
-      command_line->GetSwitchValueASCII(switches::kCameraSuperResOverride) !=
-          switches::kCameraSuperResForceDisabled,
-      /*should_remove_both=*/false);
-
   std::string face_retouch_override =
       command_line->GetSwitchValueASCII(switches::kFaceRetouchOverride);
   CreateFile(
diff --git a/media/capture/video/chromeos/video_capture_features_chromeos.cc b/media/capture/video/chromeos/video_capture_features_chromeos.cc
index b017ce51..bf5156e 100644
--- a/media/capture/video/chromeos/video_capture_features_chromeos.cc
+++ b/media/capture/video/chromeos/video_capture_features_chromeos.cc
@@ -12,7 +12,6 @@
 
 const char kForceControlFaceAe[] = "force-control-face-ae";
 const char kAutoFramingOverride[] = "auto-framing-override";
-const char kCameraSuperResOverride[] = "camera-super-res-override";
 const char kFaceRetouchOverride[] = "face-retouch-override";
 
 }  // namespace switches
diff --git a/media/capture/video/chromeos/video_capture_features_chromeos.h b/media/capture/video/chromeos/video_capture_features_chromeos.h
index 97af23c..de7c43f 100644
--- a/media/capture/video/chromeos/video_capture_features_chromeos.h
+++ b/media/capture/video/chromeos/video_capture_features_chromeos.h
@@ -18,10 +18,6 @@
 inline constexpr char kAutoFramingForceEnabled[] = "force-enabled";
 inline constexpr char kAutoFramingForceDisabled[] = "force-disabled";
 
-CAPTURE_EXPORT extern const char kCameraSuperResOverride[];
-inline constexpr char kCameraSuperResForceEnabled[] = "force-enabled";
-inline constexpr char kCameraSuperResForceDisabled[] = "force-disabled";
-
 CAPTURE_EXPORT extern const char kFaceRetouchOverride[];
 inline constexpr char kFaceRetouchForceEnabledWithRelighting[] =
     "force-enabled-with-relighting";
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index d5ad15e..bf75ca6 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2025-01-04 12:55 UTC
+# Last updated: 2025-01-05 12:53 UTC
 PinsListTimestamp
-1735995326
+1736081630
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index 5a589c2..ee6c368e 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2025-01-04 12:55 UTC
+// Last updated: 2025-01-05 12:53 UTC
 //
 {
   "pinsets": [
diff --git a/third_party/blink/renderer/modules/webaudio/DEPS b/third_party/blink/renderer/modules/webaudio/DEPS
index 420b1720..1ec448c 100644
--- a/third_party/blink/renderer/modules/webaudio/DEPS
+++ b/third_party/blink/renderer/modules/webaudio/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
     "+media/base",
+    "+media/mojo",
     "+services/metrics/public/cpp/ukm_builders.h",
     "+services/metrics/public/cpp/ukm_recorder.h",
     "-third_party/blink/renderer/modules",
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc
index 6fe6638e..239f9f5 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -9,6 +9,7 @@
 #include "build/build_config.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/mediastream/media_devices.h"
 #include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
@@ -42,6 +43,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/media/player_id_generator.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
@@ -270,7 +272,11 @@
           !GetExecutionContext()->IsFeatureEnabled(
               mojom::blink::PermissionsPolicyFeature::
                   kMediaPlaybackWhileNotVisible,
-              ReportOptions::kDoNotReport)) {
+              ReportOptions::kDoNotReport)),
+      player_id_(GetNextMediaPlayerId()),
+      media_player_host_(&window),
+      media_player_receiver_(this, &window),
+      media_player_observer_(&window) {
   RecordAudioContextOperation(AudioContextOperation::kCreate);
   SendLogMessage(__func__, GetAudioContextLogString(latency_hint, sample_rate));
 
@@ -386,6 +392,9 @@
   visitor->Trace(media_device_service_);
   visitor->Trace(media_device_service_receiver_);
   visitor->Trace(v8_sink_id_);
+  visitor->Trace(media_player_host_);
+  visitor->Trace(media_player_receiver_);
+  visitor->Trace(media_player_observer_);
   BaseAudioContext::Trace(visitor);
   FrameVisibilityObserver::Trace(visitor);
 }
@@ -620,6 +629,10 @@
   }
 }
 
+void AudioContext::SetVolumeMultiplier(double multiplier) {
+  volume_multiplier_ = multiplier;
+}
+
 double AudioContext::baseLatency() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_sequence_checker_);
   DCHECK(destination());
@@ -918,6 +931,14 @@
   if (audio_context_manager_.is_bound()) {
     audio_context_manager_->AudioContextAudiblePlaybackStarted(context_id_);
   }
+
+  EnsureMediaPlayerConnection();
+  if (media_player_observer_.is_bound()) {
+    media_player_observer_->OnMediaMetadataChanged(
+        /*has_audio=*/true, /*has_video=*/false,
+        media::MediaContentType::kAmbient);
+    media_player_observer_->OnMediaPlaying();
+  }
 }
 
 void AudioContext::HandlePostRenderTasks() {
@@ -966,6 +987,12 @@
   }
 }
 
+void AudioContext::HandleVolumeMultiplier(AudioBus* destination_bus) {
+  if (volume_multiplier_ != 1.0) {
+    destination_bus->Scale(volume_multiplier_);
+  }
+}
+
 void AudioContext::ResolvePromisesForUnpause() {
   // This runs inside the BaseAudioContext's lock when handling pre-render
   // tasks.
@@ -992,6 +1019,13 @@
   if (audio_context_manager_.is_bound()) {
     audio_context_manager_->AudioContextAudiblePlaybackStopped(context_id_);
   }
+
+  EnsureMediaPlayerConnection();
+  if (media_player_observer_.is_bound()) {
+    media_player_observer_->OnMediaMetadataChanged(
+        /*has_audio=*/false, /*has_video=*/false,
+        media::MediaContentType::kAmbient);
+  }
 }
 
 void AudioContext::EnsureAudioContextManagerService() {
@@ -1421,4 +1455,33 @@
   return window->GetFrame();
 }
 
+void AudioContext::EnsureMediaPlayerConnection() {
+  if (media_player_host_.is_bound() || !GetWindow()) {
+    return;
+  }
+
+  GetWindow()
+      ->GetFrame()
+      ->GetRemoteNavigationAssociatedInterfaces()
+      ->GetInterface(media_player_host_.BindNewEndpointAndPassReceiver(
+          GetWindow()->GetTaskRunner(TaskType::kInternalMedia)));
+  media_player_host_.set_disconnect_handler(WTF::BindOnce(
+      &AudioContext::OnMediaPlayerDisconnect, WrapWeakPersistent(this)));
+
+  media_player_host_->OnMediaPlayerAdded(
+      media_player_receiver_.BindNewEndpointAndPassRemote(
+          GetWindow()->GetTaskRunner(TaskType::kInternalMedia)),
+      media_player_observer_.BindNewEndpointAndPassReceiver(
+          GetWindow()->GetTaskRunner(TaskType::kInternalMedia)),
+      player_id_);
+  media_player_observer_.set_disconnect_handler(WTF::BindOnce(
+      &AudioContext::OnMediaPlayerDisconnect, WrapWeakPersistent(this)));
+}
+
+void AudioContext::OnMediaPlayerDisconnect() {
+  media_player_host_.reset();
+  media_player_observer_.reset();
+  volume_multiplier_ = 1.0;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.h b/third_party/blink/renderer/modules/webaudio/audio_context.h
index cbaab8d..2b309088 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -7,6 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/time/time.h"
+#include "media/mojo/mojom/media_player.mojom-blink.h"
 #include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
 #include "third_party/blink/public/mojom/webaudio/audio_context_manager.mojom-blink.h"
@@ -24,6 +25,8 @@
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -51,7 +54,8 @@
     : public BaseAudioContext,
       public mojom::blink::PermissionObserver,
       public mojom::blink::MediaDevicesListener,
-      public FrameVisibilityObserver {
+      public FrameVisibilityObserver,
+      public media::mojom::blink::MediaPlayer {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -105,6 +109,23 @@
   void FrameVisibilityChanged(
       mojom::blink::FrameVisibility frame_visibility) override;
 
+  // media::mojom::MediaPlayer  implementation.
+  void RequestPlay() override {}
+  void RequestPause(bool triggered_by_user) override {}
+  void RequestSeekForward(base::TimeDelta seek_time) override {}
+  void RequestSeekBackward(base::TimeDelta seek_time) override {}
+  void RequestSeekTo(base::TimeDelta seek_time) override {}
+  void RequestEnterPictureInPicture() override {}
+  void RequestMute(bool mute) override {}
+  void SetVolumeMultiplier(double multiplier) override;
+  void SetPersistentState(bool persistent) override {}
+  void SetPowerExperimentState(bool enabled) override {}
+  void SetAudioSinkId(const String&) override {}
+  void SuspendForFrameClosed() override {}
+  void RequestMediaRemoting() override {}
+  void RequestVisibility(
+      RequestVisibilityCallback request_visibility_cb) override {}
+
   // https://webaudio.github.io/web-audio-api/#AudioContext
   double baseLatency() const;
   double outputLatency() const;
@@ -133,6 +154,10 @@
 
   void HandleAudibility(AudioBus* destination_bus);
 
+  // Adjusts the output volume of the rendered audio in case we are being
+  // ducked.
+  void HandleVolumeMultiplier(AudioBus* destination_bus);
+
   AudioCallbackMetric GetCallbackMetric() const;
 
   // Returns the audio buffer duration of the output driving playout of
@@ -286,6 +311,12 @@
 
   LocalFrame* GetLocalFrame() const;
 
+  // Connects to the MediaPlayerHost to register as a media player.
+  void EnsureMediaPlayerConnection();
+
+  // Handles a disconnection from the MediaPlayerHost.
+  void OnMediaPlayerDisconnect();
+
   // https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspended-by-user-slot
   bool suspended_by_user_ = false;
 
@@ -411,6 +442,20 @@
   int pending_device_list_updates_
       GUARDED_BY_CONTEXT(main_thread_sequence_checker_) = 0;
 
+  // ID used for mojo communication with the MediaPlayerHost.
+  const int player_id_;
+
+  // Volume multiplier applied to audio output. Used to duck audio when the
+  // MediaPlayerHost requests ducking.
+  double volume_multiplier_ = 1.0;
+
+  HeapMojoAssociatedRemote<media::mojom::blink::MediaPlayerHost>
+      media_player_host_;
+  HeapMojoAssociatedReceiver<media::mojom::blink::MediaPlayer, AudioContext>
+      media_player_receiver_;
+  HeapMojoAssociatedRemote<media::mojom::blink::MediaPlayerObserver>
+      media_player_observer_;
+
   SEQUENCE_CHECKER(main_thread_sequence_checker_);
 };
 
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
index e2fe11c..def09a6 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
@@ -263,6 +263,8 @@
 
   context->HandlePostRenderTasks();
 
+  context->HandleVolumeMultiplier(destination_bus);
+
   context->HandleAudibility(destination_bus);
 
   // Advances the current sample-frame.
diff --git a/third_party/dawn b/third_party/dawn
index 28858cf..3f908f3 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 28858cfac0b9028bc69a27e17c0bb85cf01441f1
+Subproject commit 3f908f3907e532481e4c91d3b814b46869405fe8
diff --git a/third_party/libc++/src b/third_party/libc++/src
index cd5c0d7..1f7db750 160000
--- a/third_party/libc++/src
+++ b/third_party/libc++/src
@@ -1 +1 @@
-Subproject commit cd5c0d7a12c69adc579a64c8e75001489f36c800
+Subproject commit 1f7db7501cf902d5d3ad5fd9b31bea33bb8bf9da
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src
index 362f042..d7c6ddd 160000
--- a/third_party/llvm-libc/src
+++ b/third_party/llvm-libc/src
@@ -1 +1 @@
-Subproject commit 362f0421a0b01997d04a0950be2af6dbdfb10443
+Subproject commit d7c6dddc045ba4080880d43c34a2d9c2ce5c600f
diff --git a/third_party/skia b/third_party/skia
index b4613ba..cb18e02 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit b4613bade556fa6e5e8264712b2ee8ccf303a959
+Subproject commit cb18e028c403caba0f1189583d281ef72b5a4a2b
diff --git a/tools/metrics/histograms/metadata/custom_tabs/enums.xml b/tools/metrics/histograms/metadata/custom_tabs/enums.xml
index 0676ac3..bcf6192 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/enums.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/enums.xml
@@ -184,6 +184,24 @@
              memory"/>
 </enum>
 
+<!-- LINT.IfChange(CustomTabsUrlScheme) -->
+
+<enum name="CustomTabsUrlScheme">
+  <int value="0" label="Unknown scheme"/>
+  <int value="1" label="HTTP"/>
+  <int value="2" label="HTTPS"/>
+  <int value="3" label="File"/>
+  <int value="4" label="Ftp"/>
+  <int value="5" label="Data"/>
+  <int value="6" label="Javascript"/>
+  <int value="7" label="Chrome"/>
+  <int value="8" label="Blob"/>
+  <int value="9" label="Content"/>
+  <int value="10" label="Intent"/>
+</enum>
+
+<!-- LINT.ThenChange(//chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java:UrlScheme) -->
+
 <enum name="GoogleBottomBarButtonEvent">
   <int value="0" label="Unknown button"/>
   <int value="1" label="Chrome Page Insights button"/>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
index 6219140..038d5b3 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -227,6 +227,18 @@
   </summary>
 </histogram>
 
+<histogram name="CustomTabs.ContextMenu.UrlScheme" enum="CustomTabsUrlScheme"
+    expires_after="2025-05-03">
+  <owner>jinsukkim@chromium.org</owner>
+  <owner>chrome-connective-tissue@google.com</owner>
+  <summary>
+    Records the scheme of the URL for which the context menu is shown on Custom
+    Tabs. This histogram is to understand the relative volume of data: scheme
+    with a view to not displaying the menu 'Preview Page' for the scheme if the
+    volume is insignificant. Recorded when the context menu is opened.
+  </summary>
+</histogram>
+
 <histogram base="true" name="CustomTabs.DetachedResourceRequest.Duration"
     units="ms" expires_after="2024-03-17">
   <owner>lizeb@chromium.org</owner>
diff --git a/ui/strings/translations/ax_strings_fr-CA.xtb b/ui/strings/translations/ax_strings_fr-CA.xtb
index 7195bf8..7d51c80f 100644
--- a/ui/strings/translations/ax_strings_fr-CA.xtb
+++ b/ui/strings/translations/ax_strings_fr-CA.xtb
@@ -57,7 +57,7 @@
 <translation id="3078740164268491126">Tableau</translation>
 <translation id="3086746722712840547">Note</translation>
 <translation id="3175736971608411871">minuteur</translation>
-<translation id="3199563858620722075">zone de liste déroulante</translation>
+<translation id="3199563858620722075">zone de liste ou de texte</translation>
 <translation id="3220661731597678625">Étape en cours</translation>
 <translation id="3329013043687509092">Saturation</translation>
 <translation id="3486220673238053218">définition</translation>