diff --git a/DEPS b/DEPS index 1280cad..0dbce8a2 100644 --- a/DEPS +++ b/DEPS
@@ -273,7 +273,7 @@ 'screen_ai_windows_386': 'version:138.04', # siso CIPD package version. - 'siso_version': 'git_revision:d704490133011610c402696584afedea80829dbd', + 'siso_version': 'git_revision:7e7d85fc69f9084d2168385fb504b31e830dbfff', # download libaom test data 'download_libaom_testdata': False, @@ -303,7 +303,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '77f35f055a1543f51099fcea9575f83304d60de5', + 'v8_revision': 'ad9041e4d0f760e0c1c87d79a60b9ff1d2c77f96', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -375,7 +375,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '885aeee863e05189c83fadb0c302d07518eb5500', + 'crossbench_revision': '1de2eca3495784b797d977b40b7291a4a7cd06c1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -391,7 +391,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'fd0c28cbf06b695f677c525b6630f9f9e4a90eee', + 'devtools_frontend_revision': '7ad25e25037043f7a75e7a838a651c110b918d48', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -415,7 +415,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': '9fd4a731474f66c1ce5465f9b13919ad7487315d', + 'dawn_revision': 'fd276573ab859ea73c18581c018a773e4e3b8902', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1521,7 +1521,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '2dbc9aa95eddeb69a73546f3076874c682375331', + 'e4201862b5cd95321ccc5abba80f47a502829743', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1680,7 +1680,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '6X6Qqncm8SLOmqyM63uBJWfHB7X5An8CrBJbRmoOIG8C', + 'version': 'Y-CbCN6v5_4a_FprX22MQBJmya6JbjaSA-BUTEYbBdoC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2878,16 +2878,16 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@9a8d0205ed06a556ff17d4097afc218c993ec260', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3395378f6990e79066b5f1647f6f8ac5de07e26d', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@05cfcc1613c28c1274036f53616d66324f7cd383', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@50daff941d88609b4d2ad076eae558e727f8e5cd', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@e0bad2825dacf274578ec6d3c0e64e406d5e4fd7', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@dec28643ed15f68a2bc95650de25e0a7486b564c', 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@b39ab380a44b6c8df462c34e976ea9ce2d2c336b', 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@22c0f133e6675f9313c12fb5e58337f8fa9b9195', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@d671923090e4dc74c0ebdb10c6e09fa0826e1fe9', 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@54c9baf20802a13279e23fa4cb0528dd5cf16064', - 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@ce9b7e404fe1a312ff4c07961dc6f8a2fd925d44', + 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@3fa19fccc75171a6b607f95510c37739c606b809', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -2932,7 +2932,7 @@ Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '74932424d457e2ad5e70c914b3cdd55bec759d6a', + Var('webrtc_git') + '/src.git' + '@' + '4c619d7b0f2020e1b54fc62aaafc24fc34af78f8', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -4718,7 +4718,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '59a93a5717e2d1a9e523d986e012bde44aa5faa2', + '3b581c6c47e23717766c2c1922d6c7111db6cb4c', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 1aac9ba..6a2ad93 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1075,6 +1075,12 @@ 'dbus': { 'filepath': 'dbus/', }, + 'desktop_composebox': { + 'filepath': '^chrome/browser/resources/new_tab_page/composebox/|'\ + '^chrome/browser/ui/webui/new_tab_page/composebox/|'\ + '^chrome/test/data/webui/new_tab_page/composebox/|'\ + '^components/omnibox/composebox/', + }, 'desktop_in_product_help': { 'filepath': 'components/feature_engagement/|'\ 'components/user_education/|'\ @@ -1086,6 +1092,23 @@ 'chrome/browser/ui/webui/user_education_internals/|'\ 'chrome/browser/ui/webui/whats_new/', }, + 'desktop_omnibox': { + 'filepath': '^chrome/browser/ash/app_list/search/omnibox/|'\ + '^chrome/browser/autocomplete/|'\ + '^chrome/browser/resources/omnibox|'\ + '^chrome/browser/ui/location_bar/|'\ + '^chrome/browser/ui/omnibox/|'\ + '^chrome/browser/ui/views/location_bar/|'\ + '^chrome/browser/ui/views/omnibox/|'\ + '^chrome/browser/ui/webui/omnibox/|'\ + '^components/omnibox/|'\ + '^components/search_engines/' + }, + 'desktop_searchbox': { + 'filepath': '^chrome/browser/ui/webui/searchbox/|'\ + '^chrome/test/data/webui/cr_components/searchbox/|'\ + '^ui/webui/resources/cr_components/searchbox/', + }, 'desktop_whats_new': { 'filepath': 'chrome/browser/resources/whats_new/|'\ 'chrome/browser/ui/webui/whats_new/', @@ -1758,21 +1781,6 @@ '|chrome/browser/android/offline_pages/'\ '|chrome/android/java/src/org/chromium/chrome/browser/offlinepages/' }, - 'omnibox_desktop': { - 'filepath': '^chrome/browser/ash/app_list/search/omnibox/|'\ - '^chrome/browser/autocomplete/|'\ - '^chrome/browser/resources/new_tab_page/realbox/|'\ - '^chrome/browser/resources/omnibox|'\ - '^chrome/browser/ui/location_bar/|'\ - '^chrome/browser/ui/omnibox/|'\ - '^chrome/browser/ui/views/location_bar/|'\ - '^chrome/browser/ui/views/omnibox/|'\ - '^chrome/browser/ui/webui/omnibox/|'\ - '^chrome/browser/ui/webui/realbox/|'\ - '^chrome/test/data/webui/new_tab_page/realbox/|'\ - '^components/omnibox/|'\ - '^components/search_engines/' - }, 'omnibox_ios': { 'filepath': '^components/omnibox/|'\ '^components/search_engines/|'\ @@ -2915,8 +2923,12 @@ 'pnevase@microsoft.com'], 'data_decoder': ['mbarowsky+watch-data-decoder@chromium.org'], 'dbus': ['hashimoto+watch@chromium.org'], + 'desktop_composebox': ['omnibox-dev+watch@chromium.org'], 'desktop_in_product_help': ['dfried+watch@chromium.org', - 'estalin+watch@chromium.org'], + 'estalin+watch@chromium.org'], + 'desktop_omnibox': ['jdonnelly+watch@chromium.org', + 'omnibox-dev+watch@chromium.org'], + 'desktop_searchbox': ['omnibox-dev+watch@chromium.org'], 'desktop_whats_new': ['mickeyburks+watch@chromium.org'], 'device_bluetooth': ['mattreynolds+watch@chromium.org'], 'device_bound_sessions': ['drubery+watch@chromium.org'], @@ -3146,8 +3158,6 @@ 'offline_pages': ['chili+watch@chromium.org', 'dimich+watch@chromium.org', 'fgorski+watch@chromium.org'], - 'omnibox_desktop': ['jdonnelly+watch@chromium.org', - 'mahmadi+watch@chromium.org'], 'omnibox_ios': ['christianxu+watch@chromium.org'], 'origin_trials': ['chasej+watch@chromium.org', 'iclelland+watch@chromium.org'],
diff --git a/build/config/ios/ios_sdk.gni b/build/config/ios/ios_sdk.gni index 9a0ea63d..cab82e04 100644 --- a/build/config/ios/ios_sdk.gni +++ b/build/config/ios/ios_sdk.gni
@@ -32,6 +32,10 @@ # Set to true if building an app extension. ios_is_app_extension = false + + # Set to `target_platform` to generate Xcode project with the + # corresponding platform SDK. + target_xcode_platform = target_platform } # Building XCTests requires copying XCTRunner.app which is part of the iOS
diff --git a/cc/tiles/picture_layer_tiling_set_unittest.cc b/cc/tiles/picture_layer_tiling_set_unittest.cc index 71e0b9d6..af0e5adc 100644 --- a/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/cc/tiles/picture_layer_tiling_set_unittest.cc
@@ -66,44 +66,10 @@ PictureLayerTilingSet::TilingRange low_res_range(0, 0); PictureLayerTilingSet::TilingRange lower_than_low_res_range(0, 0); PictureLayerTiling* high_res_tiling; - PictureLayerTiling* low_res_tiling; scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds); - std::unique_ptr<TestablePictureLayerTilingSet> set = CreateTilingSet(&client); - set->AddTiling(gfx::AxisTransform2d(2.0, gfx::Vector2dF()), raster_source); - high_res_tiling = set->AddTiling(gfx::AxisTransform2d(), raster_source); - high_res_tiling->set_resolution(HIGH_RESOLUTION); - set->AddTiling(gfx::AxisTransform2d(0.5, gfx::Vector2dF()), raster_source); - low_res_tiling = set->AddTiling(gfx::AxisTransform2d(0.25, gfx::Vector2dF()), - raster_source); - low_res_tiling->set_resolution(LOW_RESOLUTION); - set->AddTiling(gfx::AxisTransform2d(0.125, gfx::Vector2dF()), raster_source); - - higher_than_high_res_range = - set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, higher_than_high_res_range.start); - EXPECT_EQ(1u, higher_than_high_res_range.end); - - high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(1u, high_res_range.start); - EXPECT_EQ(2u, high_res_range.end); - - between_high_and_low_res_range = - set->GetTilingRange(PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(2u, between_high_and_low_res_range.start); - EXPECT_EQ(3u, between_high_and_low_res_range.end); - - low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(3u, low_res_range.start); - EXPECT_EQ(4u, low_res_range.end); - - lower_than_low_res_range = - set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(4u, lower_than_low_res_range.start); - EXPECT_EQ(5u, lower_than_low_res_range.end); - std::unique_ptr<TestablePictureLayerTilingSet> set_without_low_res = CreateTilingSet(&client); set_without_low_res->AddTiling(gfx::AxisTransform2d(2.0, gfx::Vector2dF()), @@ -139,40 +105,6 @@ PictureLayerTilingSet::LOWER_THAN_LOW_RES); EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); - std::unique_ptr<TestablePictureLayerTilingSet> - set_with_only_high_and_low_res = CreateTilingSet(&client); - high_res_tiling = set_with_only_high_and_low_res->AddTiling( - gfx::AxisTransform2d(), raster_source); - high_res_tiling->set_resolution(HIGH_RESOLUTION); - low_res_tiling = set_with_only_high_and_low_res->AddTiling( - gfx::AxisTransform2d(0.5, gfx::Vector2dF()), raster_source); - low_res_tiling->set_resolution(LOW_RESOLUTION); - - higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange( - PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, - higher_than_high_res_range.end - higher_than_high_res_range.start); - - high_res_range = set_with_only_high_and_low_res->GetTilingRange( - PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(0u, high_res_range.start); - EXPECT_EQ(1u, high_res_range.end); - - between_high_and_low_res_range = - set_with_only_high_and_low_res->GetTilingRange( - PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(0u, between_high_and_low_res_range.end - - between_high_and_low_res_range.start); - - low_res_range = set_with_only_high_and_low_res->GetTilingRange( - PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(1u, low_res_range.start); - EXPECT_EQ(2u, low_res_range.end); - - lower_than_low_res_range = set_with_only_high_and_low_res->GetTilingRange( - PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); - std::unique_ptr<TestablePictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client); high_res_tiling =
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 03f399e..c46677ea 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -585,81 +585,6 @@ EXPECT_EQ(all_expected_tiles, all_actual_tiles); } -TEST_F(TileManagerTilePriorityQueueTest, - RasterTilePriorityQueueHighLowTilings) { - const gfx::Size layer_bounds(1000, 1000); - const gfx::Size viewport(800, 800); - host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(viewport)); - SetupDefaultTrees(layer_bounds); - - pending_layer()->tilings()->AddTiling( - gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), - pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling( - gfx::AxisTransform2d(1.5f, gfx::Vector2dF()), - active_layer()->raster_source()); - pending_layer()->tilings()->AddTiling( - gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), - pending_layer()->raster_source()); - active_layer()->tilings()->AddTiling( - gfx::AxisTransform2d(1.7f, gfx::Vector2dF()), - active_layer()->raster_source()); - - pending_layer()->tilings()->UpdateTilePriorities(gfx::Rect(viewport), 1.f, - 5.0, Occlusion(), true); - active_layer()->tilings()->UpdateTilePriorities(gfx::Rect(viewport), 1.f, 5.0, - Occlusion(), true); - - std::set<Tile*> all_expected_tiles; - for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) { - PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale_key() == 1.f) { - tiling->set_resolution(HIGH_RESOLUTION); - const auto& all_tiles = tiling->AllTilesForTesting(); - all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); - } else { - tiling->set_resolution(NON_IDEAL_RESOLUTION); - } - } - - for (size_t i = 0; i < active_layer()->num_tilings(); ++i) { - PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i); - if (tiling->contents_scale_key() == 1.5f) { - tiling->set_resolution(HIGH_RESOLUTION); - const auto& all_tiles = tiling->AllTilesForTesting(); - all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); - } else { - tiling->set_resolution(LOW_RESOLUTION); - // Low res tilings with a high res pending twin have to be processed - // because of possible activation tiles. - if (tiling->contents_scale_key() == 1.f) { - tiling->UpdateAndGetAllPrioritizedTilesForTesting(); - const auto& all_tiles = tiling->AllTilesForTesting(); - for (auto* tile : all_tiles) - EXPECT_TRUE(tile->required_for_activation()); - all_expected_tiles.insert(all_tiles.begin(), all_tiles.end()); - } - } - } - - std::unique_ptr<RasterTilePriorityQueue> queue(host_impl()->BuildRasterQueue( - SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); - EXPECT_FALSE(queue->IsEmpty()); - - size_t tile_count = 0; - std::set<Tile*> all_actual_tiles; - while (!queue->IsEmpty()) { - EXPECT_TRUE(queue->Top().tile()); - all_actual_tiles.insert(queue->Top().tile()); - ++tile_count; - queue->Pop(); - } - - EXPECT_EQ(tile_count, all_actual_tiles.size()); - EXPECT_EQ(all_expected_tiles.size(), all_actual_tiles.size()); - EXPECT_EQ(all_expected_tiles, all_actual_tiles); -} - TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueInvalidation) { const gfx::Size layer_bounds(1000, 1000); host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(500, 500)); @@ -2090,89 +2015,74 @@ TestSoftwareRasterBufferProvider raster_buffer_provider_; }; -TEST_F(PixelInspectTileManagerTest, LowResHasNoImage) { +TEST_F(PixelInspectTileManagerTest, ImageDrawn) { gfx::Size size(10, 12); - auto resolutions = - std::to_array<TileResolution>({HIGH_RESOLUTION, LOW_RESOLUTION}); host_impl()->CreatePendingTree(); - for (size_t i = 0; i < std::size(resolutions); ++i) { - SCOPED_TRACE(resolutions[i]); + SCOPED_TRACE(HIGH_RESOLUTION); - // Make a RasterSource that will draw a blue bitmap image. - sk_sp<SkSurface> surface = SkSurfaces::Raster( - SkImageInfo::MakeN32Premul(size.width(), size.height())); - ASSERT_NE(surface, nullptr); - surface->getCanvas()->clear(SK_ColorBLUE); - sk_sp<SkImage> blue_image = surface->makeImageSnapshot(); + // Make a RasterSource that will draw a blue bitmap image. + sk_sp<SkSurface> surface = SkSurfaces::Raster( + SkImageInfo::MakeN32Premul(size.width(), size.height())); + ASSERT_NE(surface, nullptr); + surface->getCanvas()->clear(SK_ColorBLUE); + sk_sp<SkImage> blue_image = surface->makeImageSnapshot(); - FakeRecordingSource recording_source(size); - recording_source.SetBackgroundColor(SkColors::kTransparent); - recording_source.SetRequiresClear(true); - PaintFlags flags; - flags.setColor(SK_ColorGREEN); - recording_source.add_draw_rect_with_flags(gfx::Rect(size), flags); - recording_source.add_draw_image(std::move(blue_image), gfx::Point()); - recording_source.Rerecord(); - scoped_refptr<RasterSource> raster = recording_source.CreateRasterSource(); + FakeRecordingSource recording_source(size); + recording_source.SetBackgroundColor(SkColors::kTransparent); + recording_source.SetRequiresClear(true); + PaintFlags flags; + flags.setColor(SK_ColorGREEN); + recording_source.add_draw_rect_with_flags(gfx::Rect(size), flags); + recording_source.add_draw_image(std::move(blue_image), gfx::Point()); + recording_source.Rerecord(); + scoped_refptr<RasterSource> raster = recording_source.CreateRasterSource(); - std::unique_ptr<PictureLayerImpl> layer = - PictureLayerImpl::Create(host_impl()->pending_tree(), 1); - layer->SetBounds(size); - layer->SetRasterSourceForTesting(raster); - PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); - layer->set_contributes_to_drawn_render_surface(true); + std::unique_ptr<PictureLayerImpl> layer = + PictureLayerImpl::Create(host_impl()->pending_tree(), 1); + layer->SetBounds(size); + layer->SetRasterSourceForTesting(raster); + PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); + layer->set_contributes_to_drawn_render_surface(true); - auto* tiling = tiling_set->AddTiling(gfx::AxisTransform2d(), raster); - tiling->set_resolution(resolutions[i]); - tiling->CreateAllTilesForTesting(gfx::Rect(size)); + auto* tiling = tiling_set->AddTiling(gfx::AxisTransform2d(), raster); + tiling->set_resolution(HIGH_RESOLUTION); + tiling->CreateAllTilesForTesting(gfx::Rect(size)); - // SMOOTHNESS_TAKES_PRIORITY ensures that we will actually raster - // LOW_RESOLUTION tiles, otherwise they are skipped. - host_impl()->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY); + // Call PrepareTiles and wait for it to complete. + auto* tile_manager = host_impl()->tile_manager(); + base::RunLoop run_loop; + EXPECT_CALL(MockHostImpl(), NotifyAllTileTasksCompleted()) + .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); + tile_manager->PrepareTiles(host_impl()->global_tile_state()); + run_loop.Run(); + tile_manager->PrepareToDraw(); - // Call PrepareTiles and wait for it to complete. - auto* tile_manager = host_impl()->tile_manager(); - base::RunLoop run_loop; - EXPECT_CALL(MockHostImpl(), NotifyAllTileTasksCompleted()) - .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); })); - tile_manager->PrepareTiles(host_impl()->global_tile_state()); - run_loop.Run(); - tile_manager->PrepareToDraw(); + Tile* tile = tiling->TileAt(0, 0); + // The tile in the tiling was rastered. + EXPECT_EQ(TileDrawInfo::RESOURCE_MODE, tile->draw_info().mode()); + EXPECT_TRUE(tile->draw_info().IsReadyToDraw()); - Tile* tile = tiling->TileAt(0, 0); - // The tile in the tiling was rastered. - EXPECT_EQ(TileDrawInfo::RESOURCE_MODE, tile->draw_info().mode()); - EXPECT_TRUE(tile->draw_info().IsReadyToDraw()); + gfx::Size resource_size = tile->draw_info().resource_size(); + SkColorType ct = ToClosestSkColorType( + TestSoftwareRasterBufferProvider::kSharedImageFormat); + auto info = SkImageInfo::Make(resource_size.width(), resource_size.height(), + ct, kPremul_SkAlphaType); + // CreateLayerTreeFrameSink() sets up a software compositing, so the + // tile resource will be a bitmap. + auto* backing = tile->draw_info().GetResource().backing(); + SkBitmap bitmap; + auto mapping = backing->shared_image()->Map(); + void* pixels = mapping->GetMemoryForPlane(0).data(); + bitmap.installPixels(info, pixels, info.minRowBytes()); - gfx::Size resource_size = tile->draw_info().resource_size(); - SkColorType ct = ToClosestSkColorType( - TestSoftwareRasterBufferProvider::kSharedImageFormat); - auto info = SkImageInfo::Make(resource_size.width(), resource_size.height(), - ct, kPremul_SkAlphaType); - // CreateLayerTreeFrameSink() sets up a software compositing, so the - // tile resource will be a bitmap. - auto* backing = tile->draw_info().GetResource().backing(); - SkBitmap bitmap; - auto mapping = backing->shared_image()->Map(); - void* pixels = mapping->GetMemoryForPlane(0).data(); - bitmap.installPixels(info, pixels, info.minRowBytes()); - - for (int x = 0; x < size.width(); ++x) { - for (int y = 0; y < size.height(); ++y) { - SCOPED_TRACE(y); - SCOPED_TRACE(x); - if (resolutions[i] == LOW_RESOLUTION) { - // Since it's low res, the bitmap was not drawn, and the background - // (green) is visible instead. - ASSERT_EQ(SK_ColorGREEN, bitmap.getColor(x, y)); - } else { - EXPECT_EQ(HIGH_RESOLUTION, resolutions[i]); - // Since it's high res, the bitmap (blue) was drawn, and the - // background is not visible. - ASSERT_EQ(SK_ColorBLUE, bitmap.getColor(x, y)); - } - } + for (int x = 0; x < size.width(); ++x) { + for (int y = 0; y < size.height(); ++y) { + SCOPED_TRACE(y); + SCOPED_TRACE(x); + // Since it's high res, the bitmap (blue) was drawn, and the + // background is not visible. + ASSERT_EQ(SK_ColorBLUE, bitmap.getColor(x, y)); } } }
diff --git a/chrome/VERSION b/chrome/VERSION index c175bdd..b3f28095 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=139 MINOR=0 -BUILD=7242 +BUILD=7243 PATCH=0
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml index 3ef2ccf..5b98898 100644 --- a/chrome/android/java/res/values/ids.xml +++ b/chrome/android/java/res/values/ids.xml
@@ -141,6 +141,7 @@ <item type="id" name="downloads_menu_id" /> <item type="id" name="all_bookmarks_menu_id" /> <item type="id" name="recent_tabs_menu_id" /> + <item type="id" name="extensions_menu_id" /> <item type="id" name="page_zoom_id" /> <item type="id" name="share_menu_id" /> <item type="id" name="direct_share_menu_id" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 8a00493..768ffca9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -3397,6 +3397,17 @@ NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_RECENT_TABS_MANAGER); } RecordUserAction.record("MobileMenuRecentTabs"); + } else if (id == R.id.extensions_menu_id) { + LoadUrlParams params = + new LoadUrlParams( + UrlConstants.CHROME_EXTENSIONS_URL, PageTransition.AUTO_TOPLEVEL); + if (currentTab == null) { + getTabCreator(getCurrentTabModel().isIncognito()) + .createNewTab(params, TabLaunchType.FROM_CHROME_UI, null); + } else { + currentTab.loadUrl(params); + } + RecordUserAction.record("MobileMenuExtensions"); } else if (id == R.id.close_tab) { // TODO(crbug.com/375468032): use triggeringMotion to decide // TabClosureParams.allowUndo.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java index 1b2b429..a6b52cdb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java
@@ -279,10 +279,6 @@ mScreenButton.setOnClickListener(view -> startAndroidCapturePrompt()); - // TODO(crbug.com/352187279): Show button once the entire screen sharing pipeline is - // working. - mScreenButton.setVisibility(View.GONE); - mModalDialogManager.showDialog(mPropertyModel, ModalDialogManager.ModalDialogType.TAB); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java index 375746a..84475ae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
@@ -57,6 +57,7 @@ import org.chromium.chrome.browser.ui.appmenu.AppMenuDelegate; import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler; import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties; +import org.chromium.chrome.browser.ui.extensions.ExtensionsBuildflags; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.browser_ui.accessibility.PageZoomCoordinator; import org.chromium.components.dom_distiller.core.DomDistillerFeatures; @@ -258,6 +259,9 @@ // Recent Tabs if (shouldShowRecentTabsItem()) modelList.add(buildRecentTabsItem()); + // Extensions + if (shouldShowExtensionsItem()) modelList.add(buildExtensionsItem()); + // Divider modelList.add( new MVCListAdapter.ListItem( @@ -585,6 +589,22 @@ shouldShowIconBeforeItem() ? R.drawable.devices_black_24dp : 0)); } + private boolean shouldShowExtensionsItem() { + return ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS + && !ChromeFeatureList.isEnabled( + ChromeFeatureList.BLOCK_INSTALLING_EXTENSIONS_ON_DESKTOP_ANDROID); + } + + private MVCListAdapter.ListItem buildExtensionsItem() { + assert shouldShowExtensionsItem(); + return new MVCListAdapter.ListItem( + AppMenuHandler.AppMenuItemType.STANDARD, + buildModelForStandardMenuItem( + R.id.extensions_menu_id, + R.string.menu_extensions, + shouldShowIconBeforeItem() ? R.drawable.ic_extension_24dp : 0)); + } + private boolean shouldShowPageZoomItem(Tab currentTab) { return currentTab != null && shouldShowWebContentsDependentMenuItem(currentTab)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 69bc392a..f0e6c83 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -2272,10 +2272,6 @@ mUpdateMenuItemHelper.registerObserver(mMenuStateObserver); } - if (mExtensionToolbarManager != null) { - mExtensionToolbarManager.initializeWithNative(); - } - mInitializedWithNative = true; mTabModelSelector.getCurrentTabModelSupplier().addObserver(mCurrentTabModelObserver); refreshSelectedTab(mActivityTabProvider.get());
diff --git a/chrome/android/junit/BUILD.gn b/chrome/android/junit/BUILD.gn index 7cf5fdeb..b584d4cf 100644 --- a/chrome/android/junit/BUILD.gn +++ b/chrome/android/junit/BUILD.gn
@@ -191,6 +191,7 @@ "//chrome/browser/ui/android/desktop_windowing:java", "//chrome/browser/ui/android/edge_to_edge:java", "//chrome/browser/ui/android/ephemeraltab:java", + "//chrome/browser/ui/android/extensions:java", "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/android/google_bottom_bar:java", "//chrome/browser/ui/android/google_bottom_bar:proto_java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java index 8a05889..55cc1677 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
@@ -105,6 +105,7 @@ import org.chromium.chrome.browser.ui.appmenu.AppMenuDelegate; import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler; import org.chromium.chrome.browser.ui.appmenu.AppMenuItemProperties; +import org.chromium.chrome.browser.ui.extensions.ExtensionsBuildflags; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.components.browser_ui.accessibility.PageZoomCoordinator; @@ -145,6 +146,7 @@ @RunWith(BaseRobolectricTestRunner.class) @DisableFeatures({ ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_PAGE_SUMMARY, + ChromeFeatureList.BLOCK_INSTALLING_EXTENSIONS_ON_DESKTOP_ANDROID, ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION, DomDistillerFeatures.READER_MODE_IMPROVEMENTS }) @@ -477,22 +479,27 @@ assertEquals(MenuGroup.PAGE_MENU, mTabbedAppMenuPropertiesDelegate.getMenuGroup()); MVCListAdapter.ModelList modelList = mTabbedAppMenuPropertiesDelegate.getMenuItems(); - Integer[] expectedItems = { - R.id.icon_row_menu_id, - R.id.new_tab_menu_id, - R.id.new_incognito_tab_menu_id, - R.id.divider_line_id, - R.id.open_history_menu_id, - R.id.quick_delete_menu_id, - R.id.quick_delete_divider_line_id, - R.id.downloads_menu_id, - R.id.all_bookmarks_menu_id, - R.id.recent_tabs_menu_id, - R.id.divider_line_id, - R.id.preferences_id, - R.id.help_id - }; - assertMenuItemsAreEqual(modelList, expectedItems); + List<Integer> expectedItems = + new ArrayList<>( + Arrays.asList( + R.id.icon_row_menu_id, + R.id.new_tab_menu_id, + R.id.new_incognito_tab_menu_id, + R.id.divider_line_id, + R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, + R.id.downloads_menu_id, + R.id.all_bookmarks_menu_id, + R.id.recent_tabs_menu_id, + R.id.divider_line_id, + R.id.preferences_id, + R.id.help_id)); + + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } + assertMenuItemsAreEqual(modelList, expectedItems.toArray(new Integer[0])); } @Test @@ -510,26 +517,31 @@ assertEquals(MenuGroup.PAGE_MENU, mTabbedAppMenuPropertiesDelegate.getMenuGroup()); MVCListAdapter.ModelList modelList = mTabbedAppMenuPropertiesDelegate.getMenuItems(); - Integer[] expectedItems = { - R.id.icon_row_menu_id, - R.id.new_tab_menu_id, - R.id.new_incognito_tab_menu_id, - R.id.divider_line_id, - R.id.open_history_menu_id, - R.id.quick_delete_menu_id, - R.id.quick_delete_divider_line_id, - R.id.downloads_menu_id, - R.id.all_bookmarks_menu_id, - R.id.recent_tabs_menu_id, - R.id.divider_line_id, - R.id.share_menu_id, - R.id.find_in_page_id, - R.id.open_with_id, - R.id.divider_line_id, - R.id.preferences_id, - R.id.help_id - }; - assertMenuItemsAreEqual(modelList, expectedItems); + List<Integer> expectedItems = + new ArrayList<>( + Arrays.asList( + R.id.icon_row_menu_id, + R.id.new_tab_menu_id, + R.id.new_incognito_tab_menu_id, + R.id.divider_line_id, + R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, + R.id.downloads_menu_id, + R.id.all_bookmarks_menu_id, + R.id.recent_tabs_menu_id, + R.id.divider_line_id, + R.id.share_menu_id, + R.id.find_in_page_id, + R.id.open_with_id, + R.id.divider_line_id, + R.id.preferences_id, + R.id.help_id)); + + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } + assertMenuItemsAreEqual(modelList, expectedItems.toArray(new Integer[0])); } @Test @@ -571,6 +583,10 @@ expectedTitles.add(R.string.menu_bookmarks); expectedItems.add(R.id.recent_tabs_menu_id); expectedTitles.add(R.string.menu_recent_tabs); + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + expectedTitles.add(R.string.menu_extensions); + } expectedItems.add(R.id.divider_line_id); expectedTitles.add(0); expectedItems.add(R.id.share_menu_id); @@ -642,6 +658,10 @@ expectedTitles.add(R.string.menu_bookmarks); expectedItems.add(R.id.recent_tabs_menu_id); expectedTitles.add(R.string.menu_recent_tabs); + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + expectedTitles.add(R.string.menu_extensions); + } expectedItems.add(R.id.divider_line_id); expectedTitles.add(0); expectedItems.add(R.id.share_menu_id); @@ -691,29 +711,33 @@ assertEquals(MenuGroup.PAGE_MENU, mTabbedAppMenuPropertiesDelegate.getMenuGroup()); MVCListAdapter.ModelList modelList = mTabbedAppMenuPropertiesDelegate.getMenuItems(); - Integer[] expectedItems = { - R.id.icon_row_menu_id, - R.id.new_tab_menu_id, - R.id.new_incognito_tab_menu_id, - R.id.divider_line_id, - R.id.open_history_menu_id, - R.id.quick_delete_menu_id, - R.id.quick_delete_divider_line_id, - R.id.downloads_menu_id, - R.id.all_bookmarks_menu_id, - R.id.recent_tabs_menu_id, - R.id.divider_line_id, - R.id.share_menu_id, - R.id.find_in_page_id, - R.id.translate_id, - R.id.universal_install, - // Request desktop site is hidden. - R.id.auto_dark_web_contents_id, - R.id.divider_line_id, - R.id.preferences_id, - R.id.help_id - }; - assertMenuItemsAreEqual(modelList, expectedItems); + List<Integer> expectedItems = + new ArrayList<>( + Arrays.asList( + R.id.icon_row_menu_id, + R.id.new_tab_menu_id, + R.id.new_incognito_tab_menu_id, + R.id.divider_line_id, + R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.quick_delete_divider_line_id, + R.id.downloads_menu_id, + R.id.all_bookmarks_menu_id, + R.id.recent_tabs_menu_id, + R.id.divider_line_id, + R.id.share_menu_id, + R.id.find_in_page_id, + R.id.translate_id, + R.id.universal_install, + // Request desktop site is hidden. + R.id.auto_dark_web_contents_id, + R.id.divider_line_id, + R.id.preferences_id, + R.id.help_id)); + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } + assertMenuItemsAreEqual(modelList, expectedItems.toArray(new Integer[0])); } @Test @@ -745,25 +769,29 @@ assertEquals(MenuGroup.PAGE_MENU, mTabbedAppMenuPropertiesDelegate.getMenuGroup()); MVCListAdapter.ModelList modelList = mTabbedAppMenuPropertiesDelegate.getMenuItems(); - Integer[] expectedItems = { - R.id.update_menu_id, - R.id.new_tab_menu_id, - R.id.new_incognito_tab_menu_id, - R.id.open_history_menu_id, - R.id.quick_delete_menu_id, - R.id.downloads_menu_id, - R.id.all_bookmarks_menu_id, - R.id.recent_tabs_menu_id, - R.id.translate_id, - R.id.share_menu_id, - R.id.find_in_page_id, - R.id.universal_install, - R.id.reader_mode_prefs_id, - R.id.auto_dark_web_contents_id, - R.id.preferences_id, - R.id.help_id - }; - assertMenuItemsHaveIcons(modelList, expectedItems); + List<Integer> expectedItems = + new ArrayList<>( + Arrays.asList( + R.id.update_menu_id, + R.id.new_tab_menu_id, + R.id.new_incognito_tab_menu_id, + R.id.open_history_menu_id, + R.id.quick_delete_menu_id, + R.id.downloads_menu_id, + R.id.all_bookmarks_menu_id, + R.id.recent_tabs_menu_id, + R.id.translate_id, + R.id.share_menu_id, + R.id.find_in_page_id, + R.id.universal_install, + R.id.reader_mode_prefs_id, + R.id.auto_dark_web_contents_id, + R.id.preferences_id, + R.id.help_id)); + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } + assertMenuItemsHaveIcons(modelList, expectedItems.toArray(new Integer[0])); } @Test @@ -880,6 +908,9 @@ if (!BuildConfig.IS_DESKTOP_ANDROID) { expectedItems.add(R.id.request_desktop_site_id); } + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } assertMenuItemsAreEqual(modelList, expectedItems.toArray(new Integer[0])); @@ -955,6 +986,9 @@ if (!BuildConfig.IS_DESKTOP_ANDROID) { expectedItems.add(R.id.request_desktop_site_id); } + if (ExtensionsBuildflags.ENABLE_DESKTOP_ANDROID_EXTENSIONS) { + expectedItems.add(R.id.extensions_menu_id); + } assertMenuItemsAreEqual(modelList, expectedItems.toArray(new Integer[0])); }
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb index 8297d1b..d02577c4 100644 --- a/chrome/app/resources/generated_resources_lo.xtb +++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -2178,6 +2178,7 @@ <translation id="24786041351753425">ເປີດການນຳໃຊ້ບໍລິການການກູ້ຄືນຂໍ້ມູນ.</translation> <translation id="2479541499757560845">ການຕັ້ງຄ່າແປ້ນພິມການຊ່ວຍເຂົ້າເຖິງ</translation> <translation id="2480868415629598489">ແກ້ໄຂຂໍ້ມູນທີ່ທ່ານສຳເນົາ ແລະ ວາງໃສ່</translation> +<translation id="2480881140544300950">ໂປຣແກຣມຊອກຫາປັດຈຸບັນທີ່ຈັດການໜ້າແຖບໃໝ່ຂອງທ່ານ</translation> <translation id="2482878487686419369">ການແຈ້ງເຕືອນ</translation> <translation id="2482895651873876648">ຍ້າຍແຖບໄປໃສ່ກຸ່ມ <ph name="GROUP_NAME" /> - <ph name="GROUP_CONTENTS" /> ແລ້ວ</translation> <translation id="2483627560139625913">ຕັ້ງໂປຣແກຣມຊອກຫາໃນການຕັ້ງຄ່າໂປຣແກຣມທ່ອງເວັບ Chrome</translation> @@ -5379,6 +5380,7 @@ <translation id="4742970037960872810">ລຶບໄຮໄລ້ອອກ</translation> <translation id="4743260470722568160"><ph name="BEGIN_LINK" />ສຶກສາວິທີອັບເດດແອັບພລິເຄຊັນ<ph name="END_LINK" /></translation> <translation id="4743990041512863976">ອະນຸຍາດ – <ph name="PERMISSION_DETAILS" />. ເປີດ <ph name="LINK_BEGIN" />ສິດເຂົ້າເຖິງໄມໂຄຣໂຟນຂອງລະບົບ<ph name="LINK_END" />.</translation> +<translation id="4744172369799559159">ທີມງານຈະກວດສອບໜ້າລະຫັດຜ່ານ ແລະ ຂໍ້ມູນທີ່ກ່ຽວຂ້ອງເພື່ອປັບປຸງຄຸນສົມບັດນີ້, ແຕ່ລະຫັດຜ່ານຂອງທ່ານຈະຖືກເຂົ້າລະຫັດໄວ້ ແລະ ຈະບໍ່ມີໃຜເບິ່ງເຫັນໄດ້.</translation> <translation id="4744260496658845719">ຄວາມສະຫວ່າງຂອງໄຟປຸ່ມແປ້ນພິມ</translation> <translation id="4744268813103118742">ເຂົ້າໄປເວັບໄຊ</translation> <translation id="4744571849207727284">Excel</translation> @@ -6337,6 +6339,7 @@ <translation id="5434065355175441495">ການໃສ່ລະຫັດ PKCS #1 RSA</translation> <translation id="5435274640623994081">ເປີດນຳໃຊ້ການບັນທຶກ earcon</translation> <translation id="5435779377906857208">ອະນຸຍາດໃຫ້ <ph name="HOST" /> ເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານທຸກເທື່ອ</translation> +<translation id="5436211819997237281">ສ່ວນຂະຫຍາຍປັດຈຸບັນທີ່ຈັດການໜ້າແຖບໃໝ່ຂອງທ່ານ</translation> <translation id="5436492226391861498">ກໍາລັງລໍຖ້າຊ່ອງພຣັອກຊີ...</translation> <translation id="5436510242972373446">ຊອກຫາ <ph name="SITE_NAME" /> :</translation> <translation id="5438014818441491616">ຕອນນີ້ໜ້າຈໍ <ph name="WINDOW_SIDE" /> ກວ້າງ <ph name="WINDOW_SIZE_PERCENT" />, ແຖບ <ph name="PANE_SIDE" /> ກວ້າງ <ph name="PANE_SIZE_PERCENT" />.</translation> @@ -9225,6 +9228,7 @@ <translation id="7529411698175791732">ກວດເບິ່ງການເຊື່ອມຕໍ່ອິນເຕີເນັດຂອງທ່ານ. ຖ້າບັນຫາຍັງສືບຕໍ່, ກະລຸນາລອງອອກຈາກລະບົບແລ້ວເຂົ້າສູ່ລະບົບຄືນໃໝ່.</translation> <translation id="7529865045818406536">ເຄືອຂ່າຍທີ່ຕ້ອງການຈະຖືກໃຊ້ຫາກມີເຄືອຂ່າຍກ່ອນໜ້າທີ່ສາມາດໃຊ້ໄດ້ຫຼາຍກວ່າໜຶ່ງເຄືອຂ່າຍ</translation> <translation id="7530016656428373557">ອັດຕາປ່ອຍອອກມາເປັນວັດຕ໌</translation> +<translation id="7530215951451994972">ສ້າງຮູບ</translation> <translation id="7531771599742723865">ມີການນຳໃຊ້ອຸປະກອນຢູ່</translation> <translation id="7531779363494549572">ໄປຫາການຕັ້ງຄ່າ > ແອັບ ແລະ ການແຈ້ງເຕືອນ > ການແຈ້ງເຕືອນ.</translation> <translation id="7532009420053991888"><ph name="LINUX_APP_NAME" /> ບໍ່ຕອບສະໜອງ. ເລືອກ "ບັງຄັບປິດ" ເພື່ອປິດແອັບ.</translation>
diff --git a/chrome/browser/ash/crosapi/structured_metrics_service_ash.cc b/chrome/browser/ash/crosapi/structured_metrics_service_ash.cc deleted file mode 100644 index db6ddb0..0000000 --- a/chrome/browser/ash/crosapi/structured_metrics_service_ash.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ash/crosapi/structured_metrics_service_ash.h" - -#include "chromeos/crosapi/mojom/structured_metrics_service.mojom.h" -#include "components/metrics/structured/event.h" -#include "components/metrics/structured/recorder.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver_set.h" - -namespace crosapi { - -StructuredMetricsServiceAsh::StructuredMetricsServiceAsh() = default; -StructuredMetricsServiceAsh::~StructuredMetricsServiceAsh() = default; - -void StructuredMetricsServiceAsh::BindReceiver( - mojo::PendingReceiver<mojom::StructuredMetricsService> receiver) { - receivers_.Add(this, std::move(receiver)); -} - -void StructuredMetricsServiceAsh::Record( - std::vector<::metrics::structured::Event> events) { - for (auto& event : events) { - metrics::structured::Recorder::GetInstance()->RecordEvent(std::move(event)); - } -} - -} // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/structured_metrics_service_ash.h b/chrome/browser/ash/crosapi/structured_metrics_service_ash.h deleted file mode 100644 index 552a0c35..0000000 --- a/chrome/browser/ash/crosapi/structured_metrics_service_ash.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ASH_CROSAPI_STRUCTURED_METRICS_SERVICE_ASH_H_ -#define CHROME_BROWSER_ASH_CROSAPI_STRUCTURED_METRICS_SERVICE_ASH_H_ - -#include "chromeos/crosapi/mojom/structured_metrics_service.mojom.h" -#include "components/metrics/structured/event.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver_set.h" - -namespace crosapi { - -// Implements the StructuredMetricsService mojo interface to record events from -// AshStructuredMetricsDelegate. Wrapper to validate and record structured -// metrics. Lives on the UI thread. Although both AshStructuredMetricsDelegate -// and StructuredMetricsServiceAsh live in the same Ash process, instantiating a -// mojo pipe adds little overhead and provides lots of benefits out of the box -// (ie message buffer). -class StructuredMetricsServiceAsh final - : public mojom::StructuredMetricsService { - public: - StructuredMetricsServiceAsh(); - StructuredMetricsServiceAsh(const StructuredMetricsServiceAsh&) = delete; - StructuredMetricsServiceAsh& operator=(const StructuredMetricsServiceAsh&) = - delete; - ~StructuredMetricsServiceAsh() override; - - void BindReceiver( - mojo::PendingReceiver<mojom::StructuredMetricsService> receiver); - - // crosapi::mojom::StructuredMetricsService - void Record(std::vector<::metrics::structured::Event> events) override; - - private: - mojo::ReceiverSet<mojom::StructuredMetricsService> receivers_; -}; - -} // namespace crosapi - -#endif // CHROME_BROWSER_ASH_CROSAPI_STRUCTURED_METRICS_SERVICE_ASH_H_
diff --git a/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc b/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc index f0f44726..f8e44a5 100644 --- a/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc +++ b/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc
@@ -62,19 +62,3 @@ autofill_ai::AutofillAiManager& ChromeAutofillAiClient::GetManager() { return prediction_improvements_manager_; } - -void ChromeAutofillAiClient::ShowSaveOrUpdateBubble( - autofill::EntityInstance new_entity, - std::optional<autofill::EntityInstance> old_entity, - EntitySaveOrUpdatePromptResultCallback prompt_acceptance_callback) { -#if !BUILDFLAG(IS_ANDROID) - if (auto* controller = - autofill_ai::SaveOrUpdateAutofillAiDataController::GetOrCreate( - &*web_contents_, GetAutofillClient().GetAppLocale())) { - controller->ShowPrompt(std::move(new_entity), std::move(old_entity), - std::move(prompt_acceptance_callback)); - return; - } -#endif // !BUILDFLAG(IS_ANDROID) - std::move(prompt_acceptance_callback).Run(EntitySaveOrUpdatePromptResult()); -}
diff --git a/chrome/browser/autofill_ai/chrome_autofill_ai_client.h b/chrome/browser/autofill_ai/chrome_autofill_ai_client.h index b42262d2..c484810 100644 --- a/chrome/browser/autofill_ai/chrome_autofill_ai_client.h +++ b/chrome/browser/autofill_ai/chrome_autofill_ai_client.h
@@ -33,11 +33,6 @@ // AutofillAiClient: autofill::ContentAutofillClient& GetAutofillClient() override; autofill_ai::AutofillAiManager& GetManager() override; - void ShowSaveOrUpdateBubble( - autofill::EntityInstance new_entity, - std::optional<autofill::EntityInstance> old_entity, - EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback) - override; private: explicit ChromeAutofillAiClient(content::WebContents* web_contents);
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index 33905e7..b71e4ce 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -141,6 +141,18 @@ feature_overrides.EnableFeature(kAndroidMediaPicker); feature_overrides.EnableFeature(features::kUserMediaScreenCapturing); + // Enable desktop tab management features. + // TODO(crbug.com/422902880): Remove when tablet rollout is complete. + feature_overrides.EnableFeature( + base::features::kUseSharedRebindServiceConnection); + // TODO(crbug.com/422902940): Remove when tablet rollout is complete. + feature_overrides.EnableFeature( + base::features::kBackgroundNotPerceptibleBinding); + // TODO(crbug.com/422902625): Remove when rollout is complete to all form + // factors. + feature_overrides.EnableFeature(chrome::android::kProcessRankPolicyAndroid); + feature_overrides.EnableFeature(features::kGroupRebindingForGroupImportance); + feature_overrides.EnableFeature(chrome::android::kProtectedTabsAndroid); #endif // BUILDFLAG(IS_DESKTOP_ANDROID) // Desktop-first features which are past incubation should either end up here, // or to a finch trial that enables it for all form factors.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index f8cf92f..facdcce 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -323,6 +323,7 @@ #include "content/public/browser/permission_descriptor_util.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/service_worker_context.h" #include "content/public/browser/site_isolation_mode.h" #include "content/public/browser/site_isolation_policy.h" #include "content/public/browser/sms_fetcher.h" @@ -340,6 +341,7 @@ #include "content/public/common/content_descriptors.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "content/public/common/origin_util.h" #include "content/public/common/url_utils.h" #include "content/public/common/window_container_type.mojom-shared.h" #include "device/fido/features.h" @@ -777,6 +779,11 @@ "SkipPagehideInCommitForDSENavigation", base::FEATURE_DISABLED_BY_DEFAULT); +// Warm up the ServiceWorker registration for DSE. +BASE_FEATURE(kPrewarmServiceWorkerRegistrationForDSE, + "PrewarmServiceWorkerRegistrationForDSE", + base::FEATURE_DISABLED_BY_DEFAULT); + // A small ChromeBrowserMainExtraParts that invokes a callback when threads are // ready. Used to initialize ChromeContentBrowserClient data that needs the UI // thread. @@ -3767,6 +3774,61 @@ return !cookie_settings->ShouldBlockThirdPartyCookies(); } +void ChromeContentBrowserClient::PrewarmServiceWorkerRegistrationForDSE( + content::BrowserContext* browser_context, + content::ServiceWorkerContext& service_worker_context) { + TRACE_EVENT( + "ServiceWorker", + "ChromeContentBrowserClient::PrewarmServiceWorkerRegistrationForDSE"); + + if (ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting()) { + CHECK_IS_TEST(); + ++(*ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting()); + } + + if (!base::FeatureList::IsEnabled(kPrewarmServiceWorkerRegistrationForDSE)) { + return; + } + + Profile* profile = Profile::FromBrowserContext(browser_context); + + if (!profile) { + return; + } + + TemplateURLService* template_url_service = + TemplateURLServiceFactory::GetForProfile(profile); + + if (!template_url_service) { + return; + } + + GURL url = + template_url_service->GenerateSearchURLForDefaultSearchProvider(u""); + + if (!content::OriginCanAccessServiceWorkers(url)) { + return; + } + + const blink::StorageKey key = + blink::StorageKey::CreateFirstParty(url::Origin::Create(url)); + + if (!service_worker_context.MaybeHasRegistrationForStorageKey(key)) { + return; + } + + service_worker_context.CheckHasServiceWorker(url, key, base::DoNothing()); +} + +// static +std::optional<int>& ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting() { + static std::optional<int> call_count; + return call_count; +} + bool ChromeContentBrowserClient::CanSendSCTAuditingReport( content::BrowserContext* browser_context) { return SCTReportingService::CanSendSCTAuditingReport();
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index f54b754..cce71f1 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -457,6 +457,11 @@ bool AreThirdPartyCookiesGenerallyAllowed( content::BrowserContext* browser_context, content::WebContents* web_contents) override; + void PrewarmServiceWorkerRegistrationForDSE( + content::BrowserContext* browser_context, + content::ServiceWorkerContext& service_worker_context) override; + static std::optional<int>& + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting(); bool CanSendSCTAuditingReport( content::BrowserContext* browser_context) override; void OnNewSCTAuditingReportSent(
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc index 2263df9..d689ce58 100644 --- a/chrome/browser/chrome_service_worker_browsertest.cc +++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -24,6 +24,7 @@ #include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" +#include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h" #include "chrome/browser/profiles/profile.h" @@ -1590,4 +1591,27 @@ EXPECT_FALSE(HasHeader(received_request(), "Cookie")); } +class ChromeServiceWorkerPrewarmForDSETest : public InProcessBrowserTest { + public: + void SetUp() override { + ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting() = 0; + // The following step starts the browser, and prewarms the registration of + // ServiceWorker for DSE. + InProcessBrowserTest::SetUp(); + } + + void TearDown() override { + ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting() = + std::nullopt; + } +}; + +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerPrewarmForDSETest, PrewarmIsCalled) { + EXPECT_GE(*ChromeContentBrowserClient:: + PrewarmServiceWorkerRegistrationForDSECalledCountForTesting(), + 1); +} + } // namespace chrome_service_worker_browser_test
diff --git a/chrome/browser/devtools/devtools_browsertest.cc b/chrome/browser/devtools/devtools_browsertest.cc index 2163522..ba244e4 100644 --- a/chrome/browser/devtools/devtools_browsertest.cc +++ b/chrome/browser/devtools/devtools_browsertest.cc
@@ -1836,7 +1836,8 @@ } // Disabled on Windows due to flakiness. http://crbug.com/183649 -#if BUILDFLAG(IS_WIN) +// TODO(crbug.com/425268770): Flaky on Linux. +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) #define MAYBE_TestDevToolsExtensionMessaging \ DISABLED_TestDevToolsExtensionMessaging #else
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc index 5496b03..7d55128c 100644 --- a/chrome/browser/extensions/extension_management.cc +++ b/chrome/browser/extensions/extension_management.cc
@@ -171,14 +171,8 @@ update_url ? *update_url : std::string()); } -ManagedInstallationMode ExtensionManagement::GetInstallationMode( - const ExtensionId& extension_id, - const std::string& update_url) { -// Block extensions for managed profiles on Desktop Android. This is -// temporary until extensions are ready for dogfooding. -// TODO(crbug.com/422307625): Remove this check once extensions are ready for -// dogfooding. -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) +bool ExtensionManagement::ExtensionsEnabledForDesktopAndroid() const { if (enterprise_util::IsBrowserManaged(profile_)) { // Disable extensions only for specific managed accounts. // This check keeps many tests from failing. @@ -187,11 +181,26 @@ if (base::Contains(user_name, "@")) { std::string domain = gaia::ExtractDomainName(user_name); if (domain == "google.com" || domain == "managedchrome.com") { - return ManagedInstallationMode::kRemoved; + return false; } } } -#endif // BUILDFLAG(IS_ANDROID) + return true; +} +#endif // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + +ManagedInstallationMode ExtensionManagement::GetInstallationMode( + const ExtensionId& extension_id, + const std::string& update_url) { +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + // Block extensions for managed profiles on Desktop Android. This is + // temporary until extensions are ready for dogfooding. + // TODO(crbug.com/422307625): Remove this check once extensions are ready for + // dogfooding. + if (!ExtensionsEnabledForDesktopAndroid()) { + return ManagedInstallationMode::kRemoved; + } +#endif // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) // Check per-extension installation mode setting first. auto* setting = GetSettingsForId(extension_id);
diff --git a/chrome/browser/extensions/extension_management.h b/chrome/browser/extensions/extension_management.h index caef9b2..81acab1 100644 --- a/chrome/browser/extensions/extension_management.h +++ b/chrome/browser/extensions/extension_management.h
@@ -86,6 +86,14 @@ // from the command line, or when loaded as an unpacked extension). bool BlocklistedByDefault() const; +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + // Checks if extensions are enabled for Desktop Android for the current + // profile. This is temporary for until extensions are ready for dogfooding. + // TODO(crbug.com/422307625): Remove this check once extensions are ready for + // dogfooding. + bool ExtensionsEnabledForDesktopAndroid() const; +#endif // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + // Returns installation mode for an extension. ManagedInstallationMode GetInstallationMode(const Extension* extension);
diff --git a/chrome/browser/extensions/load_error_reporter.cc b/chrome/browser/extensions/load_error_reporter.cc index 8af69ff..bf5982f0 100644 --- a/chrome/browser/extensions/load_error_reporter.cc +++ b/chrome/browser/extensions/load_error_reporter.cc
@@ -72,24 +72,7 @@ LOG(WARNING) << "Extension error: " << message; if (enable_noisy_errors_ && be_noisy) { - // This dialog is synchronous to prevent a race condition during startup. - // - // In the asynchronous case, the sequence of events is: - // 1. A startup task to load an extension fails, and an asynchronous call - // is made to show this parentless dialog. - // 2. The dialog's widget initializes, registering an accessibility observer - // with `AXPlatform`. The async call then returns immediately, marking - // the startup task as complete. - // 3. Because the startup task is finished and no windows are open, the - // browser process begins its shutdown sequence. - // 4. During shutdown, `AXPlatform` is destroyed before the dialog is. Its - // destructor's `CHECK` for no remaining observers fails because the - // dialog's observer is still registered, causing a crash. - // - // By using a synchronous dialog, we block the startup task from completing - // until the user dismisses the alert, ensuring steps 3 and 4 cannot - // happen until after the dialog and its observers are gone. - chrome::ShowWarningMessageBoxSync( + chrome::ShowWarningMessageBoxAsync( gfx::NativeWindow(), l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_ERROR_ALERT_HEADING), message);
diff --git a/chrome/browser/preloading/search_preload/search_preload_browsertest.cc b/chrome/browser/preloading/search_preload/search_preload_browsertest.cc index 609a682..b6415a5 100644 --- a/chrome/browser/preloading/search_preload/search_preload_browsertest.cc +++ b/chrome/browser/preloading/search_preload/search_preload_browsertest.cc
@@ -36,6 +36,7 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/navigation/preloading_headers.h" namespace { @@ -55,6 +56,8 @@ } // namespace alternative_content +constexpr static char kSearchTerms_502OnPrefetch[] = "502-on-prefetch"; + std::optional<net::HttpNoVarySearchData> ParseNoVarySearchData(std::string s) { auto headers = base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK\n"); @@ -252,20 +255,38 @@ std::unique_ptr<net::test_server::HttpResponse> HandleSearchRequest( const net::test_server::HttpRequest& request) { + const bool is_prefetch = + request.headers.find(blink::kPurposeHeaderName) != + request.headers.end() && + request.headers.find(blink::kPurposeHeaderName)->second == + blink::kSecPurposePrefetchHeaderValue; + CHECK_EQ(is_prefetch, + request.headers.find(blink::kSecPurposeHeaderName) != + request.headers.end() && + request.headers.find(blink::kSecPurposeHeaderName)->second == + blink::kSecPurposePrefetchPrerenderHeaderValue); + + if (request.GetURL().spec().find(kSearchTerms_502OnPrefetch) != + std::string::npos && + is_prefetch) { + net::HttpStatusCode code = net::HTTP_BAD_GATEWAY; + std::string content = "<html><body>preeftch</body></html>"; + base::StringPairs headers = { + {"Content-Length", base::NumberToString(content.length())}, + {"Content-Type", "text/html"}, + {"No-Vary-Search", R"(key-order, params, except=("q"))"}, + }; + return CreateDeferrableResponse(code, headers, content); + } + net::HttpStatusCode code = net::HttpStatusCode::HTTP_OK; - std::string content = R"( - <html><body> - PRERENDER: HI PREFETCH! \o/ - </body></html> - )"; + std::string content = "<html><body>prefetch</body></html>"; base::StringPairs headers = { {"Content-Length", base::NumberToString(content.length())}, {"Content-Type", "text/html"}, {"No-Vary-Search", R"(key-order, params, except=("q"))"}, }; - std::unique_ptr<net::test_server::HttpResponse> response = - CreateDeferrableResponse(code, headers, content); - return response; + return CreateDeferrableResponse(code, headers, content); } enum class PrefetchHint { kEnabled, kDisabled }; @@ -943,6 +964,123 @@ ParseNoVarySearchData(R"(key-order, params, except=("q"))")); } +// A pipeline is consumed by navigation. +// +// Note that this is for aligning the behavior of `SearchPrefetchService`. It +// would be nice to discuss the ideal behavior. +// +// See also +// https://docs.google.com/document/d/1NjxwlOEoBwpXojG13M85XtS8nH-S4uc0F6VOrlwIAXE/edit?pli=1&tab=t.0#heading=h.5qv0ome418fo +IN_PROC_BROWSER_TEST_F(SearchPreloadBrowserTest, + PipelineIsConsumedByNavigation) { + SetUpTemplateURLService(); + SetUpSearchPreloadService({ + .no_vary_search_data_cache = R"(key-order, params, except=("q"))", + }); + + ASSERT_TRUE(content::NavigateToURL( + &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); + + std::string original_query = "hello"; + std::string search_terms = original_query; + SearchUrls urls = GetSearchUrls(search_terms); + + { + content::test::TestPrefetchWatcher watcher; + + ChangeAutocompleteResult(original_query, search_terms, + PrefetchHint::kEnabled, PrerenderHint::kDisabled); + + watcher.WaitUntilPrefetchResponseCompleted(std::nullopt, + urls.prefetch_on_suggest); + } + + EXPECT_EQ(1, request_collector().CountByPath(urls.prefetch_on_suggest)); + EXPECT_EQ(0, request_collector().CountByPath(urls.prerender)); + + // Navigate. + ASSERT_TRUE(content::NavigateToURL(&GetWebContents(), urls.navigation)); + + // Prefetch is used. + EXPECT_EQ(1, request_collector().CountByPath(urls.prefetch_on_suggest)); + EXPECT_EQ(0, request_collector().CountByPath(urls.navigation)); + + // Prefetch was consumed by the navigation. + ASSERT_FALSE(GetSearchPreloadService().InvalidatePipelineForTesting( + GetWebContents(), urls.navigation)); + + // Navigate. + ASSERT_TRUE(content::NavigateToURL(&GetWebContents(), urls.navigation)); + + // Prefetch is not available. + EXPECT_EQ(1, request_collector().CountByPath(urls.prefetch_on_suggest)); + EXPECT_EQ(1, request_collector().CountByPath(urls.navigation)); +} + +class SearchPreloadBrowserTest_ErrorBackoffDuration + : public SearchPreloadBrowserTestBase { + void InitFeatures( + base::test::ScopedFeatureList& scoped_feature_list) override { + scoped_feature_list.InitWithFeaturesAndParameters( + { + { + features::kPrefetchPrerenderIntegration, + {}, + }, + { + features::kDsePreload2, + { + {"kDsePreload2ErrorBackoffDuration", "1000ms"}, + {"kDsePreload2DeviceMemoryThresholdMiB", "0"}, + }, + }, + }, + /*disabled_features=*/{}); + } +}; + +IN_PROC_BROWSER_TEST_F( + SearchPreloadBrowserTest_ErrorBackoffDuration, + PreloadsAreNotTriggeredCertainPeriodAfterPrefetchFailed) { + SetUpTemplateURLService(); + SetUpSearchPreloadService({ + .no_vary_search_data_cache = R"(key-order, params, except=("q"))", + }); + + ASSERT_TRUE(content::NavigateToURL( + &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); + + auto check = [&](std::string original_query, + const bool is_triggered_expected) { + request_collector().Reset(); + + std::string search_terms = original_query; + SearchUrls urls = GetSearchUrls(search_terms); + + { + content::test::TestPrefetchWatcher watcher; + + ChangeAutocompleteResult(original_query, search_terms, + PrefetchHint::kEnabled, + PrerenderHint::kDisabled); + + if (is_triggered_expected) { + watcher.WaitUntilPrefetchResponseCompleted(std::nullopt, + urls.prefetch_on_suggest); + } + } + + EXPECT_EQ(is_triggered_expected, + request_collector().CountByPath(urls.prefetch_on_suggest)); + EXPECT_EQ(0, request_collector().CountByPath(urls.prerender)); + }; + + check(kSearchTerms_502OnPrefetch, true); + check("two", false); + WaitForDuration(base::Milliseconds(1000)); + check("three", true); +} + class SearchPreloadBrowserTest_DeviceMemoryThreshold : public SearchPreloadBrowserTestBase { void InitFeatures(
diff --git a/chrome/browser/preloading/search_preload/search_preload_features.cc b/chrome/browser/preloading/search_preload/search_preload_features.cc index c7b0abd..7cce0e3 100644 --- a/chrome/browser/preloading/search_preload/search_preload_features.cc +++ b/chrome/browser/preloading/search_preload/search_preload_features.cc
@@ -17,6 +17,9 @@ &kDsePreload2, "kDsePreload2DeviceMemoryThresholdMiB", // 3 GiB = 3 * 2**10 * 2**20 3072}; +const base::FeatureParam<base::TimeDelta> kDsePreload2ErrorBackoffDuration{ + &kDsePreload2, "kDsePreload2ErrorBackoffDuration", + base::Milliseconds(60000)}; const base::FeatureParam<size_t> kDsePreload2MaxPrefetch{ &kDsePreload2, "kDsePreload2MaxPrefetch", 7}; const base::FeatureParam<base::TimeDelta> kDsePreload2PrefetchTtl{
diff --git a/chrome/browser/preloading/search_preload/search_preload_features.h b/chrome/browser/preloading/search_preload/search_preload_features.h index e8214d9..896b3b60 100644 --- a/chrome/browser/preloading/search_preload/search_preload_features.h +++ b/chrome/browser/preloading/search_preload/search_preload_features.h
@@ -25,6 +25,9 @@ // The feature is disabled if device memory is smaller than the threshold. extern const base::FeatureParam<size_t> kDsePreload2DeviceMemoryThresholdMiB; +// Pause triggering preloads when on-suggest prefetch failed. +extern const base::FeatureParam<base::TimeDelta> + kDsePreload2ErrorBackoffDuration; extern const base::FeatureParam<size_t> kDsePreload2MaxPrefetch; // Time to live (TTL) of prefetch. extern const base::FeatureParam<base::TimeDelta> kDsePreload2PrefetchTtl;
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc index dbdc2de9..7e27979 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc
@@ -52,7 +52,8 @@ base::WeakPtr<SearchPreloadService> search_preload_service, const GURL& prefetch_url, content::PreloadingPredictor predictor, - const std::optional<net::HttpNoVarySearchData>& no_vary_search_hint) { + const std::optional<net::HttpNoVarySearchData>& no_vary_search_hint, + bool is_navigation_likely) { // Don't trigger prefetch if already triggered and is alive. // // TODO(crbug.com/394213503): Reconsider the behavior when prefetch is already @@ -91,8 +92,14 @@ /*holdback_status_override=*/std::nullopt, /*ttl=*/features::kDsePreload2PrefetchTtl.Get()); CHECK(prefetch_handle_); - prefetch_handle_->SetOnPrefetchHeadReceived(base::BindRepeating( + prefetch_handle_->SetOnPrefetchHeadReceivedCallback(base::BindRepeating( &SearchPreloadService::OnPrefetchHeadReceived, search_preload_service)); + if (!is_navigation_likely) { + prefetch_handle_->SetOnPrefetchCompletedOrFailedCallback( + base::BindRepeating( + &SearchPreloadService::OnOnSuggestPrefetchCompletedOrFailed, + search_preload_service)); + } return true; }
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline.h b/chrome/browser/preloading/search_preload/search_preload_pipeline.h index 8ab1819..a792bec 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline.h +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline.h
@@ -39,7 +39,8 @@ base::WeakPtr<SearchPreloadService> search_preload_service, const GURL& prefetch_url, content::PreloadingPredictor predictor, - const std::optional<net::HttpNoVarySearchData>& no_vary_search_hint); + const std::optional<net::HttpNoVarySearchData>& no_vary_search_hint, + bool is_navigation_likely); // Starts prerender if not triggered yet and prefetch is alive. void StartPrerender(content::WebContents& web_contents, const GURL& prerernder_url,
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc index 6c49e64..7ad6a30 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc
@@ -16,6 +16,7 @@ #include "components/omnibox/browser/base_search_provider.h" #include "components/omnibox/browser/omnibox.mojom-shared.h" #include "components/search_engines/template_url_service.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/preloading_data.h" #include "content/public/browser/web_contents.h" @@ -54,8 +55,8 @@ SearchPreloadPipelineManager::SearchPreloadPipelineManager( content::WebContents* web_contents) - : content::WebContentsUserData<SearchPreloadPipelineManager>( - *web_contents) { + : content::WebContentsUserData<SearchPreloadPipelineManager>(*web_contents), + content::WebContentsObserver(web_contents) { auto* preloading_data = content::PreloadingData::GetOrCreateForWebContents(web_contents); SetIsNavigationInDomainCallback(preloading_data); @@ -63,6 +64,33 @@ SearchPreloadPipelineManager::~SearchPreloadPipelineManager() = default; +void SearchPreloadPipelineManager::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + const bool is_primary_main_frame_navigation = + navigation_handle->HasCommitted() && + navigation_handle->IsInPrimaryMainFrame() && + !navigation_handle->IsSameDocument(); + if (!is_primary_main_frame_navigation) { + return; + } + + content::BrowserContext* browser_context = + GetWebContents().GetBrowserContext(); + if (!browser_context) { + return; + } + + // Invalidate a pipeline if it is likely used. + std::optional<GURL> maybe_canonical_url = GetCanonicalUrlForSearchPreload( + *browser_context, navigation_handle->GetURL()); + if (!maybe_canonical_url.has_value()) { + return; + } + const GURL& canonical_url = maybe_canonical_url.value(); + + pipelines_.erase(canonical_url); +} + void SearchPreloadPipelineManager::ClearPreloads() { pipelines_.clear(); } @@ -169,7 +197,8 @@ /*is_navigation_likely=*/false); pipelines_[canonical_url]->StartPrefetch( GetWebContents(), search_preload_service, prefetch_url, - chrome_preloading_predictor::kDefaultSearchEngine, no_vary_search_hint); + chrome_preloading_predictor::kDefaultSearchEngine, no_vary_search_hint, + /*is_navigation_likely=*/false); // Trigger prerender without waiting prefetch. // @@ -289,7 +318,8 @@ pipelines_[canonical_url]->UpdateConfidence(GetWebContents(), 100); return pipelines_[canonical_url]->StartPrefetch( GetWebContents(), search_preload_service, prefetch_url, predictor, - no_vary_search_hint); + no_vary_search_hint, + /*is_navigation_likely=*/true); } bool SearchPreloadPipelineManager::InvalidatePipelineForTesting(
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h index 05acdb6f..31af94816 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h
@@ -8,6 +8,7 @@ #include "base/containers/flat_map.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/preloading/search_preload/search_preload_pipeline.h" +#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "url/gurl.h" @@ -30,7 +31,8 @@ // - Manages preload pipelines per WebContents. // - Starts preloads in response to Omnibox events. class SearchPreloadPipelineManager - : public content::WebContentsUserData<SearchPreloadPipelineManager> { + : public content::WebContentsUserData<SearchPreloadPipelineManager>, + public content::WebContentsObserver { public: ~SearchPreloadPipelineManager() override; @@ -46,6 +48,10 @@ return weak_factory_.GetWeakPtr(); } + // Implements `content::WebContentsObserver` + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + // Clears all preloads. void ClearPreloads();
diff --git a/chrome/browser/preloading/search_preload/search_preload_service.cc b/chrome/browser/preloading/search_preload/search_preload_service.cc index 12314c5e..1ddece1 100644 --- a/chrome/browser/preloading/search_preload/search_preload_service.cc +++ b/chrome/browser/preloading/search_preload/search_preload_service.cc
@@ -115,6 +115,17 @@ } } +void SearchPreloadService::OnOnSuggestPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) { + const bool is_2xx = response_code.has_value() && + (200 <= response_code && response_code < 300); + if (!is_2xx) { + pause_triggering_until_ = base::TimeTicks::Now() + + features::kDsePreload2ErrorBackoffDuration.Get(); + } +} + SearchPreloadPipelineManager& SearchPreloadService::GetOrCreatePipelineManagerWithLimit( content::WebContents& web_contents) { @@ -146,6 +157,10 @@ return; } + if (base::TimeTicks::Now() < pause_triggering_until_) { + return; + } + GetOrCreatePipelineManagerWithLimit(*web_contents) .OnAutocompleteResultChanged(*profile_, GetWeakPtr(), result, no_vary_search_data_cache_); @@ -160,6 +175,10 @@ return false; } + if (base::TimeTicks::Now() < pause_triggering_until_) { + return false; + } + return GetOrCreatePipelineManagerWithLimit(*web_contents) .OnNavigationLikely(*profile_, GetWeakPtr(), match, navigation_predictor, no_vary_search_data_cache_);
diff --git a/chrome/browser/preloading/search_preload/search_preload_service.h b/chrome/browser/preloading/search_preload/search_preload_service.h index c4f4115..1c5ffdfe 100644 --- a/chrome/browser/preloading/search_preload/search_preload_service.h +++ b/chrome/browser/preloading/search_preload/search_preload_service.h
@@ -73,6 +73,9 @@ void ClearPreloads(); void OnPrefetchHeadReceived(const network::mojom::URLResponseHead& head); + void OnOnSuggestPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code); // Called when autocomplete is updated. void OnAutocompleteResultChanged(content::WebContents* web_contents, @@ -112,6 +115,9 @@ // prefetch. std::optional<net::HttpNoVarySearchData> no_vary_search_data_cache_; + // If prefetch on-suggest failed, pause triggering preloads until this time. + base::TimeTicks pause_triggering_until_; + base::WeakPtrFactory<SearchPreloadService> weak_factory_{this}; };
diff --git a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc index c95aebe7..5c4a281 100644 --- a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
@@ -58,38 +58,7 @@ base::CallbackListSubscription test_signin_client_subscription_; }; -// The unconsented primary account isn't supported on ChromeOS. -#if !BUILDFLAG(IS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(SingleClientSecondaryAccountSyncTest, - StartsSyncTransportOnSignin) { - ASSERT_TRUE(SetupClients()); - - // Signing in (without granting sync consent or explicitly setting up Sync) - // should trigger starting the Sync machinery in standalone transport mode. - secondary_account_helper::SignInUnconsentedAccount( - profile(), &test_url_loader_factory_, "user@email.com"); - - EXPECT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - - EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, - GetSyncService(0)->GetTransportState()); - - ASSERT_FALSE(GetSyncService(0) - ->GetUserSettings() - ->IsInitialSyncFeatureSetupComplete()); - - EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); - EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureActive()); - - // Make sure that only the allowed types got activated. Note that, depending - // on some other feature flags, not all of the allowed types are necessarily - // active, and that's okay. - syncer::DataTypeSet bad_types = - base::Difference(GetSyncService(0)->GetActiveDataTypes(), - AllowedTypesInStandaloneTransportMode()); - EXPECT_TRUE(bad_types.empty()) << syncer::DataTypeSetToDebugString(bad_types); -} -#else +#if BUILDFLAG(IS_CHROMEOS) IN_PROC_BROWSER_TEST_F(SingleClientSecondaryAccountSyncTest, DoesNotStartSyncTransportOnSignin) { ASSERT_TRUE(SetupClients()); @@ -102,7 +71,7 @@ EXPECT_EQ(syncer::SyncService::TransportState::DISABLED, GetSyncService(0)->GetTransportState()); } -#endif // !BUILDFLAG(IS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS) // ChromeOS doesn't support changes to the primary account after startup, so // this test doesn't apply.
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc index 13f91cc..cb06b47 100644 --- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -10,6 +10,7 @@ #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/test/integration/encryption_helper.h" +#include "chrome/browser/sync/test/integration/secondary_account_helper.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/sync_service_impl_harness.h" #include "chrome/browser/sync/test/integration/sync_test.h" @@ -24,6 +25,8 @@ #include "components/sync/test/nigori_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_launcher.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(IS_CHROMEOS) #include "ash/constants/ash_features.h" @@ -31,6 +34,18 @@ namespace { +using testing::ContainerEq; + +constexpr syncer::DataTypeSet kTypesGatedBehindHistoryOptIn{ + syncer::COLLABORATION_GROUP, + syncer::HISTORY, + syncer::HISTORY_DELETE_DIRECTIVES, + syncer::SAVED_TAB_GROUP, + syncer::SHARED_TAB_GROUP_DATA, + syncer::SHARED_TAB_GROUP_ACCOUNT_DATA, + syncer::SESSIONS, + syncer::USER_EVENTS}; + #if !BUILDFLAG(IS_ANDROID) base::FilePath GetTestFilePathForCacheGuid() { base::FilePath user_data_path; @@ -63,14 +78,34 @@ }; #endif // BUILDFLAG(IS_CHROMEOS) -class SingleClientStandaloneTransportSyncTest : public SyncTest { +class SingleClientStandaloneTransportSyncTest + : public SyncTest, + public testing::WithParamInterface<bool> { public: - SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) {} + SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) { + if (GetParam()) { + override_features_ + .InitWithFeatures(/*enabled_features=*/ + {syncer:: + kSyncEnableContactInfoDataTypeForCustomPassphraseUsers, + syncer::kReplaceSyncPromosWithSignInPromos}, + /*disabled_features=*/{}); + } else { + override_features_.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/ + {syncer::kSyncEnableContactInfoDataTypeForCustomPassphraseUsers, + syncer::kReplaceSyncPromosWithSignInPromos}); + } + } + + private: + base::test::ScopedFeatureList override_features_; }; // On Chrome OS sync auto-starts on sign-in. #if !BUILDFLAG(IS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, StartsSyncTransportOnSignin) { ASSERT_TRUE(SetupClients()); @@ -94,20 +129,16 @@ EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureActive()); - - // Make sure that only the allowed types got activated. Note that, depending - // on some other feature flags, not all of the allowed types are necessarily - // active, and that's okay. - syncer::DataTypeSet bad_types = - base::Difference(GetSyncService(0)->GetActiveDataTypes(), - AllowedTypesInStandaloneTransportMode()); - EXPECT_TRUE(bad_types.empty()) << syncer::DataTypeSetToDebugString(bad_types); } #endif // !BUILDFLAG(IS_CHROMEOS) #if !BUILDFLAG(IS_ANDROID) -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, SwitchesBetweenTransportAndFeature) { + const syncer::DataType kDataTypeExcludedInTransportMode = syncer::AUTOFILL; + CHECK(!AllowedTypesInStandaloneTransportMode().Has( + kDataTypeExcludedInTransportMode)); + ASSERT_TRUE(SetupClients()); // Setup a primary account, but don't actually enable Sync-the-feature (so @@ -119,10 +150,26 @@ GetSyncService(0)->GetTransportState()); ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive()); - syncer::DataTypeSet bad_types = - base::Difference(GetSyncService(0)->GetActiveDataTypes(), - AllowedTypesInStandaloneTransportMode()); - EXPECT_TRUE(bad_types.empty()) << syncer::DataTypeSetToDebugString(bad_types); + syncer::DataTypeSet expected_types = Difference( + AllowedTypesInStandaloneTransportMode(), kTypesGatedBehindHistoryOptIn); + + // Bookmarks and reading list require a separate opt in, unless + // `syncer::kReplaceSyncPromosWithSignInPromos` is enabled. + // TODO(crbug.com/424124636): This shouldn't be necessary if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + expected_types.Remove(syncer::BOOKMARKS); + expected_types.Remove(syncer::READING_LIST); + + // TODO(crbug.com/424124636): The types below should probably be excluded. + if (base::FeatureList::IsEnabled( + syncer::kReplaceSyncPromosWithSignInPromos)) { + expected_types.Put(syncer::PRODUCT_COMPARISON); + expected_types.Put(syncer::AUTOFILL_WALLET_METADATA); + expected_types.Put(syncer::AUTOFILL_WALLET_OFFER); + } + + ASSERT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types)); // Turn Sync-the-feature on. ASSERT_TRUE(GetClient(0)->SetupSync()); @@ -132,18 +179,18 @@ EXPECT_TRUE(GetSyncService(0)->IsSyncFeatureActive()); // Make sure that some data type which is not allowed in transport-only mode // got activated. - ASSERT_FALSE(AllowedTypesInStandaloneTransportMode().Has(syncer::AUTOFILL)); ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( syncer::UserSelectableType::kAutofill)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::AUTOFILL)); + EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( + kDataTypeExcludedInTransportMode)); } -#endif // BUILDFLAG(IS_ANDROID) +#endif // !BUILDFLAG(IS_ANDROID) // Tests the behavior of receiving a "Reset Sync" operation from the dashboard // while Sync-the-feature is active: On non-ChromeOS, this signs the user out, // so Sync will be fully disabled. On ChromeOS, there is no sign-out, so // Sync-the-transport will start. -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, HandlesResetFromDashboardWhenSyncActive) { ASSERT_TRUE(SetupClients()); @@ -173,6 +220,39 @@ EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE, GetSyncService(0)->GetTransportState()); EXPECT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); + + // There are no immediate plans to launch additional types on ChromeOS, so the + // list is hardcoded here. + EXPECT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(syncer::DataTypeSet{ + syncer::AUTOFILL_WALLET_CREDENTIAL, + syncer::AUTOFILL_WALLET_DATA, + syncer::AUTOFILL_WALLET_USAGE, + syncer::DEVICE_INFO, + syncer::NIGORI, + syncer::USER_CONSENTS, + syncer::SEND_TAB_TO_SELF, + syncer::SECURITY_EVENTS, + syncer::SHARING_MESSAGE, + syncer::ARC_PACKAGE, + syncer::OS_PREFERENCES, + syncer::OS_PRIORITY_PREFERENCES, + // TODO(crbug.com/424698545): This seems off: many of the + // datatypes below should not start. + syncer::APP_LIST, + syncer::COLLABORATION_GROUP, + syncer::CONTACT_INFO, + syncer::EXTENSIONS, + syncer::EXTENSION_SETTINGS, + syncer::INCOMING_PASSWORD_SHARING_INVITATION, + syncer::OUTGOING_PASSWORD_SHARING_INVITATION, + syncer::PASSWORDS, + syncer::PRODUCT_COMPARISON, + syncer::SAVED_TAB_GROUP, + syncer::SHARED_TAB_GROUP_DATA, + syncer::SHARED_TAB_GROUP_ACCOUNT_DATA, + syncer::WEBAUTHN_CREDENTIAL, + })); #else // On platforms other than Ash, the "Reset Sync" operation should revoke // the Sync consent. On Mobile, "Reset Sync" also clears the primary account. @@ -189,7 +269,7 @@ #if !BUILDFLAG(IS_ANDROID) // Regression test for crbug.com/955989 that verifies the cache GUID is not // reset upon restart of the browser, in standalone transport mode. -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, PRE_ReusesSameCacheGuid) { ASSERT_TRUE(SetupClients()); ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); @@ -220,7 +300,7 @@ ASSERT_TRUE(base::WriteFile(GetTestFilePathForCacheGuid(), cache_guid)); } -IN_PROC_BROWSER_TEST_F(SingleClientStandaloneTransportSyncTest, +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, ReusesSameCacheGuid) { ASSERT_TRUE(SetupClients()); ASSERT_FALSE(GetSyncService(0)->HasDisableReason( @@ -255,40 +335,8 @@ } #endif // BUILDFLAG(IS_ANDROID) -class SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest - : public SingleClientStandaloneTransportSyncTest { - public: - SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest() { - override_features_.InitWithFeatures( - /*enabled_features=*/ - {switches::kEnablePreferencesAccountStorage, - syncer::kSeparateLocalAndAccountSearchEngines, - syncer::kSyncEnableContactInfoDataTypeForCustomPassphraseUsers, - syncer::kReplaceSyncPromosWithSignInPromos, - syncer::kSyncAutofillWalletCredentialData}, - /*disabled_features=*/{}); - } - ~SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest() override = - default; - - bool WaitForPassphraseRequired() { - return PassphraseRequiredChecker(GetSyncService(0)).Wait(); - } - - bool WaitForPassphraseAccepted() { - return PassphraseAcceptedChecker(GetSyncService(0)).Wait(); - } - - private: - base::test::ScopedFeatureList override_features_; -}; - -// This test is disabled on CrOS as the signed in, non-syncing state does not -// exist. -#if !BUILDFLAG(IS_CHROMEOS) -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest, - DataTypesEnabledInTransportModeWithoutHistorySync) { +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, + DataTypesEnabledInTransportModeWithoutAdditionalOptIns) { ASSERT_TRUE(SetupClients()); // Sign in, without turning on Sync-the-feature. ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); @@ -299,79 +347,116 @@ ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( syncer::UserSelectableType::kHistory)); - // With `kReplaceSyncPromosWithSignInPromos` and by default (without opting - // into history), all the history-related should be disabled in transport - // mode. - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::HISTORY)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::HISTORY_DELETE_DIRECTIVES)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::SESSIONS)); - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_EVENTS)); + // Make sure that only the allowed types got activated. + syncer::DataTypeSet expected_types = Difference( + AllowedTypesInStandaloneTransportMode(), kTypesGatedBehindHistoryOptIn); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PREFERENCES)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::PRIORITY_PREFERENCES)); +#if !BUILDFLAG(IS_ANDROID) + // Bookmarks and reading list require a separate opt in, unless + // `syncer::kReplaceSyncPromosWithSignInPromos` is enabled. + // TODO(crbug.com/424124636): This shouldn't be necessary if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + expected_types.Remove(syncer::BOOKMARKS); + expected_types.Remove(syncer::READING_LIST); +#endif // !BUILDFLAG(IS_ANDROID) - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_CREDENTIAL)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_DATA)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_METADATA)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_OFFER)); - EXPECT_TRUE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + EXPECT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types)); } -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest, - DataTypesEnabledInTransportModeWithHistorySync) { +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, + DataTypesEnabledInTransportModeWithHistorySync) { + // Opting into history is only meaningful if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + if (!GetParam()) { + GTEST_SKIP(); + } + ASSERT_TRUE(SetupClients()); // Sign in, without turning on Sync-the-feature. ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, + GetSyncService(0)->GetTransportState()); ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); + ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( + syncer::UserSelectableType::kHistory)); // Opt in to history and tabs. GetSyncService(0)->GetUserSettings()->SetSelectedType( syncer::UserSelectableType::kHistory, true); GetSyncService(0)->GetUserSettings()->SetSelectedType( syncer::UserSelectableType::kTabs, true); +#if !BUILDFLAG(IS_ANDROID) + GetSyncService(0)->GetUserSettings()->SetSelectedType( + syncer::UserSelectableType::kSavedTabGroups, true); +#endif // !BUILDFLAG(IS_ANDROID) ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, GetSyncService(0)->GetTransportState()); - // With `kReplaceSyncPromosWithSignInPromos`, all the history-related types - // should be enabled in transport mode. - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::HISTORY)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::HISTORY_DELETE_DIRECTIVES)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::SESSIONS)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_EVENTS)); + // With the history opt in, all types that can run in transport mode should + // be active. + syncer::DataTypeSet expected_types = AllowedTypesInStandaloneTransportMode(); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PREFERENCES)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::PRIORITY_PREFERENCES)); +#if !BUILDFLAG(IS_ANDROID) + // Bookmarks and reading list require a separate opt in, unless + // `syncer::kReplaceSyncPromosWithSignInPromos` is enabled. + // TODO(crbug.com/424124636): This shouldn't be necessary if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + expected_types.Remove(syncer::BOOKMARKS); + expected_types.Remove(syncer::READING_LIST); +#endif // !BUILDFLAG(IS_ANDROID) - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_CREDENTIAL)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_DATA)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_METADATA)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::AUTOFILL_WALLET_OFFER)); - EXPECT_TRUE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + EXPECT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types)); } -#endif // !BUILDFLAG(IS_CHROMEOS) + +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, + DataTypesEnabledForImplicitSignIn) { + ASSERT_TRUE(SetupClients()); + + // Signing in (without granting sync consent or explicitly setting up Sync) + // should trigger starting the Sync machinery in standalone transport mode. + secondary_account_helper::ImplicitSignInUnconsentedAccount( + GetProfile(0), &test_url_loader_factory_, "user@email.com"); + + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, + GetSyncService(0)->GetTransportState()); + + // There are no immediate plans to launch additional types to implicitly + // signed in users, so the list is hardcoded here. + syncer::DataTypeSet expected_types{syncer::AUTOFILL_WALLET_CREDENTIAL, + syncer::AUTOFILL_WALLET_DATA, + syncer::AUTOFILL_WALLET_USAGE, + syncer::DEVICE_INFO, + syncer::NIGORI, + syncer::PRIORITY_PREFERENCES, + syncer::USER_CONSENTS, + syncer::SEND_TAB_TO_SELF, + syncer::SECURITY_EVENTS, + syncer::SHARING_MESSAGE}; + + // TODO(crbug.com/424124636): The types below should probably be excluded. + if (base::FeatureList::IsEnabled( + syncer::kReplaceSyncPromosWithSignInPromos)) { + expected_types.Put(syncer::PRODUCT_COMPARISON); + expected_types.Put(syncer::AUTOFILL_WALLET_METADATA); + expected_types.Put(syncer::AUTOFILL_WALLET_OFFER); + } + + EXPECT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types)); +} +#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) // TODO(crbug.com/40200835): Android currently doesn't support PRE_ tests. #if !BUILDFLAG(IS_ANDROID) -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest, +IN_PROC_BROWSER_TEST_P( + SingleClientStandaloneTransportSyncTest, PRE_DataTypesEnabledInTransportModeWithCustomPassphrase) { // There's a custom passphrase on the server. const syncer::KeyParamsForTesting kKeyParams = @@ -382,63 +467,89 @@ ASSERT_TRUE(SetupClients()); // Sign in, without turning on Sync-the-feature. ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); - ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); - - // Opt in to history and tabs. - GetSyncService(0)->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kHistory, true); - GetSyncService(0)->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kTabs, true); - // Preferences are opted-into by default. - ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kPreferences)); - - ASSERT_TRUE(WaitForPassphraseRequired()); + ASSERT_TRUE(PassphraseRequiredChecker(GetSyncService(0)).Wait()); ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->SetDecryptionPassphrase( kKeyParams.password)); - ASSERT_TRUE(WaitForPassphraseAccepted()); + ASSERT_TRUE(PassphraseAcceptedChecker(GetSyncService(0)).Wait()); ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, GetSyncService(0)->GetTransportState()); + ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); - // With a custom passphrase, the actual HISTORY types are not supported. - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::HISTORY)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::HISTORY_DELETE_DIRECTIVES)); - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_EVENTS)); - // But SESSIONS aka Open Tabs still works. - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::SESSIONS)); - - // With `kReplaceSyncPromosWithSignInPromos`, both PREFERENCES and - // PRIORITY_PREFERENCES should be enabled in transport mode. - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PREFERENCES)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::PRIORITY_PREFERENCES)); + // Make sure that only the allowed types got activated. + syncer::DataTypeSet expected_types = Difference( + AllowedTypesInStandaloneTransportMode(), kTypesGatedBehindHistoryOptIn); // CONTACT_INFO should be disabled by default for explicit-passphrase users. - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + expected_types.Remove(syncer::CONTACT_INFO); - // Enabling kAutofill to enable CONTACT_INFO. - GetSyncService(0)->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kAutofill, true); + // Bookmarks and reading list require a separate opt in, unless + // `syncer::kReplaceSyncPromosWithSignInPromos` is enabled. + // TODO(crbug.com/424124636): This shouldn't be necessary if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + expected_types.Remove(syncer::BOOKMARKS); + expected_types.Remove(syncer::READING_LIST); - ASSERT_NE(syncer::SyncService::TransportState::ACTIVE, - GetSyncService(0)->GetTransportState()); - ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + ASSERT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types)); - // CONTACT_INFO should be enabled. - EXPECT_TRUE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + // Opting into history is only meaningful if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + if (GetParam()) { + // Opt in to history and tabs. + GetSyncService(0)->GetUserSettings()->SetSelectedType( + syncer::UserSelectableType::kHistory, true); + GetSyncService(0)->GetUserSettings()->SetSelectedType( + syncer::UserSelectableType::kTabs, true); + GetSyncService(0)->GetUserSettings()->SetSelectedType( + syncer::UserSelectableType::kSavedTabGroups, true); + + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, + GetSyncService(0)->GetTransportState()); + + syncer::DataTypeSet expected_types_after_history_opt_in = + AllowedTypesInStandaloneTransportMode(); + + // CONTACT_INFO should remain disabled since it's gated by kAutofill. + expected_types_after_history_opt_in.Remove(syncer::CONTACT_INFO); + + // With a custom passphrase, the actual HISTORY types are not supported. + expected_types_after_history_opt_in.Remove(syncer::HISTORY); + expected_types_after_history_opt_in.Remove( + syncer::HISTORY_DELETE_DIRECTIVES); + expected_types_after_history_opt_in.Remove(syncer::USER_EVENTS); + + // But SESSIONS aka Open Tabs still works. + CHECK(expected_types_after_history_opt_in.Has(syncer::SESSIONS)); + +#if !BUILDFLAG(IS_ANDROID) + // On desktop, bookmarks and reading list require a separate opt in. + // TODO(crbug.com/424124636): This shouldn't be necessary if + // `kReplaceSyncPromosWithSignInPromos` is enabled. + expected_types_after_history_opt_in.Remove(syncer::BOOKMARKS); + expected_types_after_history_opt_in.Remove(syncer::READING_LIST); +#endif // !BUILDFLAG(IS_ANDROID) + + EXPECT_THAT(GetSyncService(0)->GetActiveDataTypes(), + ContainerEq(expected_types_after_history_opt_in)); + + // Enabling kAutofill to enable CONTACT_INFO. + GetSyncService(0)->GetUserSettings()->SetSelectedType( + syncer::UserSelectableType::kAutofill, true); + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + + // CONTACT_INFO should be enabled. + EXPECT_TRUE( + GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + } } // Tests that a custom passphrase user's opt-in to kAutofill (which happened in // the PRE_ test) survives a browser restart. -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest, - DataTypesEnabledInTransportModeWithCustomPassphrase) { +IN_PROC_BROWSER_TEST_P(SingleClientStandaloneTransportSyncTest, + DataTypesEnabledInTransportModeWithCustomPassphrase) { ASSERT_TRUE(SetupClients()); ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); @@ -446,152 +557,30 @@ ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, GetSyncService(0)->GetTransportState()); - // CONTACT_INFO should be enabled after restarting. - EXPECT_TRUE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO)); + // CONTACT_INFO should be enabled after restarting, if and only if + // `kSyncEnableContactInfoDataTypeForCustomPassphraseUsers` is enabled. + EXPECT_EQ(GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO), + GetParam()); } #endif // BUILDFLAG(IS_ANDROID) -class SingleClientStandaloneTransportWithoutReplaceSyncWithSigninSyncTest - : public SingleClientStandaloneTransportSyncTest { - public: - SingleClientStandaloneTransportWithoutReplaceSyncWithSigninSyncTest() { -#if BUILDFLAG(IS_ANDROID) - // On Android, PREFERENCES is active in transport mode only with - // `kReplaceSyncPromosWithSignInPromos` enabled. - override_features_.InitWithFeatures( - /*enabled_features=*/{switches::kEnablePreferencesAccountStorage}, - /*disabled_features=*/{syncer::kReplaceSyncPromosWithSignInPromos}); +INSTANTIATE_TEST_SUITE_P(ReplaceSyncWithSignin, + SingleClientStandaloneTransportSyncTest, +#if BUILDFLAG(IS_CHROMEOS) + // On ChromeOS, the behavior after enabling + // `syncer::kReplaceSyncPromosWithSignInPromos` is + // unspecified, so no need to test it. + ::testing::Values(false)); +#elif BUILDFLAG(IS_ANDROID) + // On Android, the feature has been enabled by + // default for a long time. There is no need to + // test the flag-disabled case. + ::testing::Values(true)); #else - // On Desktop, PREFERENCES, SEARCH_ENGINES and THEMES are active in - // transport mode irrespective of `kReplaceSyncPromosWithSignInPromos`. - // TODO(crbug.com/330677712): Merge this with the Android branch once - // `kReplaceSyncPromosWithSignInPromos` is removed. - override_features_.InitWithFeatures( - /*enabled_features=*/{switches::kEnablePreferencesAccountStorage, - syncer::kSeparateLocalAndAccountSearchEngines, - syncer::kSeparateLocalAndAccountThemes}, - /*disabled_features=*/{syncer::kReplaceSyncPromosWithSignInPromos}); -#endif // BUILDFLAG(IS_ANDROID) - } - ~SingleClientStandaloneTransportWithoutReplaceSyncWithSigninSyncTest() - override = default; + ::testing::Bool()); +#endif - private: - base::test::ScopedFeatureList override_features_; -}; - -#if BUILDFLAG(IS_ANDROID) - -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithoutReplaceSyncWithSigninSyncTest, - DataTypesNotEnabledInTransportMode) { - ASSERT_TRUE(SetupClients()); - // Sign in, without turning on Sync-the-feature. - ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); - ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); - - // Without `kReplaceSyncPromosWithSignInPromos`, neither History/Tabs nor - // Preferences are supported in transport mode, so they're reported as not - // selected even if the user explicitly tries to turn them on. - syncer::UserSelectableTypeSet types = - GetSyncService(0)->GetUserSettings()->GetRegisteredSelectableTypes(); - ASSERT_TRUE(types.HasAll({syncer::UserSelectableType::kHistory, - syncer::UserSelectableType::kTabs, - syncer::UserSelectableType::kPreferences})); - GetSyncService(0)->GetUserSettings()->SetSelectedTypes( - /*sync_everything=*/true, types); - ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kHistory)); - ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kTabs)); - ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kPreferences)); - - ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - GetSyncService(0)->GetTransportState()); - - // Without `kReplaceSyncPromosWithSignInPromos`, none of the history-related - // types should be active in transport mode (even if the user has opted in). - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::HISTORY)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::HISTORY_DELETE_DIRECTIVES)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::SESSIONS)); - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_EVENTS)); - - // Without `kReplaceSyncPromosWithSignInPromos`, PREFERENCES should not be - // active in transport mode (even if the user has opted in). - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::PREFERENCES)); - // TODO(crbug.com/412602018): With - // `kSyncSupportAlwaysSyncingPriorityPreferences` enabled, - // PRIORITY_PREFERENCES are active in transport mode and decoupled from user - // toggle. Update or add new test to cover PRIORITY_PREFERENCES. -} - -#else - -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportWithoutReplaceSyncWithSigninSyncTest, - DataTypesNotEnabledInTransportMode) { - ASSERT_TRUE(SetupClients()); - // Sign in, without turning on Sync-the-feature. - ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); - ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); - - // Without `kReplaceSyncPromosWithSignInPromos`, History/Tabs are not are - // supported in transport mode, so they're reported as not selected even if - // the user explicitly tries to turn them on. - syncer::UserSelectableTypeSet types = - GetSyncService(0)->GetUserSettings()->GetRegisteredSelectableTypes(); - ASSERT_TRUE(types.HasAll({syncer::UserSelectableType::kHistory, - syncer::UserSelectableType::kTabs, - syncer::UserSelectableType::kPreferences})); - GetSyncService(0)->GetUserSettings()->SetSelectedTypes( - /*sync_everything=*/true, types); - ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kHistory)); - ASSERT_FALSE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kTabs)); - // Preferences, Themes and Search Engines are supported in transport mode, - // provided the enabled feature flags, irrespective of - // `kReplaceSyncPromosWithSignInPromos`. So they're reported as selected even - // when the user explicitly turns them on. - ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().HasAll( - {syncer::UserSelectableType::kPreferences, - syncer::UserSelectableType::kThemes})); - - ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE, - GetSyncService(0)->GetTransportState()); - - // Without `kReplaceSyncPromosWithSignInPromos`, none of the history-related - // types should be active in transport mode (even if the user has opted in). - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::HISTORY)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has( - syncer::HISTORY_DELETE_DIRECTIVES)); - EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::SESSIONS)); - EXPECT_FALSE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_EVENTS)); - - // PREFERENCES, SEARCH_ENGINES and THEMES are active in transport mode - // irrespective of `kReplaceSyncPromosWithSignInPromos`, provided the - // enabled feature flags. - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::THEMES)); - EXPECT_TRUE( - GetSyncService(0)->GetActiveDataTypes().Has(syncer::SEARCH_ENGINES)); - EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PREFERENCES)); - // TODO(crbug.com/412602018): With - // `kSyncSupportAlwaysSyncingPriorityPreferences` enabled, - // PRIORITY_PREFERENCES are active in transport mode and decoupled from user - // toggle. Update or add new test to cover PRIORITY_PREFERENCES. -} - -#endif // BUILDFLAG(IS_ANDROID) - -// SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest is +// ReplaceSyncWithSigninMigrationSyncTest is // disabled on CrOS as the signed in, non-syncing state does not exist. // TODO(crbug.com/40145099): Android currently doesn't support PRE_ tests and // all of these are. @@ -602,10 +591,9 @@ // This test intends to test the mobile migration behavior, but runs on desktop. // Desktop and mobile have different behaviors, and as a consequence is test is // only an approximation. -class SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest - : public SingleClientStandaloneTransportSyncTest { +class ReplaceSyncWithSigninMigrationSyncTest : public SyncTest { public: - SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest() { + ReplaceSyncWithSigninMigrationSyncTest() : SyncTest(SINGLE_CLIENT) { // Various features that are required for types to be supported in transport // mode are unconditionally enabled. default_features_.InitWithFeatures( @@ -622,17 +610,15 @@ {{syncer::kReplaceSyncPromosWithSignInPromos, !content::IsPreTest()}, {switches::kEnablePreferencesAccountStorage, !content::IsPreTest()}}); } - ~SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest() - override = default; + ~ReplaceSyncWithSigninMigrationSyncTest() override = default; private: base::test::ScopedFeatureList default_features_; base::test::ScopedFeatureList sync_to_signin_feature_; }; -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest, - PRE_MigratesSignedInUser) { +IN_PROC_BROWSER_TEST_F(ReplaceSyncWithSigninMigrationSyncTest, + PRE_MigratesSignedInUser) { ASSERT_TRUE(SetupClients()); // Sign in, without turning on Sync-the-feature. ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); @@ -661,9 +647,8 @@ GetSyncService(0)->GetTransportState()); } -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest, - MigratesSignedInUser) { +IN_PROC_BROWSER_TEST_F(ReplaceSyncWithSigninMigrationSyncTest, + MigratesSignedInUser) { ASSERT_TRUE(SetupClients()); ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); @@ -687,9 +672,8 @@ syncer::UserSelectableType::kPreferences)); } -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest, - PRE_MigratesSignedInCustomPassphraseUser) { +IN_PROC_BROWSER_TEST_F(ReplaceSyncWithSigninMigrationSyncTest, + PRE_MigratesSignedInCustomPassphraseUser) { ASSERT_TRUE(SetupClients()); // Sign in, without turning on Sync-the-feature. ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); @@ -714,9 +698,8 @@ syncer::UserSelectableType::kPreferences)); } -IN_PROC_BROWSER_TEST_F( - SingleClientStandaloneTransportReplaceSyncWithSigninMigrationSyncTest, - MigratesSignedInCustomPassphraseUser) { +IN_PROC_BROWSER_TEST_F(ReplaceSyncWithSigninMigrationSyncTest, + MigratesSignedInCustomPassphraseUser) { ASSERT_TRUE(SetupClients()); ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index 5744fb9c..c2eddc6c 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -58,6 +58,8 @@ #include "chrome/common/chrome_switches.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/browser_sync/browser_sync_switches.h" +#include "components/commerce/core/commerce_feature_list.h" +#include "components/data_sharing/public/features.h" #include "components/gcm_driver/fake_gcm_profile_service.h" #include "components/gcm_driver/gcm_profile_service.h" #include "components/gcm_driver/instance_id/instance_id.h" @@ -65,6 +67,8 @@ #include "components/gcm_driver/instance_id/instance_id_profile_service.h" #include "components/keyed_service/core/keyed_service.h" #include "components/os_crypt/sync/os_crypt_mocker.h" +#include "components/password_manager/core/browser/password_manager_buildflags.h" +#include "components/plus_addresses/features.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_switches.h" @@ -105,6 +109,7 @@ #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_ANDROID) +#include "chrome/browser/password_manager/android/password_manager_util_bridge.h" #include "chrome/browser/sync/test/integration/sync_test_utils_android.h" #else // BUILDFLAG(IS_ANDROID) #include "chrome/browser/ui/browser.h" @@ -1075,12 +1080,19 @@ syncer::DataTypeSet AllowedTypesInStandaloneTransportMode() { static_assert(55 == syncer::GetNumDataTypes(), "Add new types below if they can run in transport mode"); + +#if BUILDFLAG(IS_ANDROID) + // On Android, `kReplaceSyncPromosWithSignInPromos` has been enabled by + // default for a long time, so it is not expected to be exercised in tests. + CHECK( + base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos)); +#endif // BUILDFLAG(IS_ANDROID) + // Only some types will run by default in transport mode (i.e. without their // own separate opt-in). syncer::DataTypeSet allowed_types = {syncer::AUTOFILL_WALLET_CREDENTIAL, syncer::AUTOFILL_WALLET_DATA, syncer::AUTOFILL_WALLET_USAGE, - syncer::CONTACT_INFO, syncer::DEVICE_INFO, syncer::SECURITY_EVENTS, syncer::SEND_TAB_TO_SELF, @@ -1088,12 +1100,20 @@ syncer::USER_CONSENTS}; allowed_types.PutAll(syncer::ControlTypes()); - allowed_types.Put(syncer::PLUS_ADDRESS); - allowed_types.Put(syncer::PLUS_ADDRESS_SETTING); - allowed_types.Put(syncer::PASSWORDS); - allowed_types.Put(syncer::WEBAUTHN_CREDENTIAL); - allowed_types.Put(syncer::INCOMING_PASSWORD_SHARING_INVITATION); - allowed_types.Put(syncer::OUTGOING_PASSWORD_SHARING_INVITATION); +#if BUILDFLAG(IS_CHROMEOS) + // OS sync types run in transport mode. + allowed_types.PutAll({syncer::APP_LIST, syncer::ARC_PACKAGE, + syncer::OS_PREFERENCES, + syncer::OS_PRIORITY_PREFERENCES}); + + // Some of the feature-guarded logic in the #else branch below could make + // sense for ChromeOS too. However, since there are no immediate plans to + // roll them out on ChromeOS, they are excluded in this test to avoid + // accidental rollouts on ChromeOS transport mode (which is somewhat special, + // and reachable only in advanced scenarios such as the user having cleared + // data via sync dashboard). +#else // BUILDFLAG(IS_CHROMEOS) + allowed_types.Put(syncer::CONTACT_INFO); if (base::FeatureList::IsEnabled( switches::kEnablePreferencesAccountStorage)) { @@ -1111,37 +1131,44 @@ syncer::kReplaceSyncPromosWithSignInPromos)) { allowed_types.Put(syncer::AUTOFILL_WALLET_METADATA); allowed_types.Put(syncer::AUTOFILL_WALLET_OFFER); - allowed_types.Put(syncer::COLLABORATION_GROUP); allowed_types.Put(syncer::HISTORY); allowed_types.Put(syncer::HISTORY_DELETE_DIRECTIVES); - allowed_types.Put(syncer::PRODUCT_COMPARISON); allowed_types.Put(syncer::SAVED_TAB_GROUP); allowed_types.Put(syncer::SESSIONS); - allowed_types.Put(syncer::SHARED_TAB_GROUP_DATA); allowed_types.Put(syncer::USER_EVENTS); + + if (data_sharing::features::IsDataSharingFunctionalityEnabled()) { + allowed_types.Put(syncer::SHARED_TAB_GROUP_DATA); + allowed_types.Put(syncer::COLLABORATION_GROUP); + + if (base::FeatureList::IsEnabled( + syncer::kSyncSharedTabGroupAccountData)) { + allowed_types.Put(syncer::SHARED_TAB_GROUP_ACCOUNT_DATA); + } + } + + if (base::FeatureList::IsEnabled(commerce::kProductSpecifications)) { + allowed_types.Put(syncer::PRODUCT_COMPARISON); + } } if (base::FeatureList::IsEnabled(syncer::kSyncAutofillLoyaltyCard)) { allowed_types.Put(syncer::AUTOFILL_VALUABLE); } - if (base::FeatureList::IsEnabled(syncer::kSyncSharedTabGroupAccountData)) { - allowed_types.Put(syncer::SHARED_TAB_GROUP_ACCOUNT_DATA); + +#if BUILDFLAG(IS_ANDROID) && !BUILDFLAG(USE_LOGIN_DATABASE_AS_BACKEND) + // On Android, PASSWORDS require that Google Play Services is present. + password_manager_android_util::PasswordManagerUtilBridge util_bridge; + if (util_bridge.IsInternalBackendPresent()) { + allowed_types.Put(syncer::PASSWORDS); } +#else // BUILDFLAG(IS_ANDROID) && !BUILDFLAG(USE_LOGIN_DATABASE_AS_BACKEND) + allowed_types.Put(syncer::PASSWORDS); +#endif // BUILDFLAG(IS_ANDROID) && !BUILDFLAG(USE_LOGIN_DATABASE_AS_BACKEND) + #if BUILDFLAG(IS_ANDROID) - if (base::FeatureList::IsEnabled(syncer::kWebApkBackupAndRestoreBackend)) { - allowed_types.Put(syncer::WEB_APKS); - } -#endif - -#if BUILDFLAG(IS_CHROMEOS) - // OS sync types run in transport mode. - allowed_types.PutAll({syncer::APP_LIST, syncer::ARC_PACKAGE, - syncer::OS_PREFERENCES, syncer::OS_PRIORITY_PREFERENCES, - syncer::PRINTERS, - syncer::PRINTERS_AUTHORIZATION_SERVERS, - syncer::WIFI_CONFIGURATIONS, syncer::WORKSPACE_DESK}); -#endif // BUILDFLAG(IS_CHROMEOS) - -#if !BUILDFLAG(IS_ANDROID) + // TODO(crbug.com/420912307): Allow `syncer::WEB_APKS` if + // `syncer::kWebApkBackupAndRestoreBackend` is enabled. +#else // BUILDFLAG(IS_ANDROID) if (base::FeatureList::IsEnabled(syncer::kSeparateLocalAndAccountThemes)) { allowed_types.Put(syncer::THEMES); } @@ -1150,7 +1177,21 @@ syncer::kSeparateLocalAndAccountSearchEngines)) { allowed_types.Put(syncer::SEARCH_ENGINES); } -#endif // !BUILDFLAG(IS_ANDROID) + + // These types are excluded on Android as they run outside Chrome. + allowed_types.Put(syncer::INCOMING_PASSWORD_SHARING_INVITATION); + allowed_types.Put(syncer::OUTGOING_PASSWORD_SHARING_INVITATION); + allowed_types.Put(syncer::WEBAUTHN_CREDENTIAL); +#endif // BUILDFLAG(IS_ANDROID) +#endif // BUILDFLAG(IS_CHROMEOS) + + if (base::FeatureList::IsEnabled( + plus_addresses::features::kPlusAddressesEnabled) && + !plus_addresses::features::kEnterprisePlusAddressServerUrl.Get() + .empty()) { + allowed_types.Put(syncer::PLUS_ADDRESS); + allowed_types.Put(syncer::PLUS_ADDRESS_SETTING); + } return allowed_types; }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 35bcb53..68ff0d1a 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1047,8 +1047,6 @@ "passwords/bubble_controllers/move_to_account_store_bubble_controller.h", "passwords/bubble_controllers/password_bubble_controller_base.cc", "passwords/bubble_controllers/password_bubble_controller_base.h", - "passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.cc", - "passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h", "passwords/bubble_controllers/password_change/successful_password_change_bubble_controller.cc", "passwords/bubble_controllers/password_change/successful_password_change_bubble_controller.h", "passwords/bubble_controllers/post_save_compromised_bubble_controller.cc", @@ -4337,8 +4335,6 @@ "views/passwords/password_auto_sign_in_view.h", "views/passwords/password_bubble_view_base.cc", "views/passwords/password_bubble_view_base.h", - "views/passwords/password_change/password_change_credential_leak_bubble_view.cc", - "views/passwords/password_change/password_change_credential_leak_bubble_view.h", "views/passwords/password_change/password_change_toast.cc", "views/passwords/password_change/password_change_toast.h", "views/passwords/password_change/successful_password_change_view.cc",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 7aafe2f..c9ed87f 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4422,6 +4422,9 @@ <message name="IDS_MENU_RECENT_TABS" desc="Menu item for opening the 'Recent tabs' page that shows recently closed tabs and pages the user has opened on his/her other devices. [CHAR_LIMIT=27]"> Recent tabs </message> + <message name="IDS_MENU_EXTENSIONS" desc="Menu item for opening the 'Extensions' page that allows the user to manage installed extensions. [CHAR_LIMIT=27]"> + Extensions + </message> <message name="IDS_MENU_TINKER_TANK" desc="Menu item for opening the tinker tank bottom sheet. [CHAR_LIMIT=27]" translateable="false"> Tinker tank </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_EXTENSIONS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_EXTENSIONS.png.sha1 new file mode 100644 index 0000000..7c143e94 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MENU_EXTENSIONS.png.sha1
@@ -0,0 +1 @@ +a1d39a56f032d53d0c50d4b1cb4e221f725cbb49 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb index a00351d..489f6c4 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
@@ -332,6 +332,7 @@ <translation id="2524132927880411790">Joan Google aplikazioaren ahozko bilaketara</translation> <translation id="2527209463677295330">Orriko testu gehiago barne hartuz gero, agian emaitza hobeak ikusiko dituzu</translation> <translation id="2527779675047087889">Ezkutatu arbeleko edukia</translation> +<translation id="2531209299761896527">Fitxak beste leiho batean irekitzeko, atximurkatu, eduki sakatuta eta arrastatu</translation> <translation id="2532336938189706096">Web-ikuspegia</translation> <translation id="253498598929009420">Webguneak pantailan agertzen dena ikusi ahal izango du</translation> <translation id="2535807170289627159">Fitxa guztiak</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb index 84f2390..9c44dcf 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
@@ -341,6 +341,7 @@ <translation id="2546283357679194313">ຄຸກກີ້ ແລະຂໍ້ມູນເວັບໄຊທ໌...</translation> <translation id="2547843573592965873">ການລັອກໂປຣໄຟລ໌ຂອງທ່ານຊ່ວຍຮັກສາຂໍ້ມູນຂອງທ່ານໃນລົດໃຫ້ປອດໄພ, ຮວມເຖິງລະຫັດຜ່ານ, ການຈ່າຍເງິນ ແລະ ອື່ນໆທີ່ບັນທຶກໄວ້ໃນບັນຊີ Google ຂອງທ່ານ.</translation> <translation id="254973855621628293">ບັນທຶກລະຫັດຜ່ານໃສ່ອຸປະກອນນີ້ແລ້ວ</translation> +<translation id="2566471851103108967">{FILE_COUNT,plural, =1{ບລັອກການດາວໂຫຼດທີ່ເປັນອັນຕະລາຍແລ້ວ}other{ບລັອກການດາວໂຫຼດ # ລາຍການທີ່ເປັນອັນຕະລາຍແລ້ວ}}</translation> <translation id="2567385386134582609">ຮູບ</translation> <translation id="2569733278091928697">ທ່ານຈະສາມາດຈັດການການຄວບຄຸມມີເດຍ, ເຊດຊັນບໍ່ເປີດເຜີຍຕົວຕົນ, ການດາວໂຫຼດ ແລະ ອື່ນໆໄດ້ຢ່າງງ່າຍດາຍ</translation> <translation id="2571711316400087311">ສະເໜີສົ່ງໜ້າເປັນພາສາອື່ນໃຫ້ Google ແປພາສາ</translation> @@ -750,6 +751,7 @@ <translation id="4479972344484327217">ກຳລັງຕິດຕັ້ງ <ph name="MODULE" /> ສໍາລັບ Chrome…</translation> <translation id="4484496141267039529">ບໍ່ມີການເຊື່ອມຕໍ່. ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ.</translation> <translation id="4487967297491345095">ທຸກຂໍ້ມູນແອັບຂອງ Chrome ຈະຖືກລຶບຢ່າງຖາວອນ. ນີ້ຮວມເອົາທຸກໄຟລ໌, ການຕັ້ງຄ່າ, ບັນຊີ, ຖານຂໍ້ມູນ ແລະ ອື່ນໆ.</translation> +<translation id="4494315997125191493">ເລືອກຈັດການເພື່ອເບິ່ງໜ້າຈໍທັງໝົດ</translation> <translation id="4494806687727322324">ຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານເປີດການບັນທຶກລະຫັດຜ່ານ</translation> <translation id="4508528996305412043">ເມນູບັດຟີດເປີດຢູ່</translation> <translation id="4509741852167209430">ຂໍ້ມູນປະເພດທີ່ຈຳກັດຈະຖືກແບ່ງປັນລະຫວ່າງເວັບໄຊຕ່າງໆເພື່ອວັດແທກປະສິດທິພາບຂອງໂຄສະນາຂອງເຂົາເຈົ້າ, ເຊັ່ນ: ທ່ານມີການຊື້ເຄື່ອງຫຼັງຈາກເຂົ້າເວັບໄຊໃດໜຶ່ງຫຼືບໍ່</translation> @@ -790,6 +792,7 @@ <translation id="4668279686271488041">ຂໍ້ມູນການວັດແທກການໂຄສະນາຖືກລຶບຢ່າງເປັນປົກກະຕິຈາກອຸປະກອນຂອງທ່ານ</translation> <translation id="4668347365065281350">ຂໍ້ມູນທັງໝົດທີ່ເກັບໄວ້ໂດຍເວັບໄຊ, ຮວມທັງຄຸກກີ້ ແລະ ຂໍ້ມູນອື່ນທີ່ເກັບໄວ້ໃນເຄື່ອງ</translation> <translation id="4678082183394354975">ຮູບແບບສີສັນມືດສຳລັບເວັບໄຊແມ່ນຖືກເປີດໃຊ້ໃນ Chrome ແລ້ວ</translation> +<translation id="4682306524980568490">ສາມາດສະແດງໄດ້ພຽງ <ph name="MAX_INSTANCE_COUNT" /> ໜ້າຈໍເທົ່ານັ້ນ</translation> <translation id="4684427112815847243">ຊິງຄ໌ທຸກຢ່າງ</translation> <translation id="4685741273709472646">ເລືອກຈາກລາຍຊື່ແບບເລື່ອນລົງ</translation> <translation id="4687718960473379118">ໂຄສະນາທີ່ເວັບໄຊແນະນຳ</translation>
diff --git a/chrome/browser/ui/android/toolbar/extension_actions_bridge.cc b/chrome/browser/ui/android/toolbar/extension_actions_bridge.cc index 6ae831c25..b71a051 100644 --- a/chrome/browser/ui/android/toolbar/extension_actions_bridge.cc +++ b/chrome/browser/ui/android/toolbar/extension_actions_bridge.cc
@@ -143,6 +143,13 @@ runner->RunAction(extension, /*grant_tab_permissions=*/true)); } +jboolean ExtensionActionsBridge::ExtensionsEnabled(JNIEnv* env) { + extensions::ExtensionManagement* extension_management = + extensions::ExtensionManagementFactory::GetForBrowserContext(profile_); + return static_cast<jboolean>( + extension_management->ExtensionsEnabledForDesktopAndroid()); +} + void ExtensionActionsBridge::OnToolbarActionAdded( const ToolbarActionsModel::ActionId& id) { Java_ExtensionActionsBridge_onActionAdded(AttachCurrentThread(), java_object_,
diff --git a/chrome/browser/ui/android/toolbar/extension_actions_bridge.h b/chrome/browser/ui/android/toolbar/extension_actions_bridge.h index ca9d0564..8e02f53 100644 --- a/chrome/browser/ui/android/toolbar/extension_actions_bridge.h +++ b/chrome/browser/ui/android/toolbar/extension_actions_bridge.h
@@ -40,6 +40,7 @@ jint RunAction(JNIEnv* env, const std::string& action_id, const base::android::JavaParamRef<jobject>& web_contents_java); + jboolean ExtensionsEnabled(JNIEnv* env); // ToolbarActionsModel::Observer: void OnToolbarActionAdded(const ToolbarActionsModel::ActionId& id) override;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsBridge.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsBridge.java index 42dc3574..ae66b052 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsBridge.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionsBridge.java
@@ -92,6 +92,15 @@ .runAction(mNativeExtensionActionsBridge, actionId, webContents); } + /** + * Returns whether the extensions are disabled on the profile for Desktop Android. This is + * temporary for until extensions are ready for dogfooding. TODO(crbug.com/422307625): Remove + * this check once extensions are ready for dogfooding. + */ + public boolean extensionsEnabled() { + return ExtensionActionsBridgeJni.get().extensionsEnabled(mNativeExtensionActionsBridge); + } + @CalledByNative @VisibleForTesting void onActionAdded(@JniType("std::string") String actionId) { @@ -194,5 +203,7 @@ long nativeExtensionActionsBridge, @JniType("std::string") String actionId, WebContents webContents); + + boolean extensionsEnabled(long nativeExtensionActionsBridge); } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java index 48d05a42..69520795 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java
@@ -52,7 +52,4 @@ themeColorProvider); return manager; } - - /** Initialize the manager with the components that had native initialization dependencies. */ - public void initializeWithNative(); }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManagerImpl.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManagerImpl.java index 7c9f5ca..decee3d 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManagerImpl.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManagerImpl.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.toolbar.extensions; import android.content.Context; -import android.view.View; import android.view.ViewStub; import android.widget.LinearLayout; @@ -14,7 +13,6 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.build.annotations.ServiceImpl; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.theme.ThemeColorProvider; @@ -59,18 +57,7 @@ mExtensionsMenuButton = container.findViewById(R.id.extensions_menu_button); mExtensionsMenuButtonCoordinator = new ExtensionsMenuButtonCoordinator( - context, mExtensionsMenuButton, themeColorProvider); - } - - @Override - public void initializeWithNative() { - assert mExtensionsMenuButton != null; - - mExtensionsMenuButton.setVisibility( - ChromeFeatureList.isEnabled( - ChromeFeatureList.BLOCK_INSTALLING_EXTENSIONS_ON_DESKTOP_ANDROID) - ? View.GONE - : View.VISIBLE); + context, mExtensionsMenuButton, themeColorProvider, profileSupplier); } @Override
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuButtonCoordinator.java index 9c97bdc..d354eaf 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuButtonCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuButtonCoordinator.java
@@ -10,9 +10,12 @@ import androidx.core.widget.ImageViewCompat; +import org.chromium.base.Callback; import org.chromium.base.lifetime.Destroyable; +import org.chromium.base.supplier.ObservableSupplier; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.theme.ThemeColorProvider; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.ui.listmenu.ListMenuButton; @@ -23,18 +26,46 @@ private final ListMenuButton mExtensionsMenuButton; private final ThemeColorProvider mThemeColorProvider; - private final ThemeColorProvider.TintObserver mTintObserver; + private final ObservableSupplier<Profile> mProfileSupplier; + + private final ThemeColorProvider.TintObserver mTintObserver = this::onTintChanged; + private final Callback<Profile> mProfileUpdatedCallback = this::onProfileUpdated; + + @Nullable private Profile mProfile; public ExtensionsMenuButtonCoordinator( Context context, ListMenuButton extensionsMenuButton, - ThemeColorProvider themeColorProvider) { + ThemeColorProvider themeColorProvider, + ObservableSupplier<Profile> profileSupplier) { mExtensionsMenuButton = extensionsMenuButton; mExtensionsMenuButton.setOnClickListener(this::onClick); + mProfileSupplier = profileSupplier; mThemeColorProvider = themeColorProvider; - mTintObserver = this::onTintChanged; mThemeColorProvider.addTintObserver(mTintObserver); + + mProfileSupplier.addObserver(mProfileUpdatedCallback); + } + + private void onProfileUpdated(@Nullable Profile profile) { + if (profile == mProfile) { + return; + } + + mProfile = profile; + + // TODO(crbug.com/422307625): Remove this check once extensions are ready for + // dogfooding. + int visibility = View.GONE; + if (mProfile != null) { + ExtensionActionsBridge extensionActionsBridge = ExtensionActionsBridge.get(mProfile); + if (extensionActionsBridge != null && extensionActionsBridge.extensionsEnabled()) { + visibility = View.VISIBLE; + } + } + + mExtensionsMenuButton.setVisibility(visibility); } void onClick(View view) { @@ -54,5 +85,7 @@ public void destroy() { mExtensionsMenuButton.setOnClickListener(null); mThemeColorProvider.removeTintObserver(mTintObserver); + mProfileSupplier.removeObserver(mProfileUpdatedCallback); + mProfile = null; } }
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc index aa84946..7aa71ad 100644 --- a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc +++ b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
@@ -585,7 +585,7 @@ return false; } - quick_answers_ui_controller_->CreateUserConsentView(anchor_bounds_, + quick_answers_ui_controller_->CreateUserConsentView(profile_, anchor_bounds_, intent_type, intent_text); consent_ui_shown_ = GetTimeTicksNow();
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc index c0bba2c..c5e5958 100644 --- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc +++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc
@@ -254,11 +254,12 @@ } void QuickAnswersUiController::CreateUserConsentView( + Profile* profile, const gfx::Rect& anchor_bounds, quick_answers::IntentType intent_type, const std::u16string& intent_text) { CreateUserConsentViewInternal( - anchor_bounds, intent_type, intent_text, + profile, anchor_bounds, intent_type, intent_text, /*use_refreshed_design=*/ chromeos::features::IsQuickAnswersMaterialNextUIEnabled()); } @@ -269,11 +270,12 @@ const std::u16string& intent_text, bool use_refreshed_design) { CHECK_IS_TEST(); - CreateUserConsentViewInternal(anchor_bounds, intent_type, intent_text, - use_refreshed_design); + CreateUserConsentViewInternal(/*profile=*/nullptr, anchor_bounds, intent_type, + intent_text, use_refreshed_design); } void QuickAnswersUiController::CreateUserConsentViewInternal( + Profile* profile, const gfx::Rect& anchor_bounds, quick_answers::IntentType intent_type, const std::u16string& intent_text, @@ -284,13 +286,16 @@ if (chromeos::features::IsMagicBoostRevampForQuickAnswersEnabled() && QuickAnswersState::GetFeatureType() == QuickAnswersState::FeatureType::kHmr) { + // Directing to the right settings toggle requires an active profile. + profile_ = profile; user_consent_view_.SetView( GetReadWriteCardsUiController().SetQuickAnswersUi( views::Builder<quick_answers::MagicBoostUserConsentView>( std::make_unique<quick_answers::MagicBoostUserConsentView>( - // TODO: crbug.com/414391121 - Populate the button label - // with the correct text. - intent_text, GetReadWriteCardsUiController())) + intent_type, intent_text, GetReadWriteCardsUiController())) + .SetSettingsButtonPressed(base::BindRepeating( + &QuickAnswersUiController::OnSettingsButtonPressed, + base::Unretained(this))) .Build())); } else { user_consent_view_.SetView(
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h index 523dd2f..cf08f20 100644 --- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h +++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h
@@ -11,6 +11,7 @@ #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h" #include "chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h" #include "chrome/browser/ui/ash/quick_answers/ui/rich_answers_view.h" #include "chrome/browser/ui/ash/quick_answers/ui/user_consent_view.h" @@ -96,7 +97,8 @@ // feature vertically aligned to the anchor. Note that user consent is handled // by Quick Answers code only if `QuickAnswersState::FeatureType` is // `kQuickAnswers`. - void CreateUserConsentView(const gfx::Rect& anchor_bounds, + void CreateUserConsentView(Profile* profile, + const gfx::Rect& anchor_bounds, quick_answers::IntentType intent_type, const std::u16string& intent_text); void CreateUserConsentViewForPixelTest(const gfx::Rect& anchor_bounds, @@ -146,6 +148,10 @@ return views::AsViewClass<quick_answers::UserConsentView>( user_consent_view_.view()); } + quick_answers::MagicBoostUserConsentView* magic_boost_user_consent_view() { + return views::AsViewClass<quick_answers::MagicBoostUserConsentView>( + user_consent_view_.view()); + } quick_answers::RichAnswersView* rich_answers_view() { return views::AsViewClass<quick_answers::RichAnswersView>( rich_answers_widget_->GetContentsView()); @@ -162,7 +168,8 @@ const std::string& query, std::optional<quick_answers::Intent> intent, quick_answers::QuickAnswersView::Params params); - void CreateUserConsentViewInternal(const gfx::Rect& anchor_bounds, + void CreateUserConsentViewInternal(Profile* profile, + const gfx::Rect& anchor_bounds, quick_answers::IntentType intent_type, const std::u16string& intent_text, bool use_refreshed_design);
diff --git a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.cc b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.cc index c58db4ec..1e9c343 100644 --- a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.cc +++ b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.cc
@@ -74,13 +74,35 @@ // Icon. constexpr gfx::Insets kIntentIconInsets = gfx::Insets(8); +std::u16string GetChipLabel(IntentType intent_type, + const std::u16string& intent_text) { + switch (intent_type) { + case IntentType::kUnit: + return l10n_util::GetStringFUTF16( + IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_UNIT_CONVERSION_INTENT_LABEL_BUTTON, + intent_text); + case IntentType::kDictionary: + return l10n_util::GetStringFUTF16( + IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_DEFINITION_INTENT_LABEL_BUTTON, + intent_text); + case IntentType::kTranslation: + return l10n_util::GetStringFUTF16( + IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_TRANSLATION_INTENT_LABEL_BUTTON, + intent_text); + case IntentType::kUnknown: + NOTREACHED() << "No chip label for Unknown intent type"; + } + NOTREACHED() << "Unknown enum"; +} + } // namespace // MagicBoostUserConsentView // ------------------------------------------------------------- MagicBoostUserConsentView::MagicBoostUserConsentView( - const std::u16string& chip_label, + IntentType intent_type, + const std::u16string& intent_text, chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller) : chromeos::ReadWriteCardsView(read_write_cards_ui_controller), focus_search_( @@ -115,7 +137,8 @@ .AddChild( views::Builder<views::LabelButton>() .CopyAddressTo(&intent_chip_) - .SetText(chip_label) + .SetText( + GetChipLabel(intent_type, intent_text)) .SetProperty(views::kMarginsKey, kChipMargin) .SetLabelStyle( views::style::STYLE_BODY_4_EMPHASIS) @@ -145,6 +168,7 @@ views::Builder<views::ImageButton>() .SetTooltipText(l10n_util::GetStringUTF16( IDS_RICH_ANSWERS_VIEW_SETTINGS_BUTTON_A11Y_NAME_TEXT)) + .CopyAddressTo(&settings_button_) .SetImageModel( views::Button::ButtonState::STATE_NORMAL, ui::ImageModel::FromVectorIcon( @@ -188,6 +212,11 @@ return focusable_views; } +void MagicBoostUserConsentView::SetSettingsButtonPressed( + views::Button::PressedCallback callback) { + settings_button_->SetCallback(std::move(callback)); +} + BEGIN_METADATA(MagicBoostUserConsentView) END_METADATA
diff --git a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h index 9cb09fb..4f387f2 100644 --- a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h +++ b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h
@@ -13,8 +13,10 @@ #include "chrome/browser/ui/ash/editor_menu/utils/focus_search.h" #include "chrome/browser/ui/ash/read_write_cards/read_write_cards_ui_controller.h" #include "chrome/browser/ui/ash/read_write_cards/read_write_cards_view.h" +#include "chromeos/components/quick_answers/quick_answers_model.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/controls/button/button.h" +#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/layout/flex_layout_view.h" #include "ui/views/metadata/view_factory.h" @@ -25,8 +27,6 @@ class LabelButton; } // namespace views -class QuickAnswersUiController; - namespace quick_answers { class MagicBoostUserConsentView : public chromeos::ReadWriteCardsView { @@ -35,10 +35,11 @@ public: static constexpr char kWidgetName[] = "MagicBoostUserConsentViewWidget"; - // TODO: crbug.com/340628664 - remove `read_write_cards_ui_controller` arg - // once we stop extending `ReadWriteCardsView`. - explicit MagicBoostUserConsentView( - const std::u16string& chip_label, + // TODO(b/340628664): remove `read_write_cards_ui_controller` arg once we stop + // extending `ReadWriteCardsView`. + MagicBoostUserConsentView( + IntentType intent_type, + const std::u16string& intent_text, chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller); // Disallow copy and assign. @@ -53,20 +54,24 @@ views::FocusTraversable* GetPaneFocusTraversable() override; void UpdateBoundsForQuickAnswers() override; + void SetSettingsButtonPressed(views::Button::PressedCallback callback); + std::u16string chip_label_for_testing(); + views::ImageButton* settings_button_for_testing() { return settings_button_; } private: // FocusSearch::GetFocusableViewsCallback to poll currently focusable views. std::vector<views::View*> GetFocusableViews(); - base::WeakPtr<QuickAnswersUiController> controller_; chromeos::editor_menu::FocusSearch focus_search_; raw_ptr<views::LabelButton> intent_chip_ = nullptr; + raw_ptr<views::ImageButton> settings_button_ = nullptr; }; BEGIN_VIEW_BUILDER(/* no export */, MagicBoostUserConsentView, chromeos::ReadWriteCardsView) +VIEW_BUILDER_PROPERTY(views::Button::PressedCallback, SettingsButtonPressed) END_VIEW_BUILDER } // namespace quick_answers
diff --git a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view_unittest.cc b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view_unittest.cc index 6d1cbd00c..1f53556 100644 --- a/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view_unittest.cc +++ b/chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view_unittest.cc
@@ -4,20 +4,161 @@ #include "chrome/browser/ui/ash/quick_answers/ui/magic_boost_user_consent_view.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/global_features.h" +#include "chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h" +#include "chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.h" #include "chrome/browser/ui/ash/read_write_cards/read_write_cards_ui_controller.h" +#include "chrome/browser/ui/settings_window_manager_chromeos.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chromeos/components/quick_answers/test/fake_quick_answers_state.h" +#include "chromeos/constants/chromeos_features.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/test/event_generator.h" +#include "ui/views/controls/button/image_button.h" #include "ui/views/test/test_layout_provider.h" namespace quick_answers { -TEST(MagicBoostUserConsentViewTest, ButtonTextLabel) { - views::test::TestLayoutProvider test_layout_provider; - chromeos::ReadWriteCardsUiController read_write_cards_ui_controller; - MagicBoostUserConsentView magic_boost_user_consent_view( - /*chip_label=*/u"testing label", read_write_cards_ui_controller); +namespace { - EXPECT_EQ(u"testing label", +constexpr gfx::Rect kDefaultAnchorBoundsInScreen = + gfx::Rect(gfx::Point(500, 250), gfx::Size(120, 140)); + +class MockSettingsWindowManager : public chrome::SettingsWindowManager { + public: + MOCK_METHOD(void, + ShowChromePageForProfile, + (Profile * profile, + const GURL& gurl, + int64_t display_id, + apps::LaunchCallback callback), + (override)); +}; + +} // namespace + +class MagicBoostUserConsentViewTest : public ChromeQuickAnswersTestBase { + protected: + MagicBoostUserConsentViewTest() = default; + MagicBoostUserConsentViewTest(const MagicBoostUserConsentViewTest&) = delete; + MagicBoostUserConsentViewTest& operator=( + const MagicBoostUserConsentViewTest&) = delete; + ~MagicBoostUserConsentViewTest() override = default; + + // ChromeQuickAnswersTestBase: + void SetUp() override { + ChromeQuickAnswersTestBase::SetUp(); + + feature_list_.InitWithFeatures( + {chromeos::features::kMagicBoostRevampForQuickAnswers}, {}); + } + + void TearDown() override { + fake_quick_answers_state_ = nullptr; + + ChromeQuickAnswersTestBase::TearDown(); + } + + std::unique_ptr<QuickAnswersControllerImpl> CreateQuickAnswersControllerImpl( + chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller) + override { + std::unique_ptr<FakeQuickAnswersState> fake_quick_answers_state = + std::make_unique<FakeQuickAnswersState>(); + fake_quick_answers_state_ = fake_quick_answers_state.get(); + fake_quick_answers_state_->OverrideFeatureType( + QuickAnswersState::FeatureType::kHmr); + return std::make_unique<QuickAnswersControllerImpl>( + TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + read_write_cards_ui_controller, std::move(fake_quick_answers_state)); + } + + public: + QuickAnswersControllerImpl* GetQuickAnswersController() { + return static_cast<QuickAnswersControllerImpl*>( + QuickAnswersController::Get()); + } + + QuickAnswersUiController* GetUiController() { + return GetQuickAnswersController()->quick_answers_ui_controller(); + } + + MagicBoostUserConsentView* GetMagicBoostUserConsentView() { + return views::AsViewClass<MagicBoostUserConsentView>( + GetUiController()->magic_boost_user_consent_view()); + } + + void CreateUserConsentView() { + GetQuickAnswersController()->SetVisibility( + QuickAnswersVisibility::kPending); + // Set up a companion menu before creating the QuickAnswersView. + CreateAndShowBasicMenu(); + GetUiController()->GetReadWriteCardsUiController().SetContextMenuBounds( + kDefaultAnchorBoundsInScreen); + + static_cast<QuickAnswersControllerImpl*>(QuickAnswersController::Get()) + ->SetVisibility(QuickAnswersVisibility::kPending); + GetUiController()->CreateUserConsentView( + GetProfile(), kDefaultAnchorBoundsInScreen, + quick_answers::IntentType::kUnit, u"Text"); + } + + private: + base::test::ScopedFeatureList feature_list_; + chromeos::ReadWriteCardsUiController controller_; + raw_ptr<FakeQuickAnswersState> fake_quick_answers_state_ = nullptr; +}; + +TEST_F(MagicBoostUserConsentViewTest, TranslateButtonTextLabel) { + MagicBoostUserConsentView magic_boost_user_consent_view( + IntentType::kTranslation, + /*intent_text=*/u"testing label", + GetUiController()->GetReadWriteCardsUiController()); + + EXPECT_EQ(u"Translate \"testing label\"", magic_boost_user_consent_view.chip_label_for_testing()); } +TEST_F(MagicBoostUserConsentViewTest, DefineButtonTextLabel) { + MagicBoostUserConsentView magic_boost_user_consent_view( + IntentType::kDictionary, + /*intent_text=*/u"testing label", + GetUiController()->GetReadWriteCardsUiController()); + + EXPECT_EQ(u"Define \"testing label\"", + magic_boost_user_consent_view.chip_label_for_testing()); +} + +TEST_F(MagicBoostUserConsentViewTest, ConvertButtonTextLabel) { + MagicBoostUserConsentView magic_boost_user_consent_view( + IntentType::kUnit, + /*intent_text=*/u"testing label", + GetUiController()->GetReadWriteCardsUiController()); + + EXPECT_EQ(u"Convert \"testing label\"", + magic_boost_user_consent_view.chip_label_for_testing()); +} + +TEST_F(MagicBoostUserConsentViewTest, OpenSettings) { + MockSettingsWindowManager mock_settings_window_manager; + chrome::SettingsWindowManager::SetInstanceForTesting( + &mock_settings_window_manager); + + CreateUserConsentView(); + + EXPECT_CALL( + mock_settings_window_manager, + ShowChromePageForProfile(testing::_, testing::_, testing::_, testing::_)); + + GetEventGenerator()->MoveMouseTo(GetMagicBoostUserConsentView() + ->settings_button_for_testing() + ->GetBoundsInScreen() + .CenterPoint()); + GetEventGenerator()->ClickLeftButton(); +} + } // namespace quick_answers
diff --git a/chrome/browser/ui/autofill/autofill_ai/mock_save_or_update_ai_data_controller.h b/chrome/browser/ui/autofill/autofill_ai/mock_save_or_update_ai_data_controller.h index b344fcb..72f284e 100644 --- a/chrome/browser/ui/autofill/autofill_ai/mock_save_or_update_ai_data_controller.h +++ b/chrome/browser/ui/autofill/autofill_ai/mock_save_or_update_ai_data_controller.h
@@ -20,12 +20,13 @@ MockSaveOrUpdateAutofillAiDataController(); ~MockSaveOrUpdateAutofillAiDataController() override; - MOCK_METHOD(void, - ShowPrompt, - (autofill::EntityInstance, - std::optional<autofill::EntityInstance>, - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback), - (override)); + MOCK_METHOD( + void, + ShowPrompt, + (autofill::EntityInstance, + std::optional<autofill::EntityInstance>, + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback), + (override)); MOCK_METHOD(base::optional_ref<const autofill::EntityInstance>, GetAutofillAiData, (),
diff --git a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller.h b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller.h index 1b07ad1..291caab 100644 --- a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller.h +++ b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller.h
@@ -82,7 +82,7 @@ virtual void ShowPrompt( autofill::EntityInstance new_entity, std::optional<autofill::EntityInstance> old_entity, - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback) = 0; // Called when the user accepts to save or update Autofill AI data.
diff --git a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.cc b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.cc index 067e54a5..feec165 100644 --- a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.cc
@@ -112,7 +112,7 @@ void SaveOrUpdateAutofillAiDataControllerImpl::ShowPrompt( autofill::EntityInstance new_entity, std::optional<autofill::EntityInstance> old_entity, - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback) { // Don't show the bubble if it's already visible. if (bubble_view()) {
diff --git a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.h b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.h index 40b00245..68c23539 100644 --- a/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.h +++ b/chrome/browser/ui/autofill/autofill_ai/save_or_update_autofill_ai_data_controller_impl.h
@@ -43,10 +43,11 @@ ~SaveOrUpdateAutofillAiDataControllerImpl() override; // SaveOrUpdateAutofillAiDataController: - void ShowPrompt(autofill::EntityInstance new_entity, - std::optional<autofill::EntityInstance> old_entity, - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback - save_prompt_acceptance_callback) override; + void ShowPrompt( + autofill::EntityInstance new_entity, + std::optional<autofill::EntityInstance> old_entity, + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback + save_prompt_acceptance_callback) override; void OnSaveButtonClicked() override; base::optional_ref<const autofill::EntityInstance> GetAutofillAiData() const override; @@ -87,7 +88,7 @@ // Callback to notify the data provider about the user decision for the save // or update prompt. - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback_; base::WeakPtrFactory<SaveOrUpdateAutofillAiDataControllerImpl>
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 98289ae..15ac269d 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -1201,4 +1201,20 @@ #endif } +void ChromeAutofillClient::ShowEntitySaveOrUpdateBubble( + EntityInstance new_entity, + std::optional<EntityInstance> old_entity, + EntitySaveOrUpdatePromptResultCallback prompt_acceptance_callback) { +#if !BUILDFLAG(IS_ANDROID) + if (auto* controller = + autofill_ai::SaveOrUpdateAutofillAiDataController::GetOrCreate( + &*web_contents(), GetAppLocale())) { + controller->ShowPrompt(std::move(new_entity), std::move(old_entity), + std::move(prompt_acceptance_callback)); + return; + } +#endif // !BUILDFLAG(IS_ANDROID) + std::move(prompt_acceptance_callback).Run(EntitySaveOrUpdatePromptResult()); +} + } // namespace autofill
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 4cffd1c..798daef 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -215,6 +215,11 @@ plus_addresses::hats::SurveyType survey_type) final; optimization_guide::ModelQualityLogsUploaderService* GetMqlsUploadService() override; + void ShowEntitySaveOrUpdateBubble( + EntityInstance new_entity, + std::optional<EntityInstance> old_entity, + EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback) + override; // TODO(crbug.com/407666146): Create a test API. base::WeakPtr<AutofillSuggestionController>
diff --git a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.cc b/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.cc deleted file mode 100644 index ff8cba8d5..0000000 --- a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.cc +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2025 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/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h" - -#include <string> - -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/sync/sync_service_factory.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate.h" -#include "chrome/browser/ui/passwords/passwords_model_delegate.h" -#include "chrome/browser/ui/passwords/ui_utils.h" -#include "chrome/grit/generated_resources.h" -#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" -#include "components/password_manager/core/browser/password_manager_metrics_util.h" -#include "components/url_formatter/elide_url.h" - -namespace metrics_util = password_manager::metrics_util; - -PasswordChangeCredentialLeakBubbleController:: - PasswordChangeCredentialLeakBubbleController( - base::WeakPtr<PasswordsModelDelegate> delegate) - : PasswordBubbleControllerBase( - delegate, - password_manager::metrics_util::UIDisplayDisposition:: - PASSWORD_CHANGE_BUBBLE), - password_change_delegate_( - delegate_->GetPasswordChangeDelegate()->AsWeakPtr()) {} - -PasswordChangeCredentialLeakBubbleController:: - ~PasswordChangeCredentialLeakBubbleController() { - OnBubbleClosing(); -} - -std::u16string PasswordChangeCredentialLeakBubbleController::GetTitle() const { - return l10n_util::GetStringUTF16( - IDS_PASSWORD_MANAGER_UI_PASSWORD_CHANGE_LEAK_BUBBLE_TITLE); -} - -void PasswordChangeCredentialLeakBubbleController::ReportInteractions() { - base::UmaHistogramEnumeration( - "PasswordManager.PasswordChange.LeakDetectionBubble", dismissal_reason_, - metrics_util::NUM_UI_RESPONSES); -} - -std::u16string PasswordChangeCredentialLeakBubbleController::GetDisplayOrigin() - const { - return password_change_delegate_->GetDisplayOrigin(); -} - -void PasswordChangeCredentialLeakBubbleController:: - NavigateToPasswordChangeSettings() { - dismissal_reason_ = metrics_util::CLICKED_ABOUT_PASSWORD_CHANGE; - delegate_->NavigateToPasswordChangeSettings(); -} - -std::u16string -PasswordChangeCredentialLeakBubbleController::GetPrimaryAccountEmail() const { - Profile* profile = GetProfile(); - return base::UTF8ToUTF16(GetDisplayableAccountName( - SyncServiceFactory::GetForProfile(profile), - IdentityManagerFactory::GetForProfile(profile))); -} - -void PasswordChangeCredentialLeakBubbleController::ChangePassword() { - dismissal_reason_ = metrics_util::CLICKED_ACCEPT; - password_change_delegate_->StartPasswordChangeFlow(); -} - -void PasswordChangeCredentialLeakBubbleController::Cancel() { - dismissal_reason_ = metrics_util::CLICKED_CANCEL; - CHECK(password_change_delegate_); - password_change_delegate_->Stop(); - delegate_->GetPasswordsLeakDialogDelegate()->OnLeakDialogHidden(); -}
diff --git a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h b/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h deleted file mode 100644 index 75dc016f..0000000 --- a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2025 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_UI_PASSWORDS_BUBBLE_CONTROLLERS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_CONTROLLER_H_ -#define CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_CONTROLLER_H_ - -#include <string> - -#include "base/memory/weak_ptr.h" -#include "chrome/browser/password_manager/password_change_delegate.h" -#include "chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate.h" -#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" - -// Controller for the credential leak bubble, which is only displayed when the -// password change is supported. -class PasswordChangeCredentialLeakBubbleController - : public PasswordBubbleControllerBase { - public: - explicit PasswordChangeCredentialLeakBubbleController( - base::WeakPtr<PasswordsModelDelegate> delegate); - - ~PasswordChangeCredentialLeakBubbleController() override; - - // PasswordBubbleControllerBase methods: - std::u16string GetTitle() const override; - void ReportInteractions() override; - - // Get the change password origin to be displayed in UI. - std::u16string GetDisplayOrigin() const; - std::u16string GetPrimaryAccountEmail() const; - - void NavigateToPasswordChangeSettings(); - void ChangePassword(); - void Cancel(); - - private: - base::WeakPtr<PasswordChangeDelegate> password_change_delegate_; - // Dismissal reason for a password bubble. - password_manager::metrics_util::UIDismissalReason dismissal_reason_ = - password_manager::metrics_util::NO_DIRECT_INTERACTION; -}; - -#endif // CHROME_BROWSER_UI_PASSWORDS_BUBBLE_CONTROLLERS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller_unittest.cc b/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller_unittest.cc deleted file mode 100644 index 10df7d7f..0000000 --- a/chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller_unittest.cc +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2025 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/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h" - -#include <memory> - -#include "base/test/metrics/histogram_tester.h" -#include "chrome/browser/password_manager/password_change_delegate_mock.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate_mock.h" -#include "chrome/browser/ui/passwords/passwords_model_delegate_mock.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::Return; -namespace metrics_util = password_manager::metrics_util; - -class PasswordChangeCredentialLeakBubbleControllerTest - : public ::testing::Test { - public: - void CreateController() { - EXPECT_CALL(mock_delegate_, OnBubbleShown()); - ON_CALL(mock_delegate_, GetPasswordChangeDelegate) - .WillByDefault(Return(&password_change_delegate_)); - ON_CALL(mock_delegate_, GetPasswordsLeakDialogDelegate) - .WillByDefault(Return(&passwords_leak_dialog_delegate_)); - controller_ = - std::make_unique<PasswordChangeCredentialLeakBubbleController>( - mock_delegate_.AsWeakPtr()); - } - - protected: - PasswordsModelDelegateMock mock_delegate_; - std::unique_ptr<PasswordChangeCredentialLeakBubbleController> controller_; - PasswordChangeDelegateMock password_change_delegate_; - PasswordsLeakDialogDelegateMock passwords_leak_dialog_delegate_; -}; - -TEST_F(PasswordChangeCredentialLeakBubbleControllerTest, - MetricsReportedForCancel) { - base::HistogramTester histogram_tester; - CreateController(); - - controller_->Cancel(); - controller_.reset(); - histogram_tester.ExpectUniqueSample( - "PasswordManager.PasswordChange.LeakDetectionBubble", - metrics_util::CLICKED_CANCEL, 1); -} - -TEST_F(PasswordChangeCredentialLeakBubbleControllerTest, - MetricsReportedForAccept) { - base::HistogramTester histogram_tester; - CreateController(); - - controller_->ChangePassword(); - controller_.reset(); - histogram_tester.ExpectUniqueSample( - "PasswordManager.PasswordChange.LeakDetectionBubble", - metrics_util::CLICKED_ACCEPT, 1); -} - -TEST_F(PasswordChangeCredentialLeakBubbleControllerTest, - MetricsReportedForAboutPasswordChange) { - base::HistogramTester histogram_tester; - CreateController(); - - controller_->NavigateToPasswordChangeSettings(); - controller_.reset(); - histogram_tester.ExpectUniqueSample( - "PasswordManager.PasswordChange.LeakDetectionBubble", - metrics_util::CLICKED_ABOUT_PASSWORD_CHANGE, 1); -}
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 688401a..4fef9ed 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -58,7 +58,6 @@ #include "chrome/browser/ui/user_education/browser_user_education_interface.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/passwords/manage_passwords_page_action_controller.h" -#include "chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/common/url_constants.h" #include "chrome/grit/branded_strings.h"
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_unittest.cc b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_browsertest.cc similarity index 76% rename from chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_unittest.cc rename to chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_browsertest.cc index 4dd33d3..d8126423d 100644 --- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_unittest.cc +++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate_browsertest.cc
@@ -8,18 +8,17 @@ #include "base/memory/raw_ptr.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/search.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/signin/chrome_signin_client_factory.h" -#include "chrome/browser/signin/chrome_signin_client_test_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/url_constants.h" -#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/search_test_utils.h" -#include "chrome/test/base/testing_profile.h" #include "components/search_engines/template_url_service.h" +#include "content/public/test/browser_test.h" // Concrete implementation of ChromeLocationBarModelDelegate. class TestChromeLocationBarModelDelegate @@ -37,7 +36,6 @@ // ChromeLocationBarModelDelegate: content::WebContents* GetActiveWebContents() const override { - browser_->tab_strip_model()->GetActiveWebContents(); return browser_->tab_strip_model()->GetActiveWebContents(); } @@ -57,18 +55,22 @@ net::CertStatus cert_status_ = 0; }; -class ChromeLocationBarModelDelegateTest : public BrowserWithTestWindowTest { +class ChromeLocationBarModelDelegateTest : public InProcessBrowserTest { protected: ChromeLocationBarModelDelegateTest() = default; - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - - TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( - profile(), + void SetUpBrowserContextKeyedServices( + content::BrowserContext* context) override { + TemplateURLServiceFactory::GetInstance()->SetTestingFactory( + context, base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor)); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(profile()); + TemplateURLServiceFactory::GetForProfile(browser()->profile()); search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service); delegate_ = std::make_unique<TestChromeLocationBarModelDelegate>(browser()); @@ -76,7 +78,7 @@ void SetSearchProvider(bool set_ntp_url) { TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(profile()); + TemplateURLServiceFactory::GetForProfile(browser()->profile()); TemplateURLData data; data.SetShortName(u"foo.com"); data.SetURL("http://foo.com/url?bar={searchTerms}"); @@ -97,14 +99,6 @@ TestChromeLocationBarModelDelegate* delegate() { return delegate_.get(); } - // BrowserWithTestWindowTest: - TestingProfile::TestingFactories GetTestingFactories() override { - return {TestingProfile::TestingFactory{ - ChromeSigninClientFactory::GetInstance(), - base::BindRepeating(&BuildChromeSigninClientWithURLLoader, - test_url_loader_factory())}}; - } - private: base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<TestChromeLocationBarModelDelegate> delegate_; @@ -113,11 +107,11 @@ // Tests whether ChromeLocationBarModelDelegate::IsNewTabPage and // ChromeLocationBarModelDelegate::IsNewTabPageURL return the expected results // for various NTP scenarios. -TEST_F(ChromeLocationBarModelDelegateTest, IsNewTabPage) { +IN_PROC_BROWSER_TEST_F(ChromeLocationBarModelDelegateTest, IsNewTabPage) { chrome::NewTab(browser()); // New Tab URL with Google DSP resolves to the local or the WebUI NTP URL. GURL ntp_url(chrome::kChromeUINewTabPageURL); - EXPECT_EQ(ntp_url, search::GetNewTabPageURL(profile())); + EXPECT_EQ(ntp_url, search::GetNewTabPageURL(browser()->profile())); EXPECT_TRUE(delegate()->IsNewTabPage()); EXPECT_TRUE(delegate()->IsNewTabPageURL(GetURL())); @@ -127,7 +121,7 @@ // New Tab URL with a user selected DSP without an NTP URL resolves to // chrome://new-tab-page-third-party/. EXPECT_EQ(GURL(chrome::kChromeUINewTabPageThirdPartyURL), - search::GetNewTabPageURL(profile())); + search::GetNewTabPageURL(browser()->profile())); EXPECT_FALSE(delegate()->IsNewTabPage()); EXPECT_TRUE(delegate()->IsNewTabPageURL(GetURL())); @@ -135,13 +129,15 @@ SetSearchProvider(true); chrome::NewTab(browser()); // New Tab URL with a user selected DSP resolves to the DSP's NTP URL. - EXPECT_EQ("https://foo.com/newtab", search::GetNewTabPageURL(profile())); + EXPECT_EQ("https://foo.com/newtab", + search::GetNewTabPageURL(browser()->profile())); EXPECT_FALSE(delegate()->IsNewTabPage()); EXPECT_TRUE(delegate()->IsNewTabPageURL(GetURL())); } -TEST_F(ChromeLocationBarModelDelegateTest, CertErrorPreventsElision) { +IN_PROC_BROWSER_TEST_F(ChromeLocationBarModelDelegateTest, + CertErrorPreventsElision) { EXPECT_FALSE(delegate()->ShouldPreventElision()); delegate()->set_cert_status(net::CERT_STATUS_REVOKED); EXPECT_TRUE(delegate()->ShouldPreventElision());
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc index e9d8b04..58adc8d 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/bookmarks/bookmark_test_helpers.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" +#include "chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.h" #include "chrome/browser/preloading/chrome_preloading.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -434,6 +435,10 @@ } } + content::test::PrerenderTestHelper& prerender_helper() { + return prerender_helper_; + } + private: base::ScopedMockElapsedTimersForTest scoped_test_timer_; content::test::PrerenderTestHelper prerender_helper_; @@ -733,6 +738,41 @@ "Bookmarks.BookmarkBar.PrerenderNavigationToActivation", 1); } +IN_PROC_BROWSER_TEST_F(PrerenderBookmarkBarOnHoverNavigationTest, + DestroyedOnNavigatedAway) { + base::HistogramTester histogram_tester; + + // Navigate to an initial page. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), https_test_server()->GetURL("/empty.html"))); + + GURL prerender_url = https_test_server()->GetURL("/simple.html?prerender"); + + BookmarkBarPreloadPipelineManager::CreateForWebContents( + GetActiveWebContents()); + auto* bookmarkbar_preload_manager = + BookmarkBarPreloadPipelineManager::FromWebContents( + GetActiveWebContents()); + + bookmarkbar_preload_manager->StartPrerender(prerender_url); + content::test::PrerenderTestHelper::WaitForPrerenderLoadCompletion( + *GetActiveWebContents(), prerender_url); + content::FrameTreeNodeId host_id = + prerender_helper().GetHostForUrl(prerender_url); + ASSERT_TRUE(host_id); + + // Navigate to a different page. This should cancel prerendering. + content::test::PrerenderHostObserver prerender_observer( + *GetActiveWebContents(), host_id); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), https_test_server()->GetURL("/simple.html?different"))); + prerender_observer.WaitForDestroyed(); + + histogram_tester.ExpectUniqueSample( + "Prerender.Experimental.PrerenderHostFinalStatus.Embedder_BookmarkBar", + kFinalStatusTriggerDestroyed, 1); +} + // TODO(crbug.com/40285326): This fails with the field trial testing config. class PrerenderBookmarkBarOnHoverNavigationTestNoTestingConfig : public PrerenderBookmarkBarOnHoverNavigationTest {
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc index d20b9d8..2f69761b 100644 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc +++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
@@ -96,7 +96,7 @@ // Keep top-chrome visible while a permission bubble is visible. auto* permission_manager = permissions::PermissionRequestManager::FromWebContents(contents); - if (permission_manager && permission_manager->IsRequestInProgress()) { + if (permission_manager && permission_manager->GetCurrentPrompt()) { return cc::BrowserControlsState::kShown; }
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc index 23ffc60..b5f7f68 100644 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -1363,9 +1363,7 @@ CheckBrowserLayout(browser_view(), TopChromeShownState::kFullyShown); } -// Sheriff 2022/04/18; flaky test crbug/1317068 -IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest, - DISABLED_TestPermissionBubble) { +IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest, TestPermissionBubble) { ToggleTabletMode(); ASSERT_TRUE(GetTabletModeEnabled()); EXPECT_TRUE(top_controls_slide_controller()->IsEnabled());
diff --git a/chrome/browser/ui/views/message_box_dialog.cc b/chrome/browser/ui/views/message_box_dialog.cc index 163159d..491b16f 100644 --- a/chrome/browser/ui/views/message_box_dialog.cc +++ b/chrome/browser/ui/views/message_box_dialog.cc
@@ -88,15 +88,6 @@ }, &run_loop, &result)); run_loop.Run(); - - // After the dialog is closed, the Widget's destruction may post final - // cleanup tasks (e.g., to the compositor). Wait until these tasks are - // fully executed. - base::RunLoop flush_loop(base::RunLoop::Type::kNestableTasksAllowed); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, flush_loop.QuitClosure()); - flush_loop.Run(); - return result; }
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.cc b/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.cc deleted file mode 100644 index e65d83ba..0000000 --- a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.cc +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2025 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/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h" - -#include <memory> - -#include "base/functional/bind.h" -#include "chrome/browser/ui/browser_actions.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate.h" -#include "chrome/browser/ui/passwords/passwords_model_delegate.h" -#include "chrome/browser/ui/ui_features.h" -#include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" -#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" -#include "chrome/browser/ui/views/page_action/page_action_icon_view.h" -#include "chrome/browser/ui/views/passwords/views_utils.h" -#include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" -#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" -#include "content/public/browser/web_contents.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/gfx/text_constants.h" -#include "ui/views/controls/styled_label.h" -#include "ui/views/layout/flex_layout.h" -#include "ui/views/vector_icons.h" - -using ClosedReason = views::Widget::ClosedReason; - -namespace { -// Returns margins for a dialog. -gfx::Insets GetDialogInsets() { - const auto* const layout_provider = ChromeLayoutProvider::Get(); - gfx::Insets margins = layout_provider->GetInsetsMetric(views::INSETS_DIALOG); - margins.set_top(0); - return margins; -} -} // namespace - -PasswordChangeCredentialLeakBubbleView::PasswordChangeCredentialLeakBubbleView( - content::WebContents* web_contents, - views::View* anchor_view) - : PasswordBubbleViewBase(web_contents, - anchor_view, - /*easily_dismissable=*/true), - controller_(PasswordsModelDelegateFromWebContents(web_contents)) { - set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH)); - int spacing = ChromeLayoutProvider::Get()->GetDistanceMetric( - DISTANCE_RELATED_CONTROL_VERTICAL_SMALL); - auto* box_layout = SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - box_layout->set_cross_axis_alignment(views::LayoutAlignment::kStretch); - box_layout->SetCollapseMarginsSpacing(true); - box_layout->set_between_child_spacing(spacing); - box_layout->set_inside_border_insets(GetDialogInsets()); - // Set the margins to 0 such that the `root_view` fills the whole page bubble - // width. - set_margins(gfx::Insets()); - - AddChildView(views::Builder<views::StyledLabel>() - .SetText(controller_.GetDisplayOrigin()) - .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT) - .SetDefaultTextStyle(views::style::STYLE_PRIMARY) - .Build()); - AddChildView(CreateBodyText()); - - SetButtons(static_cast<int>(ui::mojom::DialogButton::kOk)); - SetButtonLabel(ui::mojom::DialogButton::kOk, - l10n_util::GetStringUTF16( - IDS_PASSWORD_MANAGER_UI_PASSWORD_CHANGE_CHANGE_PASSWORD)); - SetAcceptCallback(base::BindOnce( - &PasswordChangeCredentialLeakBubbleController::ChangePassword, - base::Unretained(&controller_))); - SetCloseCallback(base::BindRepeating( - [](PasswordChangeCredentialLeakBubbleView* view) { - ClosedReason reason = view->GetWidget()->closed_reason(); - // Cancel the flow if the dialog is explicitly closed. - if (reason == ClosedReason::kCloseButtonClicked || - reason == ClosedReason::kEscKeyPressed) { - // `controller_.Cancel()` may trigger Save/Update password prompt, so - // we need to hide this bubble earlier. - view->GetWidget()->Hide(); - view->controller_.Cancel(); - } - }, - this)); -} - -PasswordChangeCredentialLeakBubbleView:: - ~PasswordChangeCredentialLeakBubbleView() = default; - -std::unique_ptr<views::StyledLabel> -PasswordChangeCredentialLeakBubbleView::CreateBodyText() { - base::RepeatingClosure navigate_to_settings = - base::BindRepeating(&PasswordChangeCredentialLeakBubbleController:: - NavigateToPasswordChangeSettings, - base::Unretained(&controller_)); - return CreateGooglePasswordManagerLabel( - /*text_message_id=*/ - IDS_PASSWORD_MANAGER_UI_PASSWORD_CHANGE_LEAK_BUBBLE_DETAILS, - /*link_message_id=*/ - IDS_PASSWORD_MANAGER_UI_PASSWORD_CHANGE_SETTINGS_LINK, - controller_.GetPrimaryAccountEmail(), navigate_to_settings, - views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_PRIMARY); -} - -PasswordBubbleControllerBase* -PasswordChangeCredentialLeakBubbleView::GetController() { - return &controller_; -} - -const PasswordBubbleControllerBase* -PasswordChangeCredentialLeakBubbleView::GetController() const { - return &controller_; -} - -void PasswordChangeCredentialLeakBubbleView::OnWidgetInitialized() { - PasswordBubbleViewBase::OnWidgetInitialized(); - GetOkButton()->SetImageModel( - views::Button::ButtonState::STATE_NORMAL, - ui::ImageModel::FromVectorIcon(views::kPasswordChangeIcon, - ui::kColorIconSecondary, - GetLayoutConstant(PAGE_INFO_ICON_SIZE))); - GetOkButton()->SetHorizontalAlignment(gfx::ALIGN_LEFT); - SetBubbleHeader(IDR_PASSWORD_CHANGE_WARNING, - IDR_PASSWORD_CHANGE_WARNING_DARK); -} - -BEGIN_METADATA(PasswordChangeCredentialLeakBubbleView) -END_METADATA
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h b/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h deleted file mode 100644 index 27d4a3d..0000000 --- a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2025 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_UI_VIEWS_PASSWORDS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_PASSWORDS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_VIEW_H_ - -#include "chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate.h" -#include "chrome/browser/ui/views/passwords/password_bubble_view_base.h" -#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" -#include "ui/views/controls/styled_label.h" - -class PasswordChangeCredentialLeakBubbleView : public PasswordBubbleViewBase { - METADATA_HEADER(PasswordChangeCredentialLeakBubbleView, - PasswordBubbleViewBase) - - public: - PasswordChangeCredentialLeakBubbleView(content::WebContents* web_contents, - views::View* anchor_view); - - private: - ~PasswordChangeCredentialLeakBubbleView() override; - - std::unique_ptr<views::StyledLabel> CreateBodyText(); - - // PasswordBubbleViewBase - PasswordBubbleControllerBase* GetController() override; - const PasswordBubbleControllerBase* GetController() const override; - - // View: - void OnWidgetInitialized() override; - - PasswordChangeCredentialLeakBubbleController controller_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PASSWORDS_PASSWORD_CHANGE_PASSWORD_CHANGE_CREDENTIAL_LEAK_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view_unittest.cc b/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view_unittest.cc deleted file mode 100644 index a142ced..0000000 --- a/chrome/browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view_unittest.cc +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2025 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/ui/views/passwords/password_change/password_change_credential_leak_bubble_view.h" - -#include "chrome/browser/password_manager/password_change_delegate_mock.h" -#include "chrome/browser/sync/sync_service_factory.h" -#include "chrome/browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller.h" -#include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate_mock.h" -#include "chrome/browser/ui/views/passwords/password_bubble_view_test_base.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" -#include "components/signin/public/identity_manager/account_info.h" -#include "components/sync/service/sync_service.h" -#include "components/sync/test/test_sync_service.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/test/test_event.h" -#include "ui/views/test/button_test_api.h" - -using testing::Invoke; -using testing::Return; -using ClosedReason = views::Widget::ClosedReason; - -namespace { -const std::u16string kTestEmail = u"account@example.com"; - -std::unique_ptr<KeyedService> BuildTestSyncService( - AccountInfo account_info, - content::BrowserContext* context) { - auto sync_service = std::make_unique<syncer::TestSyncService>(); - sync_service->SetSignedIn(signin::ConsentLevel::kSync, account_info); - return sync_service; -} -} // namespace - -class PasswordChangeCredentialLeakBubbleViewTest - : public PasswordBubbleViewTestBase { - public: - PasswordChangeCredentialLeakBubbleViewTest() = default; - ~PasswordChangeCredentialLeakBubbleViewTest() override = default; - - void SetUp() override { - PasswordBubbleViewTestBase::SetUp(); - password_change_delegate_ = std::make_unique<PasswordChangeDelegateMock>(); - ON_CALL(*password_change_delegate_, GetDisplayOrigin()) - .WillByDefault(Return(u"example.com")); - ON_CALL(*model_delegate_mock(), GetPasswordChangeDelegate()) - .WillByDefault(Return(password_change_delegate_.get())); - ON_CALL(*model_delegate_mock(), GetPasswordsLeakDialogDelegate()) - .WillByDefault(Return(&passwords_leak_dialog_delegate_)); - AccountInfo account_info = identity_test_env()->MakePrimaryAccountAvailable( - base::UTF16ToUTF8(kTestEmail), signin::ConsentLevel::kSignin); - SyncServiceFactory::GetInstance()->SetTestingFactory( - profile(), - base::BindRepeating(&BuildTestSyncService, std::move(account_info))); - } - - void TearDown() override { - view_->GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kCloseButtonClicked); - view_ = nullptr; - PasswordBubbleViewTestBase::TearDown(); - } - - void CreateAndShowView() { - CreateAnchorViewAndShow(); - - view_ = new PasswordChangeCredentialLeakBubbleView(web_contents(), - anchor_view()); - views::BubbleDialogDelegateView::CreateBubble(view_)->Show(); - } - - PasswordChangeCredentialLeakBubbleView* view() { return view_; } - - PasswordChangeDelegateMock* password_change_delegate() { - return password_change_delegate_.get(); - } - - PasswordsLeakDialogDelegateMock* passwords_leak_dialog_delegate() { - return &passwords_leak_dialog_delegate_; - } - - private: - raw_ptr<PasswordChangeCredentialLeakBubbleView> view_; - std::unique_ptr<PasswordChangeDelegateMock> password_change_delegate_; - PasswordsLeakDialogDelegateMock passwords_leak_dialog_delegate_; -}; - -TEST_F(PasswordChangeCredentialLeakBubbleViewTest, ChangePasswordIsTriggered) { - CreateAndShowView(); - - EXPECT_CALL(*password_change_delegate(), StartPasswordChangeFlow); - EXPECT_CALL(*model_delegate_mock(), OnBubbleHidden); - views::test::ButtonTestApi(view()->GetOkButton()) - .NotifyClick(ui::test::TestEvent()); -} - -TEST_F(PasswordChangeCredentialLeakBubbleViewTest, - PasswordChangeLinkIsTriggered) { - CreateAndShowView(); - - auto* controller = static_cast<PasswordChangeCredentialLeakBubbleController*>( - static_cast<PasswordBubbleViewBase*>(view())->GetController()); - EXPECT_CALL(*model_delegate_mock(), NavigateToPasswordChangeSettings); - controller->NavigateToPasswordChangeSettings(); -} - -TEST_F(PasswordChangeCredentialLeakBubbleViewTest, - OnLeakDialogHiddenIsTriggeredOnClose) { - CreateAndShowView(); - - EXPECT_CALL(*passwords_leak_dialog_delegate(), OnLeakDialogHidden); - view()->GetWidget()->CloseWithReason(ClosedReason::kCloseButtonClicked); -}
diff --git a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc index 848a5ca..dd8dcb17 100644 --- a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc +++ b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc
@@ -543,6 +543,13 @@ return false; } + // Only preloads for regular profiles because WebContents::GetWebUI() + // may crash due to dangling RFH if navigation fails. See crbug.com/409389408. + // TODO(crbug.com/424551539): remove after fixing dangling RFH. + if (!Profile::FromBrowserContext(browser_context)->IsRegularProfile()) { + return false; + } + // Don't preload if under heavy memory pressure. const auto* memory_monitor = base::MemoryPressureMonitor::Get(); if (memory_monitor && memory_monitor->GetCurrentPressureLevel() >=
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 3df86fa..df3cb591 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1750009617-bbfeebdfad78b22da897197df9e2c2884d7eca3d-f6ac3cb5a4c11c6645de8f6c2268c1194015d70f.profdata +chrome-android32-main-1750053232-d5e827b0aae26bd92cef8256c29d0eec51b348e6-1e7bd3c1484bb4a9e8c3ff5e58bcfe93f4fe86ba.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 89d189822..e7afea96 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1750015598-6439d4f9c5744cd57ff1dced75e3f34ff3ed5902-09516d32715f9bd80489f60c53c77b1021081774.profdata +chrome-android64-main-1750059333-20e55cfa5577ef42522c4973ab6147afc1acf57c-2dde65da9b24ed2fcf986f8ce3ab6aaa5c0f0da5.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 48f40bd..61adb2c 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1750009617-6eb2c7fe91c4b06a5af3e2e13402bf081fe3de6f-f6ac3cb5a4c11c6645de8f6c2268c1194015d70f.profdata +chrome-linux-main-1750053232-9965326834ecf9c33e3fb654f094cd1899a47b64-1e7bd3c1484bb4a9e8c3ff5e58bcfe93f4fe86ba.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 292d89f..63d0154f 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1750015598-0ff44c5aac07a439ed53c4c5fd045b028bab5526-09516d32715f9bd80489f60c53c77b1021081774.profdata +chrome-mac-arm-main-1750060693-c2a26aec9aa22aefec7d6151373d8d8989dee0cb-8d8a660571fbfbc6989167053297f9d8f84aa315.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 094de419..d62823999 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1750009617-05adae8e20951b03b0ea348000c68b4285cafb40-f6ac3cb5a4c11c6645de8f6c2268c1194015d70f.profdata +chrome-mac-main-1750053232-55f1879cb103295582b4ad7a15ac82753f013e00-1e7bd3c1484bb4a9e8c3ff5e58bcfe93f4fe86ba.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 926728de..d8f0642 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1749967031-d1c7b5ce762613d774449d613e40ca3d704ac388-1ef2b77bb4414969924929ac44548cef351a11a7.profdata +chrome-win-arm64-main-1750053232-33b168960ff3c97f61df406ebc8f69dec041a246-1e7bd3c1484bb4a9e8c3ff5e58bcfe93f4fe86ba.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index b50a3149..5c960237 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1749988628-4287abccd4efa8b9e34c1b13d84ee64289a1b8cf-8e8a0caa003533ccb469c4a67aef1241fe241952.profdata +chrome-win32-main-1750042359-79ec791e4b9dafe825d5c07bec701a38be69f1b8-5175ec0ed798bc0e0853112f2aca712067e5c1d4.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 9f771456..d74227f 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1749999351-2255fb30d49c619811527c22d680e8d62ad24fda-76e12975326cf471fe76aeb19ca5ecdbffc1f9fc.profdata +chrome-win64-main-1750042359-0e9d34015b69504bc6585da69dbbf7b3a25d22f9-5175ec0ed798bc0e0853112f2aca712067e5c1d4.profdata
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn index 3a7cd8c..2aa4730 100644 --- a/chrome/installer/linux/BUILD.gn +++ b/chrome/installer/linux/BUILD.gn
@@ -98,6 +98,7 @@ "debian/deb_version.py", "debian/dist_package_versions.json", "debian/package_version_interval.py", + "//build/action_helpers.py", "//third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl", ] outputs = [ "$root_out_dir/deb_{{source_name_part}}.deps" ] @@ -135,7 +136,10 @@ deps = [ ":installer_deps" ] script = "rpm/calculate_package_deps.py" sources = packaging_files_binaries - inputs = [ "rpm/dist_package_provides.json" ] + inputs = [ + "rpm/dist_package_provides.json", + "//build/action_helpers.py", + ] outputs = [ "$root_out_dir/rpm_{{source_name_part}}.deps" ] args = [ "{{source}}", @@ -151,7 +155,10 @@ deps = [ ":calculate_rpm_dependencies" ] script = "rpm/merge_package_deps.py" additional_deps = "rpm/additional_deps" - inputs = [ additional_deps ] + inputs = [ + additional_deps, + "//build/action_helpers.py", + ] outputs = [ "$root_out_dir/rpm_common.deps" ] args = [ "rpm_common.deps",
diff --git a/chrome/installer/linux/debian/calculate_package_deps.py b/chrome/installer/linux/debian/calculate_package_deps.py index 8a8b294..d4bb857 100755 --- a/chrome/installer/linux/debian/calculate_package_deps.py +++ b/chrome/installer/linux/debian/calculate_package_deps.py
@@ -119,7 +119,10 @@ file=sys.stderr) ret_code = 1 if ret_code == 0: - with open(dep_filename, 'w') as dep_file: + sys.path.append(os.path.join(script_dir, os.path.pardir, os.path.pardir, + os.path.pardir, os.path.pardir, 'build')) + import action_helpers + with action_helpers.atomic_output(dep_filename, mode='w') as dep_file: lines = [interval_set.formatted() + '\n' for interval_set in interval_sets] dep_file.write(''.join(sorted(lines)))
diff --git a/chrome/installer/linux/rpm/calculate_package_deps.py b/chrome/installer/linux/rpm/calculate_package_deps.py index c7c09851..9ed8e58 100755 --- a/chrome/installer/linux/rpm/calculate_package_deps.py +++ b/chrome/installer/linux/rpm/calculate_package_deps.py
@@ -64,8 +64,11 @@ ret_code = 1 continue if ret_code == 0: + sys.path.append(os.path.join(script_dir, os.path.pardir, os.path.pardir, + os.path.pardir, os.path.pardir, 'build')) + import action_helpers requires = requires.difference(remove_requires) - with open(dep_filename, 'w') as dep_file: + with action_helpers.atomic_output(dep_filename, mode='w') as dep_file: for requirement in sorted(list(requires)): dep_file.write(requirement + '\n') sys.exit(ret_code)
diff --git a/chrome/installer/linux/rpm/merge_package_deps.py b/chrome/installer/linux/rpm/merge_package_deps.py index 282e8b4..5cfa026 100755 --- a/chrome/installer/linux/rpm/merge_package_deps.py +++ b/chrome/installer/linux/rpm/merge_package_deps.py
@@ -3,8 +3,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import os import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), + os.path.pardir, os.path.pardir, os.path.pardir, + os.path.pardir, 'build')) +import action_helpers + if len(sys.argv) < 3: print ('Usage: %s output_deps_file input1_deps_file input2_deps_file ...' % sys.argv[0]) @@ -24,5 +30,5 @@ continue requires.add(line) -with open(output_filename, 'w') as output_file: +with action_helpers.atomic_output(output_filename, mode='w') as output_file: output_file.write(''.join(sorted(list(requires))))
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index da901b2..9b0778b8a 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3474,6 +3474,7 @@ "../browser/ui/thumbnails/thumbnail_readiness_tracker_browsertest.cc", "../browser/ui/toolbar/cast/cast_contextual_menu_browsertest.cc", "../browser/ui/toolbar/cast/cast_toolbar_button_controller_browsertest.cc", + "../browser/ui/toolbar/chrome_location_bar_model_delegate_browsertest.cc", "../browser/ui/toolbar/pinned_toolbar/pinned_toolbar_actions_model_browsertest.cc", "../browser/ui/toolbar/toolbar_actions_model_browsertest.cc", "../browser/ui/unload_controller_browsertest.cc", @@ -8002,7 +8003,6 @@ "../browser/ui/passwords/bubble_controllers/common_saved_account_manager_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/manage_passwords_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/move_to_account_store_bubble_controller_unittest.cc", - "../browser/ui/passwords/bubble_controllers/password_change/password_change_credential_leak_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/password_change/successful_password_change_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/post_save_compromised_bubble_controller_unittest.cc", "../browser/ui/passwords/bubble_controllers/save_unsynced_credentials_locally_bubble_controller_unittest.cc", @@ -8038,7 +8038,6 @@ "../browser/ui/toolbar/app_menu_model_unittest.cc", "../browser/ui/toolbar/back_forward_menu_model_unittest.cc", "../browser/ui/toolbar/chrome_labs/chrome_labs_model_unittest.cc", - "../browser/ui/toolbar/chrome_location_bar_model_delegate_unittest.cc", "../browser/ui/toolbar/location_bar_model_unittest.cc", "../browser/ui/toolbar/toolbar_actions_model_unittest.cc", "../browser/ui/url_identity_unittest.cc", @@ -8056,7 +8055,6 @@ "../browser/ui/views/passwords/move_to_account_store_bubble_view_unittest.cc", "../browser/ui/views/passwords/password_bubble_view_test_base.cc", "../browser/ui/views/passwords/password_bubble_view_test_base.h", - "../browser/ui/views/passwords/password_change/password_change_credential_leak_bubble_view_unittest.cc", "../browser/ui/views/passwords/password_change/password_change_toast_unittest.cc", "../browser/ui/views/passwords/password_change/successful_password_change_view_unittest.cc", "../browser/ui/views/passwords/password_save_unsynced_credentials_locally_view_unittest.cc", @@ -12211,10 +12209,13 @@ "//components/bookmarks/browser:test_support", "//components/bookmarks/managed", "//components/browser_sync", + "//components/commerce/core:feature_list", "//components/favicon/core", "//components/invalidation/impl", "//components/invalidation/impl:test_support", "//components/os_crypt/sync:test_support", + "//components/password_manager/core/browser:password_manager_buildflags", + "//components/plus_addresses:features", "//components/saved_tab_groups/public", "//components/signin/public/identity_manager:test_support", "//components/sync", @@ -12272,6 +12273,7 @@ ":sync_integration_test_support_jni_headers", ":test_support_jni_headers", "//chrome/browser/android/webapk:webapk_sources", + "//chrome/browser/password_manager/android:utils", "//chrome/browser/ui/android/tab_model", "//components/saved_tab_groups/public:conversion_utils", ]
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 47cb02a..86bfbc3 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -262,18 +262,6 @@ #endif } -constexpr const char* BuildArch() { -#if defined(ARCH_CPU_ARM64) - return "64 bit (ARM)"; -#elif defined(ARCH_CPU_X86_64) - return "64 bit (x64)"; -#elif defined(ARCH_CPU_X86) - return "32 bit (x86)"; -#else -#error CPU architecture is unknown. -#endif -} - std::string OperatingSystemVersion() { #if BUILDFLAG(IS_WIN) const base::win::OSInfo::VersionNumber v = @@ -326,7 +314,8 @@ const UpdaterScope updater_scope = GetUpdaterScope(); InitLogging(updater_scope); VLOG(1) << "Version: " << kUpdaterVersion << ", " << BuildFlavor() << ", " - << BuildArch() << ", command line: " << GetCommandLineString(); + << base::SysInfo::ProcessCPUArchitecture() + << ", command line: " << GetCommandLineString(); VLOG(1) << "OS version: " << OperatingSystemVersion() << ", System uptime (seconds): " << base::SysInfo::Uptime().InSeconds() << ", parent pid: "
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index a0e040a..eaf0bfd9 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16320.0.0-1069610 \ No newline at end of file +16320.0.0-1069621 \ No newline at end of file
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index aa513a8..2faaf3c2 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -258,6 +258,15 @@ <message name="IDS_QUICK_ANSWERS_USER_CONSENT_TITLE_UNIT_CONVERSION_INTENT" desc="Title text of the dialog that opens up to seek user-consent for the Quick Answers feature when the supported intent is generated from the query."> Convert "<ph name="query">$1<ex>1kg</ex></ph>" </message> + <message name="IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_DEFINITION_INTENT_LABEL_BUTTON" desc="Button label for Dictionary intent in the magic boost user consent view which leads to the magic boost disclaimer UI when clicked upon."> + Define "<ph name="query">$1<ex>unfathomable</ex></ph>" + </message> + <message name="IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_TRANSLATION_INTENT_LABEL_BUTTON" desc="Button label for Translation intent in the magic boost user consent view which leads to the magic boost disclaimer UI when clicked upon."> + Translate "<ph name="query">$1<ex>信息</ex></ph>" + </message> + <message name="IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_UNIT_CONVERSION_INTENT_LABEL_BUTTON" desc="Button label for Unit Conversion intent in the magic boost user consent view which leads to the magic boost disclaimer UI when clicked upon."> + Convert "<ph name="query">$1<ex>1kg</ex></ph>" + </message> <message name="IDS_QUICK_ANSWERS_USER_CONSENT_VIEW_TITLE_TEXT_WITH_INTENT" desc="Title text of the dialog that opens up to seek user-consent for the Quick Answers feature when supported intent is generated."> Get the <ph name="intent">$1<ex>definition</ex></ph> for "<ph name="query">$2<ex>unfathomable</ex></ph>" and more </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_DEFINITION_INTENT_LABEL_BUTTON.png.sha1 b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_DEFINITION_INTENT_LABEL_BUTTON.png.sha1 new file mode 100644 index 0000000..07de6f4a --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_DEFINITION_INTENT_LABEL_BUTTON.png.sha1
@@ -0,0 +1 @@ +6895d347beb0e7002c50898e1240a19373151665 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_TRANSLATION_INTENT_LABEL_BUTTON.png.sha1 b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_TRANSLATION_INTENT_LABEL_BUTTON.png.sha1 new file mode 100644 index 0000000..865908f9 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_TRANSLATION_INTENT_LABEL_BUTTON.png.sha1
@@ -0,0 +1 @@ +98bac6ce039952cfba1e7ddde2d5f7066e591274 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_UNIT_CONVERSION_INTENT_LABEL_BUTTON.png.sha1 b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_UNIT_CONVERSION_INTENT_LABEL_BUTTON.png.sha1 new file mode 100644 index 0000000..ea96441 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_QUICK_ANSWERS_MAGIC_BOOST_USER_CONSENT_UNIT_CONVERSION_INTENT_LABEL_BUTTON.png.sha1
@@ -0,0 +1 @@ +f8f891246e5003da6d250e562f3d3bd85eda261d \ No newline at end of file
diff --git a/clank b/clank index 2dbc9aa..e420186 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 2dbc9aa95eddeb69a73546f3076874c682375331 +Subproject commit e4201862b5cd95321ccc5abba80f47a502829743
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn index 1e51b2a0c..009b765 100644 --- a/components/autofill/content/renderer/BUILD.gn +++ b/components/autofill/content/renderer/BUILD.gn
@@ -144,4 +144,8 @@ "//testing/gtest", "//third_party/blink/public:blink", ] + + if (is_ios) { + deps += [ "//components/test:dom_label_test_bundle_data" ] + } }
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 8b8ba63..c3a502a 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -732,6 +732,7 @@ "webdata/payments/payments_autofill_table.h", "webdata/payments/payments_sync_bridge_util.cc", "webdata/payments/payments_sync_bridge_util.h", + "webdata/payments/server_cvc.h", "webdata/valuables/valuable_data_type_controller.cc", "webdata/valuables/valuable_data_type_controller.h", "webdata/valuables/valuable_sync_bridge.cc",
diff --git a/components/autofill/core/browser/foundations/autofill_client.cc b/components/autofill/core/browser/foundations/autofill_client.cc index 0881a03..7e05c8e 100644 --- a/components/autofill/core/browser/foundations/autofill_client.cc +++ b/components/autofill/core/browser/foundations/autofill_client.cc
@@ -50,6 +50,31 @@ AutofillClient::PopupOpenArgs& AutofillClient::PopupOpenArgs::operator=( AutofillClient::PopupOpenArgs&&) = default; +AutofillClient::EntitySaveOrUpdatePromptResult::EntitySaveOrUpdatePromptResult( + bool did_user_decline, + std::optional<EntityInstance> entity) + : did_user_decline(did_user_decline), entity(std::move(entity)) {} + +AutofillClient::EntitySaveOrUpdatePromptResult:: + EntitySaveOrUpdatePromptResult() = default; + +AutofillClient::EntitySaveOrUpdatePromptResult::EntitySaveOrUpdatePromptResult( + const AutofillClient::EntitySaveOrUpdatePromptResult&) = default; + +AutofillClient::EntitySaveOrUpdatePromptResult::EntitySaveOrUpdatePromptResult( + AutofillClient::EntitySaveOrUpdatePromptResult&&) = default; + +AutofillClient::EntitySaveOrUpdatePromptResult& +AutofillClient::EntitySaveOrUpdatePromptResult::operator=( + const AutofillClient::EntitySaveOrUpdatePromptResult&) = default; + +AutofillClient::EntitySaveOrUpdatePromptResult& +AutofillClient::EntitySaveOrUpdatePromptResult::operator=( + AutofillClient::EntitySaveOrUpdatePromptResult&&) = default; + +AutofillClient::EntitySaveOrUpdatePromptResult:: + ~EntitySaveOrUpdatePromptResult() = default; + version_info::Channel AutofillClient::GetChannel() const { return version_info::Channel::UNKNOWN; } @@ -260,4 +285,9 @@ return nullptr; } +void AutofillClient::ShowEntitySaveOrUpdateBubble( + EntityInstance new_entity, + std::optional<EntityInstance> old_entity, + EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback) {} + } // namespace autofill
diff --git a/components/autofill/core/browser/foundations/autofill_client.h b/components/autofill/core/browser/foundations/autofill_client.h index 4e40f9e..4b97a3d 100644 --- a/components/autofill/core/browser/foundations/autofill_client.h +++ b/components/autofill/core/browser/foundations/autofill_client.h
@@ -209,6 +209,28 @@ ArrowPosition arrow_position; }; + // Contains the result of a user interaction with the save/update AutofillAi + // prompt. + struct EntitySaveOrUpdatePromptResult final { + EntitySaveOrUpdatePromptResult(); + EntitySaveOrUpdatePromptResult(bool did_user_decline, + std::optional<EntityInstance> entity); + EntitySaveOrUpdatePromptResult(const EntitySaveOrUpdatePromptResult&); + EntitySaveOrUpdatePromptResult(EntitySaveOrUpdatePromptResult&&); + EntitySaveOrUpdatePromptResult& operator=( + const EntitySaveOrUpdatePromptResult&); + EntitySaveOrUpdatePromptResult& operator=(EntitySaveOrUpdatePromptResult&&); + ~EntitySaveOrUpdatePromptResult(); + + // Whether the user explicitly declined the dialog. + bool did_user_decline = false; + + // Non-empty iff the prompt was accepted. + std::optional<EntityInstance> entity; + }; + using EntitySaveOrUpdatePromptResultCallback = + base::OnceCallback<void(EntitySaveOrUpdatePromptResult result)>; + // Callback to run when the user makes a decision on whether to save the // profile. If the user edits the Autofill profile and then accepts edits, the // edited version of the profile should be passed as the second parameter. No @@ -626,6 +648,14 @@ // Returns the service used in order to log metrics into MQLS. virtual optimization_guide::ModelQualityLogsUploaderService* GetMqlsUploadService(); + + // Shows a bubble asking whether the user wants to save or update Autofill AI + // data. `old_entity` is present in the update cases. It is used to give users + // a better understanding of what was updated. + virtual void ShowEntitySaveOrUpdateBubble( + EntityInstance new_entity, + std::optional<EntityInstance> old_entity, + EntitySaveOrUpdatePromptResultCallback save_prompt_acceptance_callback); }; } // namespace autofill
diff --git a/components/autofill/core/browser/geo/country_data.cc b/components/autofill/core/browser/geo/country_data.cc index aa14c53..7ae6a59 100644 --- a/components/autofill/core/browser/geo/country_data.cc +++ b/components/autofill/core/browser/geo/country_data.cc
@@ -7,37 +7,29 @@ #include <array> #include <utility> +#include "base/containers/extend.h" +#include "base/containers/fixed_flat_map.h" +#include "base/containers/flat_map.h" +#include "base/containers/to_vector.h" #include "base/memory/singleton.h" +#include "base/strings/string_util.h" #include "components/strings/grit/components_strings.h" #include "third_party/icu/source/common/unicode/locid.h" namespace autofill { namespace { -struct StaticCountryAddressImportRequirementsData { - char country_code[3]; - RequiredFieldsForAddressImport address_import_field_requirements; -}; - -// Alias definitions record for CountryData requests. A request for -// |country_code_alias| is served with the |CountryData| for -// |country_code_target|. -struct StaticCountryCodeAliasData { - char country_code_alias[3]; - char country_code_target[3]; -}; - -// Alias definitions. +// Alias definitions. A request for the key is served with the `CountryData` for +// the target. constexpr auto kCountryCodeAliases = - std::to_array<StaticCountryCodeAliasData>({{"UK", "GB"}}); + base::MakeFixedFlatMap<std::string_view, std::string_view>({{"UK", "GB"}}); -// Maps country codes to address import requirements. Keep this sorted -// by country code. +// Maps country codes to address import requirements. // This list is comprized of countries appearing in both // //third_party/icu/source/data/region/en.txt and // //third_party/libaddressinput/src/cpp/src/region_data_constants.cc. constexpr auto kCountryAddressImportRequirementsData = - std::to_array<StaticCountryAddressImportRequirementsData>( + base::MakeFixedFlatMap<std::string_view, RequiredFieldsForAddressImport>( {{"AC", ADDRESS_REQUIRES_LINE1_CITY}, {"AD", ADDRESS_REQUIRES_LINE1}, {"AE", ADDRESS_REQUIRES_LINE1_STATE}, @@ -292,52 +284,36 @@ {"ZW", ADDRESS_REQUIRES_LINE1_CITY}}); // GetCountryCodes and GetCountryData compute the data for CountryDataMap -// based on |kCountryAddressImportRequirementsData|. +// based on `kCountryAddressImportRequirementsData`. std::vector<std::string> GetCountryCodes() { - std::vector<std::string> country_codes; - country_codes.reserve(std::size(kCountryAddressImportRequirementsData)); - for (const auto& static_data : kCountryAddressImportRequirementsData) { - country_codes.push_back(static_data.country_code); - } - return country_codes; + return base::ToVector( + kCountryAddressImportRequirementsData, + [](const auto& static_data) { return std::string(static_data.first); }); } -std::map<std::string, RequiredFieldsForAddressImport> GetCountryDataMap() { - std::map<std::string, RequiredFieldsForAddressImport> import_requirements; - // Add all the countries we have explicit data for. - for (const auto& static_data : kCountryAddressImportRequirementsData) { - import_requirements.insert( - import_requirements.end(), - std::make_pair(static_data.country_code, - static_data.address_import_field_requirements)); - } - - // Add any other countries that ICU knows about, falling back to default data - // values. +base::flat_map<std::string, RequiredFieldsForAddressImport> +GetCountryDataMap() { + // Collect other countries that ICU knows about but for which we have no + // manually specified requirements. + std::vector<std::pair<std::string, RequiredFieldsForAddressImport>> + other_countries; // SAFETY: `icu::Locale::getISOCountries` returns a C-style array whose last // entry is a nullptr. for (const char* const* country_pointer = icu::Locale::getISOCountries(); *country_pointer; UNSAFE_BUFFERS(++country_pointer)) { - std::string country_code = *country_pointer; - if (!import_requirements.count(country_code)) { - import_requirements.insert(std::make_pair( - std::move(country_code), - RequiredFieldsForAddressImport::ADDRESS_REQUIREMENTS_UNKNOWN)); + if (!kCountryAddressImportRequirementsData.contains(*country_pointer)) { + other_countries.emplace_back( + *country_pointer, + RequiredFieldsForAddressImport::ADDRESS_REQUIREMENTS_UNKNOWN); } } - return import_requirements; -} -std::map<std::string, std::string> GetCountryCodeAliasMap() { - std::map<std::string, std::string> country_code_aliases; - // Create mappings for the aliases defined in |kCountryCodeAliases|. - for (const auto& static_alias_data : kCountryCodeAliases) { - // Insert the alias. - country_code_aliases.insert( - std::make_pair(std::string(static_alias_data.country_code_alias), - std::string(static_alias_data.country_code_target))); - } - return country_code_aliases; + // Combine the other countries with those with explicit data. + other_countries.insert(other_countries.end(), + kCountryAddressImportRequirementsData.begin(), + kCountryAddressImportRequirementsData.end()); + return base::MakeFlatMap<std::string, RequiredFieldsForAddressImport>( + std::move(other_countries)); } } // namespace @@ -349,19 +325,18 @@ CountryDataMap::CountryDataMap() : required_fields_for_address_import_map_(GetCountryDataMap()), - country_code_aliases_(GetCountryCodeAliasMap()), country_codes_(GetCountryCodes()) {} CountryDataMap::~CountryDataMap() = default; bool CountryDataMap::HasRequiredFieldsForAddressImport( - const std::string& country_code) const { - return required_fields_for_address_import_map_.count(country_code) > 0; + std::string_view country_code) const { + return required_fields_for_address_import_map_.contains(country_code); } RequiredFieldsForAddressImport CountryDataMap::GetRequiredFieldsForAddressImport( - const std::string& country_code) const { + std::string_view country_code) const { auto lookup = required_fields_for_address_import_map_.find(country_code); if (lookup != required_fields_for_address_import_map_.end()) return lookup->second; @@ -370,18 +345,18 @@ } bool CountryDataMap::HasCountryCodeAlias( - const std::string& country_code_alias) const { - return country_code_aliases_.count(country_code_alias) > 0; + std::string_view country_code_alias) const { + return kCountryCodeAliases.contains(country_code_alias); } -const std::string CountryDataMap::GetCountryCodeForAlias( - const std::string& country_code_alias) const { - auto lookup = country_code_aliases_.find(country_code_alias); - if (lookup != country_code_aliases_.end()) { +std::string_view CountryDataMap::GetCountryCodeForAlias( + std::string_view country_code_alias) const { + auto lookup = kCountryCodeAliases.find(country_code_alias); + if (lookup != kCountryCodeAliases.end()) { DCHECK(HasRequiredFieldsForAddressImport(lookup->second)); return lookup->second; } - return std::string(); + return {}; } } // namespace autofill
diff --git a/components/autofill/core/browser/geo/country_data.h b/components/autofill/core/browser/geo/country_data.h index 8a30405f..e2a6cc9f 100644 --- a/components/autofill/core/browser/geo/country_data.h +++ b/components/autofill/core/browser/geo/country_data.h
@@ -5,10 +5,11 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_COUNTRY_DATA_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_COUNTRY_DATA_H_ -#include <map> #include <string> #include <vector> +#include "base/containers/flat_map.h" + namespace base { template <typename T> struct DefaultSingletonTraits; @@ -62,22 +63,23 @@ CountryDataMap(const CountryDataMap&) = delete; CountryDataMap& operator=(const CountryDataMap&) = delete; - // Returns true if a |CountryData| entry for the supplied |country_code| + // Returns true if a `CountryData` entry for the supplied `country_code` // exists. - bool HasRequiredFieldsForAddressImport(const std::string& country_code) const; + bool HasRequiredFieldsForAddressImport(std::string_view country_code) const; - // Returns true if there is a country code alias for |country_code|. - bool HasCountryCodeAlias(const std::string& country_code_alias) const; + // Returns true if there is a country code alias for `country_code`. + bool HasCountryCodeAlias(std::string_view country_code_alias) const; - // Returns the country code for a country code alias. If no alias definition - // is present return an empty string. - const std::string GetCountryCodeForAlias( - const std::string& country_code_alias) const; + // Returns the country code for a country code alias or an empty string if no + // alias definition is present. + std::string_view GetCountryCodeForAlias( + std::string_view country_code_alias) const; - // Lookup the |RequiredFieldForAddressImport| for the supplied |country_code|. - // If no entry exists, return requirements for the US as a best guess. + // Looks up the `RequiredFieldForAddressImport` for the supplied + // `country_code`. Returns requirements for the US as a best guess if no entry + // exists. RequiredFieldsForAddressImport GetRequiredFieldsForAddressImport( - const std::string& country_code) const; + std::string_view country_code) const; // Return a constant reference to a vector of all country codes. const std::vector<std::string>& country_codes() const { @@ -89,9 +91,8 @@ ~CountryDataMap(); friend struct base::DefaultSingletonTraits<CountryDataMap>; - const std::map<std::string, RequiredFieldsForAddressImport> + const base::flat_map<std::string, RequiredFieldsForAddressImport> required_fields_for_address_import_map_; - const std::map<std::string, std::string> country_code_aliases_; const std::vector<std::string> country_codes_; };
diff --git a/components/autofill/core/browser/webdata/autofill_change.h b/components/autofill/core/browser/webdata/autofill_change.h index 6a4d6fe..6cf57da6 100644 --- a/components/autofill/core/browser/webdata/autofill_change.h +++ b/components/autofill/core/browser/webdata/autofill_change.h
@@ -16,7 +16,7 @@ #include "components/autofill/core/browser/data_model/payments/credit_card.h" #include "components/autofill/core/browser/data_model/payments/iban.h" #include "components/autofill/core/browser/webdata/autocomplete/autocomplete_entry.h" -#include "components/autofill/core/browser/webdata/payments/payments_autofill_table.h" +#include "components/autofill/core/browser/webdata/payments/server_cvc.h" namespace autofill {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index 24a5042..04553d7 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -37,6 +37,7 @@ #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" #include "components/autofill/core/browser/webdata/payments/payments_autofill_table.h" +#include "components/autofill/core/browser/webdata/payments/server_cvc.h" #include "components/autofill/core/browser/webdata/valuables/valuables_table.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/dense_set.h"
diff --git a/components/autofill/core/browser/webdata/payments/autofill_wallet_credential_sync_bridge.cc b/components/autofill/core/browser/webdata/payments/autofill_wallet_credential_sync_bridge.cc index 3c66c30d..c8d0768 100644 --- a/components/autofill/core/browser/webdata/payments/autofill_wallet_credential_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/payments/autofill_wallet_credential_sync_bridge.cc
@@ -14,6 +14,7 @@ #include "components/autofill/core/browser/webdata/autofill_sync_metadata_table.h" #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" +#include "components/autofill/core/browser/webdata/payments/payments_autofill_table.h" #include "components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.h" #include "components/sync/base/data_type.h" #include "components/sync/base/deletion_origin.h"
diff --git a/components/autofill/core/browser/webdata/payments/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/payments/autofill_wallet_sync_bridge.h index 4369c38..fa46a8b 100644 --- a/components/autofill/core/browser/webdata/payments/autofill_wallet_sync_bridge.h +++ b/components/autofill/core/browser/webdata/payments/autofill_wallet_sync_bridge.h
@@ -24,6 +24,7 @@ class AutofillSyncMetadataTable; class AutofillWebDataBackend; class AutofillWebDataService; +class BankAccount; class CreditCard; class Iban; struct CreditCardCloudTokenData;
diff --git a/components/autofill/core/browser/webdata/payments/payments_autofill_table.cc b/components/autofill/core/browser/webdata/payments/payments_autofill_table.cc index 2b4e3e1..67e0335 100644 --- a/components/autofill/core/browser/webdata/payments/payments_autofill_table.cc +++ b/components/autofill/core/browser/webdata/payments/payments_autofill_table.cc
@@ -48,6 +48,7 @@ #include "components/autofill/core/browser/payments/payments_customer_data.h" #include "components/autofill/core/browser/webdata/autofill_change.h" #include "components/autofill/core/browser/webdata/autofill_table_utils.h" +#include "components/autofill/core/browser/webdata/payments/server_cvc.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h"
diff --git a/components/autofill/core/browser/webdata/payments/payments_autofill_table.h b/components/autofill/core/browser/webdata/payments/payments_autofill_table.h index 73bc6e0..89dd29f 100644 --- a/components/autofill/core/browser/webdata/payments/payments_autofill_table.h +++ b/components/autofill/core/browser/webdata/payments/payments_autofill_table.h
@@ -7,14 +7,11 @@ #include <stddef.h> -#include <map> #include <memory> #include <optional> #include <string> #include <vector> -#include "base/gtest_prod_util.h" -#include "base/time/time.h" #include "components/autofill/core/browser/data_model/payments/credit_card_benefit.h" #include "components/sync/base/data_type.h" #include "components/sync/protocol/autofill_specifics.pb.h" @@ -22,10 +19,6 @@ class WebDatabase; -namespace base { -class Time; -} - namespace autofill { class AutofillOfferData; @@ -35,19 +28,8 @@ class Iban; struct PaymentsCustomerData; struct PaymentsMetadata; +struct ServerCvc; class VirtualCardUsageData; -// Helper struct to better group server cvc related variables for better -// passing last_updated_timestamp, which is needed for sync bridge. Limited -// scope in autofill table & sync bridge. -struct ServerCvc { - bool operator==(const ServerCvc&) const = default; - // A server generated id to identify the corresponding credit card. - int64_t instrument_id; - // CVC value of the card. - std::u16string cvc; - // The timestamp of the most recent update to the data entry. - base::Time last_updated_timestamp; -}; // This class manages the various payments Autofill tables within the SQLite // database passed to the constructor. It expects the following schemas:
diff --git a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc index fd44f39..7f2bb419 100644 --- a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc +++ b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_util.cc
@@ -27,6 +27,7 @@ #include "components/autofill/core/browser/payments/constants.h" #include "components/autofill/core/browser/payments/payments_customer_data.h" #include "components/autofill/core/browser/webdata/payments/payments_autofill_table.h" +#include "components/autofill/core/browser/webdata/payments/server_cvc.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/credit_card_network_identifiers.h"
diff --git a/components/autofill/core/browser/webdata/payments/server_cvc.h b/components/autofill/core/browser/webdata/payments/server_cvc.h new file mode 100644 index 0000000..afbf2f24 --- /dev/null +++ b/components/autofill/core/browser/webdata/payments/server_cvc.h
@@ -0,0 +1,32 @@ +// Copyright 2025 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_AUTOFILL_CORE_BROWSER_WEBDATA_PAYMENTS_SERVER_CVC_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_PAYMENTS_SERVER_CVC_H_ + +#include <stddef.h> + +#include <string> + +#include "base/time/time.h" + +namespace autofill { + +// Helper struct to better group server cvc related variables for better +// passing last_updated_timestamp, which is needed for sync bridge. Limited +// scope in autofill table & sync bridge. +struct ServerCvc { + bool operator==(const ServerCvc&) const = default; + + // A server generated id to identify the corresponding credit card. + int64_t instrument_id; + // CVC value of the card. + std::u16string cvc; + // The timestamp of the most recent update to the data entry. + base::Time last_updated_timestamp; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_PAYMENTS_SERVER_CVC_H_
diff --git a/components/autofill_ai/core/browser/autofill_ai_client.cc b/components/autofill_ai/core/browser/autofill_ai_client.cc index cd6e525..63e8e0db 100644 --- a/components/autofill_ai/core/browser/autofill_ai_client.cc +++ b/components/autofill_ai/core/browser/autofill_ai_client.cc
@@ -11,32 +11,4 @@ namespace autofill_ai { -AutofillAiClient::EntitySaveOrUpdatePromptResult:: - EntitySaveOrUpdatePromptResult( - bool did_user_decline, - std::optional<autofill::EntityInstance> entity) - : did_user_decline(did_user_decline), entity(std::move(entity)) {} - -AutofillAiClient::EntitySaveOrUpdatePromptResult:: - EntitySaveOrUpdatePromptResult() = default; - -AutofillAiClient::EntitySaveOrUpdatePromptResult:: - EntitySaveOrUpdatePromptResult( - const AutofillAiClient::EntitySaveOrUpdatePromptResult&) = default; - -AutofillAiClient::EntitySaveOrUpdatePromptResult:: - EntitySaveOrUpdatePromptResult( - AutofillAiClient::EntitySaveOrUpdatePromptResult&&) = default; - -AutofillAiClient::EntitySaveOrUpdatePromptResult& -AutofillAiClient::EntitySaveOrUpdatePromptResult::operator=( - const AutofillAiClient::EntitySaveOrUpdatePromptResult&) = default; - -AutofillAiClient::EntitySaveOrUpdatePromptResult& -AutofillAiClient::EntitySaveOrUpdatePromptResult::operator=( - AutofillAiClient::EntitySaveOrUpdatePromptResult&&) = default; - -AutofillAiClient::EntitySaveOrUpdatePromptResult:: - ~EntitySaveOrUpdatePromptResult() = default; - } // namespace autofill_ai
diff --git a/components/autofill_ai/core/browser/autofill_ai_client.h b/components/autofill_ai/core/browser/autofill_ai_client.h index 72ad474..5067eae 100644 --- a/components/autofill_ai/core/browser/autofill_ai_client.h +++ b/components/autofill_ai/core/browser/autofill_ai_client.h
@@ -28,29 +28,6 @@ // Autofill in the settings while the client is alive. class AutofillAiClient { public: - // Contains the result of a user interaction with the save/update AutofillAi - // prompt. - struct EntitySaveOrUpdatePromptResult final { - EntitySaveOrUpdatePromptResult(); - EntitySaveOrUpdatePromptResult( - bool did_user_decline, - std::optional<autofill::EntityInstance> entity); - EntitySaveOrUpdatePromptResult(const EntitySaveOrUpdatePromptResult&); - EntitySaveOrUpdatePromptResult(EntitySaveOrUpdatePromptResult&&); - EntitySaveOrUpdatePromptResult& operator=( - const EntitySaveOrUpdatePromptResult&); - EntitySaveOrUpdatePromptResult& operator=(EntitySaveOrUpdatePromptResult&&); - ~EntitySaveOrUpdatePromptResult(); - - // Whether the user explicitly declined the dialog. - bool did_user_decline = false; - - // Non-empty iff the prompt was accepted. - std::optional<autofill::EntityInstance> entity; - }; - using EntitySaveOrUpdatePromptResultCallback = - base::OnceCallback<void(EntitySaveOrUpdatePromptResult result)>; - virtual ~AutofillAiClient() = default; // Returns the AutofillClient that is scoped to the same object (e.g., tab) as @@ -64,15 +41,6 @@ // Returns the `AutofillAiManager` associated with this // client. virtual AutofillAiManager& GetManager() = 0; - - // Shows a bubble asking whether the user wants to save or update Autofill AI - // data. `old_entity` is present in the update cases. It is used to give users - // a better understanding of what was updated. - virtual void ShowSaveOrUpdateBubble( - autofill::EntityInstance new_entity, - std::optional<autofill::EntityInstance> old_entity, - EntitySaveOrUpdatePromptResultCallback - save_prompt_acceptance_callback) = 0; }; } // namespace autofill_ai
diff --git a/components/autofill_ai/core/browser/autofill_ai_manager.cc b/components/autofill_ai/core/browser/autofill_ai_manager.cc index d436b26..c31912d 100644 --- a/components/autofill_ai/core/browser/autofill_ai_manager.cc +++ b/components/autofill_ai/core/browser/autofill_ai_manager.cc
@@ -306,9 +306,9 @@ auto prompt_result_callback = BindOnce(&AutofillAiManager::HandleSavePromptResult, GetWeakPtr(), form.source_url(), entity); - client_->ShowSaveOrUpdateBubble(std::move(entity), - /*old_entity=*/std::nullopt, - std::move(prompt_result_callback)); + client_->GetAutofillClient().ShowEntitySaveOrUpdateBubble( + std::move(entity), + /*old_entity=*/std::nullopt, std::move(prompt_result_callback)); return true; } if (std::optional<std::pair<EntityInstance, EntityInstance>> @@ -320,9 +320,9 @@ auto prompt_result_callback = BindOnce(&AutofillAiManager::HandleUpdatePromptResult, GetWeakPtr(), old_entity.guid()); - client_->ShowSaveOrUpdateBubble(std::move(new_entity), - std::move(old_entity), - std::move(prompt_result_callback)); + client_->GetAutofillClient().ShowEntitySaveOrUpdateBubble( + std::move(new_entity), std::move(old_entity), + std::move(prompt_result_callback)); return true; } } @@ -332,7 +332,7 @@ void AutofillAiManager::HandleSavePromptResult( const GURL& form_url, const autofill::EntityInstance& entity, - AutofillAiClient::EntitySaveOrUpdatePromptResult result) { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult result) { if (!result.entity) { if (result.did_user_decline) { AddStrikeForSaveAttempt(form_url, entity); @@ -352,7 +352,7 @@ void AutofillAiManager::HandleUpdatePromptResult( const base::Uuid& entity_uuid, - AutofillAiClient::EntitySaveOrUpdatePromptResult result) { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult result) { if (!result.entity) { if (result.did_user_decline) { AddStrikeForUpdateAttempt(entity_uuid);
diff --git a/components/autofill_ai/core/browser/autofill_ai_manager.h b/components/autofill_ai/core/browser/autofill_ai_manager.h index 893d860..4932eb6 100644 --- a/components/autofill_ai/core/browser/autofill_ai_manager.h +++ b/components/autofill_ai/core/browser/autofill_ai_manager.h
@@ -91,12 +91,12 @@ void HandleSavePromptResult( const GURL& form_url, const autofill::EntityInstance& entity, - AutofillAiClient::EntitySaveOrUpdatePromptResult result); + autofill::AutofillClient::EntitySaveOrUpdatePromptResult result); // Updates the `EntityDataManager` and the update strike database depending on // the prompt `result`. void HandleUpdatePromptResult( const base::Uuid& entity_uuid, - AutofillAiClient::EntitySaveOrUpdatePromptResult result); + autofill::AutofillClient::EntitySaveOrUpdatePromptResult result); autofill::LogManager* GetCurrentLogManager();
diff --git a/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc b/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc index a787be9..74acaa4f 100644 --- a/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc +++ b/components/autofill_ai/core/browser/autofill_ai_manager_unittest.cc
@@ -120,6 +120,22 @@ std::move(license_plate), /*app_locale=*/""); } +class MockAutofillClient : public autofill::TestAutofillClient { + public: + MockAutofillClient() = default; + MockAutofillClient(const MockAutofillClient&) = delete; + MockAutofillClient& operator=(const MockAutofillClient&) = delete; + ~MockAutofillClient() override = default; + + MOCK_METHOD( + void, + ShowEntitySaveOrUpdateBubble, + (autofill::EntityInstance entity, + std::optional<autofill::EntityInstance> old_entity, + EntitySaveOrUpdatePromptResultCallback prompt_acceptance_callback), + (override)); +}; + class AutofillAiManagerTest : public testing::Test { public: AutofillAiManagerTest() { @@ -181,7 +197,7 @@ return edm().GetEntityInstances(); } - autofill::TestAutofillClient& autofill_client() { return autofill_client_; } + MockAutofillClient& autofill_client() { return autofill_client_; } MockAutofillAiClient& client() { return client_; } autofill::EntityDataManager& edm() { return *autofill_client().GetEntityDataManager(); @@ -195,7 +211,7 @@ autofill::test::AutofillUnitTestEnvironment autofill_test_env_; autofill::AutofillWebDataServiceTestHelper webdata_helper_{ std::make_unique<autofill::EntityTable>()}; - autofill::TestAutofillClient autofill_client_; + NiceMock<MockAutofillClient> autofill_client_; NiceMock<MockAutofillAiClient> client_; autofill::TestStrikeDatabase strike_database_; AutofillAiManager manager_{&client(), &strike_database_}; @@ -357,25 +373,28 @@ // Tests that save prompts are only shown three times per url and entity type. TEST_F(AutofillAiManagerImportFormTest, StrikesForSavePromptsPerUrl) { constexpr char16_t kOtherPassportNumber[] = u"67867"; - AutofillAiClient::EntitySaveOrUpdatePromptResult decline = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult decline = { /*did_user_decline=*/true, std::nullopt}; MockFunction<void()> check; { InSequence s; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(decline)); EXPECT_CALL(check, Call); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(decline)); - EXPECT_CALL(client(), - ShowSaveOrUpdateBubble( + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( VehicleWithLicensePlate(kDefaultLicensePlate), _, _)) .WillOnce(RunOnceCallback<2>(decline)); } @@ -404,25 +423,28 @@ // this case, passport number). TEST_F(AutofillAiManagerImportFormTest, StrikesForSavePromptsPerAttribute) { constexpr char16_t kOtherPassportNumber[] = u"567435"; - AutofillAiClient::EntitySaveOrUpdatePromptResult decline = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult decline = { /*did_user_decline=*/true, std::nullopt}; - AutofillAiClient::EntitySaveOrUpdatePromptResult ignore = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult ignore = { /*did_user_decline=*/false, std::nullopt}; MockFunction<void()> check; { InSequence s; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(ignore)); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(3) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); EXPECT_CALL(check, Call); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(decline)); } @@ -454,40 +476,45 @@ constexpr char16_t kOtherPassportNumber[] = u"67867"; constexpr char16_t kOtherPassportNumber2[] = u"6785634567"; - AutofillAiClient::EntitySaveOrUpdatePromptResult decline = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult decline = { /*did_user_decline=*/true, std::nullopt}; - AutofillAiClient::EntitySaveOrUpdatePromptResult ignore = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult ignore = { /*did_user_decline=*/false, std::nullopt}; - AutofillAiClient::EntitySaveOrUpdatePromptResult accept = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult accept = { /*did_user_decline=*/false, GetPassportEntityInstance({.number = kDefaultPassportNumber})}; { InSequence s; // Accept the first prompt. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(accept)); // Accept the third prompt. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(accept)); // If the user just ignores the prompt, no strikes are recorded. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber2), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber2), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(ignore)); // Only three more prompts will be shown for the next update because the // user declines explicitly. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber2), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber2), _, _)) .Times(3) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); } @@ -526,9 +553,9 @@ constexpr char16_t kOtherPassportNumber[] = u"56745"; constexpr char16_t kOtherLicensePlate[] = u"MU-LJ-4500"; - AutofillAiClient::EntitySaveOrUpdatePromptResult decline{ + autofill::AutofillClient::EntitySaveOrUpdatePromptResult decline{ /*did_user_interact=*/true, std::nullopt}; - AutofillAiClient::EntitySaveOrUpdatePromptResult accept = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult accept = { /*did_user_decline=*/false, GetPassportEntityInstance({.number = kDefaultPassportNumber})}; MockFunction<void()> check; @@ -536,31 +563,34 @@ InSequence s; // First, we expect to see two save attempts for a passport and two save // attempts for a vehicle. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); - EXPECT_CALL(client(), - ShowSaveOrUpdateBubble( + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( VehicleWithLicensePlate(kDefaultLicensePlate), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); EXPECT_CALL(check, Call); // We accept the next save prompt for a passport form. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(accept)); // We now only get one more vehicle save prompt (despite submitting a form // twice), but two more passport prompts because passport strikes were // reset. - EXPECT_CALL(client(), - ShowSaveOrUpdateBubble( + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( VehicleWithLicensePlate(kOtherLicensePlate), _, _)) .WillOnce(RunOnceCallback<2>(decline)); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kOtherPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kOtherPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); } @@ -594,28 +624,31 @@ // Tests that accepting a save prompt for an entity resets the strike counter // for the strike key attributes of that entity. TEST_F(AutofillAiManagerImportFormTest, AcceptingResetsStrikesPerAttribute) { - AutofillAiClient::EntitySaveOrUpdatePromptResult decline = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult decline = { /*did_user_decline=*/true, std::nullopt}; - AutofillAiClient::EntitySaveOrUpdatePromptResult accept = { + autofill::AutofillClient::EntitySaveOrUpdatePromptResult accept = { /*did_user_decline=*/false, GetPassportEntityInstance({.number = kDefaultPassportNumber})}; { InSequence s; // First, we expect to see two save attempts for a passport. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); // We accept the next save prompt for a passport form. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .WillOnce(RunOnceCallback<2>(accept)); // (User now deletes the passport.) // We now get more prompts for the same passport number again. - EXPECT_CALL(client(), ShowSaveOrUpdateBubble( - PassportWithNumber(kDefaultPassportNumber), _, _)) + EXPECT_CALL(autofill_client(), + ShowEntitySaveOrUpdateBubble( + PassportWithNumber(kDefaultPassportNumber), _, _)) .Times(2) .WillRepeatedly(RunOnceCallbackRepeatedly<2>(decline)); } @@ -648,8 +681,9 @@ std::optional<EntityInstance> new_entity; std::optional<EntityInstance> old_entity; - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback save_callback; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble) + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback + save_callback; + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble) .WillOnce(DoAll(SaveArg<0>(&new_entity), SaveArg<1>(&old_entity), MoveArg<2>(&save_callback))); EXPECT_TRUE(manager().OnFormSubmitted(*form, /*ukm_source_id=*/{})); @@ -658,7 +692,7 @@ // Accept the bubble. std::move(save_callback) - .Run(AutofillAiClient::EntitySaveOrUpdatePromptResult( + .Run(autofill::AutofillClient::EntitySaveOrUpdatePromptResult( /*did_user_decline=*/false, new_entity)); // Tests that the expected entity was saved. base::span<const EntityInstance> saved_entities = GetEntityInstances(); @@ -684,14 +718,15 @@ form->field(0)->set_value(u"Jon Doe"); form->field(1)->set_value(u"1234321"); - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback save_callback; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble) + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback + save_callback; + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble) .WillOnce(MoveArg<2>(&save_callback)); EXPECT_TRUE(manager().OnFormSubmitted(*form, /*ukm_source_id=*/{})); // Decline the bubble. std::move(save_callback) - .Run(AutofillAiClient::EntitySaveOrUpdatePromptResult()); + .Run(autofill::AutofillClient::EntitySaveOrUpdatePromptResult()); // Tests that the no entity was saved. base::span<const EntityInstance> saved_entities = GetEntityInstances(); EXPECT_EQ(saved_entities.size(), 0u); @@ -705,7 +740,7 @@ form->field(0)->set_value(u"Germany"); form->field(1)->set_value(u"1234321"); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble).Times(0); + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble).Times(0); EXPECT_FALSE(manager().OnFormSubmitted(*form, /*ukm_source_id=*/{})); // Tests that no entity was saved. @@ -726,7 +761,7 @@ entity, autofill::DRIVERS_LICENSE_NUMBER, /*app_locale=*/"")); AddOrUpdateEntityInstance(entity); - EXPECT_CALL(client(), ShowSaveOrUpdateBubble).Times(0); + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble).Times(0); EXPECT_FALSE(manager().OnFormSubmitted(*form, /*ukm_source_id=*/{})); // Tests that no entity was saved. @@ -746,8 +781,9 @@ std::optional<EntityInstance> entity; std::optional<EntityInstance> old_entity; - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback save_callback; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble) + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback + save_callback; + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble) .WillOnce(DoAll(SaveArg<0>(&entity), SaveArg<1>(&old_entity), MoveArg<2>(&save_callback))); @@ -757,7 +793,7 @@ // Accept the bubble. std::move(save_callback) - .Run(AutofillAiClient::EntitySaveOrUpdatePromptResult( + .Run(autofill::AutofillClient::EntitySaveOrUpdatePromptResult( /*did_user_decline=*/false, entity)); // Tests that the expected entity was saved. base::span<const EntityInstance> saved_entities = GetEntityInstances(); @@ -815,8 +851,9 @@ std::optional<EntityInstance> entity; std::optional<EntityInstance> old_entity; - AutofillAiClient::EntitySaveOrUpdatePromptResultCallback save_callback; - EXPECT_CALL(client(), ShowSaveOrUpdateBubble) + autofill::AutofillClient::EntitySaveOrUpdatePromptResultCallback + save_callback; + EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble) .WillOnce(DoAll(SaveArg<0>(&entity), SaveArg<1>(&old_entity), MoveArg<2>(&save_callback))); EXPECT_TRUE(manager().OnFormSubmitted(*form, /*ukm_source_id=*/{})); @@ -826,7 +863,7 @@ // Accept the bubble. std::move(save_callback) - .Run(AutofillAiClient::EntitySaveOrUpdatePromptResult( + .Run(autofill::AutofillClient::EntitySaveOrUpdatePromptResult( /*did_user_interact=*/true, entity)); // Tests that the expected entity was updated. base::span<const EntityInstance> saved_entities = GetEntityInstances();
diff --git a/components/autofill_ai/core/browser/mock_autofill_ai_client.h b/components/autofill_ai/core/browser/mock_autofill_ai_client.h index e3d98d3..9be3bd37 100644 --- a/components/autofill_ai/core/browser/mock_autofill_ai_client.h +++ b/components/autofill_ai/core/browser/mock_autofill_ai_client.h
@@ -20,13 +20,6 @@ MOCK_METHOD(autofill::AutofillClient&, GetAutofillClient, (), (override)); MOCK_METHOD(AutofillAiManager&, GetManager, (), (override)); - MOCK_METHOD( - void, - ShowSaveOrUpdateBubble, - (autofill::EntityInstance entity, - std::optional<autofill::EntityInstance> old_entity, - EntitySaveOrUpdatePromptResultCallback prompt_acceptance_callback), - (override)); }; } // namespace autofill_ai
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn index dcb5096..39a837865 100644 --- a/components/browser_ui/styles/android/BUILD.gn +++ b/components/browser_ui/styles/android/BUILD.gn
@@ -191,6 +191,7 @@ "java/res/drawable/ic_drive_document_24dp.xml", "java/res/drawable/ic_drive_file_24dp.xml", "java/res/drawable/ic_drive_image_24dp.xml", + "java/res/drawable/ic_extension_24dp.xml", "java/res/drawable/ic_eye_crossed.xml", "java/res/drawable/ic_fast_forward_white_24dp.xml", "java/res/drawable/ic_fast_rewind_white_24dp.xml",
diff --git a/components/browser_ui/styles/android/java/res/drawable/ic_extension_24dp.xml b/components/browser_ui/styles/android/java/res/drawable/ic_extension_24dp.xml new file mode 100644 index 0000000..f08b267 --- /dev/null +++ b/components/browser_ui/styles/android/java/res/drawable/ic_extension_24dp.xml
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2025 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="960" + android:viewportHeight="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,608Q168,608 204,577.5Q240,547 240,500Q240,453 204,422.5Q168,392 120,392L120,240Q120,207 143.5,183.5Q167,160 200,160L360,160Q360,118 389,89Q418,60 460,60Q502,60 531,89Q560,118 560,160L720,160Q753,160 776.5,183.5Q800,207 800,240L800,400Q842,400 871,429Q900,458 900,500Q900,542 871,571Q842,600 800,600L800,760Q800,793 776.5,816.5Q753,840 720,840L200,840ZM200,760L720,760L720,240L200,240L200,328Q254,348 287,395Q320,442 320,500Q320,557 287,604Q254,651 200,672L200,760ZM460,500L460,500L460,500Q460,500 460,500Q460,500 460,500Q460,500 460,500L460,500L460,500Z"/> +</vector> \ No newline at end of file
diff --git a/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc b/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc index cf06f978..195b4285 100644 --- a/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc +++ b/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
@@ -357,7 +357,8 @@ scoped_refptr<media::VideoFrame> hw_out_frame_; // Used to create Gpu memory buffer for DMA-buf encoding tests. - std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; + std::unique_ptr<media::LocalGpuMemoryBufferManager> + gpu_memory_buffer_manager_; base::WeakPtrFactory<JpegClient> weak_factory_{this}; };
diff --git a/components/enterprise/common/proto/BUILD.gn b/components/enterprise/common/proto/BUILD.gn index f365b7d..f89d0f3 100644 --- a/components/enterprise/common/proto/BUILD.gn +++ b/components/enterprise/common/proto/BUILD.gn
@@ -29,9 +29,6 @@ "//components/safe_browsing/core/common/proto:csd_proto", "//components/safe_browsing/core/common/proto:csd_proto_extras", ] - - # The fuzzable_proto_library rule above uses the full protobuf runtime. - protobuf_full_support = true } proto_library("dlp_policy_event_proto") {
diff --git a/components/input/android/input_receiver_data.cc b/components/input/android/input_receiver_data.cc index 2c03b95..8544638 100644 --- a/components/input/android/input_receiver_data.cc +++ b/components/input/android/input_receiver_data.cc
@@ -6,6 +6,8 @@ #include <utility> +#include "base/android/android_info.h" + namespace input { InputReceiverData::InputReceiverData( @@ -26,9 +28,9 @@ InputReceiverData::~InputReceiverData() = default; -void InputReceiverData::OnDestroyedCompositorFrameSink( - const viz::FrameSinkId& frame_sink_id) { - if (root_frame_sink_id() != frame_sink_id) { +void InputReceiverData::OnDestroyedCompositorFrameSink() { + if (base::android::android_info::sdk_int() >= + base::android::android_info::SdkVersion::SDK_VERSION_BAKLAVA) { return; } pending_destruction_ = true;
diff --git a/components/input/android/input_receiver_data.h b/components/input/android/input_receiver_data.h index 922921f..b93f225 100644 --- a/components/input/android/input_receiver_data.h +++ b/components/input/android/input_receiver_data.h
@@ -31,7 +31,7 @@ ~InputReceiverData(); - void OnDestroyedCompositorFrameSink(const viz::FrameSinkId& frame_sink_id); + void OnDestroyedCompositorFrameSink(); const viz::FrameSinkId& root_frame_sink_id() { return android_input_callback_->root_frame_sink_id();
diff --git a/components/input/android/scoped_input_receiver.cc b/components/input/android/scoped_input_receiver.cc index 5cb2be6..5d5def8 100644 --- a/components/input/android/scoped_input_receiver.cc +++ b/components/input/android/scoped_input_receiver.cc
@@ -4,6 +4,7 @@ #include "components/input/android/scoped_input_receiver.h" +#include "base/android/android_info.h" #include "base/android/android_input_receiver_compat.h" namespace input { @@ -34,10 +35,12 @@ if (a_input_receiver_ == nullptr) { return; } - // Not calling release due to AOSP crash on calling the API - - // b/368251173. - // base::AndroidInputReceiverCompat::GetInstance() - // .AInputReceiver_releaseFn(a_input_receiver_); + if (base::android::android_info::sdk_int() >= + base::android::android_info::SdkVersion::SDK_VERSION_BAKLAVA) { + // Calling AInputReceiver_release on Android V, results in app crash. + base::AndroidInputReceiverCompat::GetInstance().AInputReceiver_releaseFn( + a_input_receiver_); + } a_input_receiver_ = nullptr; }
diff --git a/components/proto_extras/BUILD.gn b/components/proto_extras/BUILD.gn index 8861c57..efdb310e 100644 --- a/components/proto_extras/BUILD.gn +++ b/components/proto_extras/BUILD.gn
@@ -2,39 +2,27 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//testing/libfuzzer/fuzzer_test.gni") - if (current_toolchain == host_toolchain) { executable("proto_extras_plugin") { sources = [ "proto_extras_plugin.cc" ] deps = [ "//base", - "//third_party/protobuf:protoc_cpp", "//third_party/protobuf:protoc_lib", + "//third_party/protobuf:protoc_cpp", ] } } -source_set("proto_extras_lib") { +component("proto_extras_lib") { public = [ "proto_extras_lib.h" ] + sources = [ + "proto_extras_lib.cc" + ] public_deps = [ "//base", "//third_party/protobuf:protobuf_lite", ] -} - -if (use_fuzzing_engine_with_lpm) { - # Component for protobuf_full support of our serialization, which is required - # by proto fuzzers. - source_set("protobuf_full_support") { - public = [ "protobuf_full_support.h" ] - sources = [ "protobuf_full_support.cc" ] - public_deps = [ - ":proto_extras_lib", - "//base", - "//third_party/protobuf:protobuf_full", - ] - } + defines = [ "IS_PROTO_EXTRAS_IMPL" ] } source_set("unit_tests") {
diff --git a/components/proto_extras/proto_extras.gni b/components/proto_extras/proto_extras.gni index 9e9c6ad..f1eba2b7 100644 --- a/components/proto_extras/proto_extras.gni +++ b/components/proto_extras/proto_extras.gni
@@ -2,26 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Generate extra functionality for protobuf messages, including: -# - Serialization to base::DictValue. -# - Stream operator support for C++ printing. -# - (future) equality operator support -# - (future) gtest matchers. -# This does not directly generate the protobuf bindings for any language, so +# Generate serializers that turn a protobuf into a base::Value. This +# does not directly generate the protobuf bindings for any language, so # callers must include the build target for C++ bindings in the deps. # -# This is a wrapper around proto_library that adds the proto_extras plugin. It -# is intended to be used in conjunction with proto_library, not on its own. -# -# The generated C++ code will be named <name>.extras.h and <name>.extras.cc. -# The primary entry point is <name>.extras.h, which declares the generated -# serialization and streaming operators. -# -# For cases where the message uses the full google::protobuf::Message type, -# the protobuf_full_support option can be used to ensure the generated code -# with the full protobuf library. Due to android build complications, this also -# requires the `use_fuzzing_engine_with_lpm` build flag to be set. -# # Caveats: # - Integer types in the proto that are not compatible with base::Value are # serialized as strings (e.g. uint64_t). @@ -35,28 +19,19 @@ # deps = [ # "mylib_proto_target" # ] -# omit_to_value_serialization = true # default is false -# omit_stream_operators = true # default is false +# # Optional: Set to true to generate C++ stream operators (operator<<) +# # for the proto messages, which will print the message using +# # base::Value::DebugString(). +# # Defaults to false. +# generate_stream_operators = true # } -import("//testing/libfuzzer/fuzzer_test.gni") import("//third_party/protobuf/proto_library.gni") template("proto_extras") { - _options = [] - if (defined(invoker.omit_to_value_serialization) && - invoker.omit_to_value_serialization) { - _options += [ "omit_to_value_serialization" ] - } - if (defined(invoker.omit_stream_operators) && invoker.omit_stream_operators) { - _options += [ "omit_stream_operators" ] - } - - _protobuf_full_support = false - if (defined(invoker.protobuf_full_support) && invoker.protobuf_full_support && - use_fuzzing_engine_with_lpm) { - _options += [ "protobuf_full_support" ] - _protobuf_full_support = true + _generate_stream_operators = false + if (defined(invoker.generate_stream_operators)) { + _generate_stream_operators = invoker.generate_stream_operators } proto_library("${target_name}") { @@ -69,16 +44,16 @@ } generator_plugin_label = "//components/proto_extras:proto_extras_plugin" - generator_plugin_suffix = ".extras" + generator_plugin_suffix = ".to_value" generate_cc = false generate_python = false link_public_deps = [ "//base" ] - link_deps = [ "//components/proto_extras:proto_extras_lib" ] - if (_protobuf_full_support) { - link_deps += [ "//components/proto_extras:protobuf_full_support" ] - } - if (_options != []) { - generator_plugin_options = string_join(",", _options) + link_deps = [ + "//components/proto_extras:proto_extras_lib", + ] + + if (_generate_stream_operators) { + generator_plugin_options = "generate_stream_operators" } } }
diff --git a/components/proto_extras/protobuf_full_support.cc b/components/proto_extras/proto_extras_lib.cc similarity index 95% rename from components/proto_extras/protobuf_full_support.cc rename to components/proto_extras/proto_extras_lib.cc index 31deed6d..11af1c9d 100644 --- a/components/proto_extras/protobuf_full_support.cc +++ b/components/proto_extras/proto_extras_lib.cc
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proto_extras/protobuf_full_support.h" +#include "components/proto_extras/proto_extras_lib.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" -#include "components/proto_extras/proto_extras_lib.h" #include "third_party/protobuf/src/google/protobuf/unknown_field_set.h" namespace proto_extras {
diff --git a/components/proto_extras/proto_extras_lib.h b/components/proto_extras/proto_extras_lib.h index f14e7f77..7dd41e4 100644 --- a/components/proto_extras/proto_extras_lib.h +++ b/components/proto_extras/proto_extras_lib.h
@@ -13,19 +13,39 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" +#include "third_party/protobuf/src/google/protobuf/message.h" +#include "third_party/protobuf/src/google/protobuf/message_lite.h" namespace google::protobuf { -class MessageLite; +class UnknownFieldSet; } // namespace google::protobuf namespace proto_extras { -// Specialization for MessageLite protos, which always returns a std::string -// for unknown fields. -template <typename MessageType> - requires requires(MessageType message) { - { message.unknown_fields() } -> std::same_as<const std::string&>; +COMPONENT_EXPORT(PROTO_EXTRAS) base::DictValue Serialize( + const google::protobuf::UnknownFieldSet& unknown_fields); + +// Specialization for Message protos, which use the UnknownFieldSet type +// allowing for more readable serialization. +template <typename MessageType, + typename std::enable_if_t< + std::is_base_of<google::protobuf::Message, MessageType>::value, + int> = 0> +void SerializeUnknownFields(const MessageType& message, base::DictValue& dict) { + if (message.unknown_fields().empty()) { + return; } + dict.Set("unknown_fields", Serialize(message.unknown_fields())); +} + +// Specialization for MessageLite protos. These types don't use the +// UnknownFieldSet, and instead store all unknown fields in a string of bytes. +template < + typename MessageType, + typename std::enable_if< + std::is_base_of<google::protobuf::MessageLite, MessageType>::value && + !std::is_base_of<google::protobuf::Message, MessageType>::value, + int>::type = 0> void SerializeUnknownFields(const MessageType& message, base::DictValue& dict) { if (message.unknown_fields().empty()) { return;
diff --git a/components/proto_extras/proto_extras_plugin.cc b/components/proto_extras/proto_extras_plugin.cc index ee2d2a5..77216be 100644 --- a/components/proto_extras/proto_extras_plugin.cc +++ b/components/proto_extras/proto_extras_plugin.cc
@@ -2,21 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <string> - #include "base/check.h" #include "base/containers/contains.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" -#include "base/notreached.h" -#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "third_party/abseil-cpp/absl/container/flat_hash_set.h" #include "third_party/protobuf/src/google/protobuf/compiler/code_generator.h" -#include "third_party/protobuf/src/google/protobuf/compiler/cpp/helpers.h" #include "third_party/protobuf/src/google/protobuf/compiler/cpp/names.h" +#include "third_party/protobuf/src/google/protobuf/compiler/cpp/helpers.h" #include "third_party/protobuf/src/google/protobuf/compiler/importer.h" #include "third_party/protobuf/src/google/protobuf/compiler/plugin.h" #include "third_party/protobuf/src/google/protobuf/descriptor.h" @@ -31,123 +26,14 @@ using google::protobuf::io::Printer; using google::protobuf::io::ZeroCopyOutputStream; -struct ProtoExtrasGeneratorOptions { - bool generate_to_value_serialization; +struct ToValueGeneratorOptions { bool generate_stream_operator; - bool protobuf_full_support; }; -void FieldToValueFunction(const FieldDescriptor& field, Printer* printer) { - using enum FieldDescriptor::Type; - auto conversion_function = [&]() -> std::string { - switch (field.type()) { - case TYPE_DOUBLE: - case TYPE_FLOAT: - return "static_cast<double>"; - case TYPE_INT32: - case TYPE_INT64: - case TYPE_UINT64: - case TYPE_UINT32: - case TYPE_FIXED64: - case TYPE_FIXED32: - case TYPE_SFIXED64: - case TYPE_SFIXED32: - case TYPE_SINT64: - case TYPE_SINT32: - return "::proto_extras::ToNumericTypeForValue"; - case TYPE_BOOL: - return "static_cast<bool>"; - case TYPE_STRING: - return "static_cast<std::string>"; - case TYPE_BYTES: - return "base::Base64Encode"; - case TYPE_ENUM: - return base::StrCat( - {google::protobuf::compiler::cpp::QualifiedClassName( - field.enum_type()), - "_Name"}); - case TYPE_MESSAGE: - case TYPE_GROUP: - // The Serialize function for the message is in the namespace of the - // nested message itself. - return base::StrCat( - {google::protobuf::compiler::cpp::Namespace(field.message_type()), - "::Serialize"}); - } - NOTREACHED(); - }; - printer->Print(conversion_function()); -} - -void CreateSerializationDefinitions( - const Descriptor& message, - Printer* printer, - const ProtoExtrasGeneratorOptions& options) { - printer->Emit( - {{"message_type", google::protobuf::compiler::cpp::ClassName(&message)}, - {"serialize_fields", - [&]() { - for (int j = 0; j < message.field_count(); j++) { - const FieldDescriptor& field = *message.field(j); - std::string field_name(field.lowercase_name()); - - auto field_to_value = [&]() { - FieldToValueFunction(field, printer); - }; - if (field.is_repeated()) { - printer->Emit({{"field_name", field_name}, - {"field_to_value", field_to_value}}, - R"( - if (!message.$field_name$().empty()) { - base::ListValue list; - for (const auto& value : message.$field_name$()) { - list.Append($field_to_value$(value)); - } - dict.Set("$field_name$", std::move(list)); - } -)"); - } else if (field.has_presence()) { - printer->Emit({{"field_name", field_name}, - {"field_to_value", field_to_value}}, - R"( - if (message.has_$field_name$()) { - dict.Set("$field_name$", $field_to_value$(message.$field_name$())); - } -)"); - } else if (field.type() == FieldDescriptor::Type::TYPE_STRING || - field.type() == FieldDescriptor::Type::TYPE_BYTES) { - printer->Emit({{"field_name", field_name}, - {"field_to_value", field_to_value}}, - R"( - if (!message.$field_name$().empty()) { - dict.Set("$field_name$", $field_to_value$(message.$field_name$())); - } -)"); - } else { - printer->Emit({{"field_name", field_name}, - {"field_to_value", field_to_value}}, - R"( - dict.Set("$field_name$", $field_to_value$(message.$field_name$())); -)"); - } - } - }}}, - R"( -base::DictValue Serialize(const $message_type$& message) { - base::DictValue dict; - if (!message.unknown_fields().empty()) { - ::proto_extras::SerializeUnknownFields(message, dict); - } - $serialize_fields$ - return dict; -} -)"); -} - -class ProtoExtrasGenerator : public google::protobuf::compiler::CodeGenerator { +class ToValueGenerator : public google::protobuf::compiler::CodeGenerator { public: - ProtoExtrasGenerator() = default; - ~ProtoExtrasGenerator() override = default; + ToValueGenerator() = default; + ~ToValueGenerator() override = default; bool Generate(const FileDescriptor* file, const std::string& options, // Options from build system @@ -155,22 +41,11 @@ std::string* error) const override { CHECK(file); - ProtoExtrasGeneratorOptions generator_options{ - .generate_to_value_serialization = - !base::Contains(options, "omit_to_value_serialization"), - .generate_stream_operator = - !base::Contains(options, "omit_stream_operators"), - .protobuf_full_support = - base::Contains(options, "protobuf_full_support"), - }; - CHECK(generator_options.generate_to_value_serialization || - generator_options.generate_stream_operator); - - base::FilePath proto_file_path = base::FilePath::FromASCII(file->name()); + base::FilePath base_file_path = ToValueFilePath(file->name()); base::FilePath h_file_path = - proto_file_path.ReplaceExtension(FILE_PATH_LITERAL("extras.h")); + base_file_path.AddExtension(FILE_PATH_LITERAL("to_value.h")); base::FilePath cc_file_path = - proto_file_path.ReplaceExtension(FILE_PATH_LITERAL("extras.cc")); + base_file_path.AddExtension(FILE_PATH_LITERAL("to_value.cc")); const std::unique_ptr<ZeroCopyOutputStream> h_stream( context->Open(h_file_path.AsUTF8Unsafe())); @@ -180,127 +55,102 @@ Printer h_printer(h_stream.get(), Printer::Options{'$', nullptr}); Printer cc_printer(cc_stream.get(), Printer::Options{'$', nullptr}); + ToValueGeneratorOptions generator_options; + generator_options.generate_stream_operator = + base::Contains(options, "generate_stream_operators"); std::string include_guard = base::ToUpperASCII(h_file_path.AsUTF8Unsafe()) + "_"; CHECK(base::ReplaceChars(include_guard, ".-/\\", "_", &include_guard)); - h_printer.Emit( - { - {"include_guard", include_guard}, - {"proto_file_path", proto_file_path.AsUTF8Unsafe()}, - {"includes", - [&] { - if (generator_options.generate_stream_operator) { - h_printer.Print("#include <iosfwd>\n\n"); - } - h_printer.Print( - "#include \"$f$\"\n", "f", - proto_file_path.ReplaceExtension(FILE_PATH_LITERAL("pb.h")) - .AsUTF8Unsafe()); - }}, - {"function_declarations", - [&] { - google::protobuf::compiler::cpp::NamespaceOpener ns( - google::protobuf::compiler::cpp::Namespace(file), - &h_printer); - for (int i = 0; i < file->message_type_count(); i++) { - PrintFunctionDeclarations(*file->message_type(i), &h_printer, - error, generator_options); - } - }}, - }, - R"(// Generated by the proto_to_extras plugin. DO NOT EDIT! -// source: $proto_file_path$ + std::string kHeader = + "// Generated by the proto to value plugin. DO NOT EDIT!\n\n"; + h_printer.Print(kHeader); + h_printer.Print("#ifndef $g$\n#define $g$\n\n", "g", include_guard); -#ifndef $include_guard$ -#define $include_guard$ - -$includes$ - -namespace base { -class DictValue; -} // namespace base - -$function_declarations$ - -#endif // $include_guard$ -)"); - - // Determine the #includes for the implementation file. - absl::flat_hash_set<std::string> impl_system_inclues; - // Always have the header and pb.h for the message. - absl::flat_hash_set<std::string> impl_user_includes = { - h_file_path.AsUTF8Unsafe(), - proto_file_path.ReplaceExtension(FILE_PATH_LITERAL("pb.h")) + if (generator_options.generate_stream_operator) { + h_printer.Print("#include <iosfwd>\n\n"); + } + std::vector<std::string> header_include_files = { + "base/values.h", + base_file_path.BaseName() + .AddExtension(FILE_PATH_LITERAL("pb.h")) .AsUTF8Unsafe(), }; + for (const auto& include : header_include_files) { + h_printer.Print("#include \"$f$\"\n", "f", include); + } + h_printer.Print("\n"); + + { + google::protobuf::compiler::cpp::NamespaceOpener ns( + google::protobuf::compiler::cpp::Namespace(file), &h_printer); + for (int i = 0; i < file->message_type_count(); i++) { + if (!PrintFunctionDeclarations(*file->message_type(i), &h_printer, + error, generator_options)) { + return false; + } + } + } + h_printer.Print("\n#endif // $g$\n", "g", include_guard); + + cc_printer.Print(kHeader); + cc_printer.Print("\n"); if (generator_options.generate_stream_operator) { - impl_system_inclues.insert("<ostream>"); + cc_printer.Print("#include <ostream>\n\n"); } - if (generator_options.generate_to_value_serialization) { - impl_user_includes.insert({"base/base64.h", "base/values.h", - "components/proto_extras/proto_extras_lib.h"}); - } + std::vector<std::string> impl_include_files = { + "base/base64.h", + "base/values.h", + base_file_path.BaseName() + .AddExtension(FILE_PATH_LITERAL("pb.h")) + .AsUTF8Unsafe(), + h_file_path.AsUTF8Unsafe(), + "components/proto_extras/proto_extras_lib.h", + }; for (int i = 0; i < file->dependency_count(); i++) { - base::FilePath dependency_proto_file_path = - base::FilePath::FromASCII(file->dependency(i)->name()); - impl_user_includes.insert( - dependency_proto_file_path - .ReplaceExtension(FILE_PATH_LITERAL("extras.h")) + impl_include_files.push_back( + ToValueFilePath(file->dependency(i)->name()) + .AddExtension(FILE_PATH_LITERAL("to_value.h")) .AsUTF8Unsafe()); } - if (generator_options.protobuf_full_support) { - impl_user_includes.insert( - "components/proto_extras/protobuf_full_support.h"); + for (const auto& include : impl_include_files) { + cc_printer.Print("#include \"$f$\"\n", "f", include); } - cc_printer.Emit( - { - {"proto_file_path", proto_file_path.AsUTF8Unsafe()}, - {"includes", - [&] { - for (const auto& include : impl_system_inclues) { - cc_printer.Print("#include $f$\n", "f", include); - } - for (const auto& include : impl_user_includes) { - cc_printer.Print("#include \"$f$\"\n", "f", include); - } - }}, - {"function_definitions", - [&] { - google::protobuf::compiler::cpp::NamespaceOpener ns( - google::protobuf::compiler::cpp::Namespace(file), - &cc_printer); - for (int i = 0; i < file->message_type_count(); i++) { - PrintFunctionDefinitions(*file->message_type(i), &cc_printer, - error, generator_options); - } - }}, - }, - R"(// Generated by the proto_to_extras plugin. DO NOT EDIT! -// source: $proto_file_path$ + cc_printer.Print("\n"); -$includes$ - -$function_definitions$ -)"); + { + google::protobuf::compiler::cpp::NamespaceOpener ns( + google::protobuf::compiler::cpp::Namespace(file), &cc_printer); + for (int i = 0; i < file->message_type_count(); i++) { + if (!PrintFunctionDefinition(*file->message_type(i), &cc_printer, error, + generator_options)) { + return false; + } + } + } return true; } - bool PrintFunctionDeclarations( - const Descriptor& message, - Printer* printer, - std::string* error, - const ProtoExtrasGeneratorOptions& options) const { + private: + base::FilePath ToValueFilePath(std::string_view file_name) const { +#if BUILDFLAG(IS_WIN) + return base::FilePath(base::ASCIIToWide(file_name)).RemoveExtension(); +#else + return base::FilePath(file_name).RemoveExtension(); +#endif + } + + bool PrintFunctionDeclarations(const Descriptor& message, + Printer* printer, + std::string* error, + const ToValueGeneratorOptions& options) const { std::string message_type = google::protobuf::compiler::cpp::ClassName(&message); - if (options.generate_to_value_serialization) { - printer->Print("base::DictValue Serialize(const $m$& message);\n", "m", - message_type); - } + printer->Print("base::Value::Dict Serialize(const $m$& message);\n", "m", + message_type); if (options.generate_stream_operator) { printer->Print( - "std::ostream& operator<<(std::ostream& out, const " - "$m$& message);\n", + "std::ostream& operator<<(std::ostream& out, const $m$& message);\n", "m", message_type); } for (int i = 0; i < message.nested_type_count(); i++) { @@ -313,38 +163,134 @@ return true; } - bool PrintFunctionDefinitions( - const Descriptor& message, - Printer* printer, - std::string* error, - const ProtoExtrasGeneratorOptions& options) const { - if (options.generate_to_value_serialization) { - CreateSerializationDefinitions(message, printer, options); + bool PrintFunctionDefinition(const Descriptor& message, + Printer* printer, + std::string* error, + const ToValueGeneratorOptions& options) const { + std::string message_type = + google::protobuf::compiler::cpp::ClassName(&message); + printer->Print("base::Value::Dict Serialize(const $m$& message) {\n", "m", + message_type); + printer->Indent(); + printer->Print("base::Value::Dict dict;\n\n"); + for (int j = 0; j < message.field_count(); j++) { + const FieldDescriptor* field = message.field(j); + std::string field_name(field->lowercase_name()); + if (field->is_repeated()) { + printer->Print("if (!message.$f$().empty()) {\n", "f", field_name); + printer->Indent(); + printer->Print("base::Value::List list;\n"); + printer->Print("for (const auto& value : message.$f$()) {\n", "f", + field_name); + printer->Indent(); + printer->Print("list.Append("); + PrintFieldToValue(*field, printer); + printer->Print("(value));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("dict.Set(\"$f$\", std::move(list));\n", "f", + field_name); + printer->Outdent(); + printer->Print("}\n"); + } else if (field->has_presence()) { + printer->Print("if (message.has_$f$()) {\n", "f", field_name); + printer->Indent(); + printer->Print("dict.Set(\"$f$\", ", "f", field_name); + PrintFieldToValue(*field, printer); + printer->Print("(message.$f$()));\n", "f", field_name); + printer->Outdent(); + printer->Print("}\n"); + } else if (field->type() == FieldDescriptor::Type::TYPE_STRING || + field->type() == FieldDescriptor::Type::TYPE_BYTES) { + printer->Print("if (!message.$f$().empty()) {\n", "f", field_name); + printer->Indent(); + printer->Print("dict.Set(\"$f$\", ", "f", field_name); + PrintFieldToValue(*field, printer); + printer->Print("(message.$f$()));\n", "f", field_name); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print("dict.Set(\"$f$\", ", "f", field_name); + PrintFieldToValue(*field, printer); + printer->Print("(message.$f$()));\n", "f", field_name); + } } + printer->Print("if (!message.unknown_fields().empty()) {\n"); + printer->Indent(); + printer->Print( + "::proto_extras::SerializeUnknownFields(message, dict);\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("return dict;\n"); + printer->Outdent(); + printer->Print("}\n"); + if (options.generate_stream_operator) { - std::string message_type = - google::protobuf::compiler::cpp::ClassName(&message); - printer->Emit({{"message_type", message_type}}, - R"( -std::ostream& operator<<(std::ostream& out, const $message_type$& message) { - return out << Serialize(message).DebugString(); -} -)"); + printer->Print( + "\nstd::ostream& operator<<(std::ostream& out, const $m$& message) " + "{\n", + "m", message_type); + printer->Indent(); + printer->Print("return out << Serialize(message).DebugString();\n"); + printer->Outdent(); + printer->Print("}\n"); } for (int i = 0; i < message.nested_type_count(); i++) { - if (!PrintFunctionDefinitions(*message.nested_type(i), printer, error, - options)) { + if (!PrintFunctionDefinition(*message.nested_type(i), printer, error, + options)) { return false; } } return true; } + + void PrintFieldToValue(const FieldDescriptor& field, Printer* printer) const { + using enum FieldDescriptor::Type; + switch (field.type()) { + case TYPE_DOUBLE: + case TYPE_FLOAT: + printer->Print("static_cast<double>"); + break; + case TYPE_INT32: + case TYPE_INT64: + case TYPE_UINT64: + case TYPE_UINT32: + case TYPE_FIXED64: + case TYPE_FIXED32: + case TYPE_SFIXED64: + case TYPE_SFIXED32: + case TYPE_SINT64: + case TYPE_SINT32: + printer->Print("::proto_extras::ToNumericTypeForValue"); + break; + case TYPE_BOOL: + printer->Print("static_cast<bool>"); + break; + case TYPE_STRING: + printer->Print("static_cast<std::string>"); + break; + case TYPE_BYTES: + printer->Print("base::Base64Encode"); + break; + case TYPE_ENUM: + printer->Print("$t$_Name", "t", + google::protobuf::compiler::cpp::QualifiedClassName( + field.enum_type())); + break; + case TYPE_MESSAGE: + case TYPE_GROUP: + printer->Print("$p$::Serialize", "p", + google::protobuf::compiler::cpp::Namespace(field.message_type())); + break; + } + } }; + } // namespace int main(int argc, char** argv) { - ProtoExtrasGenerator generator; + ToValueGenerator generator; return google::protobuf::compiler::PluginMain(argc, argv, &generator); }
diff --git a/components/proto_extras/proto_extras_unittest.cc b/components/proto_extras/proto_extras_unittest.cc index bf7b00d..73a07f5 100644 --- a/components/proto_extras/proto_extras_unittest.cc +++ b/components/proto_extras/proto_extras_unittest.cc
@@ -3,12 +3,12 @@ // found in the LICENSE file. #include "base/test/values_test_util.h" -#include "components/proto_extras/test_proto/test_proto.extras.h" #include "components/proto_extras/test_proto/test_proto.pb.h" -#include "components/proto_extras/test_proto/test_proto_dependency.extras.h" +#include "components/proto_extras/test_proto/test_proto.to_value.h" #include "components/proto_extras/test_proto/test_proto_dependency.pb.h" -#include "components/proto_extras/test_proto2/test_proto2.extras.h" +#include "components/proto_extras/test_proto/test_proto_dependency.to_value.h" #include "components/proto_extras/test_proto2/test_proto2.pb.h" +#include "components/proto_extras/test_proto2/test_proto2.to_value.h" #include "testing/gtest/include/gtest/gtest.h" namespace proto_extras {
diff --git a/components/proto_extras/protobuf_full_support.h b/components/proto_extras/protobuf_full_support.h deleted file mode 100644 index ef668fc..0000000 --- a/components/proto_extras/protobuf_full_support.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2025 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_PROTO_EXTRAS_PROTOBUF_FULL_SUPPORT_H_ -#define COMPONENTS_PROTO_EXTRAS_PROTOBUF_FULL_SUPPORT_H_ - -#include "base/component_export.h" -#include "base/values.h" -#include "third_party/protobuf/src/google/protobuf/message.h" -#include "third_party/protobuf/src/google/protobuf/unknown_field_set.h" - -namespace google::protobuf { -class UnknownFieldSet; -} // namespace google::protobuf - -namespace proto_extras { - -base::DictValue Serialize( - const google::protobuf::UnknownFieldSet& unknown_fields); - -template <typename MessageType> - requires std::is_base_of_v<google::protobuf::Message, MessageType> -void SerializeUnknownFields(const MessageType& message, base::DictValue& dict) { - if (message.unknown_fields().empty()) { - return; - } - dict.Set("unknown_fields", Serialize(message.unknown_fields())); -} - -} // namespace proto_extras - -#endif // COMPONENTS_PROTO_EXTRAS_PROTOBUF_FULL_SUPPORT_H_
diff --git a/components/proto_extras/test_proto2/BUILD.gn b/components/proto_extras/test_proto2/BUILD.gn index 0a65bdf..06d83310 100644 --- a/components/proto_extras/test_proto2/BUILD.gn +++ b/components/proto_extras/test_proto2/BUILD.gn
@@ -14,4 +14,6 @@ sources = [ "test_proto2.proto" ] deps = [ ":test_proto2" ] + + generate_stream_operators = true }
diff --git a/components/safe_browsing/content/browser/web_ui/DEPS b/components/safe_browsing/content/browser/web_ui/DEPS index c60c73f..a2e080da 100644 --- a/components/safe_browsing/content/browser/web_ui/DEPS +++ b/components/safe_browsing/content/browser/web_ui/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+components/enterprise/common/proto/connectors.pb.h", - "+components/enterprise/common/proto/connectors.extras.h", + "+components/enterprise/common/proto/connectors.to_value.h", "+components/grit/safe_browsing_resources.h", "+components/grit/safe_browsing_resources_map.h", "+components/password_manager/core/browser/hash_password_manager.h",
diff --git a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc index a9302ab..dfc119a 100644 --- a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
@@ -36,11 +36,11 @@ #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/core/browser/referrer_chain_provider.h" #include "components/safe_browsing/core/common/features.h" -#include "components/safe_browsing/core/common/proto/csd.extras.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" -#include "components/safe_browsing/core/common/proto/realtimeapi.extras.h" -#include "components/safe_browsing/core/common/proto/safebrowsingv5.extras.h" +#include "components/safe_browsing/core/common/proto/csd.to_value.h" +#include "components/safe_browsing/core/common/proto/realtimeapi.to_value.h" #include "components/safe_browsing/core/common/proto/safebrowsingv5.pb.h" +#include "components/safe_browsing/core/common/proto/safebrowsingv5.to_value.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/safe_browsing/core/common/web_ui_constants.h" #include "components/strings/grit/components_strings.h" @@ -58,8 +58,8 @@ #endif #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) && !BUILDFLAG(IS_ANDROID) -#include "components/enterprise/common/proto/connectors.extras.h" #include "components/enterprise/common/proto/connectors.pb.h" +#include "components/enterprise/common/proto/connectors.to_value.h" #endif using base::Time;
diff --git a/components/safe_browsing/core/common/proto/BUILD.gn b/components/safe_browsing/core/common/proto/BUILD.gn index 377f7cb..a13eed7 100644 --- a/components/safe_browsing/core/common/proto/BUILD.gn +++ b/components/safe_browsing/core/common/proto/BUILD.gn
@@ -24,9 +24,6 @@ proto_extras("csd_proto_extras") { sources = [ "csd.proto" ] deps = [ ":csd_proto" ] - - # The fuzzable_proto_library rule above uses the full protobuf runtime. - protobuf_full_support = true } proto_library("webui_proto") { @@ -51,9 +48,6 @@ "//components/enterprise/common/proto:connectors_proto", "//components/enterprise/common/proto:connectors_proto_extras", ] - - # The fuzzable_proto_library rule above uses the full protobuf runtime. - protobuf_full_support = true } fuzzable_proto_library("client_model_proto") {
diff --git a/components/search_engines/search_engine_choice/search_engine_choice_service.cc b/components/search_engines/search_engine_choice/search_engine_choice_service.cc index ebe4df0..e2c7d387 100644 --- a/components/search_engines/search_engine_choice/search_engine_choice_service.cc +++ b/components/search_engines/search_engine_choice/search_engine_choice_service.cc
@@ -233,9 +233,22 @@ base::Time::Exploded exploded; timestamp->LocalExplode(&exploded); + // For reporting purposes, we want to keep the date in the range [2022-01, + // 2050-12]. Dates that are before 2022 are reported as `1000-01`, and dates + // after 2050 are reported as `3000-01`. + int year = exploded.year; + int month = exploded.month; + if (exploded.year < 2022) { + year = 1000; + month = 1; + } else if (exploded.year > 2050) { + year = 3000; + month = 1; + } + // Expected value space is 12 samples / year. base::UmaHistogramSparse(kSearchEngineChoiceCompletedOnMonthHistogram, - exploded.year * 100 + exploded.month); + year * 100 + month); } } // namespace @@ -545,7 +558,8 @@ profile_prefs_.get(), SearchEngineChoiceWipeReason::kInvalidMetadataVersion); return; - case ChoiceCompletionMetadata::ParseError::kOther: + case ChoiceCompletionMetadata::ParseError::kMissingTimestamp: + case ChoiceCompletionMetadata::ParseError::kNullTimestamp: WipeSearchEngineChoicePrefs( profile_prefs_.get(), SearchEngineChoiceWipeReason::kInvalidMetadata);
diff --git a/components/search_engines/search_engine_choice/search_engine_choice_service_unittest.cc b/components/search_engines/search_engine_choice/search_engine_choice_service_unittest.cc index 767d71a..fb83113 100644 --- a/components/search_engines/search_engine_choice/search_engine_choice_service_unittest.cc +++ b/components/search_engines/search_engine_choice/search_engine_choice_service_unittest.cc
@@ -713,6 +713,46 @@ kSearchEngineChoiceCompletedOnMonthHistogram, 202504, 1); } +// Tests if choice screen completion date is recorded. +TEST_F(SearchEngineChoiceServiceTest, + RecordsChoiceScreenCompletionDateBefore2022Histogram) { + base::HistogramTester histogram_tester; + + // July 1993. What is specific about this timestamp (in windows epoch seconds) + // is that it is before 2022. + int64_t windows_epoch_timestamp = 12388103000; + + pref_service()->SetString( + prefs::kDefaultSearchProviderChoiceScreenCompletionVersion, "1.0.0.0"); + pref_service()->SetInt64( + prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp, + windows_epoch_timestamp); + + search_engine_choice_service(); + histogram_tester.ExpectUniqueSample( + kSearchEngineChoiceCompletedOnMonthHistogram, 100001, 1); +} + +// Tests if choice screen completion date is recorded. +TEST_F(SearchEngineChoiceServiceTest, + RecordsChoiceScreenCompletionDateAfter2050Histogram) { + base::HistogramTester histogram_tester; + + // December 2056. What is specific about this timestamp (in windows epoch + // seconds) is that it is after 2050. + int64_t windows_epoch_timestamp = 14388103000; + + pref_service()->SetString( + prefs::kDefaultSearchProviderChoiceScreenCompletionVersion, "1.0.0.0"); + pref_service()->SetInt64( + prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp, + windows_epoch_timestamp); + + search_engine_choice_service(); + histogram_tester.ExpectUniqueSample( + kSearchEngineChoiceCompletedOnMonthHistogram, 300001, 1); +} + // Test that the user is not reprompted if the reprompt parameter is not a valid // JSON string. TEST_F(SearchEngineChoiceServiceTest, NoRepromptForSyntaxError) {
diff --git a/components/search_engines/search_engine_choice/search_engine_choice_utils.cc b/components/search_engines/search_engine_choice/search_engine_choice_utils.cc index d7f89c6..8e149a90 100644 --- a/components/search_engines/search_engine_choice/search_engine_choice_utils.cc +++ b/components/search_engines/search_engine_choice/search_engine_choice_utils.cc
@@ -112,8 +112,7 @@ return std::nullopt; } - if (!parsed_country_id.has_value() || - !parsed_search_engines) { + if (!parsed_country_id.has_value() || !parsed_search_engines) { return std::nullopt; } @@ -123,9 +122,8 @@ static_cast<SearchEngineType>(search_engine_type.GetInt())); } - return ChoiceScreenDisplayState( - search_engines, parsed_country_id.value(), - parsed_selected_engine_index); + return ChoiceScreenDisplayState(search_engines, parsed_country_id.value(), + parsed_selected_engine_index); } ChoiceScreenData::ChoiceScreenData( @@ -226,8 +224,8 @@ prefs::kDefaultSearchProviderPendingChoiceScreenDisplayState); #if BUILDFLAG(IS_IOS) - profile_prefs.ClearPref( - prefs::kDefaultSearchProviderChoiceScreenSkippedCount); + profile_prefs.ClearPref( + prefs::kDefaultSearchProviderChoiceScreenSkippedCount); #endif } @@ -251,15 +249,19 @@ ChoiceCompletionMetadata::ParseError::kInvalidVersion); } - // Note: Other error conditions don't have dedicated handling, so we log all - // of them as `kOther`. + if (!prefs.HasPrefPath( + prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp)) { + return base::unexpected( + ChoiceCompletionMetadata::ParseError::kMissingTimestamp); + } base::Time timestamp = base::Time::FromDeltaSinceWindowsEpoch(base::Seconds(prefs.GetInt64( - prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp))); + prefs::kDefaultSearchProviderChoiceScreenCompletionTimestamp))); if (timestamp.is_null()) { - return base::unexpected(ChoiceCompletionMetadata::ParseError::kOther); + return base::unexpected( + ChoiceCompletionMetadata::ParseError::kNullTimestamp); } return ChoiceCompletionMetadata{
diff --git a/components/search_engines/search_engine_choice/search_engine_choice_utils.h b/components/search_engines/search_engine_choice/search_engine_choice_utils.h index d084ff5a..d931580f4 100644 --- a/components/search_engines/search_engine_choice/search_engine_choice_utils.h +++ b/components/search_engines/search_engine_choice/search_engine_choice_utils.h
@@ -58,7 +58,7 @@ inline constexpr char kSearchEngineChoiceRepromptSpecificCountryHistogram[] = "Search.ChoiceReprompt.SpecificCountry"; inline constexpr char kSearchEngineChoiceCompletedOnMonthHistogram[] = - "Search.ChoiceCompletedOnMonth.OnProfileLoad"; + "Search.ChoiceCompletedOnMonth.OnProfileLoad2"; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -295,7 +295,8 @@ kAbsent, kMissingVersion, kInvalidVersion, - kOther, + kMissingTimestamp, + kNullTimestamp, }; base::Time timestamp;
diff --git a/components/strings/components_strings_eu.xtb b/components/strings/components_strings_eu.xtb index 0e9f3545..0c84d3a 100644 --- a/components/strings/components_strings_eu.xtb +++ b/components/strings/components_strings_eu.xtb
@@ -522,6 +522,7 @@ <translation id="1863257867908022953">12. erretilua</translation> <translation id="1864927262126810325">Iturburua: <ph name="SOURCE_NAME" /></translation> <translation id="186539747722034544">Kable eta satelite bidezko hornitzaileak</translation> +<translation id="1866757068250903512">Kontrolatu <ph name="READERNAME" /> izeneko autentifikazio-gailuak eta haiekin erabilitako txartel adimendunak</translation> <translation id="1870473978371099486">Klase pribatuak</translation> <translation id="1871208020102129563">Proxy-zerbitzari finkoak erabiltzeko konfiguratu da proxya, ez .pac scripteko URLak erabiltzeko.</translation> <translation id="1871284979644508959">Nahitaezko eremua</translation>
diff --git a/components/test/BUILD.gn b/components/test/BUILD.gn index a84aef2..db5f9db2 100644 --- a/components/test/BUILD.gn +++ b/components/test/BUILD.gn
@@ -71,6 +71,10 @@ testonly = true filelist_name = "data/dom_distiller/unit_tests_bundle_data.filelist" } + bundle_data_from_filelist("dom_label_test_bundle_data") { + testonly = true + filelist_name = "data/autofill/label-doms/unit_tests_bundle_data.filelist" + } bundle_data_from_filelist("feed_test_bundle_data") { testonly = true filelist_name = "data/feed/unit_tests_bundle_data.filelist"
diff --git a/components/test/PRESUBMIT.py b/components/test/PRESUBMIT.py index ddd2486a..051e97c 100644 --- a/components/test/PRESUBMIT.py +++ b/components/test/PRESUBMIT.py
@@ -24,6 +24,9 @@ 'data/dom_distiller/unit_tests_bundle_data') results += presubmit_support.CheckBundleData( input_api, output_api, + 'data/autofill/label-doms/unit_tests_bundle_data') + results += presubmit_support.CheckBundleData( + input_api, output_api, 'data/feed/unit_tests_bundle_data') results += presubmit_support.CheckBundleData( input_api, output_api,
diff --git a/components/test/data/autofill/label-doms/unit_tests_bundle_data.filelist b/components/test/data/autofill/label-doms/unit_tests_bundle_data.filelist new file mode 100644 index 0000000..dc58fe3 --- /dev/null +++ b/components/test/data/autofill/label-doms/unit_tests_bundle_data.filelist
@@ -0,0 +1,8 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# NOTE: this file is generated by build/ios/update_bundle_filelist.py +# If it requires updating, you should get a presubmit error with +# instructions on how to regenerate. Otherwise, do not edit. +//components/test/data/autofill/label-doms/basic-test.html +//components/test/data/autofill/label-doms/basic-test.json
diff --git a/components/test/data/autofill/label-doms/unit_tests_bundle_data.globlist b/components/test/data/autofill/label-doms/unit_tests_bundle_data.globlist new file mode 100644 index 0000000..c4a55d975 --- /dev/null +++ b/components/test/data/autofill/label-doms/unit_tests_bundle_data.globlist
@@ -0,0 +1,10 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# See build/ios/update_bundle_filelist.py for details on how .globlist +# files are used to update their .filelist counterparts. + +//components/test/data/autofill/label-doms/** +-//components/test/data/autofill/label-doms/*.filelist +-//components/test/data/autofill/label-doms/*.globlist
diff --git a/components/viz/service/display/readback_pixeltest.cc b/components/viz/service/display/readback_pixeltest.cc index 7fe6540c..ee7a639 100644 --- a/components/viz/service/display/readback_pixeltest.cc +++ b/components/viz/service/display/readback_pixeltest.cc
@@ -1004,9 +1004,7 @@ auto shared_image = sii->CreateSharedImage( {MultiPlaneFormat::kNV12, source_size, gfx::ColorSpace::CreateREC709(), - gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | - gpu::SHARED_IMAGE_USAGE_RASTER_WRITE, - "TestLabels"}, + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ, "TestLabels"}, gpu::kNullSurfaceHandle); CHECK(shared_image);
diff --git a/components/viz/service/input/input_manager.cc b/components/viz/service/input/input_manager.cc index 011b34ef..131b037 100644 --- a/components/viz/service/input/input_manager.cc +++ b/components/viz/service/input/input_manager.cc
@@ -56,6 +56,11 @@ surface_handle, viz_input_token_java); } +void DestroyReceiverData( + std::unique_ptr<input::InputReceiverData> receiver_data) { + receiver_data.reset(); +} + #endif // BUILDFLAG(IS_ANDROID) bool IsFrameMetadataAvailable(CompositorFrameSinkSupport* support) { @@ -249,8 +254,14 @@ TRACE_EVENT("viz", "InputManager::OnDestroyedCompositorFrameSink", "frame_sink_id", frame_sink_id); #if BUILDFLAG(IS_ANDROID) - if (receiver_data_) { - receiver_data_->OnDestroyedCompositorFrameSink(frame_sink_id); + if (receiver_data_ && receiver_data_->root_frame_sink_id() == frame_sink_id) { + receiver_data_->OnDestroyedCompositorFrameSink(); + if (base::android::android_info::sdk_int() >= + base::android::android_info::SdkVersion::SDK_VERSION_BAKLAVA) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(&DestroyReceiverData, std::move(receiver_data_))); + } } #endif // BUILDFLAG(IS_ANDROID)
diff --git a/components/viz/service/input/input_manager.h b/components/viz/service/input/input_manager.h index 67061a7..7d8484e 100644 --- a/components/viz/service/input/input_manager.h +++ b/components/viz/service/input/input_manager.h
@@ -23,6 +23,7 @@ #include "mojo/public/cpp/bindings/associated_receiver_set.h" #if BUILDFLAG(IS_ANDROID) +#include "base/android/android_info.h" #include "components/input/android/input_receiver_data.h" #include "components/viz/service/input/android_state_transfer_handler.h" #include "components/viz/service/input/render_input_router_support_android.h"
diff --git a/content/browser/indexed_db/BUILD.gn b/content/browser/indexed_db/BUILD.gn index c01b146..214e23da 100644 --- a/content/browser/indexed_db/BUILD.gn +++ b/content/browser/indexed_db/BUILD.gn
@@ -70,6 +70,10 @@ "instance/lock_request_data.h", "instance/pending_connection.cc", "instance/pending_connection.h", + "instance/record.cc", + "instance/record.h", + "instance/sqlite/backing_store_cursor_impl.cc", + "instance/sqlite/backing_store_cursor_impl.h", "instance/sqlite/backing_store_database_impl.cc", "instance/sqlite/backing_store_database_impl.h", "instance/sqlite/backing_store_impl.cc", @@ -78,6 +82,8 @@ "instance/sqlite/backing_store_transaction_impl.h", "instance/sqlite/database_connection.cc", "instance/sqlite/database_connection.h", + "instance/sqlite/record_iterator.cc", + "instance/sqlite/record_iterator.h", "instance/transaction.cc", "instance/transaction.h", "list_set.h",
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc index bb1ac2a2..cc2f1f4e 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -420,13 +420,14 @@ return EncodeIDBKeyRecursively(value, into, 0); } -void EncodeSortableIDBKey(const IndexedDBKey& value, std::string* into) { +void EncodeSortableIDBKeyRecursively(const IndexedDBKey& value, + std::string* into) { size_t previous_size = into->size(); switch (value.type()) { case blink::mojom::IDBKeyType::Array: { EncodeByte(kOrderedArrayTypeByte, into); for (const IndexedDBKey& key : value.array()) { - EncodeSortableIDBKey(key, into); + EncodeSortableIDBKeyRecursively(key, into); } EncodeByte(kSentinel, into); DCHECK_GT(into->size(), previous_size); @@ -456,6 +457,12 @@ } } +std::string EncodeSortableIDBKey(const IndexedDBKey& value) { + std::string encoded; + EncodeSortableIDBKeyRecursively(value, &encoded); + return encoded; +} + #define COMPILE_ASSERT_MATCHING_VALUES(a, b) \ static_assert( \ static_cast<unsigned char>(a) == static_cast<unsigned char>(b), \
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.h b/content/browser/indexed_db/indexed_db_leveldb_coding.h index 4716a71b..829f37b 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.h +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -73,8 +73,8 @@ // collation operation. Unlike `EncodeIDBKey`, which makes use of length bytes, // this operation re-encodes variable-length values in a way that supports // sentinels. -CONTENT_EXPORT void EncodeSortableIDBKey(const blink::IndexedDBKey& value, - std::string* into); +CONTENT_EXPORT std::string EncodeSortableIDBKey( + const blink::IndexedDBKey& value); CONTENT_EXPORT void EncodeIDBKeyPath(const blink::IndexedDBKeyPath& value, std::string* into); CONTENT_EXPORT void EncodeBlobJournal(const BlobJournalType& journal,
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc index 7d4f3b2..9f3be06e 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -852,11 +852,9 @@ EXPECT_TRUE(key_a.IsLessThan(key_b)); - std::string encoded_a; - EncodeSortableIDBKey(key_a, &encoded_a); + std::string encoded_a = EncodeSortableIDBKey(key_a); EXPECT_TRUE(encoded_a.size()); - std::string encoded_b; - EncodeSortableIDBKey(key_b, &encoded_b); + std::string encoded_b = EncodeSortableIDBKey(key_b); EXPECT_TRUE(encoded_b.size()); auto sqlite_compare = [](const std::string& a, const std::string& b) { @@ -876,8 +874,7 @@ } // Also test decoding by treating all test cases as one massive array key. const IndexedDBKey all_keys_key(std::move(keys_vec)); - std::string encoded; - EncodeSortableIDBKey(all_keys_key, &encoded); + std::string encoded = EncodeSortableIDBKey(all_keys_key); IndexedDBKey decoded_value = DecodeSortableIDBKey(encoded); ASSERT_TRUE(decoded_value.IsValid()); EXPECT_TRUE(all_keys_key.Equals(decoded_value)) @@ -937,13 +934,11 @@ SCOPED_TRACE(testing::Message() << "Comparing " << value_a << " and " << value_b); - std::string encoded_a; - EncodeSortableIDBKey( - IndexedDBKey(value_a, blink::mojom::IDBKeyType::Number), &encoded_a); + std::string encoded_a = EncodeSortableIDBKey( + IndexedDBKey(value_a, blink::mojom::IDBKeyType::Number)); EXPECT_TRUE(encoded_a.size()); - std::string encoded_b; - EncodeSortableIDBKey( - IndexedDBKey(value_b, blink::mojom::IDBKeyType::Number), &encoded_b); + std::string encoded_b = EncodeSortableIDBKey( + IndexedDBKey(value_b, blink::mojom::IDBKeyType::Number)); EXPECT_TRUE(encoded_b.size()); EXPECT_EQ(encoded_a.size(), encoded_b.size()); @@ -964,8 +959,7 @@ for (double value : values) { const IndexedDBKey key(value, blink::mojom::IDBKeyType::Number); - std::string encoded; - EncodeSortableIDBKey(key, &encoded); + std::string encoded = EncodeSortableIDBKey(key); IndexedDBKey decoded_value = DecodeSortableIDBKey(encoded); ASSERT_TRUE(decoded_value.IsValid()); EXPECT_TRUE(key.Equals(decoded_value))
diff --git a/content/browser/indexed_db/instance/backing_store.h b/content/browser/indexed_db/instance/backing_store.h index 8519190..cad6561 100644 --- a/content/browser/indexed_db/instance/backing_store.h +++ b/content/browser/indexed_db/instance/backing_store.h
@@ -214,13 +214,12 @@ // keys are valid, advances the cursor to the row for `key` or `key` and // `primary_key`. Returns true on success, or false if no eligible row was // found. Returns an error if there was a DB error. + virtual StatusOr<bool> Continue() = 0; virtual StatusOr<bool> Continue(const blink::IndexedDBKey& key, const blink::IndexedDBKey& primary_key) = 0; virtual StatusOr<bool> Advance(uint32_t count) = 0; // Clone may return a nullptr if cloning fails for any reason. virtual std::unique_ptr<Cursor> Clone() const = 0; - - StatusOr<bool> Continue() { return Continue({}, {}); } }; virtual ~BackingStore() = default;
diff --git a/content/browser/indexed_db/instance/leveldb/backing_store.cc b/content/browser/indexed_db/instance/leveldb/backing_store.cc index bf102b3..d02ba75 100644 --- a/content/browser/indexed_db/instance/leveldb/backing_store.cc +++ b/content/browser/indexed_db/instance/leveldb/backing_store.cc
@@ -3247,7 +3247,7 @@ StatusOr<bool> BackingStore::Cursor::Advance(uint32_t count) { while (count--) { - StatusOr<bool> result = indexed_db::BackingStore::Cursor::Continue(); + StatusOr<bool> result = Continue(); if (!result.has_value()) { return base::unexpected(result.error()); } @@ -3259,6 +3259,10 @@ return true; } +StatusOr<bool> BackingStore::Cursor::Continue() { + return Continue({}, {}); +} + StatusOr<bool> BackingStore::Cursor::Continue(const IndexedDBKey& key, const IndexedDBKey& primary_key) { return Continue(key, primary_key, SEEK);
diff --git a/content/browser/indexed_db/instance/leveldb/backing_store.h b/content/browser/indexed_db/instance/leveldb/backing_store.h index 98ddfea..eef58b36 100644 --- a/content/browser/indexed_db/instance/leveldb/backing_store.h +++ b/content/browser/indexed_db/instance/leveldb/backing_store.h
@@ -365,6 +365,7 @@ const blink::IndexedDBKey& GetKey() const override; const blink::IndexedDBKey& GetPrimaryKey() const override; blink::IndexedDBKey TakeKey() && override; + StatusOr<bool> Continue() override; StatusOr<bool> Continue(const blink::IndexedDBKey& key, const blink::IndexedDBKey& primary_key) override; StatusOr<bool> Advance(uint32_t count) override;
diff --git a/content/browser/indexed_db/instance/record.cc b/content/browser/indexed_db/instance/record.cc new file mode 100644 index 0000000..409745a --- /dev/null +++ b/content/browser/indexed_db/instance/record.cc
@@ -0,0 +1,40 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/instance/record.h" + +#include <utility> + +#include "base/notreached.h" + +namespace content::indexed_db { + +ObjectStoreRecord::ObjectStoreRecord(blink::IndexedDBKey key, + IndexedDBValue value) + : key_(std::move(key)), value_(std::move(value)) {} + +ObjectStoreRecord::~ObjectStoreRecord() = default; + +blink::IndexedDBKey& ObjectStoreRecord::key() { + return key_; +} + +blink::IndexedDBKey& ObjectStoreRecord::primary_key() { + return key_; +} + +IndexedDBValue& ObjectStoreRecord::value() { + return value_; +} + +ObjectStoreKeyOnlyRecord::ObjectStoreKeyOnlyRecord(blink::IndexedDBKey key) + : ObjectStoreRecord(std::move(key), /*value=*/{}) {} + +ObjectStoreKeyOnlyRecord::~ObjectStoreKeyOnlyRecord() = default; + +IndexedDBValue& ObjectStoreKeyOnlyRecord::value() { + NOTREACHED(); +} + +} // namespace content::indexed_db
diff --git a/content/browser/indexed_db/instance/record.h b/content/browser/indexed_db/instance/record.h new file mode 100644 index 0000000..6956401f --- /dev/null +++ b/content/browser/indexed_db/instance/record.h
@@ -0,0 +1,50 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_RECORD_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_RECORD_H_ + +#include "content/browser/indexed_db/indexed_db_value.h" +#include "third_party/blink/public/common/indexeddb/indexeddb_key.h" + +namespace content::indexed_db { + +// Base class for an IndexedDB record. +class Record { + public: + virtual ~Record() = default; + + virtual blink::IndexedDBKey& key() = 0; + virtual blink::IndexedDBKey& primary_key() = 0; + virtual IndexedDBValue& value() = 0; +}; + +// An object store record has a key and value, with `primary_key()` being the +// key itself. +class ObjectStoreRecord : public Record { + public: + ObjectStoreRecord(blink::IndexedDBKey key, IndexedDBValue value); + ~ObjectStoreRecord() override; + + blink::IndexedDBKey& key() override; + blink::IndexedDBKey& primary_key() override; + IndexedDBValue& value() override; + + private: + blink::IndexedDBKey key_; + IndexedDBValue value_; +}; + +// It is an error to call `value()` on this type of record. +class ObjectStoreKeyOnlyRecord : public ObjectStoreRecord { + public: + explicit ObjectStoreKeyOnlyRecord(blink::IndexedDBKey key); + ~ObjectStoreKeyOnlyRecord() override; + + IndexedDBValue& value() override; +}; + +} // namespace content::indexed_db + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_RECORD_H_
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.cc b/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.cc new file mode 100644 index 0000000..b1bfda1c --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.cc
@@ -0,0 +1,69 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.h" + +#include <memory> +#include <utility> + +#include "base/types/expected.h" +#include "content/browser/indexed_db/instance/record.h" +#include "content/browser/indexed_db/instance/sqlite/record_iterator.h" +#include "content/browser/indexed_db/status.h" + +namespace content::indexed_db::sqlite { + +content::indexed_db::sqlite::BackingStoreCursorImpl::BackingStoreCursorImpl( + std::unique_ptr<RecordIterator> iterator, + std::unique_ptr<Record> initial_record) + : iterator_(std::move(iterator)), + current_record_(std::move(initial_record)) {} + +BackingStoreCursorImpl::~BackingStoreCursorImpl() = default; + +const blink::IndexedDBKey& BackingStoreCursorImpl::GetKey() const { + return current_record_->key(); +} + +blink::IndexedDBKey BackingStoreCursorImpl::TakeKey() && { + return std::move(current_record_->key()); +} + +const blink::IndexedDBKey& BackingStoreCursorImpl::GetPrimaryKey() const { + return current_record_->primary_key(); +} + +IndexedDBValue& BackingStoreCursorImpl::GetValue() { + return current_record_->value(); +} + +std::unique_ptr<BackingStore::Cursor> BackingStoreCursorImpl::Clone() const { + // This is needed by `Cursor::PrefetchIterationOperation()`. + // TODO(crbug.com/419208481): Implement prefetch without using `Clone()`. + return nullptr; +} + +StatusOr<bool> BackingStoreCursorImpl::Continue() { + return Advance(1); +} + +StatusOr<bool> BackingStoreCursorImpl::Continue( + const blink::IndexedDBKey& key, + const blink::IndexedDBKey& primary_key) { + return iterator_->Iterate(key, primary_key) + .transform([this](std::unique_ptr<Record> new_record) { + current_record_ = std::move(new_record); + return current_record_ != nullptr; + }); +} + +StatusOr<bool> BackingStoreCursorImpl::Advance(uint32_t count) { + return iterator_->Iterate(count).transform( + [this](std::unique_ptr<Record> new_record) { + current_record_ = std::move(new_record); + return current_record_ != nullptr; + }); +} + +} // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.h b/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.h new file mode 100644 index 0000000..4f136e6 --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.h
@@ -0,0 +1,46 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_CURSOR_IMPL_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_CURSOR_IMPL_H_ + +#include <memory> + +#include "base/types/pass_key.h" +#include "content/browser/indexed_db/instance/backing_store.h" + +namespace content::indexed_db { +class Record; + +namespace sqlite { +class RecordIterator; + +class BackingStoreCursorImpl : public BackingStore::Cursor { + public: + using PassKey = base::PassKey<BackingStoreCursorImpl>; + + BackingStoreCursorImpl(std::unique_ptr<RecordIterator> iterator, + std::unique_ptr<Record> initial_record); + ~BackingStoreCursorImpl() override; + + // BackingStore::Cursor: + const blink::IndexedDBKey& GetKey() const override; + blink::IndexedDBKey TakeKey() && override; + const blink::IndexedDBKey& GetPrimaryKey() const override; + IndexedDBValue& GetValue() override; + std::unique_ptr<Cursor> Clone() const override; + StatusOr<bool> Continue() override; + StatusOr<bool> Continue(const blink::IndexedDBKey& key, + const blink::IndexedDBKey& primary_key) override; + StatusOr<bool> Advance(uint32_t count) override; + + private: + std::unique_ptr<RecordIterator> iterator_; + std::unique_ptr<Record> current_record_; +}; + +} // namespace sqlite +} // namespace content::indexed_db + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_CURSOR_IMPL_H_
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc index fde8437f..9faf1f4 100644 --- a/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc +++ b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc
@@ -188,18 +188,18 @@ BackingStoreTransactionImpl::OpenObjectStoreKeyCursor( int64_t object_store_id, const blink::IndexedDBKeyRange& key_range, - blink::mojom::IDBCursorDirection) { - NOTIMPLEMENTED(); - return base::unexpected(Status::InvalidArgument("Not implemented")); + blink::mojom::IDBCursorDirection direction) { + return db_->OpenObjectStoreCursor(PassKey(), object_store_id, key_range, + direction, /*key_only=*/true); } StatusOr<std::unique_ptr<indexed_db::BackingStore::Cursor>> BackingStoreTransactionImpl::OpenObjectStoreCursor( int64_t object_store_id, const blink::IndexedDBKeyRange& key_range, - blink::mojom::IDBCursorDirection) { - NOTIMPLEMENTED(); - return base::unexpected(Status::InvalidArgument("Not implemented")); + blink::mojom::IDBCursorDirection direction) { + return db_->OpenObjectStoreCursor(PassKey(), object_store_id, key_range, + direction, /*key_only=*/false); } StatusOr<std::unique_ptr<indexed_db::BackingStore::Cursor>>
diff --git a/content/browser/indexed_db/instance/sqlite/database_connection.cc b/content/browser/indexed_db/instance/sqlite/database_connection.cc index effa745..11228b63f 100644 --- a/content/browser/indexed_db/instance/sqlite/database_connection.cc +++ b/content/browser/indexed_db/instance/sqlite/database_connection.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/check.h" +#include "base/functional/callback.h" #include "base/memory/ptr_util.h" #include "base/notimplemented.h" #include "base/notreached.h" @@ -18,7 +19,10 @@ #include "base/types/expected.h" #include "content/browser/indexed_db/indexed_db_value.h" #include "content/browser/indexed_db/instance/backing_store.h" +#include "content/browser/indexed_db/instance/record.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_cursor_impl.h" #include "content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h" +#include "content/browser/indexed_db/instance/sqlite/record_iterator.h" #include "content/browser/indexed_db/status.h" #include "sql/database.h" #include "sql/meta_table.h" @@ -170,6 +174,113 @@ return metadata; } +// Returns a `RecordIterator` and the initial `Record` for the range of object +// store records determined by the parameters. Returns nullptrs if the range is +// empty or an error if one occurs. +StatusOr<std::pair<std::unique_ptr<RecordIterator>, std::unique_ptr<Record>>> +CreateObjectStoreRecordIterator(sql::Database* db, + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + bool ascending_order, + bool key_only) { + std::vector<std::string_view> query_pieces{ + "SELECT ", key_only ? "key" : "key, value", + " FROM records WHERE object_store_id = @object_store_id"}; + if (key_range.lower().IsValid()) { + query_pieces.push_back(key_range.lower_open() ? " AND key > @lower" + : " AND key >= @lower"); + } + if (key_range.upper().IsValid()) { + query_pieces.push_back(key_range.upper_open() ? " AND key < @upper" + : " AND key <= @upper"); + } + if (ascending_order) { + query_pieces.push_back( + " AND (@is_first_seek = 1 OR key > @position)" + " AND (@target_key IS NULL OR key >= @target_key)" + " ORDER BY key ASC"); + } else { + query_pieces.push_back( + " AND (@is_first_seek = 1 OR key < @position)" + " AND (@target_key IS NULL OR key <= @target_key)" + " ORDER BY key DESC"); + } + // LIMIT is needed to use OFFSET. A negative LIMIT implies no limit on the + // number of rows returned: + // https://www.sqlite.org/lang_select.html#the_limit_clause. + query_pieces.push_back(" LIMIT -1 OFFSET @offset"); + + auto statement = std::make_unique<sql::Statement>( + db->GetReadonlyStatement(base::StrCat(query_pieces))); + int param_index = 0; + statement->BindInt64(param_index++, object_store_id); + if (key_range.lower().IsValid()) { + statement->BindBlob(param_index++, EncodeSortableIDBKey(key_range.lower())); + } + if (key_range.upper().IsValid()) { + statement->BindBlob(param_index++, EncodeSortableIDBKey(key_range.upper())); + } + int is_first_seek_index = param_index++; + int position_index = param_index++; + int target_key_index = param_index++; + int offset_index = param_index++; + + RecordIterator::BindCallback bind_parameters = base::BindRepeating( + [](int is_first_seek_index, int position_index, int target_key_index, + int offset_index, sql::Statement& statement, + const std::string& position, const blink::IndexedDBKey& target_key, + const blink::IndexedDBKey& _, uint32_t offset) { + statement.BindBool(is_first_seek_index, false); + statement.BindBlob(position_index, position); + if (target_key.IsValid()) { + statement.BindBlob(target_key_index, + EncodeSortableIDBKey(target_key)); + } else { + statement.BindNull(target_key_index); + } + statement.BindInt64(offset_index, offset); + }, + is_first_seek_index, position_index, target_key_index, offset_index); + + RecordIterator::ReadCallback read_row = base::BindRepeating( + [](bool key_only, sql::Statement& statement) + -> StatusOr<RecordIterator::PositionAndRecord> { + std::string position; + TRANSIENT_CHECK(statement.ColumnBlobAsString(0, &position)); + blink::IndexedDBKey key = DecodeSortableIDBKey(position); + if (key_only) { + return std::make_pair( + std::move(position), + std::make_unique<ObjectStoreKeyOnlyRecord>(std::move(key))); + } + IndexedDBValue value; + TRANSIENT_CHECK(statement.ColumnBlobAsVector(1, &value.bits)); + return std::make_pair(std::move(position), + std::make_unique<ObjectStoreRecord>( + std::move(key), std::move(value))); + }, + key_only); + + // Attempt to find the initial record in the range. + statement->BindBool(is_first_seek_index, true); + statement->BindNull(position_index); + statement->BindNull(target_key_index); + statement->BindInt(offset_index, 0); + if (!statement->Step()) { + TRANSIENT_CHECK(statement->Succeeded()); + // Empty range. + return std::make_pair(nullptr, nullptr); + } + return read_row.Run(*statement) + .transform([&](RecordIterator::PositionAndRecord result) { + return std::make_pair( + std::make_unique<RecordIterator>( + std::move(statement), std::move(bind_parameters), + std::move(read_row), std::move(result.first)), + std::move(result.second)); + }); +} + } // namespace // static @@ -362,10 +473,8 @@ db_->GetCachedStatement(SQL_FROM_HERE, "SELECT row_id FROM records " "WHERE object_store_id = ? AND key = ?")); - std::string encoded_key; - EncodeSortableIDBKey(key, &encoded_key); statement.BindInt64(0, object_store_id); - statement.BindBlob(1, std::move(encoded_key)); + statement.BindBlob(1, EncodeSortableIDBKey(key)); if (statement.Step()) { return BackingStore::RecordIdentifier{statement.ColumnInt64(0)}; } @@ -381,10 +490,8 @@ db_->GetCachedStatement(SQL_FROM_HERE, "SELECT value FROM records " "WHERE object_store_id = ? AND key = ?")); - std::string encoded_key; - EncodeSortableIDBKey(key, &encoded_key); statement.BindInt64(0, object_store_id); - statement.BindBlob(1, std::move(encoded_key)); + statement.BindBlob(1, EncodeSortableIDBKey(key)); if (statement.Step()) { IndexedDBValue value; TRANSIENT_CHECK(statement.ColumnBlobAsVector(0, &value.bits)); @@ -404,9 +511,7 @@ "INSERT OR REPLACE INTO records " "(object_store_id, key, value) VALUES (?, ?, ?)")); statement.BindInt64(0, object_store_id); - std::string encoded_key; - EncodeSortableIDBKey(key, &encoded_key); - statement.BindBlob(1, std::move(encoded_key)); + statement.BindBlob(1, EncodeSortableIDBKey(key)); statement.BindBlob(2, std::move(value.bits)); TRANSIENT_CHECK(statement.Run()); return BackingStore::RecordIdentifier{db_->GetLastInsertRowId()}; @@ -418,19 +523,13 @@ blink::IndexedDBKeyRange key_range) { std::vector<std::string_view> query_pieces{ "SELECT COUNT() FROM records WHERE object_store_id = ?"}; - std::string lower_encoded; - std::string upper_encoded; if (key_range.lower().IsValid()) { - EncodeSortableIDBKey(key_range.lower(), &lower_encoded); - query_pieces.insert( - query_pieces.end(), - {" AND key ", key_range.lower_open() ? ">" : ">=", " ?"}); + query_pieces.push_back(key_range.lower_open() ? " AND key > ?" + : " AND key >= ?"); } if (key_range.upper().IsValid()) { - EncodeSortableIDBKey(key_range.upper(), &upper_encoded); - query_pieces.insert( - query_pieces.end(), - {" AND key ", key_range.upper_open() ? "<" : "<=", " ?"}); + query_pieces.push_back(key_range.upper_open() ? " AND key < ?" + : " AND key <= ?"); } // TODO(crbug.com/40253999): Evaluate performance benefit of using @@ -439,14 +538,36 @@ db_->GetReadonlyStatement(base::StrCat(query_pieces))); int param_index = 0; statement.BindInt64(param_index++, object_store_id); - if (!lower_encoded.empty()) { - statement.BindBlob(param_index++, lower_encoded); + if (key_range.lower().IsValid()) { + statement.BindBlob(param_index++, EncodeSortableIDBKey(key_range.lower())); } - if (!upper_encoded.empty()) { - statement.BindBlob(param_index++, upper_encoded); + if (key_range.upper().IsValid()) { + statement.BindBlob(param_index++, EncodeSortableIDBKey(key_range.upper())); } TRANSIENT_CHECK(statement.Step()); return statement.ColumnInt(0); } +StatusOr<std::unique_ptr<BackingStore::Cursor>> +DatabaseConnection::OpenObjectStoreCursor( + base::PassKey<BackingStoreTransactionImpl>, + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection direction, + bool key_only) { + bool ascending_order = + (direction == blink::mojom::IDBCursorDirection::Next || + direction == blink::mojom::IDBCursorDirection::NextNoDuplicate); + return CreateObjectStoreRecordIterator(db_.get(), object_store_id, key_range, + ascending_order, key_only) + .transform([](std::pair<std::unique_ptr<RecordIterator>, + std::unique_ptr<Record>> result) { + return result.first + ? std::make_unique<BackingStoreCursorImpl>( + std::move(result.first), std::move(result.second)) + // Empty range. + : nullptr; + }); +} + } // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/database_connection.h b/content/browser/indexed_db/instance/sqlite/database_connection.h index baab3d5..211e989 100644 --- a/content/browser/indexed_db/instance/sqlite/database_connection.h +++ b/content/browser/indexed_db/instance/sqlite/database_connection.h
@@ -111,6 +111,13 @@ int64_t object_store_id, blink::IndexedDBKeyRange key_range); + StatusOr<std::unique_ptr<BackingStore::Cursor>> OpenObjectStoreCursor( + base::PassKey<BackingStoreTransactionImpl>, + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection direction, + bool key_only); + private: DatabaseConnection(std::unique_ptr<sql::Database> db, std::unique_ptr<sql::MetaTable> meta_table,
diff --git a/content/browser/indexed_db/instance/sqlite/record_iterator.cc b/content/browser/indexed_db/instance/sqlite/record_iterator.cc new file mode 100644 index 0000000..ea8c2ea --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/record_iterator.cc
@@ -0,0 +1,77 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/instance/sqlite/record_iterator.h" + +#include <memory> +#include <optional> +#include <string> +#include <utility> + +#include "base/check.h" +#include "base/functional/callback.h" +#include "base/types/expected.h" +#include "content/browser/indexed_db/instance/record.h" +#include "content/browser/indexed_db/status.h" +#include "sql/statement.h" +#include "third_party/blink/public/common/indexeddb/indexeddb_key.h" + +// TODO(crbug.com/40253999): Remove after handling all error cases. +#define TRANSIENT_CHECK(condition) CHECK(condition) + +namespace content::indexed_db::sqlite { + +RecordIterator::RecordIterator(std::unique_ptr<sql::Statement> statement, + BindCallback bind_parameters, + ReadCallback read_row, + std::string initial_position) + : statement_(std::move(statement)), + bind_parameters_(std::move(bind_parameters)), + read_row_(std::move(read_row)), + current_position_(std::move(initial_position)) {} + +RecordIterator::~RecordIterator() = default; + +StatusOr<std::unique_ptr<Record>> RecordIterator::Iterate( + const blink::IndexedDBKey& key, + const blink::IndexedDBKey& primary_key) { + statement_->Reset(/*clear_bound_vars=*/false); + bind_parameters_.Run(*statement_, *current_position_, key, primary_key, + /*offset=*/0); + if (!statement_->Step()) { + TRANSIENT_CHECK(statement_->Succeeded()); + // End of range. + current_position_.reset(); + return nullptr; + } + return read_row_.Run(*statement_).transform([this](PositionAndRecord result) { + current_position_ = std::move(result.first); + return std::move(result.second); + }); +} + +StatusOr<std::unique_ptr<Record>> RecordIterator::Iterate(uint32_t count) { + TRANSIENT_CHECK(count > 0); + + // TODO(crbug.com/419208481): Implement a fast path where `statement_` is + // stepped without being reset when no record has changed in the range. + statement_->Reset(/*clear_bound_vars=*/false); + + // Iterate count times => offset by (i.e., skip) [count - 1] rows. + bind_parameters_.Run(*statement_, *current_position_, /*key=*/{}, + /*primary_key=*/{}, + /*offset=*/count - 1); + if (!statement_->Step()) { + TRANSIENT_CHECK(statement_->Succeeded()); + // End of range. + current_position_.reset(); + return nullptr; + } + return read_row_.Run(*statement_).transform([this](PositionAndRecord result) { + current_position_ = std::move(result.first); + return std::move(result.second); + }); +} + +} // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/record_iterator.h b/content/browser/indexed_db/instance/sqlite/record_iterator.h new file mode 100644 index 0000000..f0cf89e --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/record_iterator.h
@@ -0,0 +1,85 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_RECORD_ITERATOR_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_RECORD_ITERATOR_H_ + +#include <memory> +#include <optional> +#include <string> +#include <utility> + +#include "base/functional/callback.h" +#include "content/browser/indexed_db/status.h" + +namespace blink { +class IndexedDBKey; +} // namespace blink + +namespace sql { +class Statement; +} + +namespace content::indexed_db { +class Record; + +namespace sqlite { + +// Iterates over a non-empty range of object store/index records, maintaining +// the position in the range and emitting `Record`s. +class RecordIterator { + public: + using PositionAndRecord = std::pair<std::string, std::unique_ptr<Record>>; + using BindCallback = base::RepeatingCallback<void( + sql::Statement& statement, + const std::string& position, + const blink::IndexedDBKey& target_key, + const blink::IndexedDBKey& target_primary_key, + uint32_t offset)>; + using ReadCallback = base::RepeatingCallback<StatusOr<PositionAndRecord>( + sql::Statement& statement)>; + + RecordIterator(std::unique_ptr<sql::Statement> statement, + BindCallback bind_parameters, + ReadCallback read_row, + std::string initial_position); + + ~RecordIterator(); + + // Iterates from the current position until the target `key` and `primary_key` + // are reached. Use when at least one of these is valid. + StatusOr<std::unique_ptr<Record>> Iterate( + const blink::IndexedDBKey& key, + const blink::IndexedDBKey& primary_key); + + // Iterates `count` times from the current position. + StatusOr<std::unique_ptr<Record>> Iterate(uint32_t count); + + private: + // The parsed and bound statement that embeds the SQL query for this iterator. + // Because the records contained in the range can change between `Iterate()` + // calls, the query needs to be typically re-executed every time. The query + // itself is immutable for the duration of `this`, however, and contains a mix + // of fixed and variable bound parameters. To avoid re-parsing the query and + // rebinding the fixed parameters every time, hold on to the prepared + // statement and rebind only the variable parameters as needed. + std::unique_ptr<sql::Statement> statement_; + + // Callback to bind variable parameters to the statement. + BindCallback bind_parameters_; + + // Callback to read the position and `Record` corresponding to the current row + // of the statement. + ReadCallback read_row_; + + // Opaque value tracking the position in the range. Typically, this is the + // encoded key from the current record. Null when and only when `this` has + // iterated past the end of its range. + std::optional<std::string> current_position_; +}; + +} // namespace sqlite +} // namespace content::indexed_db + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_RECORD_ITERATOR_H_
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc index fcf8bed..428135ba 100644 --- a/content/browser/preloading/prefetch/prefetch_container.cc +++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -1438,6 +1438,15 @@ } } + std::optional<int> response_code = std::nullopt; + if (net_error == net::OK && GetNonRedirectHead() && + GetNonRedirectHead()->headers) { + response_code = GetNonRedirectHead()->headers->response_code(); + } + for (auto& observer : observers_) { + observer.OnPrefetchCompletedOrFailed(completion_status, response_code); + } + if (GetPrefetchResponseCompletedCallbackForTesting()) { GetPrefetchResponseCompletedCallbackForTesting().Run( // IN-TEST GetWeakPtr());
diff --git a/content/browser/preloading/prefetch/prefetch_container.h b/content/browser/preloading/prefetch/prefetch_container.h index 7b2bd87..3b97186 100644 --- a/content/browser/preloading/prefetch/prefetch_container.h +++ b/content/browser/preloading/prefetch/prefetch_container.h
@@ -248,6 +248,10 @@ // successfully received or fetch requests including redirects failed. // Callers can check success/failure by `GetNonRedirectHead()`. virtual void OnDeterminedHead(PrefetchContainer& prefetch_container) = 0; + // Called when load of prefetch completed or failed. + virtual void OnPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) = 0; }; void OnWillBeDestroyed();
diff --git a/content/browser/preloading/prefetch/prefetch_handle_impl.cc b/content/browser/preloading/prefetch/prefetch_handle_impl.cc index fc9ab138..b097c3e 100644 --- a/content/browser/preloading/prefetch/prefetch_handle_impl.cc +++ b/content/browser/preloading/prefetch/prefetch_handle_impl.cc
@@ -11,17 +11,29 @@ #include "content/browser/preloading/prefetch/prefetch_type.h" #include "content/public/browser/preloading_data.h" #include "content/public/browser/web_contents.h" +#include "services/network/public/cpp/url_loader_completion_status.h" #include "services/network/public/mojom/url_response_head.mojom.h" namespace content { -PrefetchContainerObserver::PrefetchContainerObserver( - base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> - on_prefetch_head_received) - : on_prefetch_head_received_(std::move(on_prefetch_head_received)) {} +PrefetchContainerObserver::PrefetchContainerObserver() = default; PrefetchContainerObserver::~PrefetchContainerObserver() = default; +void PrefetchContainerObserver::SetOnPrefetchHeadReceivedCallback( + base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> + on_prefetch_head_received) { + on_prefetch_head_received_ = std::move(on_prefetch_head_received); +} + +void PrefetchContainerObserver::SetOnPrefetchCompletedOrFailedCallback( + base::RepeatingCallback< + void(const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed) { + on_prefetch_completed_or_failed_ = std::move(on_prefetch_completed_or_failed); +} + void PrefetchContainerObserver::OnWillBeDestroyed( PrefetchContainer& prefetch_container) {} @@ -31,15 +43,25 @@ void PrefetchContainerObserver::OnDeterminedHead( PrefetchContainer& prefetch_container) { - // This condition will be used in a callback provided in the future. - // See - // https://chromium-review.googlesource.com/c/chromium/src/+/6615559/comment/3f439d19_8c9cf99a - // - // TODO(crbug.com/400761083): Use the callback. - if (prefetch_container.GetNonRedirectResponseReader() && - prefetch_container.GetNonRedirectResponseReader()->load_state() == - PrefetchResponseReader::LoadState::kResponseReceived) { - on_prefetch_head_received_.Run(*prefetch_container.GetNonRedirectHead()); + if (on_prefetch_head_received_) { + // This condition will be used in a callback provided in the future. + // See + // https://chromium-review.googlesource.com/c/chromium/src/+/6615559/comment/3f439d19_8c9cf99a + // + // TODO(crbug.com/400761083): Use the callback. + if (prefetch_container.GetNonRedirectResponseReader() && + prefetch_container.GetNonRedirectResponseReader()->load_state() == + PrefetchResponseReader::LoadState::kResponseReceived) { + on_prefetch_head_received_.Run(*prefetch_container.GetNonRedirectHead()); + } + } +} + +void PrefetchContainerObserver::OnPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) { + if (on_prefetch_completed_or_failed_) { + on_prefetch_completed_or_failed_.Run(completion_status, response_code); } } @@ -47,9 +69,20 @@ base::WeakPtr<PrefetchService> prefetch_service, base::WeakPtr<PrefetchContainer> prefetch_container) : prefetch_service_(std::move(prefetch_service)), - prefetch_container_(std::move(prefetch_container)) {} + prefetch_container_(std::move(prefetch_container)) { + CHECK(prefetch_service_); + // Note that `prefetch_container_` can be nullptr. + + if (prefetch_container_) { + prefetch_container_->AddObserver(&prefetch_container_observer_); + } +} PrefetchHandleImpl::~PrefetchHandleImpl() { + if (prefetch_container_) { + prefetch_container_->RemoveObserver(&prefetch_container_observer_); + } + // Notify `PrefetchService` that the corresponding `PrefetchContainer` is no // longer needed. `PrefetchService` might release the container and its // corresponding resources by its decision with best-effort. @@ -73,14 +106,20 @@ } } -void PrefetchHandleImpl::SetOnPrefetchHeadReceived( +void PrefetchHandleImpl::SetOnPrefetchHeadReceivedCallback( base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> on_prefetch_head_received) { - CHECK(!prefetch_container_observer_); - - prefetch_container_observer_ = std::make_unique<PrefetchContainerObserver>( + prefetch_container_observer_.SetOnPrefetchHeadReceivedCallback( std::move(on_prefetch_head_received)); - prefetch_container_->AddObserver(prefetch_container_observer_.get()); +} + +void PrefetchHandleImpl::SetOnPrefetchCompletedOrFailedCallback( + base::RepeatingCallback< + void(const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed) { + prefetch_container_observer_.SetOnPrefetchCompletedOrFailedCallback( + std::move(on_prefetch_completed_or_failed)); } bool PrefetchHandleImpl::IsAlive() const {
diff --git a/content/browser/preloading/prefetch/prefetch_handle_impl.h b/content/browser/preloading/prefetch/prefetch_handle_impl.h index 63f0b4e6..ec04aff 100644 --- a/content/browser/preloading/prefetch/prefetch_handle_impl.h +++ b/content/browser/preloading/prefetch/prefetch_handle_impl.h
@@ -21,9 +21,7 @@ // TODO(crbug.com/400761083): Put it into `namespace prefetch_handle`. class PrefetchContainerObserver final : public PrefetchContainer::Observer { public: - explicit PrefetchContainerObserver( - base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> - on_prefetch_head_received); + PrefetchContainerObserver(); ~PrefetchContainerObserver() override; // Not movable nor copyable. @@ -34,15 +32,31 @@ PrefetchContainerObserver& operator=(const PrefetchContainerObserver&) = delete; + void SetOnPrefetchHeadReceivedCallback( + base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> + on_prefetch_head_received); + void SetOnPrefetchCompletedOrFailedCallback( + base::RepeatingCallback< + void(const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed); + // Implements `PrefetchContainer::Observer`. void OnWillBeDestroyed(PrefetchContainer& prefetch_container) override; void OnGotInitialEligibility(PrefetchContainer& prefetch_container, PreloadingEligibility eligibility) override; void OnDeterminedHead(PrefetchContainer& prefetch_container) override; + void OnPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) override; private: base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> on_prefetch_head_received_; + base::RepeatingCallback<void( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed_; }; class PrefetchHandleImpl final : public PrefetchHandle { @@ -52,9 +66,14 @@ ~PrefetchHandleImpl() override; // `PrefetchHandle` implementations - void SetOnPrefetchHeadReceived( + void SetOnPrefetchHeadReceivedCallback( base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> on_prefetch_head_received) override; + void SetOnPrefetchCompletedOrFailedCallback( + base::RepeatingCallback< + void(const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed) override; bool IsAlive() const override; // TODO(crbug.com/390329781): The following methods are tentative interface @@ -70,7 +89,7 @@ private: base::WeakPtr<PrefetchService> prefetch_service_; base::WeakPtr<PrefetchContainer> prefetch_container_; - std::unique_ptr<PrefetchContainerObserver> prefetch_container_observer_; + PrefetchContainerObserver prefetch_container_observer_; std::optional<PrefetchStatus> prefetch_status_on_release_started_prefetch_; };
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.cc b/content/browser/preloading/prefetch/prefetch_match_resolver.cc index 97eec695..5475f69 100644 --- a/content/browser/preloading/prefetch/prefetch_match_resolver.cc +++ b/content/browser/preloading/prefetch/prefetch_match_resolver.cc
@@ -19,6 +19,7 @@ #include "content/browser/preloading/prerender/prerender_host_registry.h" #include "content/browser/renderer_host/render_frame_host_delegate.h" #include "content/public/browser/navigation_handle_user_data.h" +#include "services/network/public/cpp/url_loader_completion_status.h" namespace content { @@ -338,6 +339,10 @@ UnblockForMatch(prefetch_container.key()); } +void PrefetchMatchResolver::OnPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) {} + void PrefetchMatchResolver::OnTimeout(PrefetchContainer::Key prefetch_key) { // `timeout_timer` is alive, which implies `candidate` is alive. CHECK(candidates_.contains(prefetch_key));
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.h b/content/browser/preloading/prefetch/prefetch_match_resolver.h index 07b578e2..4ac11bae 100644 --- a/content/browser/preloading/prefetch/prefetch_match_resolver.h +++ b/content/browser/preloading/prefetch/prefetch_match_resolver.h
@@ -47,6 +47,9 @@ void OnGotInitialEligibility(PrefetchContainer& prefetch_container, PreloadingEligibility eligibility) override; void OnDeterminedHead(PrefetchContainer& prefetch_container) override; + void OnPrefetchCompletedOrFailed( + const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code) override; // Finds prefetch that matches to a navigation and is servable. //
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc index 23b19cc..a5bc6f6 100644 --- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc +++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -44,12 +44,12 @@ #if BUILDFLAG(ENABLE_SCREEN_CAPTURE) #include "content/browser/media/capture/desktop_capture_device_uma_types.h" #include "content/browser/media/capture/web_contents_video_capture_device.h" -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) +#if !BUILDFLAG(IS_IOS) #if defined(USE_AURA) #include "content/browser/media/capture/aura_window_video_capture_device.h" #endif // defined(USE_AURA) #include "content/browser/media/capture/desktop_capture_device.h" -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) +#endif // !BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_MAC) #include "content/browser/media/capture/desktop_capture_device_mac.h" #include "content/browser/media/capture/screen_capture_kit_device_utils_mac.h" @@ -202,12 +202,11 @@ if ((device_out = CreateDesktopCaptureDeviceMac(desktop_id))) { return kDesktopCaptureDeviceMac; } -#endif // BUILDFLAG(IS_MAC) -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) +#elif !BUILDFLAG(IS_IOS) if ((device_out = DesktopCaptureDevice::Create(desktop_id))) { return kLegacyDesktopCaptureDevice; } -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) +#endif // !BUILDFLAG(IS_IOS) return kNoImplementation; } #endif // BUILDFLAG(ENABLE_SCREEN_CAPTURE)
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 0287e30..32f3bf2 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -314,6 +314,9 @@ quota_manager_proxy, special_storage_policy, std::move(non_network_pending_loader_factory_bundle_for_update_check), core_observer_list_.get(), core_sync_observer_list_.get(), this); + + GetContentClient()->browser()->PrewarmServiceWorkerRegistrationForDSE( + browser_context, *this); } void ServiceWorkerContextWrapper::Shutdown() {
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc index ef831a8..45e818b6 100644 --- a/content/browser/webauth/authenticator_common_impl.cc +++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -36,6 +36,7 @@ #include "base/metrics/user_metrics_action.h" #include "base/notreached.h" #include "base/strings/string_view_util.h" +#include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "build/build_config.h" @@ -972,10 +973,8 @@ base::BindOnce(&AuthenticatorCommonImpl::OnCancelFromUI, weak_factory_.GetWeakPtr()) /* cancel_callback */, base::BindOnce( - &AuthenticatorCommonImpl::CancelWithStatus, - weak_factory_.GetWeakPtr(), - blink::mojom::AuthenticatorStatus:: - IMMEDIATE_NOT_FOUND) /* immediate_not_found_callback */, + &AuthenticatorCommonImpl::CancelRequestForImmediateMediation, + weak_factory_.GetWeakPtr()) /* immediate_not_found_callback */, base::BindRepeating( &AuthenticatorCommonImpl::StartGetAssertionRequest, weak_factory_.GetWeakPtr(), @@ -2559,7 +2558,7 @@ void AuthenticatorCommonImpl::OnImmediateTimeout() { base::UmaHistogramBoolean(kImmediateTimeoutWhileWaitingForUi, true); - CancelWithStatus(blink::mojom::AuthenticatorStatus::IMMEDIATE_NOT_FOUND); + CancelRequestForImmediateMediation(); } void AuthenticatorCommonImpl::CancelImmediateTimeout() { @@ -2571,6 +2570,24 @@ req_state_->immediate_timer->Stop(); } +void AuthenticatorCommonImpl::CancelRequestForImmediateMediation() { + // Post a task to defer the cancellation, otherwise a reentrancy may occur. + // For example all authenticators may report no credentials; but the + // discoveries may still be active. See crbug.com/424491613 for an example. + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<AuthenticatorCommonImpl> auth_ptr) { + if (!auth_ptr) { + return; + } + + auth_ptr->CancelWithStatus( + blink::mojom::AuthenticatorStatus::IMMEDIATE_NOT_FOUND); + }, + weak_factory_.GetWeakPtr())); +} + void AuthenticatorCommonImpl::CancelWithStatus( blink::mojom::AuthenticatorStatus status) { // Callers may attempt to cancel whether there is a request or not.
diff --git a/content/browser/webauth/authenticator_common_impl.h b/content/browser/webauth/authenticator_common_impl.h index 5528d7e..b5e848d 100644 --- a/content/browser/webauth/authenticator_common_impl.h +++ b/content/browser/webauth/authenticator_common_impl.h
@@ -298,6 +298,10 @@ // Cancels the immediate mediation timer when the UI is shown. void CancelImmediateTimeout(); + // Cancels the current request if it's an immediate mediation and no immediate + // mediation UI was shown. + void CancelRequestForImmediateMediation(); + // Cancels the currently pending request (if any) with the supplied status. void CancelWithStatus(blink::mojom::AuthenticatorStatus status);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/InputTransferHandler.java b/content/public/android/java/src/org/chromium/content_public/browser/InputTransferHandler.java index 41ac46e..a3f22d55 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/InputTransferHandler.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/InputTransferHandler.java
@@ -64,11 +64,12 @@ } // Browser InputTransfeToken might have changed. On Viz side we aren't destroying - // InputReceiver (due to platform bug: b/385124056) which was created with the initial - // Browser token. Attempt at transferring touch sequence using new Browser token and old Viz - // token would fail, so just early out here instead of making a binder call later. + // InputReceiver (due to platform bug: b/385124056 on Android V) which was created with the + // initial Browser token. Attempt at transferring touch sequence using new Browser token and + // old Viz token would fail, so just early out here instead of making a binder call later. assert sInitialBrowserToken != null; - if (sInitialBrowserToken != mBrowserToken.hashCode()) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.BAKLAVA + && sInitialBrowserToken != mBrowserToken.hashCode()) { return TransferInputToVizResult.BROWSER_TOKEN_CHANGED; }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index fe00e15e..ae53bdb6 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -743,6 +743,10 @@ return true; } +void ContentBrowserClient::PrewarmServiceWorkerRegistrationForDSE( + BrowserContext* browser_context, + ServiceWorkerContext& service_worker_context) {} + bool ContentBrowserClient::CanSendSCTAuditingReport( BrowserContext* browser_context) { return false;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index f9db6c5..668c600 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -262,6 +262,7 @@ class RenderProcessHost; class ResponsivenessCalculatorDelegate; class SerialDelegate; +class ServiceWorkerContext; class SiteInstance; class SpeculationHostDelegate; class SpeechRecognitionManagerDelegate; @@ -1285,6 +1286,12 @@ content::BrowserContext* browser_context, content::WebContents* web_contents); + // Prewarms the ServiceWorker registration of the DefaultSearchEngine (DSE) by + // prefetching it from the database. + virtual void PrewarmServiceWorkerRegistrationForDSE( + BrowserContext* browser_context, + ServiceWorkerContext& service_worker_context); + // Allows the embedder to implement policy for whether an SCT auditing report // should be sent. virtual bool CanSendSCTAuditingReport(BrowserContext* browser_context);
diff --git a/content/public/browser/desktop_capture.cc b/content/public/browser/desktop_capture.cc index d208b6e86..6496f78f 100644 --- a/content/public/browser/desktop_capture.cc +++ b/content/public/browser/desktop_capture.cc
@@ -15,6 +15,10 @@ #include "content/browser/media/capture/desktop_capturer_ash.h" #endif +#if BUILDFLAG(IS_ANDROID) +#include "content/browser/media/capture/desktop_capturer_android.h" +#endif + #if defined(WEBRTC_USE_PIPEWIRE) #include "base/environment.h" #include "base/nix/xdg_util.h" @@ -91,7 +95,12 @@ return std::make_unique<DesktopCapturerAsh>(); } #endif // BUILDFLAG(IS_CHROMEOS) + +#if BUILDFLAG(IS_ANDROID) + return std::make_unique<DesktopCapturerAndroid>(options); +#else return webrtc::DesktopCapturer::CreateScreenCapturer(options); +#endif // BUILDFLAG(IS_ANDROID) } std::unique_ptr<webrtc::DesktopCapturer> CreateWindowCapturer( @@ -100,7 +109,11 @@ options.set_allow_wgc_capturer_fallback(true); #endif // defined(RTC_ENABLE_WIN_WGC) +#if BUILDFLAG(IS_ANDROID) + return std::make_unique<DesktopCapturerAndroid>(options); +#else return webrtc::DesktopCapturer::CreateWindowCapturer(options); +#endif // BUILDFLAG(IS_ANDROID) } bool CanUsePipeWire() {
diff --git a/content/public/browser/prefetch_handle.h b/content/public/browser/prefetch_handle.h index 720f1d2..4af3f513 100644 --- a/content/public/browser/prefetch_handle.h +++ b/content/public/browser/prefetch_handle.h
@@ -5,9 +5,15 @@ #ifndef CONTENT_PUBLIC_BROWSER_PREFETCH_HANDLE_H_ #define CONTENT_PUBLIC_BROWSER_PREFETCH_HANDLE_H_ +#include <optional> + #include "base/functional/callback_forward.h" #include "services/network/public/mojom/url_response_head.mojom-forward.h" +namespace network { +struct URLLoaderCompletionStatus; +} // namespace network + namespace content { // The interface to control prefetch resources associated with this. @@ -25,11 +31,15 @@ PrefetchHandle& operator=(PrefetchHandle&& other) = default; // Sets a callback called when non-redirect header is successfully received. - // - // Panics when called multiple times. - virtual void SetOnPrefetchHeadReceived( + virtual void SetOnPrefetchHeadReceivedCallback( base::RepeatingCallback<void(const network::mojom::URLResponseHead&)> on_prefetch_head_received) = 0; + // Sets a callback called when loading of prefetch failed. + virtual void SetOnPrefetchCompletedOrFailedCallback( + base::RepeatingCallback< + void(const network::URLLoaderCompletionStatus& completion_status, + const std::optional<int>& response_code)> + on_prefetch_completed_or_failed) = 0; // Returns true if the underlying `PrefetchContainer` is alive. virtual bool IsAlive() const = 0;
diff --git a/gin/OWNERS b/gin/OWNERS index 0e039294..b053b89 100644 --- a/gin/OWNERS +++ b/gin/OWNERS
@@ -7,8 +7,6 @@ mlippautz@chromium.org # For adding JS/Wasm feature kill-switches. -per-file gin_features.*=syg@chromium.org -per-file v8_initializer.cc=syg@chromium.org # For ThreadIsolation related changes. per-file thread_isolation.*=sroettger@google.com
diff --git a/gpu/command_buffer/client/client_shared_image.cc b/gpu/command_buffer/client/client_shared_image.cc index f3509f1..7df28daa 100644 --- a/gpu/command_buffer/client/client_shared_image.cc +++ b/gpu/command_buffer/client/client_shared_image.cc
@@ -552,12 +552,6 @@ InterfaceBase* raster_interface, const SyncToken& sync_token, bool readonly) { - SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel", debug_label_); - SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage", metadata_.usage); - DUMP_WILL_BE_CHECK( - metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_READ) || - metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_WRITE) || - metadata_.usage.Has(SHARED_IMAGE_USAGE_RASTER_COPY_SOURCE)); return base::WrapUnique( new RasterScopedAccess(raster_interface, this, sync_token, readonly)); } @@ -798,17 +792,6 @@ CHECK(raster_interface_); shared_image_->BeginAccess(readonly); raster_interface_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); - SCOPED_CRASH_KEY_STRING32("ClientSharedImage", "DebugLabel", - shared_image_->debug_label()); - SCOPED_CRASH_KEY_NUMBER("ClientSharedImage", "Usage", shared_image_->usage()); - if (readonly) { - DUMP_WILL_BE_CHECK( - shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_READ) || - shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_COPY_SOURCE)); - } else { - DUMP_WILL_BE_CHECK( - shared_image_->usage().Has(SHARED_IMAGE_USAGE_RASTER_WRITE)); - } } // static
diff --git a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc index e6f3c9a..c5dae54 100644 --- a/gpu/command_buffer/service/shared_image/android_video_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/android_video_image_backing.cc
@@ -42,11 +42,11 @@ alpha_type, // This SI will be used to back a VideoFrame. As such, it // will potentially be sent to the display compositor and read by the - // GL interface for WebGL, and read by raster interface. + // GL interface for WebGL. // TODO: crbug.com/354856448 - add a parameter to the constructor that // allows to specify whether SCANOUT is needed. {SHARED_IMAGE_USAGE_DISPLAY_READ, SHARED_IMAGE_USAGE_GLES2_READ, - SHARED_IMAGE_USAGE_RASTER_READ, SHARED_IMAGE_USAGE_SCANOUT}, + SHARED_IMAGE_USAGE_SCANOUT}, std::move(debug_label), viz::SinglePlaneFormat::kRGBA_8888.EstimatedSizeInBytes(size), is_thread_safe,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory.cc b/gpu/ipc/service/gpu_memory_buffer_factory.cc index 59b2817..b01c0d0d 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory.cc
@@ -109,19 +109,4 @@ return handle; } -void GpuMemoryBufferFactory::CreateGpuMemoryBufferAsync( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - SurfaceHandle surface_handle, - CreateGpuMemoryBufferAsyncCallback callback) { - // By default, we assume it's ok to allocate GMBs synchronously on the IO - // thread. However, subclasses can override this assumption. - std::move(callback).Run( - CreateGpuMemoryBuffer(id, size, /*framebuffer_size=*/size, format, usage, - client_id, surface_handle)); -} - } // namespace gpu
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory.h b/gpu/ipc/service/gpu_memory_buffer_factory.h index 6bfff24..8ad6128 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory.h
@@ -71,20 +71,6 @@ int client_id, SurfaceHandle surface_handle) = 0; - // Same as above, but returns the result asynchrounously. Safe to use on the - // IO thread. |callback| will be called on the same thread that calls this - // method, and it might be called on the same call stack. - using CreateGpuMemoryBufferAsyncCallback = - base::OnceCallback<void(gfx::GpuMemoryBufferHandle)>; - virtual void CreateGpuMemoryBufferAsync( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - SurfaceHandle surface_handle, - CreateGpuMemoryBufferAsyncCallback callback); - // Destroys GPU memory buffer identified by |id|. It can be called on any // thread. virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc index 9bc8abf..2737e335 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
@@ -50,24 +50,6 @@ client_id, std::move(pixmap)); } -void GpuMemoryBufferFactoryNativePixmap::CreateGpuMemoryBufferAsync( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - SurfaceHandle surface_handle, - CreateGpuMemoryBufferAsyncCallback callback) { - ui::OzonePlatform::GetInstance() - ->GetSurfaceFactoryOzone() - ->CreateNativePixmapAsync( - surface_handle, GetVulkanDeviceQueue(), size, format, usage, - base::BindOnce( - &GpuMemoryBufferFactoryNativePixmap::OnNativePixmapCreated, id, - size, format, usage, client_id, std::move(callback), - weak_factory_.GetWeakPtr())); -} - void GpuMemoryBufferFactoryNativePixmap::DestroyGpuMemoryBuffer( gfx::GpuMemoryBufferId id, int client_id) { @@ -92,24 +74,6 @@ return nullptr; } -// static -void GpuMemoryBufferFactoryNativePixmap::OnNativePixmapCreated( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - CreateGpuMemoryBufferAsyncCallback callback, - base::WeakPtr<GpuMemoryBufferFactoryNativePixmap> weak_ptr, - scoped_refptr<gfx::NativePixmap> pixmap) { - if (weak_ptr) { - std::move(callback).Run(weak_ptr->CreateGpuMemoryBufferFromNativePixmap( - id, size, format, usage, client_id, pixmap)); - } else { - std::move(callback).Run(gfx::GpuMemoryBufferHandle()); - } -} - gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryNativePixmap::CreateGpuMemoryBufferFromNativePixmap( gfx::GpuMemoryBufferId id,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h index 9e9d719..bcc77d5b 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h
@@ -43,14 +43,6 @@ gfx::BufferUsage usage, int client_id, SurfaceHandle surface_handle) override; - void CreateGpuMemoryBufferAsync( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - SurfaceHandle surface_handle, - CreateGpuMemoryBufferAsyncCallback callback) override; void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id) override; bool FillSharedMemoryRegionWithBufferContents( @@ -64,16 +56,6 @@ scoped_refptr<gfx::NativePixmap>, NativePixmapMapKeyHash>; - static void OnNativePixmapCreated( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - int client_id, - CreateGpuMemoryBufferAsyncCallback callback, - base::WeakPtr<GpuMemoryBufferFactoryNativePixmap> weak_ptr, - scoped_refptr<gfx::NativePixmap> pixmap); - gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromNativePixmap( gfx::GpuMemoryBufferId id, const gfx::Size& size,
diff --git a/infra/config/generated/builders/ci/Win x64 Builder/targets/chromium.win.json b/infra/config/generated/builders/ci/Win x64 Builder/targets/chromium.win.json index a4ad240..54a6feb 100644 --- a/infra/config/generated/builders/ci/Win x64 Builder/targets/chromium.win.json +++ b/infra/config/generated/builders/ci/Win x64 Builder/targets/chromium.win.json
@@ -446,7 +446,7 @@ "os": "Windows-10-19045" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 11 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/generated/builders/ci/Win10 Tests x64/targets/chromium.win.json b/infra/config/generated/builders/ci/Win10 Tests x64/targets/chromium.win.json index 58626b42..6d193b8 100644 --- a/infra/config/generated/builders/ci/Win10 Tests x64/targets/chromium.win.json +++ b/infra/config/generated/builders/ci/Win10 Tests x64/targets/chromium.win.json
@@ -422,7 +422,7 @@ "os": "Windows-10-19045" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 11 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json index 1a8d8eb..f2a14e5 100644 --- a/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json
@@ -944,7 +944,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "shards": 5 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json index 722b6b0..7c48fb6f 100644 --- a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json
@@ -51,7 +51,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 + "shards": 22 }, "test": "android_browsertests", "test_id_prefix": "ninja://chrome/test:android_browsertests/"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json index 1f23b66b..12b32eb6 100644 --- a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json
@@ -46,7 +46,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 + "shards": 22 }, "test": "android_browsertests", "test_id_prefix": "ninja://chrome/test:android_browsertests/"
diff --git a/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json b/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json index 087275a..8e2d143 100644 --- a/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json +++ b/infra/config/generated/builders/ci/linux-chromeos-rel/targets/chromium.chromiumos.json
@@ -296,7 +296,7 @@ "os": "Ubuntu-22.04" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 187 + "shards": 140 }, "test": "browser_tests", "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json index 1a8d8eb..f2a14e5 100644 --- a/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json
@@ -944,7 +944,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "shards": 5 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json index 722b6b0..7c48fb6f 100644 --- a/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json
@@ -51,7 +51,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 + "shards": 22 }, "test": "android_browsertests", "test_id_prefix": "ninja://chrome/test:android_browsertests/"
diff --git a/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json index 722b6b0..7c48fb6f 100644 --- a/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json
@@ -51,7 +51,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 + "shards": 22 }, "test": "android_browsertests", "test_id_prefix": "ninja://chrome/test:android_browsertests/"
diff --git a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json index d6bf78a..529d9ceb 100644 --- a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json
@@ -1001,7 +1001,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "shards": 5 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json b/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json index 087275a..8e2d143 100644 --- a/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json +++ b/infra/config/generated/builders/try/linux-chromeos-rel/targets/chromium.chromiumos.json
@@ -296,7 +296,7 @@ "os": "Ubuntu-22.04" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 187 + "shards": 140 }, "test": "browser_tests", "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/infra/config/generated/builders/try/win-rel/targets/chromium.win.json b/infra/config/generated/builders/try/win-rel/targets/chromium.win.json index 50dd036..0944606 100644 --- a/infra/config/generated/builders/try/win-rel/targets/chromium.win.json +++ b/infra/config/generated/builders/try/win-rel/targets/chromium.win.json
@@ -446,7 +446,7 @@ "os": "Windows-10-19045" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 11 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/infra/config/targets/autoshard_exceptions.json b/infra/config/targets/autoshard_exceptions.json index da8ff4a..14280c6 100644 --- a/infra/config/targets/autoshard_exceptions.json +++ b/infra/config/targets/autoshard_exceptions.json
@@ -16,7 +16,7 @@ "try_builder": "android-x64-rel" }, "components_browsertests": { - "shards": 3, + "shards": 5, "try_builder": "android-x64-rel" } }, @@ -46,7 +46,7 @@ "chromium.android.desktop": { "android-desktop-x64-rel-15-tests": { "android_browsertests": { - "shards": 25, + "shards": 22, "try_builder": "android-desktop-x64-rel" }, "unit_tests": { @@ -72,7 +72,7 @@ "try_builder": "linux-chromeos-rel" }, "browser_tests": { - "shards": 187, + "shards": 140, "try_builder": "linux-chromeos-rel" }, "components_unittests": { @@ -222,7 +222,7 @@ "chromium.win": { "Win10 Tests x64": { "content_browsertests": { - "shards": 10, + "shards": 11, "try_builder": "win-rel" }, "headless_shell_wpt_tests": {
diff --git a/ios/chrome/app/strings/resources/ios_strings_eu.xtb b/ios/chrome/app/strings/resources/ios_strings_eu.xtb index 50e56be8..5e8a4f7 100644 --- a/ios/chrome/app/strings/resources/ios_strings_eu.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_eu.xtb
@@ -1444,6 +1444,7 @@ <translation id="6831043979455480757">Itzuli</translation> <translation id="6842136130964845393">Gordetako pasahitzak edonoiz atzitu ahal izango dituzula ziurtatzeko, egiaztatu zeu zarela</translation> <translation id="6851516051005285358">Eskatu ordenagailuetarako webgunea</translation> +<translation id="6857446173140146664">Ezabatu atzeko planoa</translation> <translation id="6858718102216837409">Gehitu hizkuntza bat…</translation> <translation id="6858855187367714033">Eskaneatuta</translation> <translation id="6859944681507688231">QR kodea edo kreditu-txartela eskaneatzeko, gaitu kamera ezarpenetan.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_lo.xtb b/ios/chrome/app/strings/resources/ios_strings_lo.xtb index ea3858a..4fa8820 100644 --- a/ios/chrome/app/strings/resources/ios_strings_lo.xtb +++ b/ios/chrome/app/strings/resources/ios_strings_lo.xtb
@@ -545,6 +545,7 @@ <translation id="3227137524299004712">ໄມໂຄຣໂຟນ</translation> <translation id="3235063766008841141">ປ້ອນໃນເວັບໄຊຫຼອກລວງແລະ ພົບເຫັນໃນການລະເມີດຂໍ້ມູນ</translation> <translation id="3235242129752692527">ແກ້ໄຂລາຍລະອຽດນັດໝາຍແລ້ວແຕະໃສ່ “ບັນທຶກ.“</translation> +<translation id="323863549127671026">ແຖບ ແລະ ກຸ່ມແຖບທີ່ເປີດຢູ່ໃນປັດຈຸບັນ</translation> <translation id="3240426699337459095">ອັດສຳເນົາລິ້ງແລ້ວ</translation> <translation id="3244271242291266297">ດດ</translation> <translation id="3245429137663807393">ຫາກທ່ານແບ່ງປັນລາຍງານການນຳໃຊ້ Chrome ນຳ, ລາຍງານເຫຼົ່ານັ້ນຈະຮວມເອົາ URL ທີ່ທ່ານເຂົ້າໄວ້ພ້ອມ</translation>
diff --git a/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_view.mm b/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_view.mm index 3be2155c..c9b34e8 100644 --- a/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_view.mm +++ b/ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_view.mm
@@ -49,20 +49,24 @@ - (instancetype)init { self = [super init]; if (self) { - // Increase blur intensity by layering some blur views to make - // content behind really not recognizeable. - for (int i = 0; i < 3; i++) { - UIBlurEffect* blurEffect = - [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; - UIVisualEffectView* blurView = - [[UIVisualEffectView alloc] initWithEffect:blurEffect]; - [self addSubview:blurView]; - blurView.translatesAutoresizingMaskIntoConstraints = NO; - AddSameConstraints(self, blurView); + if (!IsIOSSoftLockEnabled()) { + // Increase blur intensity by layering some blur views to make + // content behind really not recognizeable. + for (int i = 0; i < 3; i++) { + UIBlurEffect* blurEffect = + [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + UIVisualEffectView* blurView = + [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + [self addSubview:blurView]; + blurView.translatesAutoresizingMaskIntoConstraints = NO; + AddSameConstraints(self, blurView); + } } - UIBlurEffect* blurEffect = - [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; + UIBlurEffect* blurEffect = [UIBlurEffect + effectWithStyle:IsIOSSoftLockEnabled() + ? UIBlurEffectStyleSystemThickMaterialDark + : UIBlurEffectStyleDark]; UIVisualEffectView* blurBackgroundView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; [self addSubview:blurBackgroundView]; @@ -314,13 +318,15 @@ [button setTitle:l10n_util::GetNSString( IDS_IOS_INCOGNITO_REAUTH_CLOSE_INCOGNITO_TABS) forState:UIControlStateNormal]; + button.titleLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; } else { [button setTitle:l10n_util::GetNSString( IDS_IOS_INCOGNITO_REAUTH_GO_TO_NORMAL_TABS) forState:UIControlStateNormal]; + button.titleLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleTitle2]; } - button.titleLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleTitle2]; button.titleLabel.adjustsFontSizeToFitWidth = YES; button.titleLabel.adjustsFontForContentSizeCategory = YES; button.pointerInteractionEnabled = YES;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_new_tab_button.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_new_tab_button.mm index a1e0fd17..669ea0f 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_new_tab_button.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_new_tab_button.mm
@@ -76,6 +76,11 @@ return self; } +- (void)setEnabled:(BOOL)enabled { + [super setEnabled:enabled]; + [self setSymbolPage:self.page]; +} + #pragma mark - Public - (void)setPage:(TabGridPage)page { @@ -90,8 +95,10 @@ case TabGridPageIncognitoTabs: self.accessibilityLabel = l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_INCOGNITO_TAB); - _imageContainer.image = SymbolWithPalette( - _symbol, @[ UIColor.blackColor, UIColor.whiteColor ]); + _imageContainer.image = SymbolWithPalette(_symbol, @[ + UIColor.blackColor, + self.enabled ? UIColor.whiteColor : UIColor.grayColor + ]); break; case TabGridPageRegularTabs: self.accessibilityLabel =
diff --git a/ios_internal b/ios_internal index 59a93a5..3b581c6 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 59a93a5717e2d1a9e523d986e012bde44aa5faa2 +Subproject commit 3b581c6c47e23717766c2c1922d6c7111db6cb4c
diff --git a/media/gpu/test/BUILD.gn b/media/gpu/test/BUILD.gn index 9d1b2ed..4c8e745b 100644 --- a/media/gpu/test/BUILD.gn +++ b/media/gpu/test/BUILD.gn
@@ -322,6 +322,7 @@ "//base", "//build/config/linux/libdrm", "//gpu/command_buffer/client", + "//gpu/ipc/common:surface_handle_type", "//third_party/minigbm", "//ui/gfx:memory_buffer", "//ui/gfx/geometry",
diff --git a/media/gpu/test/local_gpu_memory_buffer_manager.h b/media/gpu/test/local_gpu_memory_buffer_manager.h index 10a0900..18018b50 100644 --- a/media/gpu/test/local_gpu_memory_buffer_manager.h +++ b/media/gpu/test/local_gpu_memory_buffer_manager.h
@@ -8,9 +8,11 @@ #include <memory> #include "base/memory/raw_ptr.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" +#include "base/synchronization/waitable_event.h" +#include "gpu/ipc/common/surface_handle.h" #include "media/gpu/media_gpu_export.h" #include "ui/gfx/buffer_types.h" +#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/linux/scoped_gbm_device.h" namespace gfx { @@ -25,8 +27,7 @@ // gfx::GpuMemoryBufferManager which interacts with the DRM render node device // directly. The LocalGpuMemoryBufferManager is only for testing purposes and // should not be used in production. -class MEDIA_GPU_EXPORT LocalGpuMemoryBufferManager - : public gpu::GpuMemoryBufferManager { +class MEDIA_GPU_EXPORT LocalGpuMemoryBufferManager { public: LocalGpuMemoryBufferManager(); @@ -34,15 +35,14 @@ LocalGpuMemoryBufferManager& operator=(const LocalGpuMemoryBufferManager&) = delete; - ~LocalGpuMemoryBufferManager() override; + ~LocalGpuMemoryBufferManager(); - // gpu::GpuMemoryBufferManager implementation std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, gpu::SurfaceHandle surface_handle, - base::WaitableEvent* shutdown_event) override; + base::WaitableEvent* shutdown_event); // Imports a DmaBuf as a GpuMemoryBuffer to be able to map it. The // GBM_BO_USE_SW_READ_OFTEN usage is specified so that the user of the
diff --git a/media/renderers/paint_canvas_video_renderer_unittest.cc b/media/renderers/paint_canvas_video_renderer_unittest.cc index f0f7029..cbeff707 100644 --- a/media/renderers/paint_canvas_video_renderer_unittest.cc +++ b/media/renderers/paint_canvas_video_renderer_unittest.cc
@@ -952,11 +952,8 @@ cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight)); gfx::Size size(kWidth, kHeight); - // We try copying the contents of the source VideoFrame *into* the - // cached SI over the raster interface. scoped_refptr<gpu::ClientSharedImage> shared_image = - gpu::ClientSharedImage::CreateForTesting( - gpu::SHARED_IMAGE_USAGE_RASTER_READ); + gpu::ClientSharedImage::CreateForTesting(); auto video_frame = VideoFrame::WrapSharedImage( PIXEL_FORMAT_NV12, shared_image, gpu::SyncToken(), base::BindOnce(MailboxHoldersReleased), size, gfx::Rect(size), size,
diff --git a/media/renderers/video_resource_updater_unittest.cc b/media/renderers/video_resource_updater_unittest.cc index 0ec5f8b..ea4aea23 100644 --- a/media/renderers/video_resource_updater_unittest.cc +++ b/media/renderers/video_resource_updater_unittest.cc
@@ -248,20 +248,12 @@ scoped_refptr<VideoFrame> CreateTestHardwareVideoFrame( viz::SharedImageFormat si_format, VideoPixelFormat format, - unsigned target, - bool needs_raster_access) { + unsigned target) { const int kDimension = 10; gfx::Size size(kDimension, kDimension); - gpu::SharedImageMetadata metadata; - metadata.format = si_format; - metadata.color_space = gfx::ColorSpace::CreateSRGB(); - metadata.surface_origin = kTopLeft_GrSurfaceOrigin; - metadata.alpha_type = kOpaque_SkAlphaType; - metadata.usage = needs_raster_access ? gpu::SHARED_IMAGE_USAGE_RASTER_READ - : gpu::SharedImageUsageSet(); scoped_refptr<gpu::ClientSharedImage> shared_image = - gpu::ClientSharedImage::CreateForTesting(metadata, target); + gpu::ClientSharedImage::CreateForTesting(si_format, target); scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapSharedImage( format, shared_image, kMailboxSyncToken, base::BindOnce(&VideoResourceUpdaterTest::SetReleaseSyncToken, @@ -276,15 +268,14 @@ scoped_refptr<VideoFrame> CreateTestRGBAHardwareVideoFrame() { return CreateTestHardwareVideoFrame(viz::SinglePlaneFormat::kRGBA_8888, - PIXEL_FORMAT_ARGB, GL_TEXTURE_2D, - /*needs_raster_access=*/false); + PIXEL_FORMAT_ARGB, GL_TEXTURE_2D); } scoped_refptr<VideoFrame> CreateTestStreamTextureHardwareVideoFrame( bool needs_copy) { scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( viz::SinglePlaneFormat::kRGBA_8888, PIXEL_FORMAT_ARGB, - GL_TEXTURE_EXTERNAL_OES, /*needs_raster_access=*/needs_copy); + GL_TEXTURE_EXTERNAL_OES); video_frame->metadata().copy_required = needs_copy; return video_frame; } @@ -293,7 +284,7 @@ scoped_refptr<VideoFrame> CreateTestDCompSurfaceVideoFrame() { scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( viz::SinglePlaneFormat::kRGBA_8888, PIXEL_FORMAT_ARGB, - GL_TEXTURE_EXTERNAL_OES, /*needs_raster_access=*/false); + GL_TEXTURE_EXTERNAL_OES); video_frame->metadata().dcomp_surface = true; return video_frame; } @@ -728,9 +719,9 @@ TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SharedImageFormat) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); - scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( - viz::MultiPlaneFormat::kI420, PIXEL_FORMAT_I420, GL_TEXTURE_RECTANGLE_ARB, - /*needs_raster_access=*/false); + scoped_refptr<VideoFrame> video_frame = + CreateTestHardwareVideoFrame(viz::MultiPlaneFormat::kI420, + PIXEL_FORMAT_I420, GL_TEXTURE_RECTANGLE_ARB); VideoFrameExternalResource resource = updater->CreateExternalResourceFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::RGB, resource.type); @@ -739,9 +730,9 @@ EXPECT_EQ(resource.resource.synchronization_type, viz::TransferableResource::SynchronizationType::kSyncToken); - video_frame = CreateTestHardwareVideoFrame( - viz::MultiPlaneFormat::kI420, PIXEL_FORMAT_I420, GL_TEXTURE_RECTANGLE_ARB, - /*needs_raster_access=*/false); + video_frame = + CreateTestHardwareVideoFrame(viz::MultiPlaneFormat::kI420, + PIXEL_FORMAT_I420, GL_TEXTURE_RECTANGLE_ARB); video_frame->metadata().read_lock_fences_enabled = true; resource = updater->CreateExternalResourceFromVideoFrame(video_frame); @@ -924,8 +915,7 @@ std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); EXPECT_EQ(0u, GetSharedImageCount()); scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( - viz::MultiPlaneFormat::kNV12, PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES, - /*needs_raster_access=*/false); + viz::MultiPlaneFormat::kNV12, PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES); VideoFrameExternalResource resource = updater->CreateExternalResourceFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::RGB, resource.type); @@ -939,9 +929,9 @@ CreateForHardwarePlanes_DualNV12_SharedImageFormat) { std::unique_ptr<VideoResourceUpdater> updater = CreateUpdaterForHardware(); EXPECT_EQ(0u, GetSharedImageCount()); - scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( - viz::MultiPlaneFormat::kNV12, PIXEL_FORMAT_NV12, GL_TEXTURE_RECTANGLE_ARB, - /*needs_raster_access=*/false); + scoped_refptr<VideoFrame> video_frame = + CreateTestHardwareVideoFrame(viz::MultiPlaneFormat::kNV12, + PIXEL_FORMAT_NV12, GL_TEXTURE_RECTANGLE_ARB); VideoFrameExternalResource resource = updater->CreateExternalResourceFromVideoFrame(video_frame); // Setting to kSharedImageFormat, resource type should bo RGB. @@ -952,8 +942,7 @@ EXPECT_EQ(0u, GetSharedImageCount()); video_frame = CreateTestHardwareVideoFrame( - viz::MultiPlaneFormat::kNV12, PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES, - /*needs_raster_access=*/false); + viz::MultiPlaneFormat::kNV12, PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES); resource = updater->CreateExternalResourceFromVideoFrame(video_frame); EXPECT_EQ(VideoFrameResourceType::RGB, resource.type); @@ -976,7 +965,7 @@ EXPECT_EQ(0u, GetSharedImageCount()); scoped_refptr<VideoFrame> video_frame = CreateTestHardwareVideoFrame( viz::MultiPlaneFormat::kP010, PIXEL_FORMAT_P010LE, - GL_TEXTURE_EXTERNAL_OES, /*needs_raster_access=*/false); + GL_TEXTURE_EXTERNAL_OES); video_frame->set_color_space(kHDR10ColorSpace); video_frame->set_hdr_metadata(hdr_metadata);
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h index 6b417ef..bb6e56a 100644 --- a/net/cookies/canonical_cookie.h +++ b/net/cookies/canonical_cookie.h
@@ -5,6 +5,7 @@ #ifndef NET_COOKIES_CANONICAL_COOKIE_H_ #define NET_COOKIES_CANONICAL_COOKIE_H_ +#include <compare> #include <memory> #include <optional> #include <string> @@ -246,14 +247,16 @@ CookieSourceType source_type = CookieSourceType::kUnknown, CookieInclusionStatus* status = nullptr); - bool operator<(const CanonicalCookie& other) const { + friend auto operator<=>(const CanonicalCookie& left, + const CanonicalCookie& right) { // Use the cookie properties that uniquely identify a cookie to determine // ordering. - return RefUniqueKey() < other.RefUniqueKey(); + return left.RefUniqueKey() <=> right.RefUniqueKey(); } - bool operator==(const CanonicalCookie& other) const { - return IsEquivalent(other); + friend bool operator==(const CanonicalCookie& left, + const CanonicalCookie& right) { + return left.RefUniqueKey() == right.RefUniqueKey(); } // See CookieBase for other accessors.
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index 78227ed1..f96ce7f 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc
@@ -83,6 +83,7 @@ void DoomedEntry(int stream_index); void BasicSparseIO(); void HugeSparseIO(); + void LargeOffsetSparseIO(); void GetAvailableRangeTest(); void CouldBeSparse(); void UpdateSparseEntry(); @@ -1616,6 +1617,38 @@ HugeSparseIO(); } +void DiskCacheEntryTest::LargeOffsetSparseIO() { + std::string key("the first key"); + disk_cache::Entry* entry; + ASSERT_THAT(CreateEntry(key, &entry), IsOk()); + + // Write 4 MB so that we cover multiple entries. + static constexpr size_t kSize = 4 * 1024 * 1024; + + auto buf_1 = CacheTestCreateAndFillBuffer(kSize, false); + auto buf_2 = base::MakeRefCounted<net::IOBufferWithSize>(kSize); + + // Write sparse data from 4GB - 2MB to 4GB + 2MB. + constexpr int64_t offset = 4LL * 1024 * 1024 * 1024 - 2 * 1024 * 1024; + + VerifySparseIO(entry, offset, buf_1.get(), kSize, buf_2.get()); + entry->Close(); + + // Check it again. + ASSERT_THAT(OpenEntry(key, &entry), IsOk()); + VerifyContentSparseIO(entry, offset, buf_1->span()); + entry->Close(); +} + +// The test only works on SimpleCache now since other backend does not support +// 2GB+ offset for 32 bits architecture. +// TODO(crbug.com/391398191): Expand the test target to all cache backend. +TEST_F(DiskCacheEntryTest, SimpleCacheLargeOffsetSparseIO) { + SetBackendToTest(BackendToTest::kSimple); + InitCache(); + LargeOffsetSparseIO(); +} + void DiskCacheEntryTest::GetAvailableRangeTest() { std::string key("the first key"); disk_cache::Entry* entry; @@ -1698,6 +1731,45 @@ GetAvailableRangeTest(); } +// The test only works on SimpleCache now since other backend does not support +// 2GB+ offset for 32 bits architecture. +// TODO(crbug.com/391398191): Expand the test target to all cache backend. +TEST_F(DiskCacheEntryTest, SimpleCacheGetAvailableRangeForLargeOffset) { + SetBackendToTest(BackendToTest::kSimple); + InitCache(); + + std::string key("the first key"); + disk_cache::Entry* entry; + ASSERT_THAT(CreateEntry(key, &entry), IsOk()); + + // Write 4 MB so that we cover multiple entries. + static constexpr size_t kSize = 4 * 1024 * 1024; + auto buf = CacheTestCreateAndFillBuffer(kSize, false); + + // Write sparse data from 4GB - 2MB to 4GB + 2MB. + constexpr int64_t offset = 4LL * 1024 * 1024 * 1024 - 2 * 1024 * 1024; + + EXPECT_EQ(kSize, WriteSparseData(entry, offset, buf.get(), kSize)); + + TestRangeResultCompletionCallback cb; + RangeResult result = + cb.GetResult(entry->GetAvailableRange(offset, kSize * 2, cb.callback())); + EXPECT_EQ(net::OK, result.net_error); + EXPECT_EQ(kSize, result.available_len); + EXPECT_EQ(offset, result.start); + + result = cb.GetResult(entry->GetAvailableRange(0, kSize, cb.callback())); + EXPECT_EQ(net::OK, result.net_error); + EXPECT_EQ(0, result.available_len); + + result = cb.GetResult( + entry->GetAvailableRange(offset - kSize, kSize, cb.callback())); + EXPECT_EQ(net::OK, result.net_error); + EXPECT_EQ(0, result.available_len); + + entry->Close(); +} + TEST_F(DiskCacheEntryTest, GetAvailableRangeBlockFileDiscontinuous) { // crbug.com/791056 --- blockfile problem when there is a sub-KiB write before // a bunch of full 1KiB blocks, and a GetAvailableRange is issued to which
diff --git a/net/disk_cache/simple/simple_entry_format.h b/net/disk_cache/simple/simple_entry_format.h index 4d4472d..01a7a35 100644 --- a/net/disk_cache/simple/simple_entry_format.h +++ b/net/disk_cache/simple/simple_entry_format.h
@@ -87,8 +87,11 @@ SimpleFileSparseRangeHeader(); uint64_t sparse_range_magic_number = 0; - int64_t offset = 0; - int64_t length = 0; + uint64_t offset = 0; + + // `length` must be size-fixed to avoid padding, so using uint64_t instead of + // size_t. + uint64_t length = 0; uint32_t data_crc32 = 0; // Avoid implicit padding so `std::has_unique_object_representations_v<>` will
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc index 641141a..6acab98e 100644 --- a/net/disk_cache/simple/simple_entry_impl.cc +++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -519,15 +519,16 @@ return net::ERR_INVALID_ARGUMENT; } - // Truncate |buf_len| to make sure that |offset + buf_len| does not overflow. + // Truncate `buf_len` to make sure that `offset + buf_len` does not overflow. // This is OK since one can't write that far anyway. - // The result of std::min is guaranteed to fit into int since |buf_len| did. - buf_len = std::min(static_cast<int64_t>(buf_len), - std::numeric_limits<int64_t>::max() - offset); + // The result of std::min is guaranteed to fit into size_t since `buf_len` + // did. + size_t length = std::min(static_cast<int64_t>(buf_len), + std::numeric_limits<int64_t>::max() - offset); ScopedOperationRunner operation_runner(this); pending_operations_.push(SimpleEntryOperation::ReadSparseOperation( - this, offset, buf_len, buf, std::move(callback))); + this, static_cast<uint64_t>(offset), length, buf, std::move(callback))); return net::ERR_IO_PENDING; } @@ -554,7 +555,8 @@ ScopedOperationRunner operation_runner(this); pending_operations_.push(SimpleEntryOperation::WriteSparseOperation( - this, offset, buf_len, buf, std::move(callback))); + this, static_cast<uint64_t>(offset), static_cast<size_t>(buf_len), buf, + std::move(callback))); return net::ERR_IO_PENDING; } @@ -565,15 +567,16 @@ if (offset < 0 || len < 0) return RangeResult(net::ERR_INVALID_ARGUMENT); - // Truncate |len| to make sure that |offset + len| does not overflow. + // Truncate `buf_len` to make sure that `offset + buf_len` does not overflow. // This is OK since one can't write that far anyway. - // The result of std::min is guaranteed to fit into int since |len| did. - len = std::min(static_cast<int64_t>(len), - std::numeric_limits<int64_t>::max() - offset); + // The result of std::min is guaranteed to fit into size_t since `buf_len` + // did. + size_t length = std::min(static_cast<int64_t>(len), + std::numeric_limits<int64_t>::max() - offset); ScopedOperationRunner operation_runner(this); pending_operations_.push(SimpleEntryOperation::GetAvailableRangeOperation( - this, offset, len, std::move(callback))); + this, static_cast<uint64_t>(offset), length, std::move(callback))); return RangeResult(net::ERR_IO_PENDING); } @@ -736,15 +739,17 @@ break; case SimpleEntryOperation::TYPE_READ_SPARSE: ReadSparseDataInternal(operation.sparse_offset(), operation.buf(), - operation.length(), operation.ReleaseCallback()); + operation.sparse_length(), + operation.ReleaseCallback()); break; case SimpleEntryOperation::TYPE_WRITE_SPARSE: WriteSparseDataInternal(operation.sparse_offset(), operation.buf(), - operation.length(), + operation.sparse_length(), operation.ReleaseCallback()); break; case SimpleEntryOperation::TYPE_GET_AVAILABLE_RANGE: - GetAvailableRangeInternal(operation.sparse_offset(), operation.length(), + GetAvailableRangeInternal(operation.sparse_offset(), + operation.sparse_length(), operation.ReleaseRangeResultCalback()); break; case SimpleEntryOperation::TYPE_DOOM:
diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h index e65ac2b..a345e63 100644 --- a/net/disk_cache/simple/simple_entry_impl.h +++ b/net/disk_cache/simple/simple_entry_impl.h
@@ -383,7 +383,7 @@ // TODO(clamy): Unify last_used_ with data in the index. base::Time last_used_; std::array<int32_t, kSimpleEntryStreamCount> data_size_; - int32_t sparse_data_size_ = 0; + uint64_t sparse_data_size_ = 0; // Number of times this object has been returned from Backend::OpenEntry() and // Backend::CreateEntry() without subsequent Entry::Close() calls. Used to
diff --git a/net/disk_cache/simple/simple_entry_operation.cc b/net/disk_cache/simple/simple_entry_operation.cc index c0c23ae..497f3e3 100644 --- a/net/disk_cache/simple/simple_entry_operation.cc +++ b/net/disk_cache/simple/simple_entry_operation.cc
@@ -22,7 +22,7 @@ SimpleEntryImpl* entry, EntryResultState result_state, EntryResultCallback callback) { - SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, + SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, 0, TYPE_OPEN, INDEX_NOEXIST, 0, false, false); op.entry_callback_ = std::move(callback); op.entry_result_state_ = result_state; @@ -34,7 +34,7 @@ SimpleEntryImpl* entry, EntryResultState result_state, EntryResultCallback callback) { - SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, + SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, 0, TYPE_CREATE, INDEX_NOEXIST, 0, false, false); op.entry_callback_ = std::move(callback); op.entry_result_state_ = result_state; @@ -47,7 +47,7 @@ OpenEntryIndexEnum index_state, EntryResultState result_state, EntryResultCallback callback) { - SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, + SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, 0, TYPE_OPEN_OR_CREATE, index_state, 0, false, false); op.entry_callback_ = std::move(callback); op.entry_result_state_ = result_state; @@ -58,7 +58,7 @@ SimpleEntryOperation SimpleEntryOperation::CloseOperation( SimpleEntryImpl* entry) { return SimpleEntryOperation(entry, nullptr, CompletionOnceCallback(), 0, 0, 0, - TYPE_CLOSE, INDEX_NOEXIST, 0, false, false); + 0, TYPE_CLOSE, INDEX_NOEXIST, 0, false, false); } // static @@ -70,7 +70,7 @@ net::IOBuffer* buf, CompletionOnceCallback callback) { return SimpleEntryOperation(entry, buf, std::move(callback), offset, 0, - length, TYPE_READ, INDEX_NOEXIST, index, false, + length, 0, TYPE_READ, INDEX_NOEXIST, index, false, false); } @@ -85,43 +85,43 @@ bool optimistic, CompletionOnceCallback callback) { return SimpleEntryOperation(entry, buf, std::move(callback), offset, 0, - length, TYPE_WRITE, INDEX_NOEXIST, index, + length, 0, TYPE_WRITE, INDEX_NOEXIST, index, truncate, optimistic); } // static SimpleEntryOperation SimpleEntryOperation::ReadSparseOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, net::IOBuffer* buf, CompletionOnceCallback callback) { return SimpleEntryOperation(entry, buf, std::move(callback), 0, sparse_offset, - length, TYPE_READ_SPARSE, INDEX_NOEXIST, 0, false, - false); + 0, sparse_length, TYPE_READ_SPARSE, INDEX_NOEXIST, + 0, false, false); } // static SimpleEntryOperation SimpleEntryOperation::WriteSparseOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, net::IOBuffer* buf, CompletionOnceCallback callback) { return SimpleEntryOperation(entry, buf, std::move(callback), 0, sparse_offset, - length, TYPE_WRITE_SPARSE, INDEX_NOEXIST, 0, - false, false); + 0, sparse_length, TYPE_WRITE_SPARSE, + INDEX_NOEXIST, 0, false, false); } // static SimpleEntryOperation SimpleEntryOperation::GetAvailableRangeOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, RangeResultCallback callback) { - SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, - sparse_offset, length, TYPE_GET_AVAILABLE_RANGE, - INDEX_NOEXIST, 0, false, false); + SimpleEntryOperation op( + entry, nullptr, CompletionOnceCallback(), 0, sparse_offset, 0, + sparse_length, TYPE_GET_AVAILABLE_RANGE, INDEX_NOEXIST, 0, false, false); op.range_callback_ = std::move(callback); return op; } @@ -132,23 +132,25 @@ net::CompletionOnceCallback callback) { net::IOBuffer* const buf = nullptr; const int offset = 0; - const int64_t sparse_offset = 0; + const uint64_t sparse_offset = 0; const int length = 0; + const size_t sparse_length = 0; const OpenEntryIndexEnum index_state = INDEX_NOEXIST; const int index = 0; const bool truncate = false; const bool optimistic = false; return SimpleEntryOperation(entry, buf, std::move(callback), offset, - sparse_offset, length, TYPE_DOOM, index_state, - index, truncate, optimistic); + sparse_offset, length, sparse_length, TYPE_DOOM, + index_state, index, truncate, optimistic); } SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry, net::IOBuffer* buf, net::CompletionOnceCallback callback, int offset, - int64_t sparse_offset, + uint64_t sparse_offset, int length, + size_t sparse_length, EntryOperationType type, OpenEntryIndexEnum index_state, int index, @@ -160,6 +162,7 @@ offset_(offset), sparse_offset_(sparse_offset), length_(length), + sparse_length_(sparse_length), type_(type), index_state_(index_state), index_(index),
diff --git a/net/disk_cache/simple/simple_entry_operation.h b/net/disk_cache/simple/simple_entry_operation.h index 63ae3dac..0f034f7c 100644 --- a/net/disk_cache/simple/simple_entry_operation.h +++ b/net/disk_cache/simple/simple_entry_operation.h
@@ -78,20 +78,20 @@ CompletionOnceCallback callback); static SimpleEntryOperation ReadSparseOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, net::IOBuffer* buf, CompletionOnceCallback callback); static SimpleEntryOperation WriteSparseOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, net::IOBuffer* buf, CompletionOnceCallback callback); static SimpleEntryOperation GetAvailableRangeOperation( SimpleEntryImpl* entry, - int64_t sparse_offset, - int length, + uint64_t sparse_offset, + size_t sparse_length, RangeResultCallback callback); static SimpleEntryOperation DoomOperation(SimpleEntryImpl* entry, CompletionOnceCallback callback); @@ -114,6 +114,7 @@ int offset() const { return offset_; } int64_t sparse_offset() const { return sparse_offset_; } int length() const { return length_; } + size_t sparse_length() const { return sparse_length_; } net::IOBuffer* buf() { return buf_.get(); } bool truncate() const { return truncate_; } bool optimistic() const { return optimistic_; } @@ -123,8 +124,9 @@ net::IOBuffer* buf, CompletionOnceCallback callback, int offset, - int64_t sparse_offset, + uint64_t sparse_offset, int length, + size_t sparse_length, EntryOperationType type, OpenEntryIndexEnum index_state, int index, @@ -144,6 +146,7 @@ const int offset_; const int64_t sparse_offset_; const int length_; + const size_t sparse_length_; // Used in get available range operations. RangeResultCallback range_callback_;
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc index 7b0b4c2..bf7db72 100644 --- a/net/disk_cache/simple/simple_synchronous_entry.cc +++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -237,7 +237,7 @@ SimpleEntryStat::SimpleEntryStat( base::Time last_used, const std::array<int32_t, kSimpleEntryStreamCount>& data_size, - const int32_t sparse_data_size) + const uint64_t sparse_data_size) : last_used_(last_used), data_size_(data_size), sparse_data_size_(sparse_data_size) {} @@ -325,8 +325,8 @@ doomed(doomed_p), request_update_crc(request_update_crc_p) {} -SimpleSynchronousEntry::SparseRequest::SparseRequest(int64_t sparse_offset_p, - int buf_len_p) +SimpleSynchronousEntry::SparseRequest::SparseRequest(uint64_t sparse_offset_p, + size_t buf_len_p) : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {} // static @@ -758,11 +758,10 @@ DCHECK(initialized_); BackendFileOperations* file_operations = nullptr; ScopedFileOperationsBinding binding(this, &file_operations); - int64_t offset = in_entry_op.sparse_offset; - int buf_len = in_entry_op.buf_len; + uint64_t offset = in_entry_op.sparse_offset; + size_t buf_len = in_entry_op.buf_len; base::span<uint8_t> buf = out_buf->span(); - int read_so_far = 0; if (!sparse_file_open() || !buf_len) { *out_result = 0; @@ -777,6 +776,8 @@ return; } + size_t read_so_far = 0; + // Find the first sparse range at or after the requested offset. auto it = sparse_ranges_.lower_bound(offset); @@ -784,20 +785,18 @@ // Hop back one range and read the one overlapping with the start. --it; SparseRange* found_range = &it->second; - DCHECK_EQ(it->first, found_range->offset); - if (found_range->offset + found_range->length > offset) { - DCHECK_GE(found_range->length, 0); - DCHECK_LE(found_range->length, std::numeric_limits<int32_t>::max()); - DCHECK_GE(offset - found_range->offset, 0); - DCHECK_LE(offset - found_range->offset, - std::numeric_limits<int32_t>::max()); - int net_offset = static_cast<int>(offset - found_range->offset); - int range_len_after_offset = - static_cast<int>(found_range->length - net_offset); - DCHECK_GE(range_len_after_offset, 0); + CHECK_EQ(it->first, found_range->offset); - int len_to_read = std::min(buf_len, range_len_after_offset); - if (!ReadSparseRange(sparse_file.get(), found_range, net_offset, + CHECK(base::CheckAdd(found_range->offset, found_range->length).IsValid()); + if (found_range->offset + found_range->length > offset) { + CHECK_LE(offset - found_range->offset, + std::numeric_limits<size_t>::max()); + size_t offset_in_range = + base::checked_cast<size_t>(offset - found_range->offset); + size_t range_len_after_offset = found_range->length - offset_in_range; + + size_t len_to_read = std::min(buf_len, range_len_after_offset); + if (!ReadSparseRange(sparse_file.get(), found_range, offset_in_range, len_to_read, buf)) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_READ_FAILURE; @@ -810,25 +809,27 @@ // Keep reading until the buffer is full or there is not another contiguous // range. - while (read_so_far < buf_len && - it != sparse_ranges_.end() && + while (read_so_far < buf_len && it != sparse_ranges_.end() && it->second.offset == offset + read_so_far) { SparseRange* found_range = &it->second; - DCHECK_EQ(it->first, found_range->offset); - int range_len = base::saturated_cast<int>(found_range->length); - int len_to_read = std::min(buf_len - read_so_far, range_len); - if (!ReadSparseRange( - sparse_file.get(), found_range, 0, len_to_read, - buf.subspan(base::checked_cast<size_t>(read_so_far)))) { + CHECK_EQ(it->first, found_range->offset); + size_t range_len = found_range->length; + size_t len_to_read = std::min(buf_len - read_so_far, range_len); + if (!ReadSparseRange(sparse_file.get(), found_range, 0, len_to_read, + buf.subspan(read_so_far))) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_READ_FAILURE; return; } + read_so_far += len_to_read; + ++it; } - *out_result = read_so_far; + // The length to read is limited to each sparse data which is far smaller than + // int max. + *out_result = base::checked_cast<int>(read_so_far); } void SimpleSynchronousEntry::WriteSparseData(const SparseRequest& in_entry_op, @@ -839,12 +840,10 @@ DCHECK(initialized_); BackendFileOperations* file_operations = nullptr; ScopedFileOperationsBinding binding(this, &file_operations); - int64_t offset = in_entry_op.sparse_offset; - int buf_len = in_entry_op.buf_len; + uint64_t offset = in_entry_op.sparse_offset; + size_t buf_len = in_entry_op.buf_len; base::span<const uint8_t> buf = in_buf->span(); - int written_so_far = 0; - int appended_so_far = 0; if (!sparse_file_open() && !CreateSparseFile(file_operations)) { DoomInternal(file_operations); @@ -859,42 +858,42 @@ return; } - int32_t sparse_data_size = out_entry_stat->sparse_data_size(); - int32_t future_sparse_data_size; + uint64_t sparse_data_size = out_entry_stat->sparse_data_size(); + uint64_t future_sparse_data_size; if (!base::CheckAdd(sparse_data_size, buf_len) - .AssignIfValid(&future_sparse_data_size) || - future_sparse_data_size < 0) { + .AssignIfValid(&future_sparse_data_size)) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_WRITE_FAILURE; return; } // This is a pessimistic estimate; it assumes the entire buffer is going to // be appended as a new range, not written over existing ranges. - if (static_cast<uint64_t>(future_sparse_data_size) > max_sparse_data_size) { + if (future_sparse_data_size > max_sparse_data_size) { DVLOG(1) << "Truncating sparse data file (" << sparse_data_size << " + " << buf_len << " > " << max_sparse_data_size << ")"; TruncateSparseFile(sparse_file.get()); - out_entry_stat->set_sparse_data_size(0); + out_entry_stat->set_sparse_data_size(0u); } + size_t written_so_far = 0; + size_t appended_so_far = 0; + auto it = sparse_ranges_.lower_bound(offset); if (it != sparse_ranges_.begin()) { --it; SparseRange* found_range = &it->second; - if (found_range->offset + found_range->length > offset) { - DCHECK_GE(found_range->length, 0); - DCHECK_LE(found_range->length, std::numeric_limits<int32_t>::max()); - DCHECK_GE(offset - found_range->offset, 0); - DCHECK_LE(offset - found_range->offset, - std::numeric_limits<int32_t>::max()); - int net_offset = static_cast<int>(offset - found_range->offset); - int range_len_after_offset = - static_cast<int>(found_range->length - net_offset); - DCHECK_GE(range_len_after_offset, 0); - int len_to_write = std::min(buf_len, range_len_after_offset); - if (!WriteSparseRange(sparse_file.get(), found_range, net_offset, + CHECK(base::CheckAdd(found_range->offset, found_range->length).IsValid()); + if (found_range->offset + found_range->length > offset) { + CHECK_LE(offset - found_range->offset, + std::numeric_limits<size_t>::max()); + size_t offset_in_range = + static_cast<size_t>(offset - found_range->offset); + size_t range_len_after_offset = found_range->length - offset_in_range; + + size_t len_to_write = std::min(buf_len, range_len_after_offset); + if (!WriteSparseRange(sparse_file.get(), found_range, offset_in_range, len_to_write, buf)) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_WRITE_FAILURE; @@ -905,41 +904,40 @@ ++it; } - while (written_so_far < buf_len && - it != sparse_ranges_.end() && + while (written_so_far < buf_len && it != sparse_ranges_.end() && it->second.offset < offset + buf_len) { SparseRange* found_range = &it->second; if (offset + written_so_far < found_range->offset) { - int len_to_append = - static_cast<int>(found_range->offset - (offset + written_so_far)); - if (!AppendSparseRange( - sparse_file.get(), offset + written_so_far, len_to_append, - buf.subspan(base::checked_cast<size_t>(written_so_far)))) { + size_t len_to_append = + static_cast<size_t>(found_range->offset - (offset + written_so_far)); + if (!AppendSparseRange(sparse_file.get(), offset + written_so_far, + len_to_append, buf.subspan(written_so_far))) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_WRITE_FAILURE; return; } + written_so_far += len_to_append; appended_so_far += len_to_append; } - int range_len = base::saturated_cast<int>(found_range->length); - int len_to_write = std::min(buf_len - written_so_far, range_len); - if (!WriteSparseRange( - sparse_file.get(), found_range, 0, len_to_write, - buf.subspan(base::checked_cast<size_t>(written_so_far)))) { + + size_t len_to_write = + std::min(buf_len - written_so_far, found_range->length); + if (!WriteSparseRange(sparse_file.get(), found_range, 0, len_to_write, + buf.subspan(written_so_far))) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_WRITE_FAILURE; return; } + written_so_far += len_to_write; ++it; } if (written_so_far < buf_len) { - int len_to_append = buf_len - written_so_far; - if (!AppendSparseRange( - sparse_file.get(), offset + written_so_far, len_to_append, - buf.subspan(base::checked_cast<size_t>(written_so_far)))) { + size_t len_to_append = buf_len - written_so_far; + if (!AppendSparseRange(sparse_file.get(), offset + written_so_far, + len_to_append, buf.subspan(written_so_far))) { DoomInternal(file_operations); *out_result = net::ERR_CACHE_WRITE_FAILURE; return; @@ -948,28 +946,32 @@ appended_so_far += len_to_append; } - DCHECK_EQ(buf_len, written_so_far); + CHECK_EQ(buf_len, written_so_far); base::Time modification_time = Time::Now(); out_entry_stat->set_last_used(modification_time); - int32_t old_sparse_data_size = out_entry_stat->sparse_data_size(); + uint64_t old_sparse_data_size = out_entry_stat->sparse_data_size(); out_entry_stat->set_sparse_data_size(old_sparse_data_size + appended_so_far); - *out_result = written_so_far; + + // The length to read is limited to each sparse data which is far smaller than + // int max. + *out_result = base::checked_cast<int>(written_so_far); } void SimpleSynchronousEntry::GetAvailableRange(const SparseRequest& in_entry_op, RangeResult* out_result) { DCHECK(initialized_); - int64_t offset = in_entry_op.sparse_offset; - int len = in_entry_op.buf_len; + uint64_t offset = in_entry_op.sparse_offset; + size_t len = in_entry_op.buf_len; auto it = sparse_ranges_.lower_bound(offset); - int64_t start = offset; - int64_t avail_so_far = 0; + uint64_t start = offset; + uint64_t avail_so_far = 0; - if (it != sparse_ranges_.end() && it->second.offset < offset + len) + if (it != sparse_ranges_.end() && it->second.offset < offset + len) { start = it->second.offset; + } if ((it == sparse_ranges_.end() || it->second.offset > offset) && it != sparse_ranges_.begin()) { @@ -988,9 +990,13 @@ ++it; } - int64_t len_from_start = len - (start - offset); - *out_result = RangeResult( - start, static_cast<int>(std::min(avail_so_far, len_from_start))); + // `range_len` must fit in size_t since it's guaranteed to be same or smaller + // than `len - (start - offset)` where `len` is within size_t range and + // `start` is same or larger than `offset`. + size_t range_len = base::checked_cast<size_t>( + std::min(avail_so_far, len - (start - offset))); + + *out_result = RangeResult(start, range_len); } int SimpleSynchronousEntry::CheckEOFRecord( @@ -1505,7 +1511,7 @@ } } - int32_t sparse_data_size = 0; + uint64_t sparse_data_size = 0u; if (!OpenSparseFileIfExists(file_operations, &sparse_data_size)) { RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED); return net::ERR_FAILED; @@ -1839,7 +1845,7 @@ bool SimpleSynchronousEntry::OpenSparseFileIfExists( BackendFileOperations* file_operations, - int32_t* out_sparse_data_size) { + uint64_t* out_sparse_data_size) { DCHECK(!sparse_file_open()); FilePath filename = @@ -1896,7 +1902,7 @@ bool SimpleSynchronousEntry::TruncateSparseFile(base::File* sparse_file) { DCHECK(sparse_file_open()); - int64_t header_and_key_length = sizeof(SimpleFileHeader) + key_->size(); + uint64_t header_and_key_length = sizeof(SimpleFileHeader) + key_->size(); if (!sparse_file->SetLength(header_and_key_length)) { DLOG(WARNING) << "Could not truncate sparse file"; return false; @@ -1933,8 +1939,8 @@ } bool SimpleSynchronousEntry::ScanSparseFile(base::File* sparse_file, - int32_t* out_sparse_data_size) { - int64_t sparse_data_size = 0; + uint64_t* out_sparse_data_size) { + uint64_t sparse_data_size = 0; SimpleFileHeader header; if (!sparse_file->ReadAndCheck(0, base::byte_span_from_ref(header))) { @@ -1954,7 +1960,7 @@ sparse_ranges_.clear(); - int64_t range_header_offset = sizeof(header) + key_->size(); + uint64_t range_header_offset = sizeof(header) + key_->size(); while (true) { SimpleFileSparseRangeHeader range_header; std::optional<size_t> range_header_read_result = sparse_file->Read( @@ -1974,20 +1980,29 @@ return false; } + if (range_header.length > std::numeric_limits<size_t>::max()) { + DLOG(WARNING) << "Too long sparse range length."; + return false; + } + + if (!base::CheckAdd(range_header.offset, range_header.length).IsValid()) { + DLOG(WARNING) << "Too large sparse range tail."; + return false; + } + SparseRange range; range.offset = range_header.offset; - range.length = range_header.length; + range.length = static_cast<size_t>(range_header.length); range.data_crc32 = range_header.data_crc32; range.file_offset = range_header_offset + sizeof(range_header); sparse_ranges_.emplace(range.offset, range); range_header_offset += sizeof(range_header) + range.length; - DCHECK_GE(sparse_data_size + range.length, sparse_data_size); sparse_data_size += range.length; } - *out_sparse_data_size = static_cast<int32_t>(sparse_data_size); + *out_sparse_data_size = sparse_data_size; sparse_tail_offset_ = range_header_offset; return true; @@ -1995,23 +2010,23 @@ bool SimpleSynchronousEntry::ReadSparseRange(base::File* sparse_file, const SparseRange* range, - size_t offset, + size_t offset_in_range, size_t len, base::span<uint8_t> buf) { - DCHECK(range); - DCHECK_LE(static_cast<int64_t>(offset), range->length); - DCHECK_LE(static_cast<int64_t>(offset + len), range->length); + CHECK(range); + CHECK_LE(offset_in_range, range->length); + CHECK_LE(offset_in_range + len, range->length); - bool bytes_read_ok = sparse_file->ReadAndCheck( - range->file_offset + offset, buf.first(base::checked_cast<size_t>(len))); + bool bytes_read_ok = + sparse_file->ReadAndCheck(range->file_offset + offset_in_range, + buf.first(base::checked_cast<size_t>(len))); if (!bytes_read_ok) { DLOG(WARNING) << "Could not read sparse range."; return false; } // If we read the whole range and we have a crc32, check it. - if (offset == 0 && static_cast<int64_t>(len) == range->length && - range->data_crc32 != 0) { + if (offset_in_range == 0 && len == range->length && range->data_crc32 != 0) { if (simple_util::Crc32(buf.first(len)) != range->data_crc32) { DLOG(WARNING) << "Sparse range crc32 mismatch."; return false; @@ -2024,15 +2039,15 @@ bool SimpleSynchronousEntry::WriteSparseRange(base::File* sparse_file, SparseRange* range, - size_t offset, + size_t offset_in_range, size_t len, base::span<const uint8_t> buf) { - DCHECK(range); - DCHECK_LE(static_cast<int64_t>(offset), range->length); - DCHECK_LE(static_cast<int64_t>(offset + len), range->length); + CHECK(range); + CHECK_LE(offset_in_range, range->length); + CHECK_LE(offset_in_range + len, range->length); uint32_t new_crc32 = 0; - if (offset == 0 && static_cast<int64_t>(len) == range->length) { + if (offset_in_range == 0 && len == range->length) { new_crc32 = simple_util::Crc32(buf.first(len)); } @@ -2053,8 +2068,8 @@ } } - bool bytes_written_ok = - sparse_file->WriteAndCheck(range->file_offset + offset, buf.first(len)); + bool bytes_written_ok = sparse_file->WriteAndCheck( + range->file_offset + offset_in_range, buf.first(len)); if (!bytes_written_ok) { DLOG(WARNING) << "Could not write sparse range."; return false; @@ -2064,10 +2079,9 @@ } bool SimpleSynchronousEntry::AppendSparseRange(base::File* sparse_file, - int64_t offset, + uint64_t offset, size_t len, base::span<const uint8_t> buf) { - DCHECK_GE(offset, 0); DCHECK_NE(len, 0u); uint32_t data_crc32 = simple_util::Crc32(buf.first(len)); @@ -2091,7 +2105,7 @@ DLOG(WARNING) << "Could not append sparse range data."; return false; } - int64_t data_file_offset = sparse_tail_offset_; + uint64_t data_file_offset = sparse_tail_offset_; sparse_tail_offset_ += *bytes_written; SparseRange range;
diff --git a/net/disk_cache/simple/simple_synchronous_entry.h b/net/disk_cache/simple/simple_synchronous_entry.h index 578c165..db62f7b 100644 --- a/net/disk_cache/simple/simple_synchronous_entry.h +++ b/net/disk_cache/simple/simple_synchronous_entry.h
@@ -61,7 +61,7 @@ public: SimpleEntryStat(base::Time last_used, const std::array<int32_t, kSimpleEntryStreamCount>& data_size, - const int32_t sparse_data_size); + const uint64_t sparse_data_size); int GetOffsetInFile(size_t key_length, int offset, int stream_index) const; int GetEOFOffsetInFile(size_t key_length, int stream_index) const; @@ -76,15 +76,15 @@ data_size_[stream_index] = data_size; } - int32_t sparse_data_size() const { return sparse_data_size_; } - void set_sparse_data_size(int32_t sparse_data_size) { + uint64_t sparse_data_size() const { return sparse_data_size_; } + void set_sparse_data_size(uint64_t sparse_data_size) { sparse_data_size_ = sparse_data_size; } private: base::Time last_used_; std::array<int32_t, kSimpleEntryStreamCount> data_size_; - int32_t sparse_data_size_; + uint64_t sparse_data_size_; }; struct SimpleStreamPrefetchData { @@ -176,10 +176,10 @@ }; struct SparseRequest { - SparseRequest(int64_t sparse_offset_p, int buf_len_p); + SparseRequest(uint64_t sparse_offset_p, size_t buf_len_p); - int64_t sparse_offset; - int buf_len; + uint64_t sparse_offset; + size_t buf_len; }; NET_EXPORT_PRIVATE SimpleSynchronousEntry( @@ -324,8 +324,8 @@ }; struct SparseRange { - int64_t offset; - int64_t length; + uint64_t offset; + size_t length; uint32_t data_crc32; int64_t file_offset; @@ -426,7 +426,7 @@ // Opens the sparse data file and scans it if it exists. bool OpenSparseFileIfExists(BackendFileOperations* file_operations, - int32_t* out_sparse_data_size); + uint64_t* out_sparse_data_size); // Creates and initializes the sparse data file. bool CreateSparseFile(BackendFileOperations* file_operations); @@ -440,16 +440,16 @@ // Removes all but the header of the sparse file. bool TruncateSparseFile(base::File* sparse_file); - // Scans the existing ranges in the sparse file. Populates |sparse_ranges_| - // and sets |*out_sparse_data_size| to the total size of all the ranges (not + // Scans the existing ranges in the sparse file. Populates `sparse_ranges_` + // and sets `*out_sparse_data_size` to the total size of all the ranges (not // including headers). - bool ScanSparseFile(base::File* sparse_file, int32_t* out_sparse_data_size); + bool ScanSparseFile(base::File* sparse_file, uint64_t* out_sparse_data_size); // Reads from a single sparse range. If asked to read the entire range, also // verifies the CRC32. bool ReadSparseRange(base::File* sparse_file, const SparseRange* range, - size_t offset, + size_t offset_in_range, size_t len, base::span<uint8_t> buf); @@ -457,13 +457,13 @@ // range, also updates the CRC32; otherwise, invalidates it. bool WriteSparseRange(base::File* sparse_file, SparseRange* range, - size_t offset, + size_t offset_in_range, size_t len, base::span<const uint8_t> buf); // Appends a new sparse range to the sparse data file. bool AppendSparseRange(base::File* sparse_file, - int64_t offset, + uint64_t offset, size_t len, base::span<const uint8_t> buf); @@ -527,14 +527,14 @@ // was created to store it. std::array<bool, kSimpleEntryNormalFileCount> empty_file_omitted_; - typedef std::map<int64_t, SparseRange> SparseRangeOffsetMap; + typedef std::map<uint64_t, SparseRange> SparseRangeOffsetMap; typedef SparseRangeOffsetMap::iterator SparseRangeIterator; SparseRangeOffsetMap sparse_ranges_; bool sparse_file_open_ = false; // Offset of the end of the sparse file (where the next sparse range will be // written). - int64_t sparse_tail_offset_; + uint64_t sparse_tail_offset_; }; } // namespace disk_cache
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc index 5a0cfd6..cb2a57e 100644 --- a/net/http/http_stream_pool_attempt_manager.cc +++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -205,13 +205,14 @@ } void HttpStreamPool::AttemptManager::RequestStream(Job* job) { - CHECK(availability_state_ == AvailabilityState::kAvailable); + // JobController should check idle streams before starting a request Job. + CHECK_EQ(group_->IdleStreamSocketCount(), 0u); TRACE_EVENT_INSTANT("net.stream", "AttemptManager::RequestStream", track_, NetLogWithSourceToFlow(job->request_net_log())); net_log_.AddEvent( - NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_START_JOB, [&] { + NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_REQUEST_STREAM, [&] { base::Value::Dict dict; dict.Set("priority", job->priority()); base::Value::List allowed_bad_certs_list; @@ -235,40 +236,11 @@ NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_JOB_BOUND, net_log_.source()); - if (job->respect_limits() == RespectLimits::kIgnore) { - limit_ignoring_jobs_.emplace(job); - } - - if (!job->enable_ip_based_pooling()) { - ip_based_pooling_disabling_jobs_.emplace(job); - } - - if (!job->enable_alternative_services()) { - alternative_service_disabling_jobs_.emplace(job); - } - - // HttpStreamPool should check the existing QUIC/SPDY sessions and idle - // streams before calling this method. - DCHECK(!CanUseExistingQuicSession()); - DCHECK(!HasAvailableSpdySession()); - CHECK_EQ(group_->IdleStreamSocketCount(), 0u); - - request_jobs_.Insert(job, job->priority()); - - MaybeChangeServiceEndpointRequestPriority(); - - if (base_ssl_config_.has_value()) { - base_ssl_config_->allowed_bad_certs = job->allowed_bad_certs(); - } - quic_version_ = job->quic_version(); - StartInternal(job); - - return; } void HttpStreamPool::AttemptManager::Preconnect(Job* job) { - CHECK(availability_state_ == AvailabilityState::kAvailable); + // JobController should check active streams before starting a preconnect Job. CHECK_LT(group_->ActiveStreamSocketCount(), job->num_streams()); TRACE_EVENT_INSTANT("net.stream", "AttemptManager::Preconnect", track_, @@ -287,14 +259,6 @@ NetLogEventType::HTTP_STREAM_POOL_JOB_CONTROLLER_PRECONNECT_BOUND, net_log_.source()); - // HttpStreamPool should check the existing QUIC/SPDY sessions before calling - // this method. - DCHECK(!CanUseExistingQuicSession()); - DCHECK(!HasAvailableSpdySession()); - - preconnect_jobs_.emplace(job); - quic_version_ = job->quic_version(); - StartInternal(job); } @@ -1027,6 +991,37 @@ } void HttpStreamPool::AttemptManager::StartInternal(Job* job) { + CHECK(availability_state_ == AvailabilityState::kAvailable); + + if (job->IsPreconnect()) { + preconnect_jobs_.emplace(job); + } else { + request_jobs_.Insert(job, job->priority()); + if (base_ssl_config_.has_value()) { + base_ssl_config_->allowed_bad_certs = job->allowed_bad_certs(); + } + } + + if (job->respect_limits() == RespectLimits::kIgnore) { + limit_ignoring_jobs_.emplace(job); + } + + if (!job->enable_ip_based_pooling()) { + ip_based_pooling_disabling_jobs_.emplace(job); + } + + if (!job->enable_alternative_services()) { + alternative_service_disabling_jobs_.emplace(job); + } + + quic_version_ = job->quic_version(); + + // JobController should check the existing QUIC/SPDY sessions before starting + // a Job. + DCHECK(!CanUseExistingQuicSession()); + DCHECK(!HasAvailableSpdySession()); + + MaybeChangeServiceEndpointRequestPriority(); RestrictAllowedProtocols(job->allowed_alpns()); UpdateTcpBasedAttemptState(); @@ -1082,7 +1077,6 @@ if (!CanUseQuic()) { // TODO(crbug.com/346835898): Use other error code? CancelQuicAttempt(ERR_ABORTED); - UpdateTcpBasedAttemptState(); } }
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index df1896c..3ab717c 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -1506,7 +1506,7 @@ // } EVENT_TYPE(HTTP_STREAM_POOL_GROUP_HANDLE_CREATED) -// Emitted when an HttpStreamPool::AttemptManager starts a stream. The event +// Emitted when an HttpStreamPool::AttemptManager requests a stream. The event // parameters are: // { // "priority": <The priority of the erquest>, @@ -1516,7 +1516,7 @@ // "quic_version": <The QUIC version to attempt>, // "source_dependency": <The source identifier of the request> // } -EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_START_JOB) +EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_REQUEST_STREAM) // Records on the caller's NetLog to indicate that an // HttpStreamPool::AttemptManager starts a Job.
diff --git a/services/webnn/tflite/graph_builder_tflite.cc b/services/webnn/tflite/graph_builder_tflite.cc index 7b99abe..47f0cc2 100644 --- a/services/webnn/tflite/graph_builder_tflite.cc +++ b/services/webnn/tflite/graph_builder_tflite.cc
@@ -1451,7 +1451,8 @@ } std::optional<GraphBuilderTflite::TensorInfo> -GraphBuilderTflite::CanFuseQuantizeAndGetOutput(const mojom::Clamp& clamp) { +GraphBuilderTflite::CanFuseQuantizeAndGetOutput(const mojom::Clamp& clamp, + bool is_emulated) { if (!IsDequantizeOutput(clamp.input_operand_id)) { return std::nullopt; } @@ -1476,6 +1477,17 @@ return std::nullopt; } + // For emulated clamp, it is emulated with min and max operations, which + // requires the input and output to have the same scale and zero_point. + // https://ai.google.dev/edge/litert/models/quantization_spec#int8_quantized_operator_specifications + if (is_emulated) { + const mojom::QuantizeLinear& output_quantize = + GetQuantizeOp(next_op->first); + if (!IsSameScaleAndZeroPoint(input_dequantize, output_quantize)) { + return std::nullopt; + } + } + return SerializeQuantizedOutput(*next_op); } @@ -3485,25 +3497,61 @@ TensorIndex output_tensor_index, base::span<const DataType> min_values, base::span<const DataType> max_values) -> OperatorOffset { + const std::array<int32_t, 1> min_values_dimensions = { + base::checked_cast<int32_t>(min_values.size())}; const TensorIndex min_value_tensor_index = - SerializeTensorWithBuffer<DataType>( - /*buffer=*/min_values, - /*dimensions=*/std::array<int32_t, 1>{ - base::checked_cast<int32_t>(min_values.size())}); + SerializeTensorWithBuffer<DataType>(min_values, min_values_dimensions); + + // If `input_tensor_info.quantize_params` is not null, it means the + // `min_values` and `max_values` should be quantized to the same data type + // with input to meet the requirements of QDQ fusion. + TensorIndex maybe_quantized_min_value_tensor_index = min_value_tensor_index; + if (!input_tensor_info.quantize_params.IsNull()) { + maybe_quantized_min_value_tensor_index = SerializeTemporaryTensor( + min_values_dimensions, input_tensor_info.data_type, + input_tensor_info.quantize_params); + const OperatorCodeIndex operator_code_index = + GetOperatorCodeIndex(::tflite::BuiltinOperator_QUANTIZE); + const std::array<TensorIndex, 1> quantize_inputs = {min_value_tensor_index}; + const std::array<TensorIndex, 1> quantize_outputs = { + maybe_quantized_min_value_tensor_index}; + operators_.emplace_back(::tflite::CreateOperator( + builder_, operator_code_index, + builder_.CreateVector<TensorIndex>(quantize_inputs), + builder_.CreateVector<TensorIndex>(quantize_outputs))); + } + const TensorIndex output_tensor_index_of_max = SerializeTemporaryTensor( - input_tensor_info.dimensions, input_tensor_info.data_type); + input_tensor_info.dimensions, input_tensor_info.data_type, + input_tensor_info.quantize_params); operators_.emplace_back(SerializeBinaryOperation( ::tflite::BuiltinOperator_MAXIMUM, input_tensor_info.index, - min_value_tensor_index, output_tensor_index_of_max)); + maybe_quantized_min_value_tensor_index, output_tensor_index_of_max)); + const std::array<int32_t, 1> max_values_dimensions = { + base::checked_cast<int32_t>(max_values.size())}; const TensorIndex max_value_tensor_index = - SerializeTensorWithBuffer<DataType>( - /*buffer=*/max_values, - /*dimensions=*/std::array<int32_t, 1>{ - base::checked_cast<int32_t>(max_values.size())}); - return SerializeBinaryOperation(::tflite::BuiltinOperator_MINIMUM, - output_tensor_index_of_max, - max_value_tensor_index, output_tensor_index); + SerializeTensorWithBuffer<DataType>(max_values, max_values_dimensions); + + TensorIndex maybe_quantized_max_value_tensor_index = max_value_tensor_index; + if (!input_tensor_info.quantize_params.IsNull()) { + maybe_quantized_max_value_tensor_index = SerializeTemporaryTensor( + max_values_dimensions, input_tensor_info.data_type, + input_tensor_info.quantize_params); + const OperatorCodeIndex operator_code_index = + GetOperatorCodeIndex(::tflite::BuiltinOperator_QUANTIZE); + const std::array<TensorIndex, 1> quantize_inputs = {max_value_tensor_index}; + const std::array<TensorIndex, 1> quantize_outputs = { + maybe_quantized_max_value_tensor_index}; + operators_.emplace_back(::tflite::CreateOperator( + builder_, operator_code_index, + builder_.CreateVector<TensorIndex>(quantize_inputs), + builder_.CreateVector<TensorIndex>(quantize_outputs))); + } + + return SerializeBinaryOperation( + ::tflite::BuiltinOperator_MINIMUM, output_tensor_index_of_max, + maybe_quantized_max_value_tensor_index, output_tensor_index); } auto GraphBuilderTflite::SerializeClamp(const mojom::Clamp& clamp) @@ -3517,7 +3565,7 @@ GetClampOperatorCode(min_value, max_value); const bool is_emulated = !operator_code.has_value(); std::optional<TensorInfo> quantized_output = - is_emulated ? std::nullopt : CanFuseQuantizeAndGetOutput(clamp); + CanFuseQuantizeAndGetOutput(clamp, is_emulated); const bool fuse_dequantize = quantized_output.has_value(); ASSIGN_OR_RETURN(const TensorInfo& input_tensor_info, SerializeInputTensorInfo(
diff --git a/services/webnn/tflite/graph_builder_tflite.h b/services/webnn/tflite/graph_builder_tflite.h index 8af8479..4852c34 100644 --- a/services/webnn/tflite/graph_builder_tflite.h +++ b/services/webnn/tflite/graph_builder_tflite.h
@@ -733,7 +733,8 @@ // op specific fusion criteria required by TFLite, if so we can remove the // preceding `dequantizeLinear` and subsequent `quantizeLinear`. std::optional<TensorInfo> CanFuseQuantizeAndGetOutput( - const mojom::Clamp& clamp); + const mojom::Clamp& clamp, + bool is_emulated); std::optional<TensorInfo> CanFuseQuantizeAndGetOutput( const mojom::Conv2d& conv2d, std::optional<OperandId> activation_output_operand_id);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index d521566..11ffb311 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -18307,6 +18307,27 @@ ] } ], + "PrewarmServiceWorkerRegistrationForDSE": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "PrewarmServiceWorkerRegistrationForDSE" + ] + } + ] + } + ], "PriceTrackingDesktopExpansionStudy": [ { "platforms": [
diff --git a/third_party/androidx/BUILD.gn b/third_party/androidx/BUILD.gn index 0cea3fb9..51137c0 100644 --- a/third_party/androidx/BUILD.gn +++ b/third_party/androidx/BUILD.gn
@@ -1317,7 +1317,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. androidx_android_aar_prebuilt("androidx_test_espresso_espresso_core_java") { - aar_path = "../androidx/cipd/libs/androidx_test_espresso_espresso_core/espresso-core-3.7.0-alpha03.aar" + aar_path = "../androidx/cipd/libs/androidx_test_espresso_espresso_core/espresso-core-3.7.0-alpha04.aar" info_path = "../androidx/committed/libs/androidx_test_espresso_espresso_core/androidx_test_espresso_espresso_core.info" enable_bytecode_checks = false testonly = true @@ -3441,7 +3441,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. androidx_android_aar_prebuilt( "androidx_test_espresso_espresso_idling_resource_java") { - aar_path = "../androidx/cipd/libs/androidx_test_espresso_espresso_idling_resource/espresso-idling-resource-3.7.0-alpha03.aar" + aar_path = "../androidx/cipd/libs/androidx_test_espresso_espresso_idling_resource/espresso-idling-resource-3.7.0-alpha04.aar" info_path = "../androidx/committed/libs/androidx_test_espresso_espresso_idling_resource/androidx_test_espresso_espresso_idling_resource.info" enable_bytecode_checks = false
diff --git a/third_party/androidx/bill_of_materials.json b/third_party/androidx/bill_of_materials.json index 8f5aed8..5df6aea 100644 --- a/third_party/androidx/bill_of_materials.json +++ b/third_party/androidx/bill_of_materials.json
@@ -962,12 +962,12 @@ { "name": "espresso-core", "group": "androidx.test.espresso", - "version": "3.7.0-alpha03" + "version": "3.7.0-alpha04" }, { "name": "espresso-idling-resource", "group": "androidx.test.espresso", - "version": "3.7.0-alpha03" + "version": "3.7.0-alpha04" }, { "name": "espresso-intents",
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle index e5d80512..619f324 100644 --- a/third_party/androidx/build.gradle +++ b/third_party/androidx/build.gradle
@@ -207,8 +207,8 @@ versionCache['androidx.startup:startup-runtime'] = '1.2.0' versionCache['androidx.swiperefreshlayout:swiperefreshlayout'] = '1.2.0-SNAPSHOT' versionCache['androidx.test.espresso:espresso-contrib'] = '3.5.1' -versionCache['androidx.test.espresso:espresso-core'] = '3.7.0-alpha03' -versionCache['androidx.test.espresso:espresso-idling-resource'] = '3.7.0-alpha03' +versionCache['androidx.test.espresso:espresso-core'] = '3.7.0-alpha04' +versionCache['androidx.test.espresso:espresso-idling-resource'] = '3.7.0-alpha04' versionCache['androidx.test.espresso:espresso-intents'] = '3.5.1' versionCache['androidx.test.espresso:espresso-web'] = '3.5.1' versionCache['androidx.test.ext:junit'] = '1.3.0-alpha03' @@ -307,7 +307,7 @@ google() maven { // This URL is generated by the fetch_all_androidx.py script. - url 'https://androidx.dev/snapshots/builds/13647192/artifacts/repository' + url 'https://androidx.dev/snapshots/builds/13649072/artifacts/repository' } mavenCentral() }
diff --git a/third_party/androidx/committed/libs/androidx_test_espresso_espresso_core/README.chromium b/third_party/androidx/committed/libs/androidx_test_espresso_espresso_core/README.chromium index fbefd82b..dc5e8f3 100644 --- a/third_party/androidx/committed/libs/androidx_test_espresso_espresso_core/README.chromium +++ b/third_party/androidx/committed/libs/androidx_test_espresso_espresso_core/README.chromium
@@ -1,7 +1,7 @@ Name: AndroidX Test Library Short Name: espresso-core URL: https://developer.android.com/testing -Version: 3.7.0-alpha03 +Version: 3.7.0-alpha04 License: Apache-2.0 License File: LICENSE CPEPrefix: unknown
diff --git a/third_party/androidx/committed/libs/androidx_test_espresso_espresso_idling_resource/README.chromium b/third_party/androidx/committed/libs/androidx_test_espresso_espresso_idling_resource/README.chromium index 4a3762d..2544db8 100644 --- a/third_party/androidx/committed/libs/androidx_test_espresso_espresso_idling_resource/README.chromium +++ b/third_party/androidx/committed/libs/androidx_test_espresso_espresso_idling_resource/README.chromium
@@ -1,7 +1,7 @@ Name: AndroidX Test Library Short Name: espresso-idling-resource URL: https://developer.android.com/testing -Version: 3.7.0-alpha03 +Version: 3.7.0-alpha04 License: Apache-2.0 License File: LICENSE CPEPrefix: unknown
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_consumer.h b/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_consumer.h index 6f1dad53..36f3d015 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_consumer.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_consumer.h
@@ -43,7 +43,7 @@ private: friend class V8CrowdsourcedCompileHintsConsumer; - WTF::BloomFilter<kBloomFilterKeySize> bloom_; + BloomFilter<kBloomFilterKeySize> bloom_; }; class DataAndScriptNameHash {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_producer.cc b/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_producer.cc index 88918c8..84355e5c 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_producer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_compile_hints_producer.cc
@@ -192,7 +192,7 @@ // containing 2 ^ 16 bits, which equals to 1024 64-bit ints. static_assert((1 << kBloomFilterKeySize) / (sizeof(int32_t) * 8) == kBloomFilterInt32Count); - WTF::BloomFilter<kBloomFilterKeySize> bloom; + BloomFilter<kBloomFilterKeySize> bloom; for (wtf_size_t script_ix = 0; script_ix < compile_hints_collectors_.size(); ++script_ix) {
diff --git a/third_party/blink/renderer/core/css/check_pseudo_has_fast_reject_filter.h b/third_party/blink/renderer/core/css/check_pseudo_has_fast_reject_filter.h index 09711c2..3e161bf 100644 --- a/third_party/blink/renderer/core/css/check_pseudo_has_fast_reject_filter.h +++ b/third_party/blink/renderer/core/css/check_pseudo_has_fast_reject_filter.h
@@ -37,7 +37,7 @@ // doesn't contain the hash for '.b'. class CORE_EXPORT CheckPseudoHasFastRejectFilter { public: - using FastRejectFilter = WTF::BloomFilter<12>; + using FastRejectFilter = BloomFilter<12>; CheckPseudoHasFastRejectFilter() = default; CheckPseudoHasFastRejectFilter(CheckPseudoHasFastRejectFilter&) = delete;
diff --git a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data.h b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data.h index 0cf9b8b..7905f74 100644 --- a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data.h +++ b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data.h
@@ -263,7 +263,7 @@ // seems a bit narrow in practice. InvalidationSetMap class_invalidation_sets; - std::unique_ptr<WTF::BloomFilter<14>> names_with_self_invalidation; + std::unique_ptr<BloomFilter<14>> names_with_self_invalidation; static constexpr int kClassSalt = 13; static constexpr int kIdSalt = 29;
diff --git a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_builder.cc b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_builder.cc index 7d69845..4efed3c 100644 --- a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_builder.cc +++ b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_builder.cc
@@ -18,7 +18,7 @@ if (other.names_with_self_invalidation) { if (rule_invalidation_data_.names_with_self_invalidation == nullptr) { rule_invalidation_data_.names_with_self_invalidation = - std::make_unique<WTF::BloomFilter<14>>(); + std::make_unique<BloomFilter<14>>(); } rule_invalidation_data_.names_with_self_invalidation->Merge( *other.names_with_self_invalidation);
diff --git a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc index 14173d50..a4a33069 100644 --- a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc +++ b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc
@@ -1977,7 +1977,7 @@ return false; } else { rule_invalidation_data_.names_with_self_invalidation = - std::make_unique<WTF::BloomFilter<14>>(); + std::make_unique<BloomFilter<14>>(); } } rule_invalidation_data_.names_with_self_invalidation->Add(value.Hash() *
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h index 0148e7b..de196c4 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -145,7 +145,7 @@ CHECK(IsWebGPU()); return ResourceProviderDEPRECATED(); } - CanvasResourceProvider* GetResourceProviderForCanvas2D() const { + CanvasResourceProvider* GetResourceProviderForCanvas2D() const override { CHECK(IsRenderingContext2D()); return ResourceProviderDEPRECATED(); }
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc index dd24101..38cae95 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -57,7 +57,7 @@ } // anonymous namespace // With 100 unique strings, a 2^12 slot table has a false positive rate of ~2%. -using ClassnameFilter = WTF::BloomFilter<12>; +using ClassnameFilter = BloomFilter<12>; using Corner = ScrollAnchor::Corner; SerializedAnchor::SerializedAnchor(const ScrollAnchorData& data,
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc index ee9412fd..88cd666 100644 --- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc +++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -536,24 +536,93 @@ CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProviderForImageBitmap() { CHECK(IsImageBitmapRenderingContext()); - return GetOrCreateResourceProviderForCanvas2DOrImageBitmap(); -} - -CanvasResourceProvider* -OffscreenCanvas::GetOrCreateResourceProviderForCanvas2D() { - CHECK(IsRenderingContext2D()); - return GetOrCreateResourceProviderForCanvas2DOrImageBitmap(); -} - -CanvasResourceProvider* -OffscreenCanvas::GetOrCreateResourceProviderForCanvas2DOrImageBitmap() { - CHECK(IsRenderingContext2D() || IsImageBitmapRenderingContext()); if (!context_ || (context_->isContextLost() && !context_->IsContextBeingRestored())) { return nullptr; } - if (CanvasResourceProvider* provider = ResourceProviderDEPRECATED()) { + if (CanvasResourceProvider* provider = GetResourceProviderForImageBitmap()) { + if (!provider->IsValid()) { + // The canvas context is not lost but the provider is invalid. This + // happens if the GPU process dies in the middle of a render task. The + // canvas is notified of GPU context losses via the `NotifyGpuContextLost` + // callback and restoration happens in `TryRestoreContextEvent`. Both + // callbacks are executed in their own separate task. If the GPU context + // goes invalid in the middle of a render task, the canvas won't + // immediately know about it and canvas APIs will continue using the + // provider that is now invalid. We can early return here, trying to + // re-create the provider right away would just fail. We need to let + // `TryRestoreContextEvent` wait for the GPU process to up again. + return nullptr; + } + return provider; + } + + if (!IsValidImageSize() && !Size().IsEmpty()) { + context_->LoseContext(CanvasRenderingContext::kInvalidCanvasSize); + return nullptr; + } + + std::unique_ptr<CanvasResourceProvider> provider; + gfx::Size surface_size(width(), height()); + const SkAlphaType alpha_type = GetRenderingContextAlphaType(); + const viz::SharedImageFormat format = GetRenderingContextFormat(); + const gfx::ColorSpace color_space = GetRenderingContextColorSpace(); + if (SharedGpuContext::IsGpuCompositingEnabled()) { + provider = CanvasResourceProvider::CreateSharedImageProvider( + Size(), format, alpha_type, color_space, + CanvasResourceProvider::ShouldInitialize::kCallClear, + SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU, + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ, this); + } else if (HasPlaceholderCanvas()) { + base::WeakPtr<CanvasResourceDispatcher> dispatcher_weakptr = + GetOrCreateResourceDispatcher()->GetWeakPtr(); + provider = + CanvasResourceProvider::CreateSharedImageProviderForSoftwareCompositor( + Size(), format, alpha_type, color_space, + CanvasResourceProvider::ShouldInitialize::kCallClear, + SharedGpuContext::SharedImageInterfaceProvider(), this); + } + + if (!provider) { + // Last resort fallback is to use the bitmap provider. Using this + // path is normal for software-rendered OffscreenCanvases that have no + // placeholder canvas. If there is a placeholder, its content will not be + // visible on screen, but at least readbacks will work. Failure to create + // another type of resource prover above is a sign that the graphics + // pipeline is in a bad state (e.g. gpu process crashed, out of memory) + provider = CanvasResourceProvider::CreateBitmapProvider( + Size(), format, alpha_type, color_space, + CanvasResourceProvider::ShouldInitialize::kCallClear, this); + } + + ReplaceResourceProvider(std::move(provider)); + + if (GetResourceProviderForImageBitmap() && + GetResourceProviderForImageBitmap()->IsValid()) { + // todo(crbug.com/1064363) Add a separate UMA for Offscreen Canvas usage + // and understand if the if (ResourceProvider() && + // ResourceProvider()->IsValid()) is really needed. + base::UmaHistogramBoolean( + "Blink.Canvas.ResourceProviderIsAccelerated", + GetResourceProviderForImageBitmap()->IsAccelerated()); + base::UmaHistogramEnumeration( + "Blink.Canvas.ResourceProviderType", + GetResourceProviderForImageBitmap()->GetType()); + DidDraw(); + } + return GetResourceProviderForImageBitmap(); +} + +CanvasResourceProvider* +OffscreenCanvas::GetOrCreateResourceProviderForCanvas2D() { + CHECK(IsRenderingContext2D()); + if (!context_ || + (context_->isContextLost() && !context_->IsContextBeingRestored())) { + return nullptr; + } + + if (CanvasResourceProvider* provider = GetResourceProviderForCanvas2D()) { if (!provider->IsValid()) { // The canvas context is not lost but the provider is invalid. This // happens if the GPU process dies in the middle of a render task. The @@ -579,18 +648,16 @@ gfx::Size surface_size(width(), height()); const bool can_use_gpu = SharedGpuContext::IsGpuCompositingEnabled() && - (IsImageBitmapRenderingContext() || - (RuntimeEnabledFeatures::Accelerated2dCanvasEnabled() && - !(context_->CreationAttributes().will_read_frequently == - CanvasContextCreationAttributesCore::WillReadFrequently::kTrue))); + RuntimeEnabledFeatures::Accelerated2dCanvasEnabled() && + !(context_->CreationAttributes().will_read_frequently == + CanvasContextCreationAttributesCore::WillReadFrequently::kTrue); const bool use_shared_image = can_use_gpu || (HasPlaceholderCanvas() && SharedGpuContext::IsGpuCompositingEnabled()); const bool use_scanout = use_shared_image && HasPlaceholderCanvas() && SharedGpuContext::MaySupportImageChromium() && - (IsRenderingContext2D() && - RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled()); + RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled(); gpu::SharedImageUsageSet shared_image_usage_flags = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ; @@ -633,17 +700,19 @@ ReplaceResourceProvider(std::move(provider)); - if (ResourceProviderDEPRECATED() && ResourceProviderDEPRECATED()->IsValid()) { + if (GetResourceProviderForCanvas2D() && + GetResourceProviderForCanvas2D()->IsValid()) { // todo(crbug/1064363) Add a separate UMA for Offscreen Canvas usage and // understand if the if (ResourceProvider() && // ResourceProvider()->IsValid()) is really needed. - base::UmaHistogramBoolean("Blink.Canvas.ResourceProviderIsAccelerated", - ResourceProviderDEPRECATED()->IsAccelerated()); + base::UmaHistogramBoolean( + "Blink.Canvas.ResourceProviderIsAccelerated", + GetResourceProviderForCanvas2D()->IsAccelerated()); base::UmaHistogramEnumeration("Blink.Canvas.ResourceProviderType", - ResourceProviderDEPRECATED()->GetType()); + GetResourceProviderForCanvas2D()->GetType()); DidDraw(); } - return ResourceProviderDEPRECATED(); + return GetResourceProviderForCanvas2D(); } void OffscreenCanvas::DidDraw(const SkIRect& rect) {
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h index 0e5654b..d247312 100644 --- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h +++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -207,6 +207,11 @@ void Trace(Visitor*) const override; + CanvasResourceProvider* GetResourceProviderForImageBitmap() { + CHECK(IsImageBitmapRenderingContext()); + return ResourceProviderDEPRECATED(); + } + class ScopedInsideWorkerRAF { STACK_ALLOCATED(); @@ -261,7 +266,6 @@ static ContextFactoryVector& RenderingContextFactories(); static CanvasRenderingContextFactory* GetRenderingContextFactory(int); - CanvasResourceProvider* GetOrCreateResourceProviderForCanvas2DOrImageBitmap(); void RecordIdentifiabilityMetric(const blink::IdentifiableSurface& surface, const IdentifiableToken& token) const;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc index 6d80c21..c940fa8 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -293,7 +293,7 @@ !host) { return; } - DCHECK(!host->ResourceProviderDEPRECATED()); + DCHECK(!host->GetResourceProviderForCanvas2D()); if (host->IsValidImageSize()) { if (dispatch_context_lost_event_timer_.IsActive()) { @@ -797,7 +797,7 @@ BaseRenderingContext2D::PaintRenderingResultsToSnapshot( SourceDrawingBuffer source_buffer, FlushReason reason) { - CanvasResourceProvider* provider = Host()->ResourceProviderDEPRECATED(); + CanvasResourceProvider* provider = Host()->GetResourceProviderForCanvas2D(); return provider ? provider->Snapshot(reason) : nullptr; } @@ -1504,7 +1504,7 @@ gpu::SyncToken canvas_access_sync_token; bool performed_copy = false; scoped_refptr<gpu::ClientSharedImage> client_si = - host->ResourceProviderDEPRECATED() + host->GetResourceProviderForCanvas2D() ->GetBackingClientSharedImageForExternalWrite( &canvas_access_sync_token, gpu::SHARED_IMAGE_USAGE_WEBGPU_READ | @@ -1587,7 +1587,7 @@ // If this canvas already has a resource provider, this means that drawing has // occurred after `transferToWebGPU`. We disallow transferring back in this // case, and raise an exception instead. - if (host->ResourceProviderDEPRECATED()) { + if (host->GetResourceProviderForCanvas2D()) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidStateError, "The canvas was touched after transferToGPUTexture.");
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h index 17abb22..ec26fc7 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
@@ -158,7 +158,7 @@ // CanvasRenderingContext implementation int AllocatedBufferCountPerPixel() override { - return (Host() && Host()->ResourceProviderDEPRECATED()) ? 1 : 0; + return (Host() && Host()->GetResourceProviderForCanvas2D()) ? 1 : 0; } int Width() const final;
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc index 0e2687a..153004ad 100644 --- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
@@ -147,11 +147,12 @@ } cc::PaintFlags paint_flags; paint_flags.setBlendMode(SkBlendMode::kSrc); - Host()->ResourceProviderDEPRECATED()->Canvas().drawImage( + OffscreenCanvas* canvas = static_cast<OffscreenCanvas*>(Host()); + canvas->GetResourceProviderForImageBitmap()->Canvas().drawImage( image->PaintImageForCurrentFrame(), 0, 0, SkSamplingOptions(), &paint_flags); scoped_refptr<CanvasResource> resource = - Host()->ResourceProviderDEPRECATED()->ProduceCanvasResource( + canvas->GetResourceProviderForImageBitmap()->ProduceCanvasResource( FlushReason::kNon2DCanvas); Host()->PushFrame( std::move(resource),
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc index 461f71c..037a2bb0 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc
@@ -3495,7 +3495,7 @@ // Front and back buffers. int buffer_count = 2; - if (Host()->ResourceProviderDEPRECATED()) { + if (Host()->GetResourceProviderForWebGL()) { buffer_count++; }
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 92eca37..8e39d4f 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1811,7 +1811,6 @@ "//services/viz/public/cpp/gpu", "//skia", "//skia:skcms", - "//third_party:freetype_buildflags", "//third_party:freetype_harfbuzz", "//third_party/abseil-cpp:absl", "//third_party/blink/public:image_resources",
diff --git a/third_party/blink/renderer/platform/fonts/simple_font_data.cc b/third_party/blink/renderer/platform/fonts/simple_font_data.cc index 32030b9..b308719a 100644 --- a/third_party/blink/renderer/platform/fonts/simple_font_data.cc +++ b/third_party/blink/renderer/platform/fonts/simple_font_data.cc
@@ -52,7 +52,6 @@ #include "third_party/blink/renderer/platform/wtf/math_extras.h" #include "third_party/blink/renderer/platform/wtf/text/character_names.h" #include "third_party/blink/renderer/platform/wtf/text/unicode.h" -#include "third_party/freetype_buildflags.h" #include "third_party/skia/include/core/SkFont.h" #include "third_party/skia/include/core/SkFontMetrics.h" #include "third_party/skia/include/core/SkPath.h" @@ -62,23 +61,14 @@ #include "ui/gfx/geometry/skia_conversions.h" #include "v8/include/v8.h" -#if !BUILDFLAG(USE_SYSTEM_FREETYPE) && BUILDFLAG(ENABLE_FREETYPE) -#include "third_party/freetype/src/src/autofit/afws-decl.h" -#endif - namespace blink { constexpr float kSmallCapsFontSizeMultiplier = 0.7f; constexpr float kEmphasisMarkFontSizeMultiplier = 0.5f; -#if !BUILDFLAG(USE_SYSTEM_FREETYPE) && BUILDFLAG(ENABLE_FREETYPE) -constexpr int32_t kFontObjectsMemoryConsumption = - std::max(sizeof(AF_LatinMetricsRec), sizeof(AF_CJKMetricsRec)); -#else // sizeof(AF_LatinMetricsRec) = 2128 // TODO(drott): Measure a new number for Fontations. constexpr int32_t kFontObjectsMemoryConsumption = 2128; -#endif SimpleFontData::SimpleFontData(const FontPlatformData* platform_data, const CustomFontData* custom_data,
diff --git a/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc b/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc index c4dce0909..2588cc2 100644 --- a/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc +++ b/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.cc
@@ -10,7 +10,6 @@ #include "skia/ext/font_utils.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/fonts/opentype/font_format_check.h" -#include "third_party/freetype_buildflags.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/ports/SkTypeface_fontations.h"
diff --git a/third_party/blink/renderer/platform/geometry/contoured_rect.cc b/third_party/blink/renderer/platform/geometry/contoured_rect.cc index 920f7392..4ae7bac1 100644 --- a/third_party/blink/renderer/platform/geometry/contoured_rect.cc +++ b/third_party/blink/renderer/platform/geometry/contoured_rect.cc
@@ -181,7 +181,7 @@ // The resulting "aligned" corner has its coordinates and curvature adjusted // in such a way that it would have consistent thickness along its entire path. Corner ContouredRect::Corner::AlignedToOrigin(const Corner& origin) const { - if (origin.IsZero() || *this == origin) { + if (origin.IsEmpty() || *this == origin) { return *this; }
diff --git a/third_party/blink/renderer/platform/geometry/contoured_rect.h b/third_party/blink/renderer/platform/geometry/contoured_rect.h index 4b1468f..91ef1ab 100644 --- a/third_party/blink/renderer/platform/geometry/contoured_rect.h +++ b/third_party/blink/renderer/platform/geometry/contoured_rect.h
@@ -139,6 +139,9 @@ } constexpr bool IsConcave() const { return curvature_ < 1; } constexpr bool IsZero() const { return Start() == End(); } + constexpr bool IsEmpty() const { + return v1().Length() == 0 || v2().Length() == 0; + } constexpr bool operator==(const Corner&) const = default; // Invert the curvature
diff --git a/third_party/blink/renderer/platform/geometry/path_builder.cc b/third_party/blink/renderer/platform/geometry/path_builder.cc index 73bdfe8..1056b13 100644 --- a/third_party/blink/renderer/platform/geometry/path_builder.cc +++ b/third_party/blink/renderer/platform/geometry/path_builder.cc
@@ -71,7 +71,7 @@ // Start the path from the beginning of the curve. path.lineTo(gfx::PointFToSkPoint(corner.Start())); - if (corner.IsStraight()) { + if (corner.IsStraight() || corner.IsEmpty()) { // Straight or very close to it, draw two lines. path.lineTo(gfx::PointFToSkPoint(corner.Outer())); path.lineTo(gfx::PointFToSkPoint(corner.End())); @@ -336,7 +336,7 @@ ContouredRect origin_contoured_rect(origin_rect, contoured_rect.GetCornerCurvature()); - if (!origin_rect.GetRadii().TopRight().IsZero()) { + if (!origin_rect.GetRadii().TopRight().IsEmpty()) { SkPath path; path.moveTo(infinite_rect.left(), infinite_rect.top()); AddCurvedCorner(path, contoured_rect.TopRightCorner()); @@ -346,7 +346,7 @@ op_builder.add(path, kIntersect_SkPathOp); } - if (!origin_rect.GetRadii().BottomRight().IsZero()) { + if (!origin_rect.GetRadii().BottomRight().IsEmpty()) { SkPath path; path.moveTo(infinite_rect.right(), infinite_rect.top()); AddCurvedCorner(path, contoured_rect.BottomRightCorner()); @@ -356,7 +356,7 @@ op_builder.add(path, kIntersect_SkPathOp); } - if (!origin_rect.GetRadii().BottomLeft().IsZero()) { + if (!origin_rect.GetRadii().BottomLeft().IsEmpty()) { SkPath path; path.moveTo(infinite_rect.right(), infinite_rect.bottom()); AddCurvedCorner(path, contoured_rect.BottomLeftCorner()); @@ -366,7 +366,7 @@ op_builder.add(path, kIntersect_SkPathOp); } - if (!origin_rect.GetRadii().TopLeft().IsZero()) { + if (!origin_rect.GetRadii().TopLeft().IsEmpty()) { SkPath path; path.moveTo(infinite_rect.left(), infinite_rect.bottom()); AddCurvedCorner(path, contoured_rect.TopLeftCorner()); @@ -377,7 +377,8 @@ } SkPath result; - CHECK(op_builder.resolve(&result)); + CHECK(op_builder.resolve(&result)) + << contoured_rect.ToString() << " " << origin_rect.ToString(); builder_.addPath(result); current_path_.reset(); return *this;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler.cc b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler.cc index e07fc58..6f48a55 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler.cc
@@ -407,7 +407,7 @@ hibernation_scheduled_ = false; CanvasResourceProvider* provider = - resource_host_->ResourceProviderDEPRECATED(); + resource_host_->GetResourceProviderForCanvas2D(); if (!provider) { ReportHibernationEvent( HibernationEvent::kHibernationAbortedBecauseNoSurface);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc index 648a11b3..f637bd7 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc
@@ -87,10 +87,11 @@ if (!page_visible) { // Trigger hibernation. scoped_refptr<StaticBitmapImage> snapshot = - host->ResourceProviderDEPRECATED()->Snapshot(FlushReason::kHibernating); + host->GetResourceProviderForCanvas2D()->Snapshot( + FlushReason::kHibernating); hibernation_handler->SaveForHibernation( snapshot->PaintImageForCurrentFrame().GetSwSkImage(), - host->ResourceProviderDEPRECATED()->ReleaseRecorder()); + host->GetResourceProviderForCanvas2D()->ReleaseRecorder()); EXPECT_TRUE(hibernation_handler->IsHibernating()); } else { // End hibernation. @@ -231,7 +232,7 @@ EXPECT_TRUE(host.GetRasterMode() == RasterMode::kGPU); EXPECT_FALSE(handler.IsHibernating()); - EXPECT_TRUE(host.ResourceProviderDEPRECATED()->IsValid()); + EXPECT_TRUE(host.GetResourceProviderForCanvas2D()->IsValid()); } TEST_P(CanvasHibernationHandlerTest, ForegroundTooEarly) {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h index a112ecdd..5eb716f4 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
@@ -63,6 +63,8 @@ virtual bool LowLatencyEnabled() const { return false; } + virtual CanvasResourceProvider* GetResourceProviderForCanvas2D() const = 0; + // TODO(crbug.com/352263194): Transition all usages of this method to // context-specific variants and eliminate the method. CanvasResourceProvider* ResourceProviderDEPRECATED() const {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc index a2541f4e..f4e4d517 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -157,13 +157,12 @@ } // These SharedImages are read and written by WebGPU clients and can then be - // sent off to the display compositor. They can also be read over raster - // interface as part of video frame. + // sent off to the display compositor. gpu::SharedImageUsageSet usage = gpu::SHARED_IMAGE_USAGE_WEBGPU_READ | gpu::SHARED_IMAGE_USAGE_WEBGPU_WRITE | gpu::SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE | - gpu::SHARED_IMAGE_USAGE_RASTER_READ | GetSharedImageUsagesForDisplay(); + GetSharedImageUsagesForDisplay(); if (usage_ & wgpu::TextureUsage::StorageBinding) { usage |= gpu::SHARED_IMAGE_USAGE_WEBGPU_STORAGE_TEXTURE; } @@ -171,9 +170,10 @@ wgpu::AdapterInfo adapter_info; device_.GetAdapter().GetInfo(&adapter_info); if (adapter_info.adapterType == wgpu::AdapterType::CPU) { - // When using the fallback adapter, service-side writes of the + // When using the fallback adapter, service-side reads and writes of the // SharedImage occur via Skia with copies from/to Dawn textures. - usage |= gpu::SHARED_IMAGE_USAGE_RASTER_WRITE; + usage |= gpu::SHARED_IMAGE_USAGE_RASTER_READ | + gpu::SHARED_IMAGE_USAGE_RASTER_WRITE; } gpu::ImageInfo info = {size,
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h b/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h index dee9234..dcfbcb2 100644 --- a/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h +++ b/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h
@@ -34,11 +34,16 @@ void SetIsHibernating(bool is_hibernating) { is_hibernating_ = is_hibernating; } + + CanvasResourceProvider* GetResourceProviderForCanvas2D() const override { + return ResourceProviderDEPRECATED(); + } + size_t GetMemoryUsage() const override { return 0; } CanvasResourceProvider* GetOrCreateCanvasResourceProviderForCanvas2D() override { - if (ResourceProviderDEPRECATED()) { - return ResourceProviderDEPRECATED(); + if (GetResourceProviderForCanvas2D()) { + return GetResourceProviderForCanvas2D(); } constexpr auto kShouldInitialize = CanvasResourceProvider::ShouldInitialize::kCallClear; @@ -65,7 +70,7 @@ ReplaceResourceProvider(std::move(provider)); - return ResourceProviderDEPRECATED(); + return GetResourceProviderForCanvas2D(); } void SetPageVisible(bool visible) {
diff --git a/third_party/blink/renderer/platform/testing/video_frame_utils.cc b/third_party/blink/renderer/platform/testing/video_frame_utils.cc index 8c7a81b..5775b14 100644 --- a/third_party/blink/renderer/platform/testing/video_frame_utils.cc +++ b/third_party/blink/renderer/platform/testing/video_frame_utils.cc
@@ -45,8 +45,7 @@ << media::VideoPixelFormatToString(pixel_format) << " has no corresponding gfx::BufferFormat"; const auto si_usage = gpu::SHARED_IMAGE_USAGE_CPU_WRITE_ONLY | - gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | - gpu::SHARED_IMAGE_USAGE_RASTER_READ; + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ; auto shared_image = test_sii->CreateSharedImage( {viz::GetSharedImageFormat(*buffer_format), coded_size, gfx::ColorSpace(), gpu::SharedImageUsageSet(si_usage),
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter.h b/third_party/blink/renderer/platform/wtf/bloom_filter.h index 95d2d29..2b12c2e 100644 --- a/third_party/blink/renderer/platform/wtf/bloom_filter.h +++ b/third_party/blink/renderer/platform/wtf/bloom_filter.h
@@ -36,7 +36,7 @@ #include "base/dcheck_is_on.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -namespace WTF { +namespace blink { // Bloom filter with k=2. Uses 2^keyBits/8 bytes of memory. // False positive rate is approximately (1-e^(-2n/m))^2, where n is the number @@ -140,6 +140,6 @@ bit_array_[BitArrayIndex(key)] |= BitMask(key); } -} // namespace WTF +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BLOOM_FILTER_H_
diff --git a/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc b/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc index 9c6d48a..f6171d7 100644 --- a/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc +++ b/third_party/blink/renderer/platform/wtf/bloom_filter_test.cc
@@ -7,7 +7,7 @@ #include "testing/gtest/include/gtest/gtest.h" -namespace WTF { +namespace blink { class BloomFilterTest : public ::testing::Test { protected: @@ -108,4 +108,4 @@ EXPECT_FALSE(filter.MayContain(charlie)); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/encoding_tables.cc b/third_party/blink/renderer/platform/wtf/text/encoding_tables.cc index 7ee29a16..5bbd8bd 100644 --- a/third_party/blink/renderer/platform/wtf/text/encoding_tables.cc +++ b/third_party/blink/renderer/platform/wtf/text/encoding_tables.cc
@@ -156,7 +156,7 @@ size_t array_index = 0; UErrorCode error = U_ZERO_ERROR; - ICUConverterWrapper icu_converter; + blink::IcuConverterWrapper icu_converter; icu_converter.converter = ucnv_open("EUC-JP", &error); DCHECK(U_SUCCESS(error)); @@ -214,7 +214,7 @@ size_t array_index = 0; UErrorCode error = U_ZERO_ERROR; - ICUConverterWrapper icu_converter; + blink::IcuConverterWrapper icu_converter; icu_converter.converter = ucnv_open("EUC-JP", &error); DCHECK(U_SUCCESS(error)); @@ -256,7 +256,7 @@ std::call_once(flag, [] { array = new EucKrEncodeIndex; UErrorCode error = U_ZERO_ERROR; - ICUConverterWrapper icu_converter; + blink::IcuConverterWrapper icu_converter; icu_converter.converter = ucnv_open("windows-949", &error); DCHECK(U_SUCCESS(error)); auto get_pair = @@ -316,7 +316,7 @@ std::call_once(flag, [] { array = new Gb18030EncodeTable; UErrorCode error = U_ZERO_ERROR; - ICUConverterWrapper icu_converter; + blink::IcuConverterWrapper icu_converter; icu_converter.converter = ucnv_open("gb18030", &error); DCHECK(U_SUCCESS(error)); for (size_t pointer = 0; pointer < 23940; pointer++) {
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc index 67b9455..5cb77de9 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
@@ -46,22 +46,23 @@ #include "third_party/blink/renderer/platform/wtf/text/text_codec_cjk.h" #include "third_party/blink/renderer/platform/wtf/threading.h" -namespace WTF { +namespace blink { const size_t kConversionBufferSize = 16384; -ICUConverterWrapper::~ICUConverterWrapper() { +IcuConverterWrapper::~IcuConverterWrapper() { if (converter) ucnv_close(converter); } -static UConverter*& CachedConverterICU() { - return WtfThreading().CachedConverterICU().converter; +static UConverter*& CachedConverterIcu() { + return WtfThreading().CachedConverterIcu().converter; } -std::unique_ptr<TextCodec> TextCodecICU::Create(const TextEncoding& encoding, - const void*) { - return base::WrapUnique(new TextCodecICU(encoding)); +std::unique_ptr<TextCodec> TextCodecIcu::Create( + const WTF::TextEncoding& encoding, + const void*) { + return base::WrapUnique(new TextCodecIcu(encoding)); } namespace { @@ -81,7 +82,7 @@ } } // namespace -void TextCodecICU::RegisterEncodingNames(EncodingNameRegistrar registrar) { +void TextCodecIcu::RegisterEncodingNames(EncodingNameRegistrar registrar) { // We register Hebrew with logical ordering using a separate name. // Otherwise, this would share the same canonical name as the // visual ordering case, and then TextEncoding could not tell them @@ -120,7 +121,7 @@ } #endif // Avoid codecs supported by `TextCodecCJK`. - if (TextCodecCJK::IsSupported(standard_name)) { + if (WTF::TextCodecCJK::IsSupported(standard_name)) { continue; } @@ -153,7 +154,7 @@ // Avoid registering codecs registered by // `TextCodecCJK::RegisterEncodingNames`. - if (!TextCodecCJK::IsSupported(standard_name)) { + if (!WTF::TextCodecCJK::IsSupported(standard_name)) { registrar(standard_name, standard_name); } @@ -270,7 +271,7 @@ #endif } -void TextCodecICU::RegisterCodecs(TextCodecRegistrar registrar) { +void TextCodecIcu::RegisterCodecs(TextCodecRegistrar registrar) { // See comment above in registerEncodingNames. registrar("ISO-8859-8-I", Create, nullptr); @@ -295,23 +296,23 @@ } #endif // Avoid codecs supported by `TextCodecCJK`. - if (TextCodecCJK::IsSupported(standard_name)) { + if (WTF::TextCodecCJK::IsSupported(standard_name)) { continue; } registrar(standard_name, Create, nullptr); } } -TextCodecICU::TextCodecICU(const TextEncoding& encoding) +TextCodecIcu::TextCodecIcu(const WTF::TextEncoding& encoding) : encoding_(encoding) {} -TextCodecICU::~TextCodecICU() { - ReleaseICUConverter(); +TextCodecIcu::~TextCodecIcu() { + ReleaseIcuConverter(); } -void TextCodecICU::ReleaseICUConverter() const { +void TextCodecIcu::ReleaseIcuConverter() const { if (converter_icu_) { - UConverter*& cached_converter = CachedConverterICU(); + UConverter*& cached_converter = CachedConverterIcu(); if (cached_converter) ucnv_close(cached_converter); cached_converter = converter_icu_; @@ -319,7 +320,7 @@ } } -void TextCodecICU::CreateICUConverter() const { +void TextCodecIcu::CreateIcuConverter() const { DCHECK(!converter_icu_); #if defined(USING_SYSTEM_ICU) @@ -330,11 +331,11 @@ UErrorCode err; - UConverter*& cached_converter = CachedConverterICU(); + UConverter*& cached_converter = CachedConverterIcu(); if (cached_converter) { err = U_ZERO_ERROR; const char* cached_name = ucnv_getName(cached_converter, &err); - if (U_SUCCESS(err) && encoding_ == TextEncoding(cached_name)) { + if (U_SUCCESS(err) && encoding_ == WTF::TextEncoding(cached_name)) { converter_icu_ = cached_converter; cached_converter = nullptr; return; @@ -349,7 +350,7 @@ ucnv_setFallback(converter_icu_, true); } -int TextCodecICU::DecodeToBuffer(UChar* target, +int TextCodecIcu::DecodeToBuffer(UChar* target, UChar* target_limit, const char*& source, const char* source_limit, @@ -396,13 +397,13 @@ UConverterToUCallback saved_action_; }; -String TextCodecICU::Decode(base::span<const uint8_t> data, +String TextCodecIcu::Decode(base::span<const uint8_t> data, FlushBehavior flush, bool stop_on_error, bool& saw_error) { // Get a converter for the passed-in encoding. if (!converter_icu_) { - CreateICUConverter(); + CreateIcuConverter(); DCHECK(converter_icu_); if (!converter_icu_) { DLOG(ERROR) @@ -511,7 +512,7 @@ UErrorCode* err) { FormatEscapedEntityCallback(context, from_u_args, code_units, length, code_point, reason, err, - kEntitiesForUnencodables); + UnencodableHandling::kEntitiesForUnencodables); } // Invalid character handler when writing escaped entities in CSS encoding for @@ -524,9 +525,9 @@ UChar32 code_point, UConverterCallbackReason reason, UErrorCode* err) { - FormatEscapedEntityCallback(context, from_u_args, code_units, length, - code_point, reason, err, - kCSSEncodedEntitiesForUnencodables); + FormatEscapedEntityCallback( + context, from_u_args, code_units, length, code_point, reason, err, + UnencodableHandling::kCSSEncodedEntitiesForUnencodables); } // Invalid character handler when writing escaped entities in HTML/XML encoding @@ -539,9 +540,9 @@ UChar32 code_point, UConverterCallbackReason reason, UErrorCode* err) { - FormatEscapedEntityCallback(context, from_u_args, code_units, length, - code_point, reason, err, - kURLEncodedEntitiesForUnencodables); + FormatEscapedEntityCallback( + context, from_u_args, code_units, length, code_point, reason, err, + UnencodableHandling::kURLEncodedEntitiesForUnencodables); } #if defined(USING_SYSTEM_ICU) @@ -645,12 +646,12 @@ STACK_ALLOCATED(); public: - TextCodecInput(const TextEncoding& encoding, + TextCodecInput(const WTF::TextEncoding& encoding, base::span<const UChar> characters) : begin_(characters.data()), end_(characters.data() + characters.size()) {} - TextCodecInput(const TextEncoding& encoding, + TextCodecInput(const WTF::TextEncoding& encoding, base::span<const LChar> characters) { buffer_.ReserveInitialCapacity( base::checked_cast<wtf_size_t>(characters.size())); @@ -668,7 +669,7 @@ Vector<UChar> buffer_; }; -std::string TextCodecICU::EncodeInternal(const TextCodecInput& input, +std::string TextCodecIcu::EncodeInternal(const TextCodecInput& input, UnencodableHandling handling) { const UChar* source = input.begin(); const UChar* end = input.end(); @@ -676,7 +677,7 @@ UErrorCode err = U_ZERO_ERROR; switch (handling) { - case kEntitiesForUnencodables: + case UnencodableHandling::kEntitiesForUnencodables: #if !defined(USING_SYSTEM_ICU) ucnv_setFromUCallBack(converter_icu_, NumericEntityCallback, nullptr, nullptr, nullptr, &err); @@ -687,7 +688,7 @@ 0, 0, &err); #endif break; - case kURLEncodedEntitiesForUnencodables: + case UnencodableHandling::kURLEncodedEntitiesForUnencodables: #if !defined(USING_SYSTEM_ICU) ucnv_setFromUCallBack(converter_icu_, UrlEscapedEntityCallback, nullptr, nullptr, nullptr, &err); @@ -698,7 +699,7 @@ 0, 0, 0, &err); #endif break; - case kCSSEncodedEntitiesForUnencodables: + case UnencodableHandling::kCSSEncodedEntitiesForUnencodables: #if !defined(USING_SYSTEM_ICU) ucnv_setFromUCallBack(converter_icu_, CssEscapedEntityCallback, nullptr, nullptr, nullptr, &err); @@ -709,7 +710,7 @@ 0, 0, 0, &err); #endif break; - case kNoUnencodables: + case UnencodableHandling::kNoUnencodables: DCHECK(encoding_ == UTF16BigEndianEncoding() || encoding_ == UTF16LittleEndianEncoding() || encoding_ == UTF8Encoding()); @@ -741,14 +742,14 @@ } template <typename CharType> -std::string TextCodecICU::EncodeCommon(base::span<const CharType> characters, +std::string TextCodecIcu::EncodeCommon(base::span<const CharType> characters, UnencodableHandling handling) { if (characters.empty()) { return ""; } if (!converter_icu_) - CreateICUConverter(); + CreateIcuConverter(); if (!converter_icu_) return std::string(); @@ -756,14 +757,14 @@ return EncodeInternal(input, handling); } -std::string TextCodecICU::Encode(base::span<const UChar> characters, +std::string TextCodecIcu::Encode(base::span<const UChar> characters, UnencodableHandling handling) { return EncodeCommon(characters, handling); } -std::string TextCodecICU::Encode(base::span<const LChar> characters, +std::string TextCodecIcu::Encode(base::span<const LChar> characters, UnencodableHandling handling) { return EncodeCommon(characters, handling); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h index 841f87bc..a68cdd0 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.h
@@ -33,22 +33,22 @@ #include "third_party/blink/renderer/platform/wtf/text/text_codec.h" #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h" -typedef struct UConverter UConverter; +using UConverter = struct UConverter; -namespace WTF { +namespace blink { class TextCodecInput; -class TextCodecICU final : public TextCodec { +class TextCodecIcu final : public TextCodec { public: static void RegisterEncodingNames(EncodingNameRegistrar); static void RegisterCodecs(TextCodecRegistrar); - ~TextCodecICU() override; + ~TextCodecIcu() override; private: - TextCodecICU(const TextEncoding&); - WTF_EXPORT static std::unique_ptr<TextCodec> Create(const TextEncoding&, + explicit TextCodecIcu(const WTF::TextEncoding&); + WTF_EXPORT static std::unique_ptr<TextCodec> Create(const WTF::TextEncoding&, const void*); String Decode(base::span<const uint8_t> data, @@ -62,8 +62,8 @@ std::string EncodeCommon(base::span<const CharType>, UnencodableHandling); std::string EncodeInternal(const TextCodecInput&, UnencodableHandling); - void CreateICUConverter() const; - void ReleaseICUConverter() const; + void CreateIcuConverter() const; + void ReleaseIcuConverter() const; int DecodeToBuffer(UChar* buffer, UChar* buffer_limit, @@ -73,27 +73,27 @@ bool flush, UErrorCode&); - TextEncoding encoding_; + WTF::TextEncoding encoding_; mutable UConverter* converter_icu_ = nullptr; #if defined(USING_SYSTEM_ICU) mutable bool needs_gbk_fallbacks_ = false; #endif - FRIEND_TEST_ALL_PREFIXES(TextCodecICUTest, IgnorableCodePoint); + FRIEND_TEST_ALL_PREFIXES(TextCodecIcuTest, IgnorableCodePoint); }; -struct ICUConverterWrapper { - USING_FAST_MALLOC(ICUConverterWrapper); +struct IcuConverterWrapper { + USING_FAST_MALLOC(IcuConverterWrapper); public: - ICUConverterWrapper() : converter(nullptr) {} - ICUConverterWrapper(const ICUConverterWrapper&) = delete; - ICUConverterWrapper& operator=(const ICUConverterWrapper&) = delete; - ~ICUConverterWrapper(); + IcuConverterWrapper() : converter(nullptr) {} + IcuConverterWrapper(const IcuConverterWrapper&) = delete; + IcuConverterWrapper& operator=(const IcuConverterWrapper&) = delete; + ~IcuConverterWrapper(); UConverter* converter; }; -} // namespace WTF +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_CODEC_ICU_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_icu_test.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_icu_test.cc index f81cd1f..9467baee 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_icu_test.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_icu_test.cc
@@ -8,27 +8,28 @@ #include "third_party/blink/renderer/platform/wtf/text/character_names.h" #include "third_party/blink/renderer/platform/wtf/vector.h" -namespace WTF { +namespace blink { -TEST(TextCodecICUTest, IgnorableCodePoint) { - TextEncoding iso2022jp("iso-2022-jp"); - std::unique_ptr<TextCodec> codec = TextCodecICU::Create(iso2022jp, nullptr); +TEST(TextCodecIcuTest, IgnorableCodePoint) { + WTF::TextEncoding iso2022jp("iso-2022-jp"); + std::unique_ptr<TextCodec> codec = TextCodecIcu::Create(iso2022jp, nullptr); Vector<UChar> source; source.push_back('a'); source.push_back(kZeroWidthJoinerCharacter); - std::string encoded = - codec->Encode(base::span(source), kEntitiesForUnencodables); + std::string encoded = codec->Encode( + base::span(source), UnencodableHandling::kEntitiesForUnencodables); EXPECT_EQ("a‍", encoded); const String source2(u"ABC~¤•★星🌟星★•¤~XYZ"); - const std::string encoded2( - codec->Encode(source2.Span16(), kEntitiesForUnencodables)); + const std::string encoded2(codec->Encode( + source2.Span16(), UnencodableHandling::kEntitiesForUnencodables)); const String source3(u"ABC~¤•★星🌟星★•¤~XYZ"); - const std::string encoded3( - codec->Encode(source3.Span16(), kEntitiesForUnencodables)); + const std::string encoded3(codec->Encode( + source3.Span16(), UnencodableHandling::kEntitiesForUnencodables)); EXPECT_EQ(encoded3, encoded2); EXPECT_EQ( "ABC~¤•\x1B$B!z@1\x1B(B🌟\x1B$B@1!z\x1B(B•¤~" "XYZ", encoded2); } -} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.cc index f1488f51..1bdd38b 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.cc
@@ -35,7 +35,7 @@ #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -namespace WTF { +namespace blink { void TextCodecUserDefined::RegisterEncodingNames( EncodingNameRegistrar registrar) { @@ -43,7 +43,7 @@ } static std::unique_ptr<TextCodec> NewStreamingTextDecoderUserDefined( - const TextEncoding&, + const WTF::TextEncoding&, const void*) { return std::make_unique<TextCodecUserDefined>(); } @@ -71,7 +71,7 @@ static std::string EncodeComplexUserDefined( base::span<const CharType> char_data, UnencodableHandling handling) { - DCHECK_NE(handling, kNoUnencodables); + DCHECK_NE(handling, UnencodableHandling::kNoUnencodables); const auto* characters = char_data.data(); const wtf_size_t length = base::checked_cast<wtf_size_t>(char_data.size()); wtf_size_t target_length = length; @@ -139,4 +139,4 @@ return EncodeCommon(characters, handling); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.h b/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.h index 551b03ad..3b93ec5 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.h +++ b/third_party/blink/renderer/platform/wtf/text/text_codec_user_defined.h
@@ -28,8 +28,9 @@ #include "third_party/blink/renderer/platform/wtf/text/text_codec.h" -namespace WTF { +namespace blink { +// https://encoding.spec.whatwg.org/#x-user-defined class TextCodecUserDefined final : public TextCodec { public: static void RegisterEncodingNames(EncodingNameRegistrar); @@ -47,6 +48,6 @@ std::string EncodeCommon(base::span<const CharType>, UnencodableHandling); }; -} // namespace WTF +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_CODEC_USER_DEFINED_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc b/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc index 7346b9929..aa9dee4 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc
@@ -170,8 +170,8 @@ blink::TextCodecUtf16::RegisterEncodingNames(AddToTextEncodingNameMap); blink::TextCodecUtf16::RegisterCodecs(AddToTextCodecMap); - TextCodecUserDefined::RegisterEncodingNames(AddToTextEncodingNameMap); - TextCodecUserDefined::RegisterCodecs(AddToTextCodecMap); + blink::TextCodecUserDefined::RegisterEncodingNames(AddToTextEncodingNameMap); + blink::TextCodecUserDefined::RegisterCodecs(AddToTextCodecMap); } static void ExtendTextCodecMaps() { @@ -181,8 +181,8 @@ TextCodecCJK::RegisterEncodingNames(AddToTextEncodingNameMap); TextCodecCJK::RegisterCodecs(AddToTextCodecMap); - TextCodecICU::RegisterEncodingNames(AddToTextEncodingNameMap); - TextCodecICU::RegisterCodecs(AddToTextCodecMap); + blink::TextCodecIcu::RegisterEncodingNames(AddToTextEncodingNameMap); + blink::TextCodecIcu::RegisterCodecs(AddToTextCodecMap); } std::unique_ptr<TextCodec> NewTextCodec(const TextEncoding& encoding) {
diff --git a/third_party/blink/renderer/platform/wtf/threading.cc b/third_party/blink/renderer/platform/wtf/threading.cc index 3a4c9d42..0391861 100644 --- a/third_party/blink/renderer/platform/wtf/threading.cc +++ b/third_party/blink/renderer/platform/wtf/threading.cc
@@ -39,7 +39,7 @@ ThreadSpecific<Threading>* Threading::static_data_; Threading::Threading() - : cached_converter_icu_(new ICUConverterWrapper), + : cached_converter_icu_(new blink::IcuConverterWrapper), thread_id_(CurrentThread()) {} Threading::~Threading() = default;
diff --git a/third_party/blink/renderer/platform/wtf/threading.h b/third_party/blink/renderer/platform/wtf/threading.h index 302a200..7d8e84cb 100644 --- a/third_party/blink/renderer/platform/wtf/threading.h +++ b/third_party/blink/renderer/platform/wtf/threading.h
@@ -41,6 +41,10 @@ #include "third_party/blink/renderer/platform/wtf/type_traits.h" #include "third_party/blink/renderer/platform/wtf/wtf_export.h" +namespace blink { +struct IcuConverterWrapper; +} + namespace WTF { #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) @@ -59,8 +63,6 @@ WTF_EXPORT void SetIsBeforeThreadCreatedForTest(); #endif -struct ICUConverterWrapper; - class WTF_EXPORT Threading { DISALLOW_NEW(); @@ -70,7 +72,9 @@ Threading& operator=(const Threading&) = delete; ~Threading(); - ICUConverterWrapper& CachedConverterICU() { return *cached_converter_icu_; } + blink::IcuConverterWrapper& CachedConverterIcu() { + return *cached_converter_icu_; + } base::PlatformThreadId ThreadId() const { return thread_id_; } @@ -82,7 +86,7 @@ #endif private: - std::unique_ptr<ICUConverterWrapper> cached_converter_icu_; + std::unique_ptr<blink::IcuConverterWrapper> cached_converter_icu_; base::PlatformThreadId thread_id_;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 8d2a06c..36659968 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2763,6 +2763,28 @@ crbug.com/413411328 external/wpt/css/css-values/urls/referrer-policy/unsafe-url/url-image-referrerpolicy-same-origin.sub.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/425041677 [ Mac ] external/wpt/svg/text/reftests/text-context-fill.svg [ Failure ] +crbug.com/425041677 [ Win ] external/wpt/svg/text/reftests/text-context-fill.svg [ Failure ] +crbug.com/425056982 [ Mac14 ] virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/devicePixelRatio-undisplayed-iframe.tentative.html [ Crash ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/async_001.htm [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/002.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/008.html [ Crash ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/json-module/charset-bom.any.worker.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/load-error-events-1.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/load-error-events-3.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/module/crossorigin.html [ Crash ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url-workers.window.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-importmap.html [ Timeout ] +crbug.com/425145242 [ Mac14 ] virtual/unified-autoplay/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some-override.https.sub.html [ Skip Timeout ] +crbug.com/425145242 [ Mac14 ] virtual/unified-autoplay/external/wpt/feature-policy/reporting/payment-reporting.https.html [ Timeout ] +crbug.com/425145242 [ Mac14 ] virtual/unified-autoplay/external/wpt/feature-policy/reporting/xr-reporting.https.html [ Timeout ] +crbug.com/425041678 [ Mac14 ] virtual/unload-allowed/external/wpt/battery-status/no-leak-on-detached-use.https.html [ Timeout ] +crbug.com/424597869 [ Mac14 ] virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/003.html [ Timeout ] +crbug.com/424597869 [ Mac14 ] virtual/unload-allowed/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-cross-origin.window.html [ Timeout ] +crbug.com/425118323 [ Mac14 ] virtual/unload-allowed/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html [ Timeout ] +crbug.com/425056982 [ Mac14 ] virtual/wide-gamut/external/wpt/css/css-images/gradient/gradient-eval-001.html [ Timeout ] crbug.com/424245323 [ Mac14 ] virtual/close-watcher/external/wpt/close-watcher/iframes/dialog-same-origin-ynn.html [ Skip Timeout ] crbug.com/424242611 [ Win11-arm64 ] external/wpt/orientation-sensor/RelativeOrientationSensor.https.html [ Failure Pass Timeout ] crbug.com/424229863 [ Android ] external/wpt/webdriver/tests/bidi/external/bluetooth/disable_simulation/context.py [ Failure ] @@ -4939,7 +4961,6 @@ crbug.com/845610 [ Win ] http/tests/inspector-protocol/target/target-browser-context.js [ Failure Pass ] # Sheriff 2018-06-07 -crbug.com/41393183 http/tests/devtools/editor/text-editor-enter-behaviour.js [ Failure Pass Timeout ] crbug.com/41392978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Failure Pass Timeout ] # User Activation @@ -5059,7 +5080,6 @@ crbug.com/1021627 [ Mac ] fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure Pass Timeout ] # Sheriff 2019-03-28 -crbug.com/41449570 http/tests/devtools/editor/text-editor-search-switch-editor.js [ Failure Pass ] crbug.com/41449571 http/tests/devtools/elements/styles-2/paste-property.js [ Crash Pass Timeout ] # Sheriff 2019-04-09 @@ -6496,6 +6516,7 @@ # Virtual suite mostly fails while feature is in development. crbug.com/40253999 virtual/indexeddb_sqlite/* [ Skip Timeout ] + crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/abort-in-initial-upgradeneeded.any.html [ Pass ] crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/abort-in-initial-upgradeneeded.any.serviceworker.html [ Pass ] crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/abort-in-initial-upgradeneeded.any.sharedworker.html [ Pass ] @@ -6505,6 +6526,23 @@ crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_count.any.sharedworker.html [ Pass ] crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_count.any.worker.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor-direction-objectstore-keyrange.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor-direction-objectstore.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_advance_objectstore.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_continue_objectstore.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_update_objectstore.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_openCursor.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_openKeyCursor.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/interleaved-cursors-large.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/interleaved-cursors-small.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/parallel-cursors-upgrade.any.html [ Pass ] + +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore-getAll-enforcerange.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore-getAllKeys-enforcerange.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAll.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAllKeys.any.html [ Pass ] +crbug.com/40253999 virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAllRecords.tentative.any.html [ Pass ] + # Sheriff 2022-08-06 crbug.com/1350337 [ Linux ] external/wpt/web-locks/query-ordering.tentative.https.html [ Failure Pass ] @@ -9141,3 +9179,6 @@ # Gardener 2025-06-12 crbug.com/422636456 [ Mac ] http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Pass Timeout ] + +# Gardener 2025-06-16 +crbug.com/424918655 [ Mac ] external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image.html [ Failure Pass ] \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index b255154..75a49e9f 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -7827,6 +7827,13 @@ null, {} ] + ], + "offscreencanvas.transfercontrol.to.offscreen-crash.html": [ + "949f49c1065cb949cc146d2246a0159c777cc272", + [ + null, + {} + ] ] } }, @@ -317298,6 +317305,19 @@ {} ] ], + "text-context-fill.svg": [ + "0262deef3b2f7a69bfa825730bb74e0c19a6f38a", + [ + null, + [ + [ + "/svg/text/reftests/text-context-fill-ref.svg", + "==" + ] + ], + {} + ] + ], "text-font-face-load-image.html": [ "eb9a5fe4357373e3be74293c66f14f621a911405", [ @@ -431017,6 +431037,10 @@ "3d3968fa4923436e760dd80b05af292a615cffcb", [] ], + "text-context-fill-ref.svg": [ + "a8fbd1964ee492b9ac54648c14419daeb45b4840", + [] + ], "text-font-face-load-image-ref.html": [ "5a668b313e5eced93cc0358d84a75a56f5b76e8c", [] @@ -709272,6 +709296,15 @@ ] ] }, + "canvas-click.html": [ + "a058a621a0e2ed048954417a77deb15a887bd6e0", + [ + null, + { + "testdriver": true + } + ] + ], "caret": { "empty-elements.html": [ "328188c957bd738af419d54e4cd5c741cecc827f",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html similarity index 94% rename from third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.html rename to third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html index 540ab89..824c75c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.html +++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <title>CSS Anchor Positioning: Transition when the anchor attribute changes</title> <link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/"> -<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9598"> +<link rel="help" href="https://github.com/whatwg/html/pull/9144"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-area-scroll-adjust.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-area-scroll-adjust.html index 497b526f..128f23f9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-area-scroll-adjust.html +++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/position-area-scroll-adjust.html
@@ -9,11 +9,13 @@ overflow: auto; } #anchor { + anchor-name: --a; background: green; width: 200px; height: 100px; } #anchored { + position-anchor: --a; position-area: bottom; margin: 0; padding: 0; @@ -28,7 +30,7 @@ <div id="scroller"> <div class="filler"></div> <div id="anchor" popovertarget="anchored"></div> - <div id="anchored" anchor="anchor" popover></div> + <div id="anchored" popover></div> <div class="filler"></div> <div class="filler"></div> </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-crash.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-crash.html new file mode 100644 index 0000000..949f49c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-crash.html
@@ -0,0 +1,7 @@ +<title>Transfer Canvas without Context</title> +<canvas id="canvas"></canvas> + +<script> +canvas.transferControlToOffscreen(); +canvas.toBlob(_ => {}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/selection/canvas-click.html b/third_party/blink/web_tests/external/wpt/selection/canvas-click.html new file mode 100644 index 0000000..a058a621a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/selection/canvas-click.html
@@ -0,0 +1,28 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Clicking on a text-selectable canvas should not select it</title> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.com" title="Mozilla"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1969829"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<style> + :root { user-select: none } + canvas { + user-select: text; + outline: 2px solid hotpink; + background-color: green; + width: 200px; + height: 200px; + } +</style> +Clicking the green square should not select it.<br> +<canvas></canvas> +<script> +promise_test(async function() { + await test_driver.click(document.querySelector("canvas")); + assert_true(getSelection().isCollapsed, "Clicking a canvas shouldn't generate a non-collapsed selection"); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill-ref.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill-ref.svg new file mode 100644 index 0000000..a8fbd196 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill-ref.svg
@@ -0,0 +1,15 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100"> + <style> + text { + font-family: Ahem; + font-size: 9px; + } + </style> + <defs> + <marker id="m" viewBox="0 0 25 10" refY="5" markerWidth="125" refX="10" markerHeight="50"> + <text x="12" y="8" fill="green">XXX</text> + </marker> + </defs> + <line y2="30" x2="50" fill="green" marker-end="url(#m)" /> + <line y2="30" x2="50" stroke="green" /> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill.svg new file mode 100644 index 0000000..0262dee --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/text-context-fill.svg
@@ -0,0 +1,18 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" width="150" height="100"> + <title>text with context-fill</title> + <h:link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1969466"/> + <h:link rel="match" href="text-context-fill-ref.svg"/> + <h:link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style> + text { + font-family: Ahem; + font-size: 9px; + } + </style> + <defs> + <marker id="m" viewBox="0 0 25 10" refY="5" markerWidth="125" refX="10" markerHeight="50"> + <text x="12" y="8" fill="context-stroke">XXX</text> + </marker> + </defs> + <line y2="30" x2="50" stroke="green" marker-end="url(#m)" /> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js index b578270..b7bcdc0 100644 --- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js +++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js
@@ -2931,6 +2931,82 @@ } } }, + { + 'name': 'quantized clamp with emulation', + 'graph': { + 'inputs': { + 'input': { + 'data': [ + 8.413617134094238, 6.108623504638672, 3.549168109893799, + 1.6811466217041016, -0.1988269537687301, -8.413617134094238, + ], + 'descriptor': {shape: [2, 3], dataType: 'float32'}, + 'constant': false + }, + 'scale': { + 'data': [0.343092918395996], + 'descriptor': {shape: [1], dataType: 'float32'}, + 'constant': true + }, + 'zeroPoint': { + 'data': [0], + 'descriptor': {shape: [1], dataType: 'int8'}, + 'constant': true + }, + }, + 'operators': [ + { + 'name': 'quantizeLinear', + 'arguments': [ + {'input': 'input'}, + {'scale': 'scale', 'zeroPoint': 'zeroPoint'} + ], + 'outputs': 'quantizedInput' + }, + { + 'name': 'dequantizeLinear', + 'arguments': [ + {'input': 'quantizedInput'}, + {'scale': 'scale', 'zeroPoint': 'zeroPoint'} + ], + 'outputs': 'dequantizedInput' + }, + { + 'name': 'clamp', + 'arguments': [ + {'input': 'dequantizedInput'}, + {'options': {'minValue': -8, 'maxValue': 8}} + ], + 'outputs': 'clampOutput' + }, + { + 'name': 'quantizeLinear', + 'arguments': [ + {'input': 'clampOutput'}, + {'scale': 'scale', 'zeroPoint': 'zeroPoint'} + ], + 'outputs': 'quantizedClampOutput' + }, + { + 'name': 'dequantizeLinear', + 'arguments': [ + {'input': 'quantizedClampOutput'}, + {'scale': 'scale', 'zeroPoint': 'zeroPoint'} + ], + 'outputs': 'output' + } + ], + 'expectedOutputs': { + 'output': { + 'data': [ + 7.89113712310791, 6.17567253112793, 3.430929183959961, + 1.7154645919799805, -0.3430929183959961, -7.89113712310791, + ], + 'descriptor': {shape: [2, 3], dataType: 'float32'} + } + } + } + }, ]; if (navigator.ml) {
diff --git a/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius-expected.png b/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius-expected.png new file mode 100644 index 0000000..76d075c --- /dev/null +++ b/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius.html b/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius.html new file mode 100644 index 0000000..cca4661 --- /dev/null +++ b/third_party/blink/web_tests/fast/borders/cornerShapeSingleRadius.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> +div { + width: 190px; + height: 190px; + box-sizing: border-box; + border-top-left-radius: 87px 0px; + border-top-right-radius: 0px 31px; + border-bottom-right-radius: 43px; + border-bottom-left-radius: 87px 1px; + border: 5px solid black; + corner-shape: scoop; + background-color: #0f0; +} +</style> +<div></div>
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/http/tests/devtools/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/DIR_METADATA index 25fe1f0c..f6ff614 100644 --- a/third_party/blink/web_tests/http/tests/devtools/DIR_METADATA +++ b/third_party/blink/web_tests/http/tests/devtools/DIR_METADATA
@@ -1,2 +1,4 @@ team_email: "devtools-dev@chromium.org" - +buganizer_public: { + component_id: 1457055 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/console/DIR_METADATA new file mode 100644 index 0000000..070fa3c --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/console/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1519297 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/domdebugger/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/domdebugger/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/domdebugger/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/resources/search-me.js b/third_party/blink/web_tests/http/tests/devtools/editor/resources/search-me.js deleted file mode 100644 index c376ab0..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/editor/resources/search-me.js +++ /dev/null
@@ -1,265 +0,0 @@ -function logMe() -{ - console.log(0); - console.log(1); - console.log(2); - console.log(3); - console.log(4); - console.log(5); - console.log(6); - console.log(7); - console.log(8); - console.log(9); - console.log(10); - console.log(11); - console.log(12); - console.log(13); - console.log(14); - console.log(15); - console.log(16); - console.log(17); - console.log(18); - console.log(19); - console.log(20); - console.log(21); - console.log(22); - console.log(23); - console.log(24); - console.log(25); - console.log(26); - console.log(27); - console.log(28); - console.log(29); - console.log(30); - console.log(31); - console.log(32); - console.log(33); - console.log(34); - console.log(35); - console.log(36); - console.log(37); - console.log(38); - console.log(39); - console.log(40); - console.log(41); - console.log(42); - console.log(43); - console.log(44); - console.log(45); - console.log(46); - console.log(47); - console.log(48); - console.log(49); - console.log(50); - console.log(51); - console.log(52); - console.log(53); - console.log(54); - console.log(55); - console.log(56); - console.log(57); - console.log(58); - console.log(59); - console.log(60); - console.log(61); - console.log(62); - console.log(63); - console.log(64); - console.log(65); - console.log(66); - console.log(67); - console.log(68); - console.log(69); - console.log(70); - console.log(71); - console.log(72); - console.log(73); - console.log(74); - console.log(75); - console.log(76); - console.log(77); - console.log(78); - console.log(79); - console.log(80); - console.log(81); - console.log(82); - console.log(83); - console.log(84); - console.log(85); - console.log(86); - console.log(87); - console.log(88); - console.log(89); - console.log(90); - console.log(91); - console.log(92); - console.log(93); - console.log(94); - console.log(95); - console.log(96); - console.log(97); - console.log(98); - console.log(99); - console.log(100); - console.log(101); - console.log(102); - console.log(103); - console.log(104); - console.log(105); - console.log(106); - console.log(107); - console.log(108); - console.log(109); - console.log(110); - console.log(111); - console.log(112); - console.log(113); - console.log(114); - console.log(115); - console.log(116); - console.log(117); - console.log(118); - console.log(119); - console.log(120); - console.log(121); - console.log(122); - console.log(123); - console.log(124); - console.log(125); - console.log(126); - console.log(127); - console.log(128); - console.log(129); - console.log(130); - console.log(131); - console.log(132); - console.log(133); - console.log(134); - console.log(135); - console.log(136); - console.log(137); - console.log(138); - console.log(139); - console.log(140); - console.log(141); - console.log(142); - console.log(143); - console.log(144); - console.log(145); - console.log(146); - console.log(147); - console.log(148); - console.log(149); - console.log(150); - console.log(151); - console.log(152); - console.log(153); - console.log(154); - console.log(155); - console.log(156); - console.log(157); - console.log(158); - console.log(159); - console.log(160); - console.log(161); - console.log(162); - console.log(163); - console.log(164); - console.log(165); - console.log(166); - console.log(167); - console.log(168); - console.log(169); - console.log(170); - console.log(171); - console.log(172); - console.log(173); - console.log(174); - console.log(175); - console.log(176); - console.log(177); - console.log(178); - console.log(179); - console.log(180); - console.log(181); - console.log(182); - console.log(183); - console.log(184); - console.log(185); - console.log(186); - console.log(187); - console.log(188); - console.log(189); - console.log(190); - console.log(191); - console.log(192); - console.log(193); - console.log(194); - console.log(195); - console.log(196); - console.log(197); - console.log(198); - console.log(199); - - // FINDME - - console.log(200); - console.log(201); - console.log(202); - console.log(203); - console.log(204); - console.log(205); - console.log(206); - console.log(207); - console.log(208); - console.log(209); - console.log(210); - console.log(211); - console.log(212); - console.log(213); - console.log(214); - console.log(215); - console.log(216); - console.log(217); - console.log(218); - console.log(219); - console.log(220); - console.log(221); - console.log(222); - console.log(223); - console.log(224); - console.log(225); - console.log(226); - console.log(227); - console.log(228); - console.log(229); - console.log(230); - console.log(231); - console.log(232); - console.log(233); - console.log(234); - console.log(235); - console.log(236); - console.log(237); - console.log(238); - console.log(239); - console.log(240); - console.log(241); - console.log(242); - console.log(243); - console.log(244); - console.log(245); - console.log(246); - console.log(247); - console.log(248); - console.log(249); - console.log(250); - console.log(251); - console.log(252); - console.log(253); - console.log(254); - console.log(255); - console.log(256); -} - -
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour-expected.txt b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour-expected.txt deleted file mode 100644 index c4ff696b..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour-expected.txt +++ /dev/null
@@ -1,158 +0,0 @@ -This test checks text editor enter behaviour. - - -Running: testEnterInTheLineEnd -function.testFunction() -{ -....var.a.=.100; -....| -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterAfterOpenCurlyBrace -function.testFunction() -{ -....| -....var.a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterInTheMiddleOfLine -function.testFunction() -{ -....var. -....|a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterInTheBeginningOfTheLine -function.testFunction() -{ - -|....var.a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterWithTheSelection -function.testFunction() -{ -.. -..|var.a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterWithReversedSelection -function.testFunction() -{ -.. -..|var.a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterWithTheMultiLineSelection -function.testFunction() -{ - -|if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterWithFullLineSelection -function.testFunction() -{ - -|....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterBeforeOpenBrace -function.testFunction() -{ -....var.a.=.100; -....var.b.=.200; -....var.c.=.(a.+.b)./.2; -....console.log(a); -....console.log(b); -....console.log(c); - -|....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} - -Running: testEnterMultiCursor -function.testFunction() -{ -....var.a.=.100; - -|....var.b.=.200; -....var.c.=.(a.+.b)./.2; -. -.|...console.log(a); -.. -..|..console.log(b); -....console.log(c); -....if.(a.>.b).{ -........console.log(a); -....} -....return.c; -} -
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour.js b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour.js deleted file mode 100644 index e03263a..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-enter-behaviour.js +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {TestRunner} from 'test_runner'; -import {SourcesTestRunner} from 'sources_test_runner'; - -import * as TextUtils from 'devtools/models/text_utils/text_utils.js'; - -(async function() { - TestRunner.addResult(`This test checks text editor enter behaviour.\n`); - await TestRunner.showPanel('sources'); - await TestRunner.evaluateInPagePromise(` - function codeSnippet() { - return document.getElementById("codeSnippet").textContent; - } - `); - -// clang-format off -function testFunction() -{ - var a = 100; - var b = 200; - var c = (a + b) / 2; - console.log(a); - console.log(b); - console.log(c); - if (a > b) { - console.log(a); - } - return c; -} -// clang-format on - - var textEditor = SourcesTestRunner.createTestEditor(); - textEditor.setMimeType('text/javascript'); - textEditor.setReadOnly(false); - textEditor.element.focus(); - - TestRunner.runTestSuite([ - function testEnterInTheLineEnd(next) { - textEditor.setText(testFunction.toString()); - var line = textEditor.line(2); - textEditor.setSelection(TextUtils.TextRange.TextRange.createFromLocation(2, line.length)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterAfterOpenCurlyBrace(next) { - textEditor.setText(testFunction.toString()); - var line = textEditor.line(1); - textEditor.setSelection(TextUtils.TextRange.TextRange.createFromLocation(1, line.length)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterInTheMiddleOfLine(next) { - textEditor.setText(testFunction.toString()); - var line = textEditor.line(2); - textEditor.setSelection(TextUtils.TextRange.TextRange.createFromLocation(2, line.length / 2)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterInTheBeginningOfTheLine(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(TextUtils.TextRange.TextRange.createFromLocation(2, 0)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterWithTheSelection(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(new TextUtils.TextRange.TextRange(2, 2, 2, 4)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterWithReversedSelection(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(new TextUtils.TextRange.TextRange(2, 4, 2, 2)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterWithTheMultiLineSelection(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(new TextUtils.TextRange.TextRange(2, 0, 8, 4)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterWithFullLineSelection(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(new TextUtils.TextRange.TextRange(2, 0, 3, 0)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterBeforeOpenBrace(next) { - textEditor.setText(testFunction.toString()); - textEditor.setSelection(new TextUtils.TextRange.TextRange(8, 0, 8, 0)); - hitEnterDumpTextAndNext(next); - }, - - function testEnterMultiCursor(next) { - textEditor.setText(testFunction.toString()); - SourcesTestRunner.setLineSelections(textEditor, [ - {line: 3, column: 0}, - {line: 5, column: 1}, - {line: 6, column: 2}, - ]); - hitEnterDumpTextAndNext(next); - } - ]); - - function hitEnterDumpTextAndNext(next) { - SourcesTestRunner.fakeKeyEvent(textEditor, 'Enter', null, step2); - function step2() { - SourcesTestRunner.dumpTextWithSelection(textEditor, true); - next(); - } - } -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor-expected.txt b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor-expected.txt deleted file mode 100644 index fe7e1bb4..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -Tests that switching editor tabs after searching does not affect editor selection and viewport. - -Performing search... -Recording editor viewport after searching... -Recording editor viewport after switching tabs... -Comparing viewports... - viewports match, SUCCESS -Comparing selection ranges... - original selection range: {"startLine":203,"startColumn":7,"endLine":203,"endColumn":7} - current selection range: {"startLine":203,"startColumn":7,"endLine":203,"endColumn":7} -
diff --git a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js b/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js deleted file mode 100644 index 1d3c3d11..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/editor/text-editor-search-switch-editor.js +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {TestRunner} from 'test_runner'; -import {SourcesTestRunner} from 'sources_test_runner'; - -import * as Sources from 'devtools/panels/sources/sources.js'; - -(async function() { - TestRunner.addResult( - `Tests that switching editor tabs after searching does not affect editor selection and viewport.\n`); - await TestRunner.showPanel('sources'); - await TestRunner.addScriptTag('../sources/debugger/resources/edit-me.js'); - await TestRunner.addScriptTag('resources/search-me.js'); - - var textEditor; - var searchString = 'FINDME'; - var searchableView = Sources.SourcesPanel.SourcesPanel.instance().searchableView(); - var sourceFrame; - SourcesTestRunner.showScriptSource('search-me.js', didShowScriptSource); - - function didShowScriptSource(shownSourceFrame) { - sourceFrame = shownSourceFrame; - textEditor = sourceFrame.textEditor; - // We are probably still updating the editor in current callstack, so postpone the test execution. - queueMicrotask(() => { - textEditorUpdated(); - }); - } - - function textEditorUpdated(sourceFrame) { - searchableView.showSearchField(); - - TestRunner.addResult('Performing search...'); - searchableView.searchInputElement.value = searchString; - searchableView.performSearch(true, true); - TestRunner.addResult('Recording editor viewport after searching...'); - - var originalViewport = {from: textEditor.firstVisibleLine(), to: textEditor.lastVisibleLine()}; - var originalSelectionRange = textEditor.selection(); - - SourcesTestRunner.showScriptSource('edit-me.js', didShowAnotherSource); - - function didShowAnotherSource(anotherSourceFrame) { - SourcesTestRunner.showScriptSource('search-me.js', didShowScriptSourceAgain); - } - - function didShowScriptSourceAgain(sourceFrame) { - TestRunner.addResult('Recording editor viewport after switching tabs...'); - var newViewport = {from: textEditor.firstVisibleLine(), to: textEditor.lastVisibleLine()}; - var newSelectionRange = textEditor.selection(); - TestRunner.addResult('Comparing viewports...'); - if (originalViewport.from === newViewport.from && originalViewport.to === newViewport.to) - TestRunner.addResult(' viewports match, SUCCESS'); - else - TestRunner.addResult(' viewports do not match, FAIL'); - TestRunner.addResult('Comparing selection ranges...'); - TestRunner.addResult(' original selection range: ' + originalSelectionRange.toString()); - TestRunner.addResult(' current selection range: ' + newSelectionRange.toString()); - TestRunner.completeTest(); - } - } -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/elements/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/network/DIR_METADATA new file mode 100644 index 0000000..2313cc64 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/network/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1456921 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/DIR_METADATA b/third_party/blink/web_tests/http/tests/devtools/sources/DIR_METADATA new file mode 100644 index 0000000..edbe824f --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/sources/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1456920 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/DIR_METADATA index 25fe1f0c..f6ff614 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/DIR_METADATA +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/DIR_METADATA
@@ -1,2 +1,4 @@ team_email: "devtools-dev@chromium.org" - +buganizer_public: { + component_id: 1457055 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/animation/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/animation/DIR_METADATA new file mode 100644 index 0000000..a51c743 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/animation/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1559716 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/console/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/console/DIR_METADATA new file mode 100644 index 0000000..070fa3c --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/console/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1519297 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/css/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/css/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/css/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/debugger/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/debugger/DIR_METADATA new file mode 100644 index 0000000..edbe824f --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/debugger/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1456920 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/dom/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/dom/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/DIR_METADATA new file mode 100644 index 0000000..0d190be --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1519296 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/network/DIR_METADATA new file mode 100644 index 0000000..2313cc64 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1456921 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/DIR_METADATA b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/DIR_METADATA new file mode 100644 index 0000000..2937b2c --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457310 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/DIR_METADATA b/third_party/blink/web_tests/inspector-protocol/DIR_METADATA index 25fe1f0c..f6ff614 100644 --- a/third_party/blink/web_tests/inspector-protocol/DIR_METADATA +++ b/third_party/blink/web_tests/inspector-protocol/DIR_METADATA
@@ -1,2 +1,4 @@ team_email: "devtools-dev@chromium.org" - +buganizer_public: { + component_id: 1457055 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/css/DIR_METADATA b/third_party/blink/web_tests/inspector-protocol/css/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/css/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/DIR_METADATA b/third_party/blink/web_tests/inspector-protocol/dom/DIR_METADATA new file mode 100644 index 0000000..7c82dcd --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/dom/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457255 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/DIR_METADATA b/third_party/blink/web_tests/inspector-protocol/performance-timeline/DIR_METADATA new file mode 100644 index 0000000..2937b2c --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457310 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/timeline/DIR_METADATA b/third_party/blink/web_tests/inspector-protocol/timeline/DIR_METADATA new file mode 100644 index 0000000..2937b2c --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/timeline/DIR_METADATA
@@ -0,0 +1,4 @@ +team_email: "devtools-dev@chromium.org" +buganizer_public: { + component_id: 1457310 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt new file mode 100644 index 0000000..1534a4d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Largest Contentful Paint: |size| attribute is bounded by display size after soft navigation. + promise_test: Unhandled rejection with value: object "Error: 2 entries of type largest-contentful-paint with soft navigation observations never arrived" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_continue_objectstore.any-expected.txt b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_continue_objectstore.any-expected.txt new file mode 100644 index 0000000..8118d60 --- /dev/null +++ b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbcursor_continue_objectstore.any-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Delete next element, and iterate to it + assert_unreached: unexpected db.error (AbortError) Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAll.any-expected.txt b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAll.any-expected.txt new file mode 100644 index 0000000..5fcf71ca --- /dev/null +++ b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAll.any-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Get all with large values + Cannot read properties of null (reading 'join') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAllRecords.tentative.any-expected.txt b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAllRecords.tentative.any-expected.txt new file mode 100644 index 0000000..afd207e9 --- /dev/null +++ b/third_party/blink/web_tests/virtual/indexeddb_sqlite/external/wpt/IndexedDB/idbobjectstore_getAllRecords.tentative.any-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Get all records with large values + Cannot read properties of null (reading 'join') +Harness: the test ran to completion. +
diff --git a/third_party/crossbench b/third_party/crossbench index 885aeee..1de2eca 160000 --- a/third_party/crossbench +++ b/third_party/crossbench
@@ -1 +1 @@ -Subproject commit 885aeee863e05189c83fadb0c302d07518eb5500 +Subproject commit 1de2eca3495784b797d977b40b7291a4a7cd06c1
diff --git a/third_party/dawn b/third_party/dawn index 9fd4a73..fd27657 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 9fd4a731474f66c1ce5465f9b13919ad7487315d +Subproject commit fd276573ab859ea73c18581c018a773e4e3b8902
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index fd0c28c..7ad25e2 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit fd0c28cbf06b695f677c525b6630f9f9e4a90eee +Subproject commit 7ad25e25037043f7a75e7a838a651c110b918d48
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn index 19e90ba..3d6c4b70 100644 --- a/third_party/protobuf/BUILD.gn +++ b/third_party/protobuf/BUILD.gn
@@ -142,10 +142,6 @@ # The Cast Core gRPC generator tool. "//third_party/cast_core/public/src/build/chromium:cast_core_grpc_generator", - - # The proto_extras plugin generates code that some of the above fuzzers - # use, and thus needs to know the full types. - "//components/proto_extras:protobuf_full_support", ] }
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src index e0bad28..dec2864 160000 --- a/third_party/spirv-tools/src +++ b/third_party/spirv-tools/src
@@ -1 +1 @@ -Subproject commit e0bad2825dacf274578ec6d3c0e64e406d5e4fd7 +Subproject commit dec28643ed15f68a2bc95650de25e0a7486b564c
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index 9a8d020..3395378 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit 9a8d0205ed06a556ff17d4097afc218c993ec260 +Subproject commit 3395378f6990e79066b5f1647f6f8ac5de07e26d
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src index ce9b7e4..3fa19fc 160000 --- a/third_party/vulkan-validation-layers/src +++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@ -Subproject commit ce9b7e404fe1a312ff4c07961dc6f8a2fd925d44 +Subproject commit 3fa19fccc75171a6b607f95510c37739c606b809
diff --git a/third_party/webrtc b/third_party/webrtc index 7493242..4c619d7 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 74932424d457e2ad5e70c914b3cdd55bec759d6a +Subproject commit 4c619d7b0f2020e1b54fc62aaafc24fc34af78f8
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 55d369d..e457ee8e 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -24426,6 +24426,12 @@ <description>Please enter the description of the metric.</description> </action> +<action name="MobileMenuExtensions"> + <owner>massan@google.com</owner> + <owner>nya@chromium.org</owner> + <description>User pressed 'Extensions' in the app menu.</description> +</action> + <action name="MobileMenuFeedback"> <owner>aurimas@chromium.org</owner> <description>User pressed 'Help and Feedback' in the app menu.</description>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 2e5a305..b063a87 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -1135,6 +1135,7 @@ units="ms" expires_after="2025-10-26"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Time between CommitNavigation to StartLoadingResponse in the renderer process. This is recorded on each new navigation for http or https URLs in @@ -1147,6 +1148,7 @@ units="ms" expires_after="2025-10-12"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Time spent processing DocumentLoader::CreateParserPostCommit() in the renderer process. This is recorded on each new navigation for http or https @@ -3109,6 +3111,7 @@ <owner> src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS </owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Measures the total elapsed time it takes to run SVGImage::DataChanged() while loading the outermost main frame document until finishing parsing. @@ -3390,6 +3393,7 @@ <owner>chikamune@chromium.org</owner> <owner>yyanagisawa@chromium.org</owner> <owner>kouhei@chromium.org</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Record when the page's main frame starts preloading {SubresourceType}. Measures the duration between when the navigation starts, to when preloading @@ -4981,6 +4985,7 @@ <owner>paint-dev@chromium.org</owner> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Time spent updating a SVG image once all data is received.
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index dfa7eb0..2af07f7 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -825,6 +825,7 @@ <owner>chikamune@chromium.org</owner> <owner>kouhei@chromium.org</owner> <owner>chrome-gpu-metric-alerts@chromium.org</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Measures the time it takes to synchronously establish the GPU channel. Logged on the first run of a sync call to EstableGpuChannelSync is made.
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index d20b3f7b..24a263315 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -785,6 +785,7 @@ units="microseconds" expires_after="2025-11-16"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Time spent processing RenderFrameImpl::CommitNavigationWithParams() in the renderer process. This is recorded on each WebFrameLoadType::kStandard @@ -1192,6 +1193,7 @@ units="microseconds" expires_after="2025-11-16"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Time spent processing GetFrameHostForNavigation() in RenderFrameHostManager::DidCreateNavigationRequest() that can prepare a @@ -1403,6 +1405,7 @@ <owner>chikamune@chromium.org</owner> <owner>yyanagisawa@chromium.org</owner> <owner>kouhei@chromium.org</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Record when (a) the navigation happened in MainFrame, (b) it was a new navigation, (c) it was not a session restore, (d) the URL was http or https, @@ -1633,6 +1636,7 @@ expires_after="2025-11-16"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Milliseconds spent to process all the beforeunload events in JavaScript and waiting time for beforeunload dialog is closed if necessary. Recorded only
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 298a0f6a..427d720 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -6011,6 +6011,7 @@ expires_after="2025-10-26"> <owner>chikamune@chromium.org</owner> <owner>chrome-loading@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Measures the elapsed time it takes to read LCPPNavigationHint and attach it to NavigationHandle. Recorded on DidStartNavigatinon or
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index d946db71..ca29724 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -2609,6 +2609,7 @@ expires_after="2025-10-12"> <owner>chikamune@chromium.org</owner> <owner>loading-dev@chromium.org</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary>{MetricName}, but recorded only for {Origin} navigations.</summary> <token key="Origin"> <variant name="CrossOrigin" summary="cross-origin"/>
diff --git a/tools/metrics/histograms/metadata/search/OWNERS b/tools/metrics/histograms/metadata/search/OWNERS index b4ab36a..3d0d35b 100644 --- a/tools/metrics/histograms/metadata/search/OWNERS +++ b/tools/metrics/histograms/metadata/search/OWNERS
@@ -7,6 +7,7 @@ # For search engine choice releated metrics only. alexilin@chromium.org +ljjlee@google.com # For auxiliary search related metrics only. hanxi@chromium.org
diff --git a/tools/metrics/histograms/metadata/search/enums.xml b/tools/metrics/histograms/metadata/search/enums.xml index 91272e5..272299f6 100644 --- a/tools/metrics/histograms/metadata/search/enums.xml +++ b/tools/metrics/histograms/metadata/search/enums.xml
@@ -326,6 +326,7 @@ <enum name="SearchEngineChoiceDate"> <summary>Year-Month</summary> + <int value="100001" label="Before 2022"/> <int value="202201" label="2022-01"/> <int value="202202" label="2022-02"/> <int value="202203" label="2022-03"/> @@ -386,6 +387,7 @@ <int value="202610" label="2026-10"/> <int value="202611" label="2026-11"/> <int value="202612" label="2026-12"/> + <int value="300001" label="After 2050"/> </enum> <enum name="SearchEngineChoiceReprompt">
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml index 3fcdc8f8..4b59380 100644 --- a/tools/metrics/histograms/metadata/search/histograms.xml +++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -325,11 +325,11 @@ </summary> </histogram> -<histogram name="Search.ChoiceCompletedOnMonth.OnProfileLoad" +<histogram name="Search.ChoiceCompletedOnMonth.OnProfileLoad2" enum="SearchEngineChoiceDate" expires_after="2026-05-01"> -<!-- When bumping expiry date, also update the enum (making the enumeration in sync with existing values). Escalate when data count -exceeds 100 entries: -https://chromium.googlesource.com/chromium/src/tools/+/HEAD/metrics/histograms/README.md#sustainability --> +<!-- When bumping expiry date, also update the enum (making the enumeration in +sync with existing values). Escalate when data count exceeds 1000 entries: +https://chromium.googlesource.com/chromium/src/tools/+/HEAD/metrics/histograms/README.md#When-To-Use-Sparse-Histograms --> <owner>dgn@google.com</owner> <owner>tju@google.com</owner> @@ -339,6 +339,10 @@ last engine choice timestamp formatted as YYYYMM integer. For convenience, the enum maps these to user readable `YYYY-MM` labels. + To avoid the histogram exceeding 1000 buckets (limit for sparse histograms), + the range is capped to [`2022-01`, `2050-12`], dates prior to 2022 being + recorded as `1000-01`, and dates after 2050 being recorded as `3000-01`. + The value is serialized as a sparse histogram with integer values. Since each client can record the same value multiple times, it might be more interesting to look at unique clients.
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml index b102b6e..eed2b10 100644 --- a/tools/metrics/histograms/metadata/service/histograms.xml +++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -586,6 +586,7 @@ expires_after="2026-05-20"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Execution time of FindRegistrationForClientUrl until continuation is called. The metric is not recorded during startup. @@ -702,6 +703,7 @@ <owner>yyanagisawa@chromium.org</owner> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) renderer process sends an IPC message to notify that a resource loading request needs to be fall back to network, to (b) browser @@ -784,6 +786,7 @@ units="ms" expires_after="2025-12-07"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of finding service worker registration, to (b) reading response body is completed. Recorded when a fetch event handler @@ -804,6 +807,7 @@ units="ms" expires_after="2025-12-07"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of finding service worker registration, to (b) browser process received the IPC. Recorded when no fetch event handler @@ -824,6 +828,7 @@ units="ms" expires_after="2025-12-07"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of finding service worker registration, to (b) the start of a navigation request. @@ -843,6 +848,7 @@ units="ms" expires_after="2025-10-19"> <owner>yyanagisawa@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) a resource loading request is routed to service worker path, to (b) a service worker is ready to handle the request. @@ -910,6 +916,7 @@ <owner>yyanagisawa@chromium.org</owner> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) response headers from service worker are received, to (b) reading response body is completed. Recorded when a fetch event @@ -946,6 +953,7 @@ units="ms" expires_after="2025-08-01"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of a navigation request, to (b) reading response body is completed. Recorded when a fetch event handler handled the @@ -966,6 +974,7 @@ units="ms" expires_after="2025-08-01"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of a navigation request, to (b) browser process received the IPC. Recorded when no fetch event handler provided a @@ -987,6 +996,7 @@ <owner>yyanagisawa@chromium.org</owner> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) the start of a navigation request, to (b) the request is forwarded to a service worker code path. @@ -1007,6 +1017,7 @@ <owner>yyanagisawa@chromium.org</owner> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The time taken from (a) browser process sends an IPC message to dispatch a fetch event, to (b) a renderer process received the IPC message and is about @@ -1220,6 +1231,7 @@ units="ms" expires_after="2025-10-12"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Execution time of FindRegistrationForClientUrl until continuation is called. It is recorded only once on browser startup. @@ -1755,6 +1767,7 @@ expires_after="2025-10-08"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Execution time of ServiceWorkerStorage::FindForClientUrlInDB which is used by FindRegistrationForClientUrl. @@ -1775,6 +1788,7 @@ expires_after="2025-11-30"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> Execution time of ServiceWorkerStorage::ReadInitialDataFromDB which reads RegisteredStorageKey from a database. @@ -1786,6 +1800,7 @@ units="ms" expires_after="2025-12-07"> <owner>chikamune@chromium.org</owner> <owner>chrome-worker@google.com</owner> + <improvement direction="LOWER_IS_BETTER"/> <summary> The cache creation time of service worker registration key on UI thread. Includes asynchronous call, thread hopping and the time of
diff --git a/v8 b/v8 index 77f35f0..ad9041e 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 77f35f055a1543f51099fcea9575f83304d60de5 +Subproject commit ad9041e4d0f760e0c1c87d79a60b9ff1d2c77f96