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 ¤t_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>