diff --git a/DEPS b/DEPS index 2920dc4..a9c65e1a 100644 --- a/DEPS +++ b/DEPS
@@ -311,11 +311,11 @@ # 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': 'f1bc03fd6b4c201abd9f0fd9d51fb989150f97b9', + 'v8_revision': 'c90f939a79eab36ff08b04ae6a619c718b363b22', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '3ca4cde711b0ee03861d1294213c5b63dbee5ef9', + 'angle_revision': '19fb11b67c6f30f440112ca5d9725d1bed9b232e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -334,7 +334,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:10.20221013.0.1', + 'fuchsia_version': 'version:9.20221006.5.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -378,7 +378,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'df8440aca35dcbdaf56ecc3a5ded229fedf80cc7', + 'catapult_revision': 'faaae893d5d2c4050d9ba741a2cbd70b4528c7fe', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -422,7 +422,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': 'aecf1a2ab5106c4a08f8e2ae79717483f3abf8ee', + 'dawn_revision': '18bcdebc0256ad3d14bd1290163c98c84baddfa3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -818,7 +818,7 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - 'f2f33b925ca49fa7e2c44d27e6a2f5b741855c0a', + 'aa0b389580b88beb9ef353b3a7bb11cfa3f8bac6', 'condition': 'checkout_android and checkout_src_internal and not checkout_clank_via_src_internal', }, @@ -923,7 +923,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'xH8MfShB-S7HYkM3gLOUa916ukoEtDJa-8X1bOwfevsC', + 'version': 'Yl7cUc03IbwQqGpCBGiiefZ83rN4O-7cUEWedTJ0qLcC', }, ], 'dep_type': 'cipd', @@ -934,7 +934,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'SWCvrm3LQO_Y0XbcVVs0q2CJOVKn0ImNLJ0WPQDKx5YC', + 'version': 'h3TMxlBpShy8lGRaIG18Il0sqnAYBWm1qQ3jArztOiQC', }, ], 'dep_type': 'cipd', @@ -1251,7 +1251,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'b2aab03500a9810f3d267f1bd72ae155937d45a0', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'd26f0c7dfd01f6ddc0a5fab146c54fa7cc31e8c0', 'condition': 'checkout_src_internal', }, @@ -1406,7 +1406,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '20f8ac695af59b6c830def7d4e95bfeb13dd7be5', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'da07448619763d1cde255b361324242646f5b268', 'src/third_party/icu4j': { 'packages': [ @@ -1921,7 +1921,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f4fd7a75dd91cc4c56f00d09ee098d86775c6e10', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4bd291c858980c53e3127bcb8a7076502f87d6a1', 'condition': 'checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 0adc954..7a9efbd4 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2772,7 +2772,6 @@ "metrics/feature_discovery_duration_reporter_impl_unittest.cc", "metrics/histogram_macros_unittest.cc", "metrics/login_metrics_recorder_unittest.cc", - "metrics/login_unlock_throughput_recorder_unittest.cc", "metrics/pointer_metrics_recorder_unittest.cc", "metrics/stylus_metrics_recorder_unittest.cc", "metrics/task_switch_metrics_recorder_unittest.cc", @@ -3215,7 +3214,6 @@ "//chromeos/crosapi/cpp", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", - "//chromeos/login/login_state:login_state", "//chromeos/services/network_config/public/cpp", "//chromeos/services/network_config/public/mojom", "//chromeos/strings:strings_grit",
diff --git a/ash/app_list/BUILD.gn b/ash/app_list/BUILD.gn index 1719f47..6da7baa 100644 --- a/ash/app_list/BUILD.gn +++ b/ash/app_list/BUILD.gn
@@ -155,10 +155,6 @@ "views/search_result_page_dialog_controller.h", "views/search_result_page_view.cc", "views/search_result_page_view.h", - "views/search_result_tile_item_list_view.cc", - "views/search_result_tile_item_list_view.h", - "views/search_result_tile_item_view.cc", - "views/search_result_tile_item_view.h", "views/search_result_view.cc", "views/search_result_view.h", "views/suggested_content_info_view.cc", @@ -311,7 +307,6 @@ "views/search_box_view_unittest.cc", "views/search_result_list_view_unittest.cc", "views/search_result_page_view_unittest.cc", - "views/search_result_tile_item_list_view_unittest.cc", "views/search_result_view_unittest.cc", ]
diff --git a/ash/app_list/app_list_color_provider_impl.cc b/ash/app_list/app_list_color_provider_impl.cc index baf96e4c..049eae0 100644 --- a/ash/app_list/app_list_color_provider_impl.cc +++ b/ash/app_list/app_list_color_provider_impl.cc
@@ -245,13 +245,6 @@ kColorAshControlBackgroundColorInactive); } -ui::ColorId AppListColorProviderImpl::GetSeparatorColorId() const { - if (ShouldUseDarkLightColors()) { - return ui::kColorAshAppListSeparatorLight; - } - return ui::kColorAshAppListSeparator; // default_color -} - SkColor AppListColorProviderImpl::GetFocusRingColor( const views::Widget* app_list_widget) const { DCHECK(app_list_widget);
diff --git a/ash/app_list/app_list_color_provider_impl.h b/ash/app_list/app_list_color_provider_impl.h index 0a4a6384..639274d 100644 --- a/ash/app_list/app_list_color_provider_impl.h +++ b/ash/app_list/app_list_color_provider_impl.h
@@ -55,7 +55,6 @@ const views::Widget* app_list_widget) const override; SkColor GetGridBackgroundCardInactiveColor( const views::Widget* app_list_widget) const override; - ui::ColorId GetSeparatorColorId() const override; SkColor GetFocusRingColor( const views::Widget* app_list_widget) const override; SkColor GetInkDropBaseColor(
diff --git a/ash/app_list/app_list_metrics_unittest.cc b/ash/app_list/app_list_metrics_unittest.cc index 6dc6946d..7d978703 100644 --- a/ash/app_list/app_list_metrics_unittest.cc +++ b/ash/app_list/app_list_metrics_unittest.cc
@@ -26,7 +26,6 @@ #include "ash/app_list/views/recent_apps_view.h" #include "ash/app_list/views/search_result_container_view.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/shelf_item_delegate.h" @@ -116,45 +115,6 @@ LeftClickOn(view_model->view_at(kBrowserAppIndexOnShelf)); } - void PopulateAndLaunchSearchBoxTileItem() { - // Populate 4 tile items. - for (size_t i = 0; i < 4; i++) { - auto search_result = std::make_unique<SearchResult>(); - search_result->set_display_type(SearchResultDisplayType::kTile); - - // Give each item a name so that the accessibility paint checks pass. - // (Focusable items should have accessible names.) - search_result->SetAccessibleName( - base::UTF8ToUTF16(base::StringPrintf("item %zu", i))); - - search_model_->results()->Add(std::move(search_result)); - } - GetAppListTestHelper()->WaitUntilIdle(); - - // Mark the privacy notices as dismissed so that the tile items will be the - // first search container. - ContentsView* contents_view = Shell::Get() - ->app_list_controller() - ->fullscreen_presenter() - ->GetView() - ->app_list_main_view() - ->contents_view(); - Shell::Get()->app_list_controller()->MarkSuggestedContentInfoDismissed(); - contents_view->search_result_page_view() - ->GetPrivacyContainerViewForTest() - ->Update(); - - SearchResultContainerView* search_result_container_view = - contents_view->search_result_page_view() - ->GetSearchResultTileItemListViewForTest(); - - // Request focus on the first tile item view. - search_result_container_view->GetFirstResultView()->RequestFocus(); - - // Press return to simulate an app launch from the tile item. - PressAndReleaseKey(ui::KeyboardCode::VKEY_RETURN); - } - void PopulateAndLaunchAppInGrid(int num = 4) { // Populate apps in the root app grid. AppListModel* model = AppListModelProvider::Get()->model(); @@ -253,33 +213,6 @@ 1 /* Number of times launched from shelf */); } -// Test that the histogram records an app launch from the search box while the -// homercher search state is showing. -TEST_P(AppListMetricsTabletTest, HomecherSearchLaunchFromSearchBox) { - // ProductivityLauncher does not tile search results. - if (features::IsProductivityLauncherEnabled()) - return; - - base::HistogramTester histogram_tester; - - // Enable tablet mode. - GetAppListTestHelper()->WaitUntilIdle(); - Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); - - // Press a letter key, the AppListView should transition to kFullscreenSearch. - PressAndReleaseKey(ui::KeyboardCode::VKEY_H); - GetAppListTestHelper()->WaitUntilIdle(); - GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); - - // Populate search box with tile items and launch a tile item. - PopulateAndLaunchSearchBoxTileItem(); - - histogram_tester.ExpectBucketCount( - "Apps.AppListAppLaunchedV2.HomecherSearch", - AppListLaunchedFrom::kLaunchedFromSearchBox, - 1 /* Number of times launched from search box */); -} - // Tests with feature ProductivityLauncher enabled. class AppListMetricsProductivityLauncherTest : public AppListMetricsTest { public:
diff --git a/ash/app_list/app_list_presenter_impl.cc b/ash/app_list/app_list_presenter_impl.cc index c801b68..1d68b14d 100644 --- a/ash/app_list/app_list_presenter_impl.cc +++ b/ash/app_list/app_list_presenter_impl.cc
@@ -29,6 +29,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/containers/contains.h" +#include "base/functional/callback_forward.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_enums.h" @@ -37,6 +38,8 @@ #include "ui/aura/window.h" #include "ui/compositor/animation_throughput_reporter.h" #include "ui/compositor/layer.h" +#include "ui/compositor/layer_animation_element.h" +#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/display/screen.h" #include "ui/display/types/display_constants.h" @@ -53,6 +56,14 @@ using assistant::AssistantExitPoint; +// The target scale to which (or from which) the fullscreen launcher will +// animate between tablet <-> clamshell mode transition. +constexpr float kFullscreenLauncherFadeAnimationScale = 0.92f; + +// The fade in/out animation duration for tablet <-> clamshell mode transition. +constexpr base::TimeDelta kFullscreenLauncherTransitionDuration = + base::Milliseconds(350); + inline ui::Layer* GetLayer(views::Widget* widget) { return widget->GetNativeView()->layer(); } @@ -105,6 +116,42 @@ } } +// Invokes `complete_callback_` at the end of animation. +class FullscreenLauncherAnimationObserver + : public ui::ImplicitAnimationObserver { + public: + explicit FullscreenLauncherAnimationObserver( + base::OnceClosure complete_callback) + : complete_callback_(std::move(complete_callback)) {} + FullscreenLauncherAnimationObserver( + const FullscreenLauncherAnimationObserver& other) = delete; + FullscreenLauncherAnimationObserver& operator=( + const FullscreenLauncherAnimationObserver& other) = delete; + ~FullscreenLauncherAnimationObserver() override { + StopObservingImplicitAnimations(); + } + + // ui::ImplicitAnimationObserver: + void OnImplicitAnimationsCompleted() override { + std::move(complete_callback_).Run(); + delete this; + } + + private: + base::OnceClosure complete_callback_; +}; + +void UpdateTabletModeTransitionAnimationSettings( + FullscreenLauncherAnimationObserver* animation_observer, + ui::ScopedLayerAnimationSettings* settings) { + settings->SetTransitionDuration(kFullscreenLauncherTransitionDuration); + settings->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); + settings->SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + if (animation_observer) + settings->AddObserver(animation_observer); +} + // Implicit animation observer that runs a scoped closure runner, and deletes // itself when the observed implicit animations complete. class CallbackRunnerLayerAnimationObserver @@ -227,8 +274,35 @@ last_open_source_ = show_source; last_open_time_ = base::Time::Now(); + auto* layer = view_->GetWidget()->GetNativeWindow()->layer(); + + float initial_opacity; + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + // `0.01f` prevents a DCHECK error (widgets cannot be shown when visible and + // fully transparent at the same time). + initial_opacity = layer->opacity() == 0.0f ? 0.01f : layer->opacity(); + } else { + initial_opacity = 1.0f; + } + layer->SetOpacity(initial_opacity); + view_->Show(preferred_state, IsSideShelf(shelf)); + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + // Set initial transform only if layer is not currently animating one (for + // example during hide animation). + if (!layer->GetAnimator()->IsAnimatingProperty( + ui::LayerAnimationElement::TRANSFORM)) { + layer->SetTransform( + gfx::GetScaleTransform(gfx::Rect(layer->size()).CenterPoint(), + kFullscreenLauncherFadeAnimationScale)); + } + UpdateScaleAndOpacityForHomeLauncher( + 1.0f, 1.0f, absl::nullopt, + base::BindRepeating(&UpdateTabletModeTransitionAnimationSettings, + nullptr)); + } + SnapAppListBoundsToDisplayEdge(); event_filter_ = @@ -304,8 +378,20 @@ last_open_source_.reset(); last_open_time_.reset(); - if (!view_->GetWidget()->GetNativeWindow()->is_destroying()) + if (!view_->GetWidget()->GetNativeWindow()->is_destroying()) { + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + base::OnceClosure animation_complete_callback = base::BindOnce( + &AppListPresenterImpl::OnTabletToClamshellTransitionAnimationDone, + weak_ptr_factory_.GetWeakPtr()); + auto* animation_observer = new FullscreenLauncherAnimationObserver( + std::move(animation_complete_callback)); + UpdateScaleAndOpacityForHomeLauncher( + kFullscreenLauncherFadeAnimationScale, 0.0f, absl::nullopt, + base::BindRepeating(&UpdateTabletModeTransitionAnimationSettings, + animation_observer)); + } view_->SetState(AppListViewState::kClosed); + } view_->SetDragAndDropHostOfCurrentAppList(nullptr); @@ -400,17 +486,12 @@ float opacity, absl::optional<TabletModeAnimationTransition> transition, UpdateHomeLauncherAnimationSettingsCallback callback) { - if (!view_) + // Exiting from overview in clamshell mode should not affect the hidden + // fullscreen launcher. + if (!view_ || view_->app_list_state() == AppListViewState::kClosed) return; ui::Layer* layer = view_->GetWidget()->GetNativeWindow()->layer(); - if (!Shell::Get()->IsInTabletMode()) { - // In clamshell mode, set the opacity of the AppList immediately to - // instantly hide it. Opacity of the AppList is reset when it is shown - // again. - layer->SetOpacity(opacity); - return; - } if (layer->GetAnimator()->is_animating()) { layer->GetAnimator()->StopAnimating(); @@ -695,4 +776,13 @@ SetViewIgnoredForAccessibility(view_->search_box_view(), false); } +void AppListPresenterImpl::OnTabletToClamshellTransitionAnimationDone() { + if (!view_) + return; + + auto* window = view_->GetWidget()->GetNativeWindow(); + if (window->layer()->GetTargetOpacity() == 0.0f) + window->Hide(); +} + } // namespace ash
diff --git a/ash/app_list/app_list_presenter_impl.h b/ash/app_list/app_list_presenter_impl.h index 2955f37c..ed06dbdb 100644 --- a/ash/app_list/app_list_presenter_impl.h +++ b/ash/app_list/app_list_presenter_impl.h
@@ -205,6 +205,10 @@ // Called when the reorder animation completes. void OnAppListReorderAnimationDone(); + // Called when the tablet to clamshell transition animation completes. + // Hides the `AppListView`'s window if target opacity is zero. + void OnTabletToClamshellTransitionAnimationDone(); + // Owns |this|. AppListControllerImpl* const controller_;
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc index dc2ec57..5de9776e 100644 --- a/ash/app_list/app_list_presenter_unittest.cc +++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -37,13 +37,13 @@ #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_page_anchored_dialog.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/constants/ash_features.h" #include "ash/keyboard/keyboard_controller_impl.h" #include "ash/keyboard/ui/keyboard_ui_controller.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/app_list/app_list_color_provider.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shelf_config.h" @@ -89,6 +89,9 @@ #include "ui/display/test/display_manager_test_api.h" #include "ui/events/event_constants.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/transform.h" +#include "ui/gfx/geometry/transform_util.h" #include "ui/touch_selection/touch_selection_menu_runner.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/textfield/textfield.h" @@ -3353,12 +3356,6 @@ EXPECT_TRUE(search_box_view->is_search_box_active()); GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); - SearchResultContainerView* const tile_item_container = - search_result_page()->GetSearchResultTileItemListViewForTest(); - ASSERT_EQ(1, tile_item_container->num_results()); - EXPECT_EQ("test_tile", - tile_item_container->GetResultViewAt(0)->result()->id()); - SearchResultContainerView* item_list_container = search_result_page()->GetSearchResultListViewForTest(); ASSERT_EQ(1, item_list_container->num_results()); @@ -3400,10 +3397,6 @@ EXPECT_TRUE(search_box_view->is_search_box_active()); GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); - ASSERT_EQ(1, tile_item_container->num_results()); - EXPECT_EQ("test_tile_override", - tile_item_container->GetResultViewAt(0)->result()->id()); - ASSERT_EQ(1, item_list_container->num_results()); EXPECT_EQ("test_override", item_list_container->GetResultViewAt(0)->result()->id()); @@ -4413,4 +4406,88 @@ EXPECT_LT(textfield->GetCursorPosition(), initial_cursor_position); } +// Temporary class to test `kAnimateScaleOnTabletModeTransition` related +// animations. +class AppListPresenterWithScaleAnimationOnTabletModeTransitionTest + : public AppListPresenterTest { + public: + AppListPresenterWithScaleAnimationOnTabletModeTransitionTest() { + scoped_feature_list_.InitAndEnableFeature( + app_list_features::kAnimateScaleOnTabletModeTransition); + } + + protected: + void EnsureAppListViewIsCached() { + ASSERT_FALSE(GetAppListTestHelper()->GetAppListView()); + + EnableTabletMode(true); + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps); + + EnableTabletMode(false); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckState(AppListViewState::kClosed); + + // Entering and exiting from tablet mode should keep `AppListView` cached. + ASSERT_TRUE(GetAppListTestHelper()->GetAppListView()); + } + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(AppListPresenterWithScaleAnimationOnTabletModeTransitionTest, + UpdatesScaleAndOpacity) { + // Enter tablet mode. + EnableTabletMode(true); + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps); + + auto* const window = + GetAppListTestHelper()->GetAppListView()->GetWidget()->GetNativeWindow(); + auto* const layer = window->layer(); + const auto center_point = gfx::Rect(layer->size()).CenterPoint(); + const auto no_transform = gfx::GetScaleTransform(center_point, 1.0f); + const auto scaled_down_transform = + gfx::GetScaleTransform(center_point, 0.92f); + + // The layer is fully visible and without applied transform. + EXPECT_EQ(layer->opacity(), 1.0f); + EXPECT_EQ(layer->transform(), no_transform); + EXPECT_TRUE(window->IsVisible()); + + // Exit tablet mode. + EnableTabletMode(false); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckState(AppListViewState::kClosed); + + // The layer is fully transparent, scaled down and the window is hidden. + EXPECT_EQ(layer->opacity(), 0.00f); + EXPECT_EQ(layer->transform(), scaled_down_transform); + EXPECT_FALSE(window->IsVisible()); +} + +TEST_F(AppListPresenterWithScaleAnimationOnTabletModeTransitionTest, + ExitingFromOverviewInClamshellModeShouldNotAffectFullscreenLauncher) { + EnsureAppListViewIsCached(); + + auto* const layer = GetAppListTestHelper() + ->GetAppListView() + ->GetWidget() + ->GetNativeWindow() + ->layer(); + const auto expected_opacity = layer->opacity(); + const auto expected_transform = layer->transform(); + + OverviewController* overview_controller = Shell::Get()->overview_controller(); + + EnterOverview(); + EXPECT_TRUE(overview_controller->InOverviewSession()); + ExitOverview(); + EXPECT_FALSE(overview_controller->InOverviewSession()); + + // Layer's opacity and transform should stay the same. + EXPECT_EQ(layer->opacity(), expected_opacity); + EXPECT_EQ(layer->transform(), expected_transform); +} + } // namespace ash
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 05da13f..fdbfb7e1 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -21,6 +21,7 @@ #include "ash/app_list/views/paged_apps_grid_view.h" #include "ash/app_list/views/search_box_view.h" #include "ash/keyboard/ui/keyboard_ui_controller.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/metrics_util.h" #include "ash/shell.h" @@ -499,9 +500,6 @@ void AppListView::Show(AppListViewState preferred_state, bool is_side_shelf) { if (!time_shown_.has_value()) time_shown_ = base::Time::Now(); - // The opacity of the AppListView may have been manipulated by overview mode, - // so reset it before it is shown. - GetWidget()->GetLayer()->SetOpacity(1.0f); is_side_shelf_ = is_side_shelf; AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); @@ -730,10 +728,20 @@ AppListState::kStateApps, !is_side_shelf_); } - if (target_state == AppListViewState::kClosed && is_side_shelf_) { - // Reset the search box to be shown again. This is done after the animation - // is complete normally, but there is no animation when |is_side_shelf_|. - search_box_view_->ClearSearchAndDeactivateSearchBox(); + if (target_state == AppListViewState::kClosed) { + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + if (app_list_state_ == AppListViewState::kFullscreenSearch) + search_box_view_->ClearSearchAndDeactivateSearchBox(); + + auto* contents_view = app_list_main_view_->contents_view(); + if (contents_view->IsShowingEmbeddedAssistantUI()) + contents_view->ShowEmbeddedAssistantUI(false); + } else if (is_side_shelf_) { + // Reset the search box to be shown again. This is done after the + // animation is complete normally, but there is no animation when + // |is_side_shelf_|. + search_box_view_->ClearSearchAndDeactivateSearchBox(); + } } } @@ -1086,7 +1094,9 @@ base::TimeDelta animation_duration = GetStateTransitionAnimationDuration(target_state); - ApplyBoundsAnimation(target_state, animation_duration); + if (!app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) + ApplyBoundsAnimation(target_state, animation_duration); + app_list_main_view_->contents_view()->OnAppListViewTargetStateChanged( target_state); app_list_main_view_->contents_view()->AnimateToViewState(target_state, @@ -1413,6 +1423,8 @@ case AppListViewState::kFullscreenSearch: return fullscreen_height; case AppListViewState::kClosed: + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) + return fullscreen_height; // Align the widget y with shelf y to avoid flicker in show animation. In // side shelf mode, the widget y is the top of work area because the // widget does not animate.
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc index f0aa533..b76d98d 100644 --- a/ash/app_list/views/app_list_view_unittest.cc +++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -33,8 +33,6 @@ #include "ash/app_list/views/search_result_container_view.h" #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" -#include "ash/app_list/views/search_result_tile_item_view.h" #include "ash/app_list/views/search_result_view.h" #include "ash/constants/ash_features.h" #include "ash/keyboard/ui/keyboard_ui_controller.h" @@ -633,12 +631,6 @@ view_->Show(AppListViewState::kFullscreenAllApps, /*is_side_shelf=*/false); } - SearchResultTileItemListView* GetSearchResultTileItemListView() { - return contents_view() - ->search_result_page_view() - ->GetSearchResultTileItemListViewForTest(); - } - SearchResultListView* GetSearchResultListView() { return contents_view() ->search_result_page_view() @@ -658,28 +650,18 @@ } // Add search results for test on focus movement. - void SetUpSearchResults(int tile_results_num, int list_results_num) { - std::vector<std::pair<SearchResult::DisplayType, int>> result_types; - result_types.emplace_back(SearchResultDisplayType::kTile, tile_results_num); - result_types.emplace_back(SearchResultDisplayType::kList, list_results_num); - + void SetUpSearchResults(int list_results_num) { SearchModel::SearchResults* results = GetSearchModel()->results(); results->DeleteAll(); - double display_score = result_types.size(); - for (const auto& data : result_types) { - // Set the display score of the results in each group in decreasing order - // (so the earlier groups have higher display score, and therefore appear - // first). - display_score -= 0.5; - for (int i = 0; i < data.second; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_display_type(data.first); - result->set_display_score(display_score); - result->SetTitle(u"Test"); - result->set_best_match(true); - results->Add(std::move(result)); - } + + for (int i = 0; i < list_results_num; ++i) { + std::unique_ptr<TestSearchResult> result = + std::make_unique<TestSearchResult>(); + result->set_display_type(SearchResultDisplayType::kList); + result->set_display_score(1); + result->SetTitle(u"Test"); + result->set_best_match(true); + results->Add(std::move(result)); } // Adding results will schedule Update(). @@ -1104,9 +1086,8 @@ search_box_view()->search_box()->InsertText( u"test", ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); - constexpr int kTileResults = 3; constexpr int kListResults = 2; - SetUpSearchResults(kTileResults, kListResults); + SetUpSearchResults(kListResults); // Move focus to the first search result. SimulateKeyPress(ui::VKEY_TAB, false); @@ -1153,7 +1134,7 @@ u"test", ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); const int kListResults = 2; - SetUpSearchResults(0, kListResults); + SetUpSearchResults(kListResults); SearchResultListView* list_view = GetSearchResultListView(); EXPECT_EQ(search_box_view()->search_box(), focused_view()); @@ -1161,28 +1142,15 @@ contents_view()->search_result_page_view()->first_result_view()); EXPECT_TRUE(list_view->GetResultViewAt(0)->selected()); - // Populate both fake list results and tile results. - const int kTileResults = 3; - SetUpSearchResults(kTileResults, kListResults); - const std::vector<SearchResultTileItemView*>& tile_views = - GetSearchResultTileItemListView()->tile_views_for_test(); - EXPECT_EQ(search_box_view()->search_box(), focused_view()); - EXPECT_EQ(tile_views[0], - contents_view()->search_result_page_view()->first_result_view()); - EXPECT_TRUE(tile_views[0]->selected()); - ResultSelectionController* selection_controller = contents_view()->search_result_page_view()->result_selection_controller(); - // Ensures the |ResultSelectionController| selects the correct result - EXPECT_EQ(selection_controller->selected_result(), tile_views[0]); - - // Ensure current highlighted result loses highlight on transition - SimulateKeyPress(ui::VKEY_TAB, false); - EXPECT_FALSE(tile_views[0]->selected()); + // Ensures the |ResultSelectionController| selects the correct result. + EXPECT_EQ(selection_controller->selected_result(), + list_view->GetResultViewAt(0)); // Clear up all search results. - SetUpSearchResults(0, 0); + SetUpSearchResults(0); EXPECT_EQ(search_box_view()->search_box(), focused_view()); EXPECT_EQ(nullptr, contents_view()->search_result_page_view()->first_result_view()); @@ -1206,23 +1174,16 @@ u"test", ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); const int kListResults = 2; - SetUpSearchResults(0, kListResults); + SetUpSearchResults(kListResults); SimulateKeyPress(ui::VKEY_RETURN, false); EXPECT_EQ(1, GetOpenFirstSearchResultCount()); EXPECT_EQ(1, GetTotalOpenSearchResultCount()); - // Populate both fake list results and tile results. Then hit Enter key. - const int kTileResults = 3; - SetUpSearchResults(kTileResults, kListResults); - SimulateKeyPress(ui::VKEY_RETURN, false); - EXPECT_EQ(2, GetOpenFirstSearchResultCount()); - EXPECT_EQ(2, GetTotalOpenSearchResultCount()); - // Clear up all search results. Then hit Enter key. - SetUpSearchResults(0, 0); + SetUpSearchResults(0); SimulateKeyPress(ui::VKEY_RETURN, false); - EXPECT_EQ(2, GetOpenFirstSearchResultCount()); - EXPECT_EQ(2, GetTotalOpenSearchResultCount()); + EXPECT_EQ(1, GetOpenFirstSearchResultCount()); + EXPECT_EQ(1, GetTotalOpenSearchResultCount()); } // Tests that search box becomes focused when it is activated.
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index aadacba..c79e83e 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -18,7 +18,6 @@ #include "ash/app_list/views/search_box_view.h" #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/constants/ash_features.h" #include "ash/keyboard/ui/keyboard_ui_controller.h" #include "ash/public/cpp/app_list/app_list_config.h" @@ -611,8 +610,13 @@ ConvertRectToWidgetWithoutTransform(search_box_bounds)); search_box->GetWidget()->SetBounds(search_rect); - const float search_box_opacity = - target_view_state() != AppListViewState::kClosed ? 1.0f : 0.0f; + float search_box_opacity; + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + search_box_opacity = 1.0f; + } else { + search_box_opacity = + target_view_state() != AppListViewState::kClosed ? 1.0f : 0.0f; + } search_box->layer()->SetOpacity(search_box_opacity); for (AppListPage* page : app_list_pages_) { @@ -631,6 +635,12 @@ ? pagination_model_.transition().target_page : pagination_model_.selected_page()); + if (app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) { + last_target_view_state_ = target_view_state; + target_page_for_last_view_state_update_ = target_page; + return; + } + // Animates layer's opacity. // |duration| - The default transition duration. The actual transition gets // halved when animating to hidden state. @@ -786,7 +796,9 @@ AppListViewState view_state) const { switch (view_state) { case AppListViewState::kClosed: - return 0; + if (!app_list_features::IsAnimateScaleOnTabletModeTransitionEnabled()) + return 0; + [[fallthrough]]; case AppListViewState::kFullscreenAllApps: case AppListViewState::kFullscreenSearch: return apps_container_view_
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index 6dd1064..f3b34834 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -23,7 +23,6 @@ #include "ash/app_list/views/search_box_view_delegate.h" #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_color_provider.h" #include "ash/public/cpp/app_list/app_list_features.h" @@ -604,19 +603,6 @@ selection = GetResultSelectionController()->selected_result(); EXPECT_EQ(u"testing", selection->result()->title()); - // Tile containers are deprecated for productivity launcher. - if (!IsProductivityLauncherEnabled()) { - // Add a new result in a tile container - verify the selected result remains - // the same. - CreateSearchResultAt(0, ash::SearchResultDisplayType::kTile, 0.9, - u"test tile", std::u16string()); - // Finish results update. - base::RunLoop().RunUntilIdle(); - - selection = GetResultSelectionController()->selected_result(); - EXPECT_EQ(u"testing", selection->result()->title()); - } - // Add a new result at the end, and verify the selection stays the same. CreateSearchResult(ash::SearchResultDisplayType::kList, 0.2, u"testing almost", std::u16string()); @@ -627,35 +613,28 @@ // Remove the result before the selected one, and verify the selection remains // the same. - results()->RemoveAt(IsProductivityLauncherEnabled() ? 0 : 1); + results()->RemoveAt(0); base::RunLoop().RunUntilIdle(); selection = GetResultSelectionController()->selected_result(); EXPECT_EQ(u"testing", selection->result()->title()); // Result should be reset if the selected result is removed. - results()->RemoveAt(IsProductivityLauncherEnabled() ? 0 : 1); + results()->RemoveAt(0); base::RunLoop().RunUntilIdle(); // Tile results are not created when testing productivity launcher. selection = GetResultSelectionController()->selected_result(); - if (IsProductivityLauncherEnabled()) { + EXPECT_EQ(u"testing almost", selection->result()->title()); // New result can override the default selection. CreateSearchResultAt(0, ash::SearchResultDisplayType::kList, 1.0, u"test", std::u16string()); - } else { - EXPECT_EQ(u"test tile", selection->result()->title()); + base::RunLoop().RunUntilIdle(); - // New result can override the default selection. - CreateSearchResultAt(0, ash::SearchResultDisplayType::kTile, 1.0, u"test", - std::u16string()); - } - base::RunLoop().RunUntilIdle(); - - selection = GetResultSelectionController()->selected_result(); - EXPECT_EQ(u"test", selection->result()->title()); + selection = GetResultSelectionController()->selected_result(); + EXPECT_EQ(u"test", selection->result()->title()); } // Tests that the default selection is reset after resetting and reactivating @@ -942,93 +921,39 @@ // titles. TEST_P(SearchBoxViewAutocompleteTest, SearchBoxAutocompletesTopListResultTitle) { - // Search result tile tests are not relevant for productivity launcher. - if (IsProductivityLauncherEnabled()) - return; - SimulateQuery(u"he"); - // Add two SearchResults, one tile and one list result. Initialize their title - // field to a non-empty string. - CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, u"hello list", + // Add two SearchResults. The higher ranked result should be selected by + // default and it's title should be autocompleted into the search box. + CreateSearchResult(ash::SearchResultDisplayType::kList, 2.0, u"hello list", std::u16string()); - CreateSearchResult(ash::SearchResultDisplayType::kTile, 0.5, u"hello tile", + CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, u"hello list2", std::u16string()); base::RunLoop().RunUntilIdle(); ProcessAutocomplete(); - EXPECT_EQ(view()->search_box()->GetText(), u"hello tile"); - EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo tile"); -} - -// Tests that autocomplete suggestions are consistent with top SearchResult tile -// titles. -TEST_P(SearchBoxViewAutocompleteTest, - SearchBoxAutocompletesTopTileResultTitle) { - // Search result tile tests are not relevant for productivity launcher. - if (IsProductivityLauncherEnabled()) - return; - - SimulateQuery(u"he"); - - // Add two SearchResults, one tile and one list result. Initialize their title - // field to a non-empty string. - CreateSearchResult(ash::SearchResultDisplayType::kTile, 1.0, u"hello tile", - std::u16string()); - CreateSearchResult(ash::SearchResultDisplayType::kList, 0.5, u"hello list", - std::u16string()); + EXPECT_EQ(view()->search_box()->GetText(), u"hello list"); + EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo list"); base::RunLoop().RunUntilIdle(); - - ProcessAutocomplete(); - EXPECT_EQ(view()->search_box()->GetText(), u"hello tile"); - EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo tile"); } // Tests that autocomplete suggestions are consistent with top SearchResult list // details. TEST_P(SearchBoxViewAutocompleteTest, SearchBoxAutocompletesTopListResultDetails) { - // Search result tile tests are not relevant for productivity launcher. - if (IsProductivityLauncherEnabled()) - return; - SimulateQuery(u"he"); - // Add two SearchResults, one tile and one list result. The tile should - // display first, despite having a lower score. Initialize their details field - // to a non-empty string. + // Add two SearchResults. The higher ranked result should be selected by + // default and it's title should be autocompleted into the search box. + CreateSearchResult(ash::SearchResultDisplayType::kList, 2.0, std::u16string(), + u"hello list"); CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, std::u16string(), - u"hello list"); - CreateSearchResult(ash::SearchResultDisplayType::kTile, 0.5, std::u16string(), - u"hello tile"); + u"hello list2"); base::RunLoop().RunUntilIdle(); ProcessAutocomplete(); - EXPECT_EQ(view()->search_box()->GetText(), u"hello tile"); - EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo tile"); -} - -// Tests that autocomplete suggestions are consistent with top SearchResult tile -// details. -TEST_P(SearchBoxViewAutocompleteTest, - SearchBoxAutocompletesTopTileResultDetails) { - // Search result tile tests are not relevant for productivity launcher. - if (IsProductivityLauncherEnabled()) - return; - - SimulateQuery(u"he"); - - // Add two SearchResults, one tile and one list result. Initialize their - // details field to a non-empty string. - CreateSearchResult(ash::SearchResultDisplayType::kTile, 1.0, std::u16string(), - u"hello tile"); - CreateSearchResult(ash::SearchResultDisplayType::kList, 0.5, std::u16string(), - u"hello list"); - base::RunLoop().RunUntilIdle(); - - ProcessAutocomplete(); - EXPECT_EQ(view()->search_box()->GetText(), u"hello tile"); - EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo tile"); + EXPECT_EQ(view()->search_box()->GetText(), u"hello list"); + EXPECT_EQ(view()->search_box()->GetSelectedText(), u"llo list"); } // Tests that SearchBoxView's textfield text does not autocomplete if the top
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index 51838ed5..92c29f2 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -18,7 +18,6 @@ #include "ash/app_list/views/search_result_base_view.h" #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_page_anchored_dialog.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_color_provider.h" #include "ash/public/cpp/app_list/app_list_config.h" @@ -61,19 +60,9 @@ constexpr int kMinHeight = 440; constexpr int kWidth = 640; -// The horizontal padding of the separator. -constexpr int kSeparatorPadding = 12; -constexpr int kSeparatorThickness = 1; - // The height of the active search box in this page. constexpr int kActiveSearchBoxHeight = 56; -// The spacing between search box bottom and separator line. -// Add 1 pixel spacing so that the search bbox bottom will not paint over -// the separator line drawn by SearchResultPageBackground in some scale factors -// due to the round up. -constexpr int kSearchBoxBottomSpacing = 1; - // Minimum spacing between shelf and bottom of search box. constexpr int kSearchResultPageMinimumBottomMargin = 24; @@ -133,64 +122,8 @@ } }; -class SearchResultPageBackground : public views::Background { - public: - SearchResultPageBackground() = default; - SearchResultPageBackground(const SearchResultPageBackground&) = delete; - SearchResultPageBackground& operator=(const SearchResultPageBackground&) = - delete; - ~SearchResultPageBackground() override = default; - - private: - // views::Background overrides: - void Paint(gfx::Canvas* canvas, views::View* view) const override { - canvas->DrawColor(get_color()); - gfx::Rect bounds = view->GetContentsBounds(); - if (bounds.height() <= kActiveSearchBoxHeight) - return; - // Draw a separator between SearchBoxView and SearchResultPageView. - bounds.set_y(kActiveSearchBoxHeight + kSearchBoxBottomSpacing); - bounds.set_height(kSeparatorThickness); - canvas->FillRect(bounds, - view->GetColorProvider()->GetColor( - AppListColorProvider::Get()->GetSeparatorColorId())); - } -}; - } // namespace -class SearchResultPageView::HorizontalSeparator : public views::View { - public: - explicit HorizontalSeparator(int preferred_width) - : preferred_width_(preferred_width) { - SetBorder(views::CreateEmptyBorder( - gfx::Insets::TLBR(0, kSeparatorPadding, 0, kSeparatorPadding))); - } - - HorizontalSeparator(const HorizontalSeparator&) = delete; - HorizontalSeparator& operator=(const HorizontalSeparator&) = delete; - - ~HorizontalSeparator() override = default; - - // views::View overrides: - const char* GetClassName() const override { return "HorizontalSeparator"; } - - gfx::Size CalculatePreferredSize() const override { - return gfx::Size(preferred_width_, kSeparatorThickness); - } - - void OnPaint(gfx::Canvas* canvas) override { - gfx::Rect rect = GetContentsBounds(); - canvas->FillRect(rect, - GetColorProvider()->GetColor( - AppListColorProvider::Get()->GetSeparatorColorId())); - View::OnPaint(canvas); - } - - private: - const int preferred_width_; -}; - SearchResultPageView::SearchResultPageView() : contents_view_(new views::View) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -204,7 +137,7 @@ // Hides this view behind the search box by using the same color and // background border corner radius. All child views' background should be // set transparent so that the rounded corner is not overwritten. - SetBackground(std::make_unique<SearchResultPageBackground>()); + SetBackground(views::CreateSolidBackground(SK_ColorTRANSPARENT)); if (features::IsProductivityLauncherEnabled()) { layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality); @@ -216,16 +149,14 @@ // App list bubble search page has its own scroller and result selection // controller so we do not need to construct new ones here. if (features::IsProductivityLauncherEnabled()) { - contents_view_->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR( - kActiveSearchBoxHeight + kSearchBoxBottomSpacing + kSeparatorThickness, - 0, 0, 0))); + contents_view_->SetBorder(views::CreateEmptyBorder( + gfx::Insets::TLBR(kActiveSearchBoxHeight, 0, 0, 0))); AddChildView(contents_view_); } else { auto scroller = std::make_unique<views::ScrollView>(); // Leaves a placeholder area for the search box and the separator below it. - scroller->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR( - kActiveSearchBoxHeight + kSearchBoxBottomSpacing + kSeparatorThickness, - 0, 0, 0))); + scroller->SetBorder(views::CreateEmptyBorder( + gfx::Insets::TLBR(kActiveSearchBoxHeight, 0, 0, 0))); scroller->SetDrawOverflowIndicator(false); scroller->SetContents(base::WrapUnique(contents_view_)); // Setting clip height is necessary to make ScrollView take into account its @@ -274,11 +205,6 @@ std::make_unique<SearchResultPageDialogController>(this); privacy_container_view_ = AddSearchResultContainerView( std::make_unique<PrivacyContainerView>(view_delegate)); - search_result_tile_item_list_view_ = AddSearchResultContainerView( - std::make_unique<SearchResultTileItemListView>( - search_box_view->search_box(), view_delegate)); - result_lists_separator_ = contents_view_->AddChildView( - std::make_unique<HorizontalSeparator>(bounds().width())); // productivity_launcher_index is not set as the feature is not enabled. search_result_list_view_ = AddSearchResultContainerView(std::make_unique<SearchResultListView>( @@ -327,8 +253,7 @@ int adjusted_height = std::min( std::max(kMinHeight, productivity_launcher_search_view_->TabletModePreferredHeight() + - kActiveSearchBoxHeight + kSearchBoxBottomSpacing + - kSeparatorThickness + + kActiveSearchBoxHeight + kExpandedSearchBoxCornerRadiusForProductivityLauncher), AppListPage::contents_view()->height()); return gfx::Size(kWidth, adjusted_height); @@ -424,10 +349,6 @@ should_show_page_view || should_show_container_view; } - result_lists_separator_->SetVisible( - search_result_tile_item_list_view_->num_results() && - search_result_list_view_->num_results() && - ShouldShowSearchResultView()); AppListPage::contents_view() ->GetSearchBoxView() ->OnResultContainerVisibilityChanged(should_show_page_view); @@ -766,11 +687,6 @@ return privacy_container_view_; } -SearchResultTileItemListView* -SearchResultPageView::GetSearchResultTileItemListViewForTest() { - return search_result_tile_item_list_view_; -} - SearchResultListView* SearchResultPageView::GetSearchResultListViewForTest() { return search_result_list_view_; }
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h index 3b69eb8b..55ae04f5 100644 --- a/ash/app_list/views/search_result_page_view.h +++ b/ash/app_list/views/search_result_page_view.h
@@ -27,7 +27,6 @@ class SearchBoxView; class SearchResultBaseView; class SearchResultListView; -class SearchResultTileItemListView; class SearchResultPageAnchoredDialog; class SystemShadow; @@ -126,7 +125,6 @@ void UpdateResultContainersVisibility(); PrivacyContainerView* GetPrivacyContainerViewForTest(); - SearchResultTileItemListView* GetSearchResultTileItemListViewForTest(); SearchResultListView* GetSearchResultListViewForTest(); private: @@ -134,9 +132,6 @@ // launcher. enum class SearchResultsState { kClosed, kActive, kExpanded }; - // Separator between SearchResultContainerView. - class HorizontalSeparator; - // Passed to |result_selection_controller_| as a callback that gets called // when the currently selected result changes. // Ensures that |scroller_| visible rect contains the newly selected result. @@ -209,15 +204,10 @@ // Search result containers shown within search results page (and added to // `result_container_views_`). PrivacyContainerView* privacy_container_view_ = nullptr; - SearchResultTileItemListView* search_result_tile_item_list_view_ = nullptr; SearchResultListView* search_result_list_view_ = nullptr; // Search result container used for productivity launcher. ProductivityLauncherSearchView* productivity_launcher_search_view_ = nullptr; - // Separator view shown between search result tile item list and search - // results list. - HorizontalSeparator* result_lists_separator_ = nullptr; - // View containing SearchCardView instances. Owned by view hierarchy. views::View* const contents_view_;
diff --git a/ash/app_list/views/search_result_page_view_unittest.cc b/ash/app_list/views/search_result_page_view_unittest.cc index a6cce84..5ec227a 100644 --- a/ash/app_list/views/search_result_page_view_unittest.cc +++ b/ash/app_list/views/search_result_page_view_unittest.cc
@@ -15,7 +15,6 @@ #include "ash/app_list/views/app_list_view.h" #include "ash/app_list/views/contents_view.h" #include "ash/app_list/views/search_result_list_view.h" -#include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/app_list/views/search_result_view.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_features.h" @@ -56,8 +55,6 @@ ContentsView* contents_view = app_list_view_->app_list_main_view()->contents_view(); view_ = contents_view->search_result_page_view(); - tile_list_view_ = contents_view->search_result_page_view() - ->GetSearchResultTileItemListViewForTest(); list_view_ = contents_view->search_result_page_view() ->GetSearchResultListViewForTest(); } @@ -69,9 +66,6 @@ protected: SearchResultPageView* view() const { return view_; } - SearchResultTileItemListView* tile_list_view() const { - return tile_list_view_; - } SearchResultListView* list_view() const { return list_view_; } SearchModel::SearchResults* GetResults() const { @@ -82,8 +76,6 @@ TestAppListColorProvider color_provider_; // Needed by AppListView. AppListView* app_list_view_ = nullptr; // Owned by native widget. SearchResultPageView* view_ = nullptr; // Owned by views hierarchy. - SearchResultTileItemListView* tile_list_view_ = - nullptr; // Owned by views hierarchy. SearchResultListView* list_view_ = nullptr; // Owned by views hierarchy. std::unique_ptr<AppListTestViewDelegate> delegate_; base::test::ScopedFeatureList scoped_feature_list_; @@ -114,13 +106,11 @@ // Adding results will schedule Update(). RunPendingMessages(); - ASSERT_GE(view()->result_container_views().size(), 3u); + ASSERT_GE(view()->result_container_views().size(), 2u); // Privacy container is hidden. EXPECT_FALSE(view()->result_container_views()[0]->GetVisible()); - EXPECT_TRUE(tile_list_view()->GetVisible()); - EXPECT_EQ(tile_list_view(), view()->result_container_views()[1]); EXPECT_TRUE(list_view()->GetVisible()); - EXPECT_EQ(list_view(), view()->result_container_views()[2]); + EXPECT_EQ(list_view(), view()->result_container_views()[1]); // Change the relevance of the tile result to be lower than list results. The // tile container should still be displayed first. @@ -131,9 +121,7 @@ // Privacy container is hidden. EXPECT_FALSE(view()->result_container_views()[0]->GetVisible()); - EXPECT_EQ(tile_list_view(), view()->result_container_views()[1]); - EXPECT_TRUE(tile_list_view()->GetVisible()); - EXPECT_EQ(list_view(), view()->result_container_views()[2]); + EXPECT_EQ(list_view(), view()->result_container_views()[1]); EXPECT_TRUE(list_view()->GetVisible()); } @@ -150,7 +138,6 @@ // Adding results will schedule Update(). RunPendingMessages(); - EXPECT_TRUE(tile_list_view()->GetVisible()); EXPECT_FALSE(list_view()->GetVisible()); } @@ -168,7 +155,6 @@ RunPendingMessages(); EXPECT_TRUE(list_view()->GetVisible()); - EXPECT_FALSE(tile_list_view()->GetVisible()); } } // namespace test
diff --git a/ash/app_list/views/search_result_tile_item_list_view.cc b/ash/app_list/views/search_result_tile_item_list_view.cc deleted file mode 100644 index 6f5bd45..0000000 --- a/ash/app_list/views/search_result_tile_item_list_view.cc +++ /dev/null
@@ -1,368 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/app_list/views/search_result_tile_item_list_view.h" - -#include <stddef.h> - -#include <algorithm> -#include <memory> -#include <set> -#include <string> - -#include "ash/app_list/app_list_model_provider.h" -#include "ash/app_list/app_list_util.h" -#include "ash/app_list/app_list_view_delegate.h" -#include "ash/app_list/model/search/search_result.h" -#include "ash/app_list/views/search_result_page_view.h" -#include "ash/public/cpp/app_list/app_list_color_provider.h" -#include "ash/public/cpp/app_list/app_list_config.h" -#include "ash/public/cpp/app_list/app_list_features.h" -#include "ash/public/cpp/app_list/app_list_notifier.h" -#include "ash/public/cpp/app_list/app_list_types.h" -#include "ash/public/cpp/app_list/internal_app_id_constants.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/i18n/rtl.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/stl_util.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/views/background.h" -#include "ui/views/border.h" -#include "ui/views/controls/separator.h" -#include "ui/views/controls/textfield/textfield.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -// Layout constants used when fullscreen app list feature is enabled. -constexpr int kItemListVerticalSpacing = 16; -constexpr int kItemListHorizontalSpacing = 12; -constexpr int kBetweenItemSpacing = 8; -constexpr int kSeparatorLeftRightPadding = 4; -constexpr int kSeparatorHeight = 46; -constexpr int kSeparatorTopPadding = 10; - -// The Delay before recording play store app results impression, i.e., if the -// play store results are displayed less than the duration, we assume user -// won't have chance to see them clearly and click on them, and wont' log -// the impression. -constexpr int kPlayStoreImpressionDelayInMs = 1000; - -// Returns true if the search result is an installable app. -bool IsResultAnInstallableApp(SearchResult* result) { - SearchResult::ResultType result_type = result->result_type(); - return result_type == AppListSearchResultType::kPlayStoreApp || - result_type == AppListSearchResultType::kPlayStoreReinstallApp || - result_type == AppListSearchResultType::kInstantApp; -} - -bool IsPlayStoreApp(SearchResult* result) { - return result->result_type() == AppListSearchResultType::kPlayStoreApp; -} - -} // namespace - -SearchResultTileItemListView::SearchResultTileItemListView( - views::Textfield* search_box, - AppListViewDelegate* view_delegate) - : SearchResultContainerView(view_delegate), - search_box_(search_box), - is_app_reinstall_recommendation_enabled_( - app_list_features::IsAppReinstallZeroStateEnabled()), - max_search_result_tiles_( - SharedAppListConfig::instance().max_search_result_tiles()) { - layout_ = SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, - gfx::Insets::VH(kItemListVerticalSpacing, kItemListHorizontalSpacing), - kBetweenItemSpacing)); - for (size_t i = 0; i < max_search_result_tiles_; ++i) { - views::Separator* separator = - AddChildView(std::make_unique<views::Separator>()); - separator->SetVisible(false); - separator->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR( - kSeparatorTopPadding, kSeparatorLeftRightPadding, - SharedAppListConfig::instance().search_tile_height() - kSeparatorHeight, - kSeparatorLeftRightPadding))); - separator->SetColorId(AppListColorProvider::Get()->GetSeparatorColorId()); - separator_views_.push_back(separator); - layout_->SetFlexForView(separator, 0); - - SearchResultTileItemView* tile_item = - AddChildView(std::make_unique<SearchResultTileItemView>(view_delegate)); - tile_item->set_index_in_container(i); - tile_views_.push_back(tile_item); - AddObservedResultView(tile_item); - } - - // Tile items are shown horizontally. - set_horizontally_traversable(true); -} - -SearchResultTileItemListView::~SearchResultTileItemListView() = default; - -SearchResultTileItemView* SearchResultTileItemListView::GetResultViewAt( - size_t index) { - DCHECK(index >= 0 && index < tile_views_.size()); - return tile_views_[index]; -} - -int SearchResultTileItemListView::DoUpdate() { - if (!GetWidget() || !GetWidget()->IsVisible() || !GetWidget()->IsActive()) { - for (size_t i = 0; i < max_search_result_tiles_; ++i) { - SearchResultBaseView* result_view = GetResultViewAt(i); - result_view->SetResult(nullptr); - result_view->SetVisible(false); - } - return 0; - } - - std::vector<SearchResult*> display_results = GetDisplayResults(); - - std::set<std::string> result_id_removed, result_id_added; - bool is_result_an_installable_app = false; - bool is_previous_result_installable_app = false; - int installed_app_index = -1; - int playstore_app_index = -1; - int app_group_index = -1; - bool found_playstore_results = false; - - for (size_t i = 0; i < max_search_result_tiles_; ++i) { - // If the current result at i exists, wants to be notified and is a - // different id, notify it that it is being hidden. - SearchResult* current_result = tile_views_[i]->result(); - if (current_result != nullptr) { - result_id_removed.insert(current_result->id()); - } - - if (i >= display_results.size()) { - separator_views_[i]->SetVisible(false); - - GetResultViewAt(i)->SetResult(nullptr); - continue; - } - - SearchResult* item = display_results[i]; - if (IsPlayStoreApp(item)) { - ++playstore_app_index; - app_group_index = playstore_app_index; - found_playstore_results = true; - } else if (item->result_type() == - AppListSearchResultType::kPlayStoreReinstallApp) { - app_group_index = playstore_app_index; - } else { - ++installed_app_index; - app_group_index = installed_app_index; - } - - GetResultViewAt(i)->SetResult(item); - GetResultViewAt(i)->set_group_index_in_container_view(app_group_index); - result_id_added.insert(item->id()); - is_result_an_installable_app = IsResultAnInstallableApp(item); - - if (i > 0 && - (is_result_an_installable_app != is_previous_result_installable_app)) { - // Add a separator between installed apps and installable apps. - // This assumes the search results are already separated in groups for - // installed and installable apps. - separator_views_[i]->SetVisible(true); - } else { - separator_views_[i]->SetVisible(false); - } - - is_previous_result_installable_app = is_result_an_installable_app; - } - - auto* notifier = view_delegate()->GetNotifier(); - if (notifier) { - std::vector<AppListNotifier::Result> notifier_results; - for (const auto* result : display_results) - notifier_results.emplace_back(result->id(), result->metrics_type()); - notifier->NotifyResultsUpdated(SearchResultDisplayType::kTile, - notifier_results); - } - - // Track play store results and start the timer for recording their impression - // UMA metrics. - std::u16string user_typed_query = GetUserTypedQuery(); - if (found_playstore_results && user_typed_query != recent_playstore_query_) { - recent_playstore_query_ = user_typed_query; - playstore_impression_timer_.Stop(); - playstore_impression_timer_.Start( - FROM_HERE, base::Milliseconds(kPlayStoreImpressionDelayInMs), this, - &SearchResultTileItemListView::OnPlayStoreImpressionTimer); - // Set the starting time in result view for play store results. - base::TimeTicks result_display_start = base::TimeTicks::Now(); - for (size_t i = 0; i < max_search_result_tiles_; ++i) { - SearchResult* result = GetResultViewAt(i)->result(); - if (result && IsPlayStoreApp(result)) { - GetResultViewAt(i)->set_result_display_start_time(result_display_start); - } - } - } else if (!found_playstore_results) { - playstore_impression_timer_.Stop(); - } - - return display_results.size(); -} - -std::vector<SearchResult*> SearchResultTileItemListView::GetDisplayResults() { - std::u16string raw_query = search_box_->GetText(); - std::u16string query; - base::TrimWhitespace(raw_query, base::TRIM_ALL, &query); - - // We ask for |max_search_result_tiles_| policy tile results first, - // then add them to their preferred position in the tile list if found. - // Note: Policy tile provides a mechanism to display the result tile at the - // preferred position recommended by display_index() property of the search - // result. This is what policy referred to. It has nothing to do with - // Enterprise policy. - auto policy_tiles_filter = - base::BindRepeating([](const SearchResult& r) -> bool { - return r.display_index() != SearchResultDisplayIndex::kUndefined && - r.display_type() == SearchResultDisplayType::kTile && - r.is_recommendation(); - }); - std::vector<SearchResult*> policy_tiles_results = - is_app_reinstall_recommendation_enabled_ && query.empty() - ? SearchModel::FilterSearchResultsByFunction( - results(), policy_tiles_filter, max_search_result_tiles_) - : std::vector<SearchResult*>(); - - SearchResult::DisplayType display_type = SearchResultDisplayType::kTile; - size_t display_num = max_search_result_tiles_ - policy_tiles_results.size(); - - // Do not display the repeat reinstall results or continue reading app in the - // search result list. - auto non_policy_tiles_filter = base::BindRepeating( - [](const SearchResult::DisplayType& display_type, - const SearchResult& r) -> bool { - return r.display_type() == display_type && - r.result_type() != - AppListSearchResultType::kPlayStoreReinstallApp && - r.id() != kInternalAppIdContinueReading; - }, - display_type); - std::vector<SearchResult*> display_results = - SearchModel::FilterSearchResultsByFunction( - results(), non_policy_tiles_filter, display_num); - - // Policy tile results will be appended to the final tiles list - // based on their specified index. If the requested index is out of - // range of the current list, the result will be appended to the back. - std::sort(policy_tiles_results.begin(), policy_tiles_results.end(), - [](const SearchResult* r1, const SearchResult* r2) -> bool { - return r1->display_index() < r2->display_index(); - }); - - const SearchResultDisplayIndex display_results_last_index = - static_cast<SearchResultDisplayIndex>(display_results.size() - 1); - for (auto* result : policy_tiles_results) { - const SearchResultDisplayIndex result_index = result->display_index(); - if (result_index > display_results_last_index) { - display_results.emplace_back(result); - } else { - // TODO(newcomer): Remove this check once we determine the root cause for - // https://crbug.com/992344. - CHECK_GE(result_index, SearchResultDisplayIndex::kFirstIndex); - display_results.emplace(display_results.begin() + result_index, result); - } - } - - return display_results; -} - -std::u16string SearchResultTileItemListView::GetUserTypedQuery() { - std::u16string search_box_text = search_box_->GetText(); - gfx::Range range = search_box_->GetSelectedRange(); - std::u16string raw_query = range.is_empty() - ? search_box_text - : search_box_text.substr(0, range.start()); - std::u16string query; - base::TrimWhitespace(raw_query, base::TRIM_ALL, &query); - return query; -} - -void SearchResultTileItemListView::OnPlayStoreImpressionTimer() { - size_t playstore_app_num = 0; - for (const auto* tile_view : tile_views_) { - SearchResult* result = tile_view->result(); - if (result == nullptr) - continue; - if (IsPlayStoreApp(result)) - ++playstore_app_num; - } - - // Log the UMA metrics of play store impression. - base::RecordAction( - base::UserMetricsAction("AppList_ShowPlayStoreQueryResults")); - - DCHECK_LE(playstore_app_num, max_search_result_tiles_); - UMA_HISTOGRAM_EXACT_LINEAR("Apps.AppListPlayStoreSearchAppsDisplayed", - playstore_app_num, max_search_result_tiles_); -} - -void SearchResultTileItemListView::CleanUpOnViewHide() { - playstore_impression_timer_.Stop(); - recent_playstore_query_.clear(); -} - -const char* SearchResultTileItemListView::GetClassName() const { - return "SearchResultTileItemListView"; -} - -void SearchResultTileItemListView::Layout() { - const bool flex = GetContentsBounds().width() < GetPreferredSize().width(); - layout_->SetDefaultFlex(flex ? 1 : 0); - layout_->set_between_child_spacing(flex ? 1 : kBetweenItemSpacing); - - views::View::Layout(); -} - -void SearchResultTileItemListView::OnShownChanged() { - SearchResultContainerView::OnShownChanged(); - for (const auto* tile_view : tile_views_) { - SearchResult* result = tile_view->result(); - if (result == nullptr) { - continue; - } - } -} - -void SearchResultTileItemListView::OnThemeChanged() { - SearchResultContainerView::OnThemeChanged(); - - const auto parent_background_color = - AppListColorProvider::Get()->GetSearchBoxCardBackgroundColor(GetWidget()); - - for (auto* tile_view : tile_views_) - tile_view->SetParentBackgroundColor(parent_background_color); -} - -void SearchResultTileItemListView::VisibilityChanged(View* starting_from, - bool is_visible) { - SearchResultContainerView::VisibilityChanged(starting_from, is_visible); - // We only do this work when is_visible is false, since this is how we - // receive the event. We filter and only run when shown. - if (is_visible && shown()) { - return; - } - - CleanUpOnViewHide(); - - for (const auto* tile_view : tile_views_) { - SearchResult* result = tile_view->result(); - if (result == nullptr) { - continue; - } - } -} - -} // namespace ash
diff --git a/ash/app_list/views/search_result_tile_item_list_view.h b/ash/app_list/views/search_result_tile_item_list_view.h deleted file mode 100644 index 886c14c..0000000 --- a/ash/app_list/views/search_result_tile_item_list_view.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_LIST_VIEW_H_ -#define ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_LIST_VIEW_H_ - -#include <vector> - -#include "ash/app_list/views/search_result_container_view.h" -#include "ash/app_list/views/search_result_tile_item_view.h" -#include "base/timer/timer.h" - -namespace views { -class BoxLayout; -class Separator; -class Textfield; -} // namespace views - -namespace ash { - -class AppListViewDelegate; - -// Displays a list of SearchResultTileItemView. -class ASH_EXPORT SearchResultTileItemListView - : public SearchResultContainerView { - public: - SearchResultTileItemListView(views::Textfield* search_box, - AppListViewDelegate* view_delegate); - SearchResultTileItemListView(const SearchResultTileItemListView&) = delete; - SearchResultTileItemListView& operator=(const SearchResultTileItemListView&) = - delete; - ~SearchResultTileItemListView() override; - - // Overridden from SearchResultContainerView: - SearchResultTileItemView* GetResultViewAt(size_t index) override; - - // Overridden from views::View: - const char* GetClassName() const override; - void Layout() override; - - const std::vector<SearchResultTileItemView*>& tile_views_for_test() const { - return tile_views_; - } - - // Overridden from SearchResultContainerView: - void OnShownChanged() override; - void OnThemeChanged() override; - - protected: - // View overrides: - void VisibilityChanged(View* starting_from, bool is_visible) override; - - private: - // Overridden from SearchResultContainerView: - int DoUpdate() override; - - std::vector<SearchResult*> GetDisplayResults(); - - std::u16string GetUserTypedQuery(); - - void OnPlayStoreImpressionTimer(); - - // Cleans up when the view is hid due to closing the suggestion widow - // or closing the launcher. - void CleanUpOnViewHide(); - - std::vector<SearchResultTileItemView*> tile_views_; - - std::vector<views::Separator*> separator_views_; - - // Owned by the views hierarchy. - views::Textfield* search_box_ = nullptr; - views::BoxLayout* layout_ = nullptr; - - std::u16string recent_playstore_query_; - - base::OneShotTimer playstore_impression_timer_; - - const bool is_app_reinstall_recommendation_enabled_; - - const size_t max_search_result_tiles_; -}; - -} // namespace ash - -#endif // ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_LIST_VIEW_H_
diff --git a/ash/app_list/views/search_result_tile_item_list_view_unittest.cc b/ash/app_list/views/search_result_tile_item_list_view_unittest.cc deleted file mode 100644 index 036c87b..0000000 --- a/ash/app_list/views/search_result_tile_item_list_view_unittest.cc +++ /dev/null
@@ -1,331 +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. - -#include "ash/app_list/views/search_result_tile_item_list_view.h" - -#include <algorithm> -#include <memory> -#include <utility> - -#include "ash/app_list/app_list_test_view_delegate.h" -#include "ash/app_list/model/app_list_model.h" -#include "ash/app_list/model/search/test_search_result.h" -#include "ash/app_list/views/search_result_tile_item_view.h" -#include "ash/app_list/views/search_result_view.h" -#include "ash/public/cpp/app_list/app_list_features.h" -#include "ash/public/cpp/test/test_app_list_color_provider.h" -#include "ash/strings/grit/ash_strings.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/accessibility/ax_node_data.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/controls/textfield/textfield.h" -#include "ui/views/test/widget_test.h" - -namespace ash { - -namespace { -constexpr size_t kInstalledApps = 4; -constexpr size_t kPlayStoreApps = 2; -constexpr size_t kRecommendedApps = 1; - -// used to test when multiple chips with specified display -// indexes have been added -constexpr size_t kRecommendedAppsWithDisplayIndex = 3; -} // namespace - -class SearchResultTileItemListViewTest - : public views::test::WidgetTest, - public ::testing::WithParamInterface<std::pair<bool, bool>> { - public: - SearchResultTileItemListViewTest() = default; - - SearchResultTileItemListViewTest(const SearchResultTileItemListViewTest&) = - delete; - SearchResultTileItemListViewTest& operator=( - const SearchResultTileItemListViewTest&) = delete; - - ~SearchResultTileItemListViewTest() override = default; - - // Overridden from testing::Test: - void SetUp() override { - views::test::WidgetTest::SetUp(); - widget_ = CreateTopLevelPlatformWidget(); - } - - void TearDown() override { - view_.reset(); - widget_->CloseNow(); - views::test::WidgetTest::TearDown(); - } - - protected: - void CreateSearchResultTileItemListView() { - scoped_feature_list_.InitWithFeatureState( - app_list_features::kEnableAppReinstallZeroState, - IsReinstallAppRecommendationEnabled()); - - // Sets up the views. - textfield_ = std::make_unique<views::Textfield>(); - view_ = std::make_unique<SearchResultTileItemListView>(textfield_.get(), - &view_delegate_); - widget_->SetBounds(gfx::Rect(0, 0, 300, 200)); - widget_->GetContentsView()->AddChildView(view_.get()); - widget_->Show(); - view_->SetResults(GetResults()); - } - - bool IsReinstallAppRecommendationEnabled() const { return GetParam().first; } - - SearchResultTileItemListView* view() { return view_.get(); } - - SearchModel::SearchResults* GetResults() { - return AppListModelProvider::Get()->search_model()->results(); - } - - void SetUpSearchResults() { - SearchModel::SearchResults* results = GetResults(); - - // Populate results for installed applications. - for (size_t i = 0; i < kInstalledApps; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("InstalledApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_result_type(AppListSearchResultType::kInstalledApp); - result->SetTitle(u"InstalledApp " + base::NumberToString16(i)); - results->Add(std::move(result)); - } - - // Populate results for Play Store search applications. - for (size_t i = 0; i < kPlayStoreApps; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("PlayStoreApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_result_type(AppListSearchResultType::kPlayStoreApp); - result->SetTitle(u"PlayStoreApp " + base::NumberToString16(i)); - result->SetRating(1 + i); - result->SetFormattedPrice(u"Price " + base::NumberToString16(i)); - results->Add(std::move(result)); - } - - if (IsReinstallAppRecommendationEnabled()) { - for (size_t i = 0; i < kRecommendedApps; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("RecommendedApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_is_recommendation(true); - result->set_result_type( - AppListSearchResultType::kPlayStoreReinstallApp); - result->set_display_index(SearchResultDisplayIndex::kSixthIndex); - result->SetTitle(u"RecommendedApp " + base::NumberToString16(i)); - result->SetRating(1 + i); - results->Add(std::move(result)); - } - } - - // Adding results calls SearchResultContainerView::ScheduleUpdate(). - // It will post a delayed task to update the results and relayout. - RunPendingMessages(); - } - - void SetUpSearchResultsWithMultipleDisplayIndexesRequested() { - SearchModel::SearchResults* results = GetResults(); - - // Populate results for installed applications. - for (size_t i = 0; i < kInstalledApps; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("InstalledApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_result_type(AppListSearchResultType::kInstalledApp); - result->SetTitle(u"InstalledApp " + base::NumberToString16(i)); - results->Add(std::move(result)); - } - - // Populate results for Play Store search applications. - for (size_t i = 0; i < kPlayStoreApps; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("PlayStoreApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_result_type(AppListSearchResultType::kPlayStoreApp); - result->SetTitle(u"PlayStoreApp " + base::NumberToString16(i)); - result->SetRating(1 + i); - result->SetFormattedPrice(u"Price " + base::NumberToString16(i)); - results->Add(std::move(result)); - } - - const SearchResultDisplayIndex - display_indexes[kRecommendedAppsWithDisplayIndex] = { - SearchResultDisplayIndex::kFourthIndex, - SearchResultDisplayIndex::kFifthIndex, - SearchResultDisplayIndex::kSixthIndex, - }; - - if (IsReinstallAppRecommendationEnabled()) { - for (size_t i = 0; i < kRecommendedAppsWithDisplayIndex; ++i) { - std::unique_ptr<TestSearchResult> result = - std::make_unique<TestSearchResult>(); - result->set_result_id("RecommendedApp " + base::NumberToString(i)); - result->set_display_type(SearchResultDisplayType::kTile); - result->set_is_recommendation(true); - result->set_result_type( - AppListSearchResultType::kPlayStoreReinstallApp); - result->set_display_index(display_indexes[i]); - result->SetTitle(u"RecommendedApp " + base::NumberToString16(i)); - result->SetRating(1 + i); - results->AddAt(display_indexes[i], std::move(result)); - } - } - - // Adding results calls SearchResultContainerView::ScheduleUpdate(). - // It will post a delayed task to update the results and relayout. - RunPendingMessages(); - } - - size_t GetOpenResultCount(int ranking) { - return view_delegate_.open_search_result_counts()[ranking]; - } - - void ResetOpenResultCount() { - view_delegate_.open_search_result_counts().clear(); - } - - size_t GetResultCount() const { return view_->num_results(); } - - private: - TestAppListColorProvider color_provider_; // Needed by AppListView. - test::AppListTestViewDelegate view_delegate_; - std::unique_ptr<SearchResultTileItemListView> view_; - views::Widget* widget_; - std::unique_ptr<views::Textfield> textfield_; - base::test::ScopedFeatureList scoped_feature_list_; -}; - -TEST_P(SearchResultTileItemListViewTest, Basic) { - CreateSearchResultTileItemListView(); - SetUpSearchResults(); - - const size_t results = GetResultCount(); - size_t expected_results = kInstalledApps; - expected_results += kPlayStoreApps; - - if (IsReinstallAppRecommendationEnabled()) { - expected_results += kRecommendedApps; - } - constexpr size_t kMaxNumSearchResultTiles = 6; - expected_results = std::min(kMaxNumSearchResultTiles, expected_results); - - ASSERT_EQ(expected_results, results); - - // When the Play Store app search or app reinstallation results are - // present, for each result, we added a separator for result type grouping. - const size_t child_step = 2; - const size_t expected_num_children = kMaxNumSearchResultTiles * child_step; - EXPECT_EQ(expected_num_children, view()->children().size()); - - /// Test accessibility descriptions of tile views. - const size_t first_child = child_step - 1; - for (size_t i = 0; i < kInstalledApps; ++i) { - ui::AXNodeData node_data; - view()->children()[first_child + i * child_step]->GetAccessibleNodeData( - &node_data); - EXPECT_EQ(ax::mojom::Role::kListBoxOption, node_data.role); - EXPECT_EQ(l10n_util::GetStringFUTF8( - IDS_APP_ACCESSIBILITY_INSTALLED_APP_ANNOUNCEMENT, - base::UTF8ToUTF16("InstalledApp " + base::NumberToString(i))), - node_data.GetStringAttribute(ax::mojom::StringAttribute::kName)); - } - - const size_t expected_install_apps = - expected_results - - (IsReinstallAppRecommendationEnabled() ? kRecommendedApps : 0) - - kInstalledApps; - for (size_t i = 0; i < expected_install_apps; ++i) { - ui::AXNodeData node_data; - view() - ->children()[first_child + (i + kInstalledApps) * child_step] - ->GetAccessibleNodeData(&node_data); - EXPECT_EQ(ax::mojom::Role::kListBoxOption, node_data.role); - EXPECT_EQ( - l10n_util::GetStringFUTF8( - IDS_APP_ACCESSIBILITY_ARC_APP_ANNOUNCEMENT, - base::UTF8ToUTF16("PlayStoreApp " + base::NumberToString(i))) + - ", Star rating " + base::NumberToString(i + 1) + ".0", - node_data.GetStringAttribute(ax::mojom::StringAttribute::kName)); - } - - // Recommendations. - const size_t start_index = kInstalledApps + expected_install_apps; - for (size_t i = 0; i < expected_results - start_index; ++i) { - ui::AXNodeData node_data; - view() - ->children()[first_child + (i + start_index) * child_step] - ->GetAccessibleNodeData(&node_data); - EXPECT_EQ(ax::mojom::Role::kListBoxOption, node_data.role); - EXPECT_EQ( - l10n_util::GetStringFUTF8( - IDS_APP_ACCESSIBILITY_APP_RECOMMENDATION_ARC, - base::UTF8ToUTF16("RecommendedApp " + base::NumberToString(i))) + - ", Star rating " + base::NumberToString(i + 1) + ".0", - node_data.GetStringAttribute(ax::mojom::StringAttribute::kName)); - } - - ResetOpenResultCount(); - for (size_t i = 0; i < results; ++i) { - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE); - for (size_t j = 0; j <= i; ++j) - view()->tile_views_for_test()[i]->OnKeyEvent(&event); - // When app reinstalls is enabled, we actually instantiate 7 results, - // but only show 6. So we have to look, for exactly 1 result, a "skip" - // ahead for the reinstall result. - if (IsReinstallAppRecommendationEnabled() && i == (results - 1)) { - EXPECT_EQ(i + 1, GetOpenResultCount(i + 1)); - } else { - EXPECT_EQ(i + 1, GetOpenResultCount(i)); - } - } -} - -// Tests that when multiple apps with specified indexes are added to the app -// results list, they are found at the indexes they requested. -TEST_P(SearchResultTileItemListViewTest, TestRecommendations) { - if (!IsReinstallAppRecommendationEnabled()) - return; - - CreateSearchResultTileItemListView(); - SetUpSearchResultsWithMultipleDisplayIndexesRequested(); - - const size_t child_step = 2; - - size_t first_index = kInstalledApps + kRecommendedAppsWithDisplayIndex; - - size_t stepper = 3; - for (size_t i = 0; i < stepper; ++i) { - ui::AXNodeData node_data; - view()->children()[first_index + i * child_step]->GetAccessibleNodeData( - &node_data); - EXPECT_EQ(ax::mojom::Role::kListBoxOption, node_data.role); - EXPECT_EQ( - l10n_util::GetStringFUTF8( - IDS_APP_ACCESSIBILITY_APP_RECOMMENDATION_ARC, - base::UTF8ToUTF16("RecommendedApp " + base::NumberToString(i))) + - ", Star rating " + base::NumberToString(i + 1) + ".0", - node_data.GetStringAttribute(ax::mojom::StringAttribute::kName)); - } -} - -INSTANTIATE_TEST_SUITE_P(, - SearchResultTileItemListViewTest, - testing::ValuesIn({std::make_pair(false, false), - std::make_pair(false, true), - std::make_pair(true, false), - std::make_pair(true, true)})); - -} // namespace ash
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc deleted file mode 100644 index 603ddbe9..0000000 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ /dev/null
@@ -1,579 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/app_list/views/search_result_tile_item_view.h" - -#include <utility> - -#include "ash/app_list/app_list_metrics.h" -#include "ash/app_list/app_list_util.h" -#include "ash/app_list/app_list_view_delegate.h" -#include "ash/app_list/model/app_list_model.h" -#include "ash/app_list/model/search/search_model.h" -#include "ash/app_list/model/search/search_result.h" -#include "ash/app_list/views/app_list_item_view.h" -#include "ash/public/cpp/app_list/app_list_color_provider.h" -#include "ash/public/cpp/app_list/app_list_config.h" -#include "ash/public/cpp/app_list/app_list_features.h" -#include "ash/public/cpp/app_list/app_list_types.h" -#include "ash/public/cpp/app_list/vector_icons/vector_icons.h" -#include "ash/public/cpp/ash_typography.h" -#include "ash/public/cpp/pagination/pagination_model.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/style/ash_color_id.h" -#include "base/bind.h" -#include "base/i18n/number_formatting.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/strings/utf_string_conversions.h" -#include "ui/accessibility/ax_node_data.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/image_model.h" -#include "ui/base/themed_vector_icon.h" -#include "ui/chromeos/styles/cros_styles.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/views/accessibility/view_accessibility.h" -#include "ui/views/background.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/controls/label.h" -#include "ui/views/controls/menu/menu_runner.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/style/typography.h" - -namespace ash { - -namespace { - -// The width of the focus ring. -constexpr int kSelectionRingWidth = 2; - -constexpr int kSearchTileWidth = 80; -constexpr int kSearchTileTopPadding = 4; -constexpr int kSearchTitleSpacing = 7; -constexpr int kSearchPriceSize = 37; -constexpr int kSearchRatingSize = 26; -constexpr int kSearchRatingStarSize = 12; -constexpr int kSearchRatingStarHorizontalSpacing = 1; -constexpr int kSearchRatingStarVerticalSpacing = 2; -// Text line height in the search result tile. -constexpr int kTileTextLineHeight = 16; -constexpr int kBadgeIconShadowWidth = 1; - -// Delta applied to the font size of SearchResultTile title. -constexpr int kSearchResultTileTitleTextSizeDelta = 1; - -constexpr int kIconSelectedSize = 58; -constexpr int kIconSelectedCornerRadius = 4; - -// Offset for centering star rating when there is no price. -constexpr int kSearchRatingCenteringOffset = - ((kSearchTileWidth - - (kSearchRatingSize + kSearchRatingStarHorizontalSpacing + - kSearchRatingStarSize)) / - 2); - -} // namespace - -SearchResultTileItemView::SearchResultTileItemView( - AppListViewDelegate* view_delegate) - : view_delegate_(view_delegate), - is_app_reinstall_recommendation_enabled_( - app_list_features::IsAppReinstallZeroStateEnabled()) { - SetCallback(base::BindRepeating(&SearchResultTileItemView::OnButtonPressed, - base::Unretained(this))); - SetFocusBehavior(FocusBehavior::ALWAYS); - - // When |result_| is null, the tile is invisible. Calling SetSearchResult with - // a non-null item makes the tile visible. - SetVisible(false); - - GetViewAccessibility().OverrideIsLeaf(true); - - // Prevent the icon view from interfering with our mouse events. - icon_ = AddChildView(std::make_unique<views::ImageView>()); - icon_->SetCanProcessEventsWithinSubtree(false); - icon_->SetVerticalAlignment(views::ImageView::Alignment::kLeading); - - badge_ = AddChildView(std::make_unique<views::ImageView>()); - badge_->SetCanProcessEventsWithinSubtree(false); - badge_->SetVerticalAlignment(views::ImageView::Alignment::kLeading); - badge_->SetVisible(false); - - title_ = AddChildView(std::make_unique<views::Label>()); - title_->SetEnabledColorId(cros_tokens::kTextColorSecondary); - title_->SetAutoColorReadabilityEnabled(false); - title_->SetLineHeight(kTileTextLineHeight); - title_->SetHorizontalAlignment(gfx::ALIGN_CENTER); - title_->SetHandlesTooltips(false); - title_->SetAllowCharacterBreak(true); - - rating_ = AddChildView(std::make_unique<views::Label>()); - rating_->SetLineHeight(kTileTextLineHeight); - rating_->SetHorizontalAlignment(gfx::ALIGN_RIGHT); - rating_->SetVisible(false); - - rating_star_ = AddChildView(std::make_unique<views::ImageView>()); - rating_star_->SetCanProcessEventsWithinSubtree(false); - rating_star_->SetVerticalAlignment(views::ImageView::Alignment::kLeading); - rating_star_->SetVisible(false); - - price_ = AddChildView(std::make_unique<views::Label>()); - price_->SetEnabledColorId(cros_tokens::kTextColorSecondary); - price_->SetLineHeight(kTileTextLineHeight); - price_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - price_->SetVisible(false); - - set_context_menu_controller(this); -} - -SearchResultTileItemView::~SearchResultTileItemView() = default; - -void SearchResultTileItemView::OnResultChanged() { - // Handle the case where this may be called from a nested run loop while its - // context menu is showing. This cancels the menu (it's for the old item). - context_menu_.reset(); - - SetVisible(!!result()); - - if (!result()) - return; - - SetTitle(result()->title()); - SetTitleTags(result()->title_tags()); - SetRating(result()->rating()); - SetPrice(result()->formatted_price()); - - const gfx::FontList& font = - SharedAppListConfig::instance().search_result_recommendation_title_font(); - if (rating_) { - if (!IsSuggestedAppTile()) { - // App search results use different fonts than AppList apps. - rating_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( - SharedAppListConfig::instance().search_result_title_font_style())); - } else { - rating_->SetFontList(font); - } - } - if (price_) { - if (!IsSuggestedAppTile()) { - // App search results use different fonts than AppList apps. - price_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( - SharedAppListConfig::instance().search_result_title_font_style())); - } else { - price_->SetFontList(font); - } - } - if (!IsSuggestedAppTile()) { - // App search results use different fonts than AppList apps. - title_->SetFontList( - ui::ResourceBundle::GetSharedInstance() - .GetFontList(SharedAppListConfig::instance() - .search_result_title_font_style()) - .DeriveWithSizeDelta(kSearchResultTileTitleTextSizeDelta)); - } else { - title_->SetFontList(font); - } - title_->SetEnabledColorId(cros_tokens::kTextColorPrimary); - title_->SetMaxLines(2); - title_->SetMultiLine( - (result()->display_type() == SearchResultDisplayType::kTile || - IsSuggestedAppTile()) && - (result()->result_type() == AppListSearchResultType::kInstalledApp || - result()->result_type() == AppListSearchResultType::kArcAppShortcut)); - - // If the new icon is null, it's being decoded asynchronously. Not updating it - // now to prevent flickering from showing an empty icon while decoding. - if (!result()->icon().icon.isNull()) - OnMetadataChanged(); - - UpdateAccessibleName(); -} - -void SearchResultTileItemView::SetParentBackgroundColor(SkColor color) { - parent_background_color_ = color; - UpdateBackgroundColor(); -} - -void SearchResultTileItemView::GetAccessibleNodeData( - ui::AXNodeData* node_data) { - views::Button::GetAccessibleNodeData(node_data); - - // The tile is a list item in the search result page's result list. - node_data->role = ax::mojom::Role::kListBoxOption; - node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kClick); - - // Specify |ax::mojom::StringAttribute::kDescription| with an empty string, so - // that long truncated names are not read twice. Details of this issue: - The - // Play Store app's name is shown in a label |title_|. - If the name is too - // long, it'll get truncated and the full name will - // go to the label's tooltip. - // - SearchResultTileItemView uses that label's tooltip as its tooltip. - // - If a view doesn't have |ax::mojom::StringAttribute::kDescription| defined - // in the - // |AXNodeData|, |AXViewObjWrapper::Serialize| will use the tooltip text - // as its description. - // - We're customizing this view's accessible name, so it get focused - // ChromeVox will read its accessible name and then its description. - node_data->AddStringAttribute(ax::mojom::StringAttribute::kDescription, ""); -} - -bool SearchResultTileItemView::OnKeyPressed(const ui::KeyEvent& event) { - // Return early if |result()| was deleted due to the search result list - // changing. see crbug.com/801142 - if (!result()) - return true; - - if (event.key_code() == ui::VKEY_RETURN) { - ActivateResult(event.flags(), false /* by_button_press */); - return true; - } - return false; -} - -void SearchResultTileItemView::StateChanged(ButtonState old_state) { - SearchResultBaseView::StateChanged(old_state); - UpdateBackgroundColor(); -} - -void SearchResultTileItemView::PaintButtonContents(gfx::Canvas* canvas) { - if (!result() || !selected()) - return; - - cc::PaintFlags flags; - flags.setAntiAlias(true); - flags.setStyle(cc::PaintFlags::kStroke_Style); - flags.setStrokeWidth(kSelectionRingWidth); - flags.setColor(AppListColorProvider::Get()->GetFocusRingColor(GetWidget())); - - gfx::RectF selection_ring = GetSelectionRingBounds(); - selection_ring.Inset(gfx::InsetsF::VH(kSelectionRingWidth / 2.0, 0)); - canvas->DrawRoundRect(selection_ring, kIconSelectedCornerRadius, flags); -} - -void SearchResultTileItemView::OnThemeChanged() { - SearchResultBaseView::OnThemeChanged(); - rating_star_->SetImage(gfx::CreateVectorIcon( - kBadgeRatingIcon, kSearchRatingStarSize, - AppListColorProvider::Get()->GetSearchBoxSecondaryTextColor( - gfx::kGoogleGrey700, GetWidget()))); -} - -gfx::RectF SearchResultTileItemView::GetSelectionRingBounds() const { - gfx::RectF bounds(GetContentsBounds()); - const float horizontal_padding = (bounds.width() - kIconSelectedSize) / 2.0; - bounds.Inset(gfx::InsetsF::VH(0, horizontal_padding)); - bounds.set_height(kIconSelectedSize); - return bounds; -} - -void SearchResultTileItemView::OnMetadataChanged() { - SetIcon(result()->icon().icon); - SetTitle(result()->title()); - SetTitleTags(result()->title_tags()); - SetBadgeIcon(result()->badge_icon(), result()->use_badge_icon_background()); - SetRating(result()->rating()); - SetPrice(result()->formatted_price()); - Layout(); -} - -void SearchResultTileItemView::ShowContextMenuForViewImpl( - views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type) { - // |result()| could be null when result list is changing. - if (!result()) - return; - - view_delegate_->GetSearchResultContextMenuModel( - result()->id(), - base::BindOnce(&SearchResultTileItemView::OnGetContextMenuModel, - weak_ptr_factory_.GetWeakPtr(), source, point, - source_type)); -} - -void SearchResultTileItemView::OnGetContextMenuModel( - views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type, - std::unique_ptr<ui::SimpleMenuModel> menu_model) { - if (!menu_model || (context_menu_ && context_menu_->IsShowingMenu())) - return; - - // Anchor the menu to the same rect that is used for selection ring. - gfx::Rect anchor_rect = gfx::ToEnclosingRect(GetSelectionRingBounds()); - views::View::ConvertRectToScreen(this, &anchor_rect); - - AppLaunchedMetricParams metric_params( - AppListLaunchedFrom::kLaunchedFromSearchBox, - AppListLaunchType::kAppSearchResult); - view_delegate_->GetAppLaunchedMetricParams(&metric_params); - - context_menu_ = std::make_unique<AppListMenuModelAdapter>( - result()->id(), std::move(menu_model), GetWidget(), source_type, - metric_params, GetAppType(), - base::BindOnce(&SearchResultTileItemView::OnMenuClosed, - weak_ptr_factory_.GetWeakPtr()), - view_delegate_->IsInTabletMode()); - context_menu_->Run(anchor_rect, views::MenuAnchorPosition::kBubbleRight, - views::MenuRunner::HAS_MNEMONICS | - views::MenuRunner::USE_ASH_SYS_UI_LAYOUT | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::FIXED_ANCHOR); - if (!selected()) { - selected_for_context_menu_ = true; - SetSelected(true, absl::nullopt); - } -} - -void SearchResultTileItemView::OnMenuClosed() { - // Release menu since its menu model delegate (AppContextMenu) could be - // released as a result of menu command execution. - context_menu_.reset(); - if (selected_for_context_menu_) { - selected_for_context_menu_ = false; - SetSelected(false, absl::nullopt); - } -} - -void SearchResultTileItemView::OnButtonPressed(const ui::Event& event) { - ActivateResult(event.flags(), true /* by_button_press */); -} - -void SearchResultTileItemView::ActivateResult(int event_flags, - bool by_button_press) { - const bool launch_as_default = is_default_result() && !by_button_press; - if (result()->result_type() == AppListSearchResultType::kPlayStoreApp) { - const base::TimeDelta activation_delay = - base::TimeTicks::Now() - result_display_start_time(); - UMA_HISTOGRAM_MEDIUM_TIMES("Arc.PlayStoreSearch.ResultClickLatency", - activation_delay); - UMA_HISTOGRAM_EXACT_LINEAR( - "Apps.AppListPlayStoreAppLaunchedIndex", - group_index_in_container_view(), - SharedAppListConfig::instance().max_search_result_tiles()); - if (launch_as_default) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "Arc.PlayStoreSearch.DefaultResultClickLatency", activation_delay); - } - } - - LogAppLaunchForSuggestedApp(); - - RecordSearchResultOpenSource(result(), view_delegate_->GetAppListViewState(), - view_delegate_->IsInTabletMode()); - view_delegate_->OpenSearchResult(result()->id(), event_flags, - AppListLaunchedFrom::kLaunchedFromSearchBox, - AppListLaunchType::kAppSearchResult, - index_in_container(), launch_as_default); -} - -void SearchResultTileItemView::SetIcon(const gfx::ImageSkia& icon) { - const int icon_size = - SharedAppListConfig::instance().search_tile_icon_dimension(); - gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage( - icon, skia::ImageOperations::RESIZE_BEST, - gfx::Size(icon_size, icon_size))); - icon_->SetImage(resized); -} - -void SearchResultTileItemView::SetBadgeIcon(const ui::ImageModel& badge_icon, - bool use_badge_icon_background) { - if (badge_icon.IsEmpty()) { - badge_->SetVisible(false); - return; - } - - gfx::ImageSkia badge_icon_skia = badge_icon.Rasterize(GetColorProvider()); - - if (use_badge_icon_background) { - badge_icon_skia = CreateIconWithCircleBackground(badge_icon_skia); - } - - gfx::ImageSkia resized_badge_icon( - gfx::ImageSkiaOperations::CreateResizedImage( - badge_icon_skia, skia::ImageOperations::RESIZE_BEST, - SharedAppListConfig::instance().search_tile_badge_icon_size())); - - gfx::ShadowValues shadow_values; - shadow_values.push_back( - gfx::ShadowValue(gfx::Vector2d(0, kBadgeIconShadowWidth), 0, - SkColorSetARGB(0x33, 0, 0, 0))); - shadow_values.push_back( - gfx::ShadowValue(gfx::Vector2d(0, kBadgeIconShadowWidth), 2, - SkColorSetARGB(0x33, 0, 0, 0))); - badge_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow( - resized_badge_icon, shadow_values)); - badge_->SetVisible(true); -} - -void SearchResultTileItemView::SetTitle(const std::u16string& title) { - title_->SetText(title); -} - -void SearchResultTileItemView::SetTitleTags(const SearchResultTags& tags) { - for (const auto& tag : tags) { - if (tag.styles & SearchResult::Tag::MATCH) { - title_->SetTextStyleRange(views::style::STYLE_EMPHASIZED, tag.range); - } - } -} - -void SearchResultTileItemView::SetRating(float rating) { - if (!rating_) - return; - - if (rating < 0) { - rating_->SetVisible(false); - rating_star_->SetVisible(false); - return; - } - - rating_->SetText(base::FormatDouble(rating, 1)); - rating_->SetVisible(true); - rating_star_->SetVisible(true); -} - -void SearchResultTileItemView::SetPrice(const std::u16string& price) { - if (!price_) - return; - - if (price.empty()) { - price_->SetVisible(false); - return; - } - - price_->SetText(price); - price_->SetVisible(true); -} - -AppListMenuModelAdapter::AppListViewAppType -SearchResultTileItemView::GetAppType() const { - if (IsSuggestedAppTile()) - return AppListMenuModelAdapter::FULLSCREEN_SUGGESTED; - - if (view_delegate_->GetAppListViewState() == - AppListViewState::kFullscreenSearch) { - return AppListMenuModelAdapter::FULLSCREEN_SEARCH_RESULT; - } - - NOTREACHED(); - return AppListMenuModelAdapter::APP_LIST_APP_TYPE_LAST; -} - -bool SearchResultTileItemView::IsSuggestedAppTile() const { - return result() && result()->is_recommendation(); -} - -void SearchResultTileItemView::LogAppLaunchForSuggestedApp() const { - // Only log the app launch if the class is being used as a suggested app. - if (!IsSuggestedAppTile()) - return; - - // We only need to record opening the installed app in zero state, no need to - // record the opening of a fast re-installed app, since the latter is already - // recorded in ArcAppReinstallAppResult::Open. - if (result()->result_type() != - AppListSearchResultType::kPlayStoreReinstallApp) { - base::RecordAction( - base::UserMetricsAction("AppList_ZeroStateOpenInstalledApp")); - } -} - -void SearchResultTileItemView::UpdateBackgroundColor() { - // Tell the label what color it will be drawn onto. It will use whether the - // background color is opaque or transparent to decide whether to use subpixel - // rendering. Does not actually set the label's background color. - title_->SetBackgroundColor(parent_background_color_); - SchedulePaint(); -} - -void SearchResultTileItemView::Layout() { - gfx::Rect rect(GetContentsBounds()); - if (rect.IsEmpty() || !result()) - return; - - gfx::Rect icon_rect(rect); - icon_rect.ClampToCenteredSize(icon_->GetImage().size()); - icon_rect.set_y(kSearchTileTopPadding); - icon_->SetBoundsRect(icon_rect); - - const int badge_icon_dimension = - SharedAppListConfig::instance().search_tile_badge_icon_dimension() + - 2 * kBadgeIconShadowWidth; - const int badge_icon_offset = - SharedAppListConfig::instance().search_tile_badge_icon_offset(); - const gfx::Rect badge_rect( - icon_rect.right() - badge_icon_dimension + badge_icon_offset, - icon_rect.bottom() - badge_icon_dimension + badge_icon_offset, - badge_icon_dimension, badge_icon_dimension); - badge_->SetBoundsRect(badge_rect); - - rect.set_y(icon_rect.bottom() + kSearchTitleSpacing); - rect.set_height(title_->GetPreferredSize().height()); - title_->SetBoundsRect(rect); - - // If there is no price set, we center the rating. - const bool center_rating = - rating_ && rating_star_ && price_ && price_->GetText().empty(); - const int rating_horizontal_offset = - center_rating ? kSearchRatingCenteringOffset : 0; - - if (rating_) { - gfx::Rect rating_rect(rect); - rating_rect.Inset(gfx::Insets::TLBR(title_->GetPreferredSize().height(), - rating_horizontal_offset, 0, 0)); - rating_rect.set_size(rating_->GetPreferredSize()); - rating_rect.set_width(kSearchRatingSize); - rating_->SetBoundsRect(rating_rect); - } - - if (rating_star_) { - gfx::Rect rating_star_rect(rect); - rating_star_rect.Inset(gfx::Insets::TLBR( - title_->GetPreferredSize().height() + kSearchRatingStarVerticalSpacing, - rating_horizontal_offset + kSearchRatingSize + - kSearchRatingStarHorizontalSpacing, - 0, 0)); - rating_star_rect.set_size(rating_star_->GetPreferredSize()); - rating_star_->SetBoundsRect(rating_star_rect); - } - - if (price_) { - gfx::Rect price_rect(rect); - price_rect.Inset(gfx::Insets::TLBR(title_->GetPreferredSize().height(), - rect.width() - kSearchPriceSize, 0, 0)); - price_rect.set_size(price_->GetPreferredSize()); - price_->SetBoundsRect(price_rect); - } -} - -const char* SearchResultTileItemView::GetClassName() const { - return "SearchResultTileItemView"; -} - -gfx::Size SearchResultTileItemView::CalculatePreferredSize() const { - if (!result()) - return gfx::Size(); - - return gfx::Size(kSearchTileWidth, - SharedAppListConfig::instance().search_tile_height()); -} - -std::u16string SearchResultTileItemView::GetTooltipText( - const gfx::Point& p) const { - // Use the label to generate a tooltip, so that it will consider its text - // truncation in making the tooltip. We do not want the label itself to have a - // tooltip, so we only temporarily enable it to get the tooltip text from the - // label, then disable it again. - title_->SetHandlesTooltips(true); - std::u16string tooltip = title_->GetTooltipText(p); - title_->SetHandlesTooltips(false); - return tooltip; -} - -} // namespace ash
diff --git a/ash/app_list/views/search_result_tile_item_view.h b/ash/app_list/views/search_result_tile_item_view.h deleted file mode 100644 index 3930629..0000000 --- a/ash/app_list/views/search_result_tile_item_view.h +++ /dev/null
@@ -1,146 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_VIEW_H_ -#define ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_VIEW_H_ - -#include <memory> -#include <vector> - -#include "ash/app_list/views/app_list_menu_model_adapter.h" -#include "ash/app_list/views/search_result_base_view.h" -#include "ash/ash_export.h" -#include "ash/public/cpp/app_list/app_list_types.h" -#include "ui/views/context_menu_controller.h" - -namespace ui { -class ImageModel; -} // namespace ui - -namespace views { -class ImageView; -class Label; -} // namespace views - -namespace ash { - -class AppListViewDelegate; -class SearchResult; - -// A tile view that displays a search result. It hosts view for search result -// that has SearchResult::DisplayType DISPLAY_TILE or DISPLAY_RECOMMENDATION. -class ASH_EXPORT SearchResultTileItemView - : public SearchResultBaseView, - public views::ContextMenuController { - public: - explicit SearchResultTileItemView(AppListViewDelegate* view_delegate); - - SearchResultTileItemView(const SearchResultTileItemView&) = delete; - SearchResultTileItemView& operator=(const SearchResultTileItemView&) = delete; - - ~SearchResultTileItemView() override; - - void OnResultChanged() override; - - // Informs the SearchResultTileItemView of its parent's background color. The - // controls within the SearchResultTileItemView will adapt to suit the given - // color. - void SetParentBackgroundColor(SkColor color); - - void set_group_index_in_container_view(int index) { - group_index_in_container_view_ = index; - } - int group_index_in_container_view() const { - return group_index_in_container_view_; - } - - // Overridden from views::Button: - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - bool OnKeyPressed(const ui::KeyEvent& event) override; - void StateChanged(ButtonState old_state) override; - void PaintButtonContents(gfx::Canvas* canvas) override; - void OnThemeChanged() override; - - // Overridden from SearchResultObserver: - void OnMetadataChanged() override; - - // views::ContextMenuController overrides: - void ShowContextMenuForViewImpl(views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type) override; - - private: - // Launch the result and log to various histograms. - // |by_button_press|: True if |result_| is activated by button pressing; - // otherwise |result| is activated by ENTER key pressing. - void ActivateResult(int event_flags, bool by_button_press); - - // Bound by ShowContextMenuForViewImpl(). - void OnGetContextMenuModel(views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type, - std::unique_ptr<ui::SimpleMenuModel> menu_model); - - // The callback used when a menu closes. - void OnMenuClosed(); - - void OnButtonPressed(const ui::Event& event); - - void SetIcon(const gfx::ImageSkia& icon); - void SetBadgeIcon(const ui::ImageModel& badge_icon, - bool use_badge_icon_background); - void SetTitle(const std::u16string& title); - void SetTitleTags(const SearchResultTags& tags); - void SetRating(float rating); - void SetPrice(const std::u16string& price); - - AppListMenuModelAdapter::AppListViewAppType GetAppType() const; - - // Whether the tile view is a suggested app. - bool IsSuggestedAppTile() const; - - // Records an app being launched. - void LogAppLaunchForSuggestedApp() const; - - void UpdateBackgroundColor(); - - // Gets the bounds for the selection ring (shown when the result is selected). - gfx::RectF GetSelectionRingBounds() const; - - // Overridden from views::View: - void Layout() override; - const char* GetClassName() const override; - gfx::Size CalculatePreferredSize() const override; - std::u16string GetTooltipText(const gfx::Point& p) const override; - - AppListViewDelegate* const view_delegate_; // Owned by AppListView. - - views::ImageView* icon_ = nullptr; // Owned by views hierarchy. - views::ImageView* badge_ = nullptr; // Owned by views hierarchy. - views::Label* title_ = nullptr; // Owned by views hierarchy. - views::Label* rating_ = nullptr; // Owned by views hierarchy. - views::Label* price_ = nullptr; // Owned by views hierarchy. - views::ImageView* rating_star_ = nullptr; // Owned by views hierarchy. - - SkColor parent_background_color_ = SK_ColorTRANSPARENT; - - // The index of the app in its display group in its container view. Currently, - // there are three separately displayed groups for apps in launcher's - // suggestion window: Installed apps, play store apps, play store reinstalled - // app. - int group_index_in_container_view_; - const bool is_app_reinstall_recommendation_enabled_; - - // Whether the result view moved into selected state only because a context - // menu was shown. - bool selected_for_context_menu_ = false; - - std::unique_ptr<AppListMenuModelAdapter> context_menu_; - - base::WeakPtrFactory<SearchResultTileItemView> weak_ptr_factory_{this}; -}; - -} // namespace ash - -#endif // ASH_APP_LIST_VIEWS_SEARCH_RESULT_TILE_ITEM_VIEW_H_
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index c53c7bb5..2a2ddde 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -2,6 +2,15 @@ <!-- This file contains the strings for ash. + +Style notes: +* Most strings are "Sentence case" with the first word capitalized and other + words not capitalized +* Specific features may be capitalized (e.g. "Bluetooth", "Nearby Share") even + if they appear in the middle of a string +* Most strings do not end in a period (e.g. "Show settings") +* Multi-phrase strings that contain a period in the middle also have a period + at the end (e.g. "Show Bluetooth settings. Bluetooth is on.") --> <grit base_dir="." latest_public_release="0" current_release="1" @@ -427,10 +436,10 @@ <ph name="SECONDS">$1<ex>40</ex></ph> sec </message> <message name="IDS_ASH_STATUS_TRAY_NEARBY_SHARE_SETTINGS_TOOLTIP" desc="Tooltip text for the status tray button that shows settings for the Nearby Share feature."> - Show Nearby Share settings. + Show Nearby Share settings </message> <message name="IDS_ASH_STATUS_TRAY_NEARBY_SHARE_TOGGLE_TOOLTIP" desc="Tooltip text used for the Nearby Share status tray button, which toggles Nearby Share high visibility mode on/off."> - Toggle Nearby Share high visibility. + Toggle Nearby Share high visibility </message> <message name="IDS_ASH_STATUS_TRAY_NIGHT_LIGHT_BUTTON_LABEL" desc="The shorter label used for the button in the status tray to toggle the Night Light feature (which controls the color temperature of the screen) on or off. [CHAR_LIMIT=14]"> Night Light @@ -472,7 +481,7 @@ Cast </message> <message name="IDS_ASH_STATUS_TRAY_CAST_TOOLTIP" desc="The tooltip text used for Cast button in system tray bubble."> - Show cast devices. + Show cast devices </message> <message name="IDS_ASH_STATUS_TRAY_CAST_NOTIFICATION_TITLE" desc="The notification title to tell the user we are casting to a cast device."> Casting to <ph name="RECEIVER_NAME">$1<ex>Living Room</ex></ph> @@ -487,7 +496,7 @@ Dark theme </message> <message name="IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP" desc="The tooltip text used for the button in the status tray to toggle the Dark theme feature on or off."> - Toggle Dark theme. <ph name="STATE_TEXT">$1<ex>Dark theme is on.</ex></ph> + Toggle Dark theme. <ph name="STATE_TEXT">$1<ex>Dark theme is on</ex></ph>. </message> <message name="IDS_ASH_STATUS_TRAY_DARK_THEME_ENABLED_STATE_TOOLTIP" desc="The tooltip text indicating the Dark theme feature is on."> Dark theme is on @@ -578,10 +587,10 @@ Bluetooth </message> <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_TOGGLE_TOOLTIP" desc="The tooltip text in the button that toggles Blueooth enabled/disabled."> - Toggle Bluetooth. <ph name="STATE_TEXT">$1<ex>Connected to 2 devices</ex></ph> + Toggle Bluetooth. <ph name="STATE_TEXT">$1<ex>Connected to 2 devices</ex></ph>. </message> <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS_TOOLTIP" desc="The tooltip text in the button that shows Blueooth settings."> - Show Bluetooth settings. <ph name="STATE_TEXT">$1<ex>Connected to 2 devices</ex></ph> + Show Bluetooth settings. <ph name="STATE_TEXT">$1<ex>Connected to 2 devices</ex></ph>. </message> <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_ENABLED_TOOLTIP" desc="The tooltip text to notify that bluetooth is enabled."> Bluetooth is on @@ -949,7 +958,7 @@ Show keyboard settings </message> <message name="IDS_ASH_STATUS_TRAY_IME_TOOLTIP_WITH_NAME" desc="The tooltip text used for IME button in system tray bubble."> - Show keyboard settings. <ph name="KEYBOARD_NAME">$1<ex>US keyboard</ex></ph> is selected + Show keyboard settings. <ph name="KEYBOARD_NAME">$1<ex>US keyboard</ex></ph> is selected. </message> <message name="IDS_ASH_STATUS_TRAY_IME" desc="The label used as the header in the IME popup. [CHAR_LIMIT=18]"> Input methods @@ -2423,10 +2432,10 @@ </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP" desc="The tooltip text for the button that toggles network enabled/disabled state."> - Toggle network connection. <ph name="STATE_TEXT">$1<ex>Connected to public wifi</ex></ph> + Toggle network connection. <ph name="STATE_TEXT">$1<ex>Connected to public wifi</ex></ph>. </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP" desc="The tooltip text for the button that shows network list."> - Show network list. <ph name="STATE_TEXT">$1<ex>Connected to public wifi</ex></ph> + Show network list. <ph name="STATE_TEXT">$1<ex>Connected to public wifi</ex></ph>. </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_PROGRESS_ACCESSIBLE_NAME" desc="The accessible name for the progress bar shown in the network settings."> Scanning
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS_TOOLTIP.png.sha1 new file mode 100644 index 0000000..85a08e3 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +14506683f4860247eb998fefef35e68d8d5ba681 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_TOGGLE_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_TOGGLE_TOOLTIP.png.sha1 new file mode 100644 index 0000000..0b4171ee --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_TOGGLE_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +5e34a89e2a19ab9c3309ecb3db36a2fcc7caafb1 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_CAST_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_CAST_TOOLTIP.png.sha1 new file mode 100644 index 0000000..fd8132f --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_CAST_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +0122e9b5756ac230cb7b723e042098776c119cf6 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP.png.sha1 index 3b00f1d..a5d652c 100644 --- a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP.png.sha1
@@ -1 +1 @@ -a3cbce9b0bd7654915d9ea33f1b1b0a151fc3388 \ No newline at end of file +24e630801e46d8a1e2adb054186bef9cf2619281 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_IME_TOOLTIP_WITH_NAME.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_IME_TOOLTIP_WITH_NAME.png.sha1 new file mode 100644 index 0000000..9c55b4ea --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_IME_TOOLTIP_WITH_NAME.png.sha1
@@ -0,0 +1 @@ +fe626ac766446f602d894e35d882a5558d81cda3 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_SETTINGS_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_SETTINGS_TOOLTIP.png.sha1 index e264bcc..c71f6cc 100644 --- a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_SETTINGS_TOOLTIP.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_SETTINGS_TOOLTIP.png.sha1
@@ -1 +1 @@ -14fa83bd6816e26df5e9ac72cbceb09818990031 \ No newline at end of file +c0e2a814eab217357d2fe53af41a110f70276f2a \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_TOGGLE_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_TOGGLE_TOOLTIP.png.sha1 index 3371c2cd..0253090 100644 --- a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_TOGGLE_TOOLTIP.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NEARBY_SHARE_TOGGLE_TOOLTIP.png.sha1
@@ -1 +1 @@ -14577c7eda36f1ee897e9d6974c02c969d478199 \ No newline at end of file +7992b9ffd8afbe69bbe52a87329d14b41537c2ac \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP.png.sha1 new file mode 100644 index 0000000..0d52da5 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +b18e7c706cfa38cd962fe35e810a1fc7ed7df4b6 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP.png.sha1 new file mode 100644 index 0000000..c90d6e4 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +f1346ee4f1f4af37d07953ffff206e5d72118225 \ No newline at end of file
diff --git a/ash/metrics/login_unlock_throughput_recorder.cc b/ash/metrics/login_unlock_throughput_recorder.cc index 28520c2..76b25081 100644 --- a/ash/metrics/login_unlock_throughput_recorder.cc +++ b/ash/metrics/login_unlock_throughput_recorder.cc
@@ -5,67 +5,20 @@ #include "ash/metrics/login_unlock_throughput_recorder.h" #include "ash/public/cpp/metrics_util.h" -#include "ash/public/cpp/shelf_model.h" #include "ash/session/session_controller_impl.h" -#include "ash/shelf/shelf_view.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/bind.h" #include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/utf_string_conversions.h" #include "chromeos/login/login_state/login_state.h" #include "chromeos/metrics/login_event_recorder.h" -#include "components/app_constants/constants.h" -#include "components/app_restore/window_properties.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" -#include "ui/compositor/compositor.h" -#include "ui/compositor/layer.h" #include "ui/compositor/total_animation_throughput_reporter.h" -#include "ui/views/animation/bounds_animator.h" -#include "ui/views/animation/bounds_animator_observer.h" namespace ash { namespace { -// A class used to wait for animations. -class AnimationObserver : public views::BoundsAnimatorObserver { - public: - AnimationObserver(ShelfView* shelf_view, base::OnceClosure& on_animation_end) - : shelf_view_(shelf_view), - on_animation_end_(std::move(on_animation_end)) {} - - AnimationObserver(const AnimationObserver&) = delete; - AnimationObserver& operator=(const AnimationObserver&) = delete; - - ~AnimationObserver() override = default; - - // ShelfViewObserver overrides: - void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override {} - void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override { - shelf_view_->RemoveAnimationObserver(this); - RunCallbackAndDestroy(); - } - - void StartObserving() { - if (shelf_view_->IsAnimating()) { - shelf_view_->AddAnimationObserver(this); - return; - } - RunCallbackAndDestroy(); - } - - private: - void RunCallbackAndDestroy() { - std::move(on_animation_end_).Run(); - delete this; - } - - base::raw_ptr<ShelfView> shelf_view_; - base::OnceClosure on_animation_end_; -}; - std::string GetDeviceModeSuffix() { return Shell::Get()->tablet_mode_controller()->InTabletMode() ? "TabletMode" @@ -104,7 +57,6 @@ LOG(WARNING) << "Zero frames expected in login animation throughput data"; return; } - chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( "LoginAnimationEnd", /*send_to_uma=*/false, @@ -124,14 +76,6 @@ "Ash.UnlockAnimation.Jank.", "Ash.UnlockAnimation.Duration."); } -void OnRestoredWindowPresentationFeedbackReceived( - int restore_window_id, - const gfx::PresentationFeedback& feedback) { - LoginUnlockThroughputRecorder* throughput_recorder = - Shell::Get()->login_unlock_throughput_recorder(); - throughput_recorder->OnRestoredWindowPresented(restore_window_id); -} - } // namespace LoginUnlockThroughputRecorder::LoginUnlockThroughputRecorder() { @@ -154,160 +98,24 @@ new ui::TotalAnimationThroughputReporter( primary_root->GetHost()->compositor(), base::BindOnce(&ReportUnlock, base::TimeTicks::Now()), - /*should_delete=*/true); + /*self_destruct=*/true); } } void LoginUnlockThroughputRecorder::LoggedInStateChanged() { auto* login_state = chromeos::LoginState::Get(); auto logged_in_user = login_state->GetLoggedInUserType(); - - if (user_logged_in_) - return; - - if (!login_state->IsUserLoggedIn()) - return; - - if (logged_in_user != chromeos::LoginState::LOGGED_IN_USER_OWNER && - logged_in_user != chromeos::LoginState::LOGGED_IN_USER_REGULAR) { - return; + if (login_state->IsUserLoggedIn() && + (logged_in_user == chromeos::LoginState::LOGGED_IN_USER_OWNER || + logged_in_user == chromeos::LoginState::LOGGED_IN_USER_REGULAR)) { + ui_recorder_.OnUserLoggedIn(); + auto* primary_root = Shell::GetPrimaryRootWindow(); + new ui::TotalAnimationThroughputReporter( + primary_root->GetHost()->compositor(), + base::BindOnce(&LoginUnlockThroughputRecorder::OnLoginAnimationFinish, + weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), + /*self_destruct=*/true); } - - user_logged_in_ = true; - ui_recorder_.OnUserLoggedIn(); - auto* primary_root = Shell::GetPrimaryRootWindow(); - primary_user_logged_in_ = base::TimeTicks::Now(); - auto* rec = new ui::TotalAnimationThroughputReporter( - primary_root->GetHost()->compositor(), - base::BindOnce(&LoginUnlockThroughputRecorder::OnLoginAnimationFinish, - weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), - /*should_delete=*/true); - login_animation_throughput_reporter_ = rec->GetWeakPtr(); - DCHECK(!scoped_throughput_reporter_blocker_); - // Login animation metrics should not be reported until all shelf icons - // were loaded. - scoped_throughput_reporter_blocker_ = - login_animation_throughput_reporter_->NewScopedBlocker(); -} - -void LoginUnlockThroughputRecorder::AddScheduledRestoreWindow( - int restore_window_id, - const std::string& app_id, - RestoreWindowType window_type) { - switch (window_type) { - case LoginUnlockThroughputRecorder::kBrowser: - DCHECK(restore_window_id); - if (app_id.empty() || app_id == app_constants::kLacrosAppId) - windows_to_restore_.insert(restore_window_id); - - break; - default: - NOTREACHED(); - } -} - -void LoginUnlockThroughputRecorder::OnRestoredWindowCreated( - int restore_window_id) { - auto it = windows_to_restore_.find(restore_window_id); - if (it == windows_to_restore_.end()) - return; - windows_to_restore_.erase(it); - if (windows_to_restore_.empty() && !primary_user_logged_in_.is_null()) { - const base::TimeDelta duration_ms = - base::TimeTicks::Now() - primary_user_logged_in_; - UMA_HISTOGRAM_CUSTOM_TIMES( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated", duration_ms, - base::Milliseconds(1), base::Seconds(100), 100); - } - restore_windows_not_shown_.insert(restore_window_id); -} - -void LoginUnlockThroughputRecorder::OnBeforeRestoredWindowShown( - int restore_window_id, - ui::Compositor* compositor) { - auto it = restore_windows_not_shown_.find(restore_window_id); - if (it == restore_windows_not_shown_.end()) - return; - - restore_windows_not_shown_.erase(it); - if (windows_to_restore_.empty() && restore_windows_not_shown_.empty() && - !primary_user_logged_in_.is_null()) { - const base::TimeDelta duration_ms = - base::TimeTicks::Now() - primary_user_logged_in_; - UMA_HISTOGRAM_CUSTOM_TIMES("Ash.LoginSessionRestore.AllBrowserWindowsShown", - duration_ms, base::Milliseconds(1), - base::Seconds(100), 100); - } - - if (!compositor) - return; - - restore_windows_presentation_time_requested_.insert(restore_window_id); - compositor->RequestPresentationTimeForNextFrame(base::BindOnce( - &OnRestoredWindowPresentationFeedbackReceived, restore_window_id)); -} - -void LoginUnlockThroughputRecorder::OnRestoredWindowPresented( - int restore_window_id) { - auto it = - restore_windows_presentation_time_requested_.find(restore_window_id); - if (it == restore_windows_presentation_time_requested_.end()) - return; - - restore_windows_presentation_time_requested_.erase(it); - if (windows_to_restore_.empty() && restore_windows_not_shown_.empty() && - restore_windows_presentation_time_requested_.empty() && - !primary_user_logged_in_.is_null()) { - const base::TimeDelta duration_ms = - base::TimeTicks::Now() - primary_user_logged_in_; - UMA_HISTOGRAM_CUSTOM_TIMES( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented", duration_ms, - base::Milliseconds(1), base::Seconds(100), 100); - } - restore_windows_presented_.insert(restore_window_id); -} - -void LoginUnlockThroughputRecorder::InitShelfIconList(const ShelfModel* model) { - shelf_initialized_ = true; - - // Copy shelf icons to the expected list. - for (int index = 0; index < model->item_count(); ++index) { - const ShelfID& id = model->items()[index].id; - const ShelfItem& item = model->items()[index]; - if (item.image.isNull()) - expected_shelf_icons_.insert(id); - } - - if (expected_shelf_icons_.empty()) - OnAllExpectedShelfIconsLoaded(); -} - -void LoginUnlockThroughputRecorder::UpdateShelfIconList( - const ShelfModel* model) { - if (!shelf_initialized_) - return; - - // Remove IDs that have icons loaded or were already deleted. - base::flat_set<ShelfID> expected_ids_without_icons; - - for (int index = 0; index < model->item_count(); ++index) { - const ShelfItem& item = model->items()[index]; - const ShelfID& id = item.id; - if (!expected_shelf_icons_.contains(id)) - continue; - - if (item.image.isNull()) - expected_ids_without_icons.insert(id); - } - expected_shelf_icons_ = expected_ids_without_icons; - - if (expected_shelf_icons_.empty()) - OnAllExpectedShelfIconsLoaded(); -} - -void LoginUnlockThroughputRecorder:: - ResetScopedThroughputReporterBlockerForTesting() { - scoped_throughput_reporter_blocker_.reset(); } void LoginUnlockThroughputRecorder::OnLoginAnimationFinish( @@ -317,43 +125,4 @@ ReportLogin(start, data); } -void LoginUnlockThroughputRecorder::SetShelfViewIfNotSet( - ShelfView* shelf_view) { - if (!shelf_view_) - shelf_view_ = shelf_view; -} - -void LoginUnlockThroughputRecorder::ScheduleWaitForShelfAnimationEnd() { - DCHECK(shelf_view_); - if (!shelf_view_) - return; - - base::OnceCallback on_animation_end = base::BindOnce( - [](base::TimeTicks primary_user_logged_in) { - const base::TimeDelta duration_ms = - base::TimeTicks::Now() - primary_user_logged_in; - UMA_HISTOGRAM_CUSTOM_TIMES( - "Ash.LoginSessionRestore.ShelfLoginAnimationEnd", duration_ms, - base::Milliseconds(1), base::Seconds(100), 100); - }, - primary_user_logged_in_); - - (new AnimationObserver(shelf_view_, on_animation_end))->StartObserving(); -} - -void LoginUnlockThroughputRecorder::OnAllExpectedShelfIconsLoaded() { - if (shelf_icons_loaded_) - return; - - scoped_throughput_reporter_blocker_.reset(); - - shelf_icons_loaded_ = true; - const base::TimeDelta duration_ms = - base::TimeTicks::Now() - primary_user_logged_in_; - UMA_HISTOGRAM_CUSTOM_TIMES("Ash.LoginSessionRestore.AllShelfIconsLoaded", - duration_ms, base::Milliseconds(1), - base::Seconds(100), 100); - ScheduleWaitForShelfAnimationEnd(); -} - } // namespace ash
diff --git a/ash/metrics/login_unlock_throughput_recorder.h b/ash/metrics/login_unlock_throughput_recorder.h index 8c1dd7e9..55f5bbc 100644 --- a/ash/metrics/login_unlock_throughput_recorder.h +++ b/ash/metrics/login_unlock_throughput_recorder.h
@@ -5,38 +5,20 @@ #ifndef ASH_METRICS_LOGIN_UNLOCK_THROUGHPUT_RECORDER_H_ #define ASH_METRICS_LOGIN_UNLOCK_THROUGHPUT_RECORDER_H_ -#include <string> - #include "ash/ash_export.h" #include "ash/metrics/ui_throughput_recorder.h" #include "ash/public/cpp/session/session_observer.h" -#include "ash/public/cpp/shelf_types.h" -#include "base/containers/flat_set.h" -#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/metrics/frame_sequence_metrics.h" #include "chromeos/login/login_state/login_state.h" -#include "ui/compositor/total_animation_throughput_reporter.h" - -namespace ui { -class Compositor; -} namespace ash { -class ShelfModel; -class ShelfView; - class ASH_EXPORT LoginUnlockThroughputRecorder : public SessionObserver, public chromeos::LoginState::Observer { public: - enum RestoreWindowType { - kBrowser, - kArc, - }; - LoginUnlockThroughputRecorder(); LoginUnlockThroughputRecorder(const LoginUnlockThroughputRecorder&) = delete; LoginUnlockThroughputRecorder& operator=( @@ -49,85 +31,12 @@ // chromeos::LoginState::Observer: void LoggedInStateChanged() override; - // Adds "restore_window_id" to the list of potentially restored windows. - // See - // https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/widget.h;l=404-415. - void AddScheduledRestoreWindow(int restore_window_id, - const std::string& app_id, - RestoreWindowType window_type); - - // This is called when restored window was created. - void OnRestoredWindowCreated(int restore_window_id); - - // This is called before window is shown to request presentation feedback. - void OnBeforeRestoredWindowShown(int restore_window_id, - ui::Compositor* compositor); - - // This is called when restored window was presented. - void OnRestoredWindowPresented(int restore_window_id); - - // This is called when the list of shelf icons is initialized. - void InitShelfIconList(const ShelfModel* model); - - // This is called when the list of shelf icons is updated. - void UpdateShelfIconList(const ShelfModel* model); - - // Remembers ShelfView pointer to watch for shelf animation finish. - void SetShelfViewIfNotSet(ShelfView* shelf_view); - - void ResetScopedThroughputReporterBlockerForTesting(); - - const ui::TotalAnimationThroughputReporter* - login_animation_throughput_reporter() const { - return login_animation_throughput_reporter_.get(); - } - private: void OnLoginAnimationFinish( base::TimeTicks start, const cc::FrameSequenceMetrics::CustomReportData& data); - void ScheduleWaitForShelfAnimationEnd(); - - void OnAllExpectedShelfIconsLoaded(); - UiThroughputRecorder ui_recorder_; - - // Set of window IDs ("restore_window_id") that could be restored but - // for which windows have not been created yet. - base::flat_set<int> windows_to_restore_; - - // Set of window IDs ("restore_window_id") that were created as a part of the - // session restore but not yet shown. - base::flat_set<int> restore_windows_not_shown_; - - // Set of window IDs ("restore_window_id") that were shown and presentation - // time was requested. - base::flat_set<int> restore_windows_presentation_time_requested_; - - // Set of window IDs ("restore_window_id") for which presentation time - // was received. - base::flat_set<int> restore_windows_presented_; - - base::TimeTicks primary_user_logged_in_; - - base::raw_ptr<ShelfView> shelf_view_ = nullptr; - - bool shelf_initialized_ = false; - - bool shelf_icons_loaded_ = false; - - bool user_logged_in_ = false; - - base::WeakPtr<ui::TotalAnimationThroughputReporter> - login_animation_throughput_reporter_; - - std::unique_ptr< - ui::TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker> - scoped_throughput_reporter_blocker_; - - base::flat_set<ShelfID> expected_shelf_icons_; - base::WeakPtrFactory<LoginUnlockThroughputRecorder> weak_ptr_factory_{this}; };
diff --git a/ash/metrics/login_unlock_throughput_recorder_unittest.cc b/ash/metrics/login_unlock_throughput_recorder_unittest.cc deleted file mode 100644 index 9051400..0000000 --- a/ash/metrics/login_unlock_throughput_recorder_unittest.cc +++ /dev/null
@@ -1,542 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/metrics/login_unlock_throughput_recorder.h" - -#include <memory> -#include <string> - -#include "ash/login/ui/login_test_base.h" -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/public/cpp/shelf_item_delegate.h" -#include "ash/public/cpp/shelf_model.h" -#include "ash/session/test_session_controller_client.h" -#include "ash/shell.h" -#include "ash/wm/tablet_mode/tablet_mode_controller.h" -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "chromeos/login/login_state/login_state.h" -#include "components/app_constants/constants.h" -#include "ui/aura/window_tree_host.h" -#include "ui/compositor/test/draw_waiter_for_test.h" -#include "ui/gfx/image/image_unittest_util.h" - -namespace ash { -namespace { - -constexpr char kAshLoginAnimationDurationTabletMode[] = - "Ash.LoginAnimation.Duration.TabletMode"; -constexpr char kAshLoginAnimationDurationClamshellMode[] = - "Ash.LoginAnimation.Duration.ClamshellMode"; -constexpr char kAshUnlockAnimationDurationTabletMode[] = - "Ash.UnlockAnimation.Duration.TabletMode"; -constexpr char kAshUnlockAnimationDurationClamshellMode[] = - "Ash.UnlockAnimation.Duration.ClamshellMode"; - -// A test shelf item delegate that simulates an activated window when a shelf -// item is selected. -class TestShelfItemDelegate : public ShelfItemDelegate { - public: - explicit TestShelfItemDelegate(const ShelfID& shelf_id) - : ShelfItemDelegate(shelf_id) {} - - // ShelfItemDelegate: - void ItemSelected(std::unique_ptr<ui::Event> event, - int64_t display_id, - ash::ShelfLaunchSource source, - ItemSelectedCallback callback, - const ItemFilterPredicate& filter_predicate) override { - std::move(callback).Run(SHELF_ACTION_WINDOW_ACTIVATED, {}); - } - void ExecuteCommand(bool from_context_menu, - int64_t command_id, - int32_t event_flags, - int64_t display_id) override {} - void Close() override {} -}; - -class TestShelfModel : public ShelfModel { - public: - TestShelfModel() = default; - TestShelfModel(const TestShelfModel&) = delete; - TestShelfModel& operator=(const TestShelfModel&) = delete; - - ~TestShelfModel() = default; - - void InitializeIconList(const std::vector<int>& ids) { - while (!items().empty()) - RemoveItemAt(0); - - for (int n : ids) { - ShelfItem item; - item.id = ShelfID(base::StringPrintf("item%d", n)); - item.type = TYPE_PINNED_APP; - Add(item, std::make_unique<TestShelfItemDelegate>(item.id)); - } - } - - void SetIconsLoadedFor(const std::vector<int>& ids) { - for (int n : ids) { - const ShelfID id(base::StringPrintf("item%d", n)); - int index = ItemIndexByID(id); - // Expect item exists. - ASSERT_GE(index, 0); - - ShelfItem item = items()[index]; - item.image = gfx::test::CreateImageSkia(/*width=*/10, /*height=*/10); - - Set(index, item); - } - } -}; - -class TestObserver final : public ui::CompositorAnimationObserver { - public: - explicit TestObserver(ui::Compositor* compositor) : compositor_(compositor) { - compositor_->AddAnimationObserver(this); - } - TestObserver(const TestObserver&) = delete; - TestObserver& operator=(const TestObserver&) = delete; - ~TestObserver() override = default; - - // ui::CompositorAnimationObserver: - void OnAnimationStep(base::TimeTicks timestamp) override { - ++count_; - if (count_ < 3) - compositor_->ScheduleFullRedraw(); - else - compositor_->RemoveAnimationObserver(this); - } - - void OnCompositingShuttingDown(ui::Compositor* compositor) override {} - - private: - int count_ = 0; - const base::raw_ptr<ui::Compositor> compositor_; -}; - -class BeginMainFrameWaiter : public ui::CompositorObserver { - public: - explicit BeginMainFrameWaiter(ui::Compositor* compositor) - : compositor_(compositor) { - compositor->AddObserver(this); - } - - ~BeginMainFrameWaiter() override { compositor_->RemoveObserver(this); } - - // ui::CompositorObserver - void OnDidBeginMainFrame(ui::Compositor* compositor) override { - DCHECK_EQ(compositor_, compositor); - done_ = true; - if (run_loop_) - run_loop_->Quit(); - } - - void Wait() { - if (done_) - return; - - run_loop_ = std::make_unique<base::RunLoop>( - base::RunLoop::Type::kNestableTasksAllowed); - run_loop_->Run(); - run_loop_.reset(); - } - - private: - const base::raw_ptr<ui::Compositor> compositor_; - bool done_ = false; - std::unique_ptr<base::RunLoop> run_loop_; -}; - -class FirstNonAnimatedFrameStartedWaiter : public ui::CompositorObserver { - public: - explicit FirstNonAnimatedFrameStartedWaiter(ui::Compositor* compositor) - : compositor_(compositor) { - compositor->AddObserver(this); - } - - ~FirstNonAnimatedFrameStartedWaiter() override { - compositor_->RemoveObserver(this); - } - - // ui::CompositorObserver - void OnFirstNonAnimatedFrameStarted(ui::Compositor* compositor) override { - DCHECK_EQ(compositor_, compositor); - done_ = true; - if (run_loop_) - run_loop_->Quit(); - } - - void Wait() { - if (done_) - return; - - run_loop_ = std::make_unique<base::RunLoop>( - base::RunLoop::Type::kNestableTasksAllowed); - run_loop_->Run(); - run_loop_.reset(); - } - - private: - ui::Compositor* compositor_; - bool done_ = false; - std::unique_ptr<base::RunLoop> run_loop_; -}; - -void GiveItSomeTime(base::TimeDelta delta) { - // Due to the |frames_to_terminate_tracker|=3 constant in - // FrameSequenceTracker::ReportSubmitFrame we need to continue generating - // frames to receive feedback. - base::RepeatingTimer begin_main_frame_scheduler( - FROM_HERE, base::Milliseconds(16), base::BindRepeating([]() { - auto* compositor = - Shell::GetPrimaryRootWindow()->GetHost()->compositor(); - compositor->ScheduleFullRedraw(); - })); - begin_main_frame_scheduler.Reset(); - - base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); - auto* compositor = Shell::GetPrimaryRootWindow()->GetHost()->compositor(); - compositor->ScheduleFullRedraw(); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), delta); - run_loop.Run(); -} - -class MetricsWaiter { - public: - MetricsWaiter(base::HistogramTester* histogram_tester, - std::string metrics_name) - : histogram_tester_(histogram_tester), metrics_name_(metrics_name) {} - - MetricsWaiter(const MetricsWaiter&) = delete; - MetricsWaiter& operator=(const MetricsWaiter&) = delete; - - ~MetricsWaiter() = default; - - void Wait() { - while (histogram_tester_->GetTotalSum(metrics_name_) == 0) { - GiveItSomeTime(base::Milliseconds(16)); - } - } - - private: - base::raw_ptr<base::HistogramTester> histogram_tester_; - const std::string metrics_name_; -}; - -} // namespace - -// Test fixture for the LoginUnlockThroughputRecorder class. -class LoginUnlockThroughputRecorderTestBase - : public LoginTestBase, - public testing::WithParamInterface<bool> { - public: - LoginUnlockThroughputRecorderTestBase() = default; - - LoginUnlockThroughputRecorderTestBase( - const LoginUnlockThroughputRecorderTestBase&) = delete; - LoginUnlockThroughputRecorderTestBase& operator=( - const LoginUnlockThroughputRecorderTestBase&) = delete; - - ~LoginUnlockThroughputRecorderTestBase() override = default; - - // LoginTestBase: - void SetUp() override { - LoginTestBase::SetUp(); - histogram_tester_ = std::make_unique<base::HistogramTester>(); - } - - void LoginOwner() { - CreateUserSessions(1); - LoginState::Get()->SetLoggedInState( - LoginState::LOGGED_IN_ACTIVE, - chromeos::LoginState::LOGGED_IN_USER_OWNER); - } - - void LockScreenAndAnimate() { - GetSessionControllerClient()->LockScreen(); - RunSimpleAnimation(); - } - - void UnlockScreenAndAnimate() { - GetSessionControllerClient()->UnlockScreen(); - RunSimpleAnimation(); - } - - void AddScheduledRestoreBrowserWindows(const std::vector<int>& ids, - bool is_lacros) { - for (int n : ids) { - throughput_recorder()->AddScheduledRestoreWindow( - n, is_lacros ? app_constants::kLacrosAppId : "", - LoginUnlockThroughputRecorder::kBrowser); - } - } - - void AddScheduledRestoreNonBrowserWindows(const std::vector<int>& ids) { - for (int n : ids) { - throughput_recorder()->AddScheduledRestoreWindow( - n, base::StringPrintf("some_app%d", n), - LoginUnlockThroughputRecorder::kBrowser); - } - } - - void RestoredWindowsCreated(const std::vector<int>& ids) { - for (int n : ids) { - throughput_recorder()->OnRestoredWindowCreated(n); - } - } - - void RestoredWindowsShown(const std::vector<int>& ids) { - ui::Compositor* compositor = - Shell::GetPrimaryRootWindow()->GetHost()->compositor(); - for (int n : ids) { - throughput_recorder()->OnBeforeRestoredWindowShown(n, compositor); - } - } - - void RestoredWindowsPresented(const std::vector<int>& ids) { - for (int n : ids) { - throughput_recorder()->OnRestoredWindowPresented(n); - } - } - - protected: - void RunSimpleAnimation() { - ui::Compositor* compositor = - Shell::GetPrimaryRootWindow()->GetHost()->compositor(); - TestObserver observer(compositor); - BeginMainFrameWaiter(compositor).Wait(); - FirstNonAnimatedFrameStartedWaiter(compositor).Wait(); - ui::DrawWaiterForTest::WaitForCompositingEnded(compositor); - } - - void EnableTabletMode(bool enable) { - Shell::Get()->tablet_mode_controller()->SetEnabledForTest(enable); - } - - LoginUnlockThroughputRecorder* throughput_recorder() { - return Shell::Get()->login_unlock_throughput_recorder(); - } - - bool IsThroughputRecorderBlocked() { - return throughput_recorder() - ->login_animation_throughput_reporter() - ->IsBlocked(); - } - - // Used to verify recorded data. - std::unique_ptr<base::HistogramTester> histogram_tester_; -}; - -using LoginUnlockThroughputRecorderLoginAnimationTest = - LoginUnlockThroughputRecorderTestBase; - -// Boolean parameter controls tablet mode. -INSTANTIATE_TEST_SUITE_P(All, - LoginUnlockThroughputRecorderLoginAnimationTest, - testing::Bool()); - -// Verifies that login animation metrics are reported correctly ignoring shelf -// initialization. -TEST_P(LoginUnlockThroughputRecorderLoginAnimationTest, - ReportLoginAnimationOnly) { - EnableTabletMode(GetParam()); - const std::string metrics_name = - GetParam() ? kAshLoginAnimationDurationTabletMode - : kAshLoginAnimationDurationClamshellMode; - - LoginOwner(); - RunSimpleAnimation(); - GiveItSomeTime(base::Milliseconds(100)); - - // Should not report login histogram until shelf is initialized. - EXPECT_EQ(histogram_tester_.get()->GetTotalSum(metrics_name), 0); - - // In this test case we ignore the shelf initialization. Pretend that it - // was done. - throughput_recorder()->ResetScopedThroughputReporterBlockerForTesting(); - RunSimpleAnimation(); - - MetricsWaiter(histogram_tester_.get(), - GetParam() ? kAshLoginAnimationDurationTabletMode - : kAshLoginAnimationDurationClamshellMode) - .Wait(); -} - -// Verifies that login animation metrics are reported correctly after shelf is -// initialized. -TEST_P(LoginUnlockThroughputRecorderLoginAnimationTest, - ReportLoginWithShelfInitialization) { - EnableTabletMode(GetParam()); - const std::string metrics_name = - GetParam() ? kAshLoginAnimationDurationTabletMode - : kAshLoginAnimationDurationClamshellMode; - - LoginOwner(); - GiveItSomeTime(base::Milliseconds(100)); - - // Should not report login histogram until shelf is initialized. - EXPECT_EQ(histogram_tester_.get()->GetTotalSum(metrics_name), 0); - - TestShelfModel model; - model.InitializeIconList({1, 2, 3, 4, 5, 6}); - - // None of the expected shelf items have icons loaded. - throughput_recorder()->InitShelfIconList(&model); - - RunSimpleAnimation(); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_TRUE(IsThroughputRecorderBlocked()); - - model.SetIconsLoadedFor({1, 2, 3}); - throughput_recorder()->UpdateShelfIconList(&model); - EXPECT_TRUE(IsThroughputRecorderBlocked()); - - // Remove last shelf button. - model.InitializeIconList({1, 2, 3, 4, 5}); - model.SetIconsLoadedFor({1, 2, 3}); - throughput_recorder()->UpdateShelfIconList(&model); - EXPECT_TRUE(IsThroughputRecorderBlocked()); - - // Add extra buttons. - model.InitializeIconList({4, 5, 6, 7, 8, 9}); - model.SetIconsLoadedFor({7, 8, 9}); - // Only 4 and 5 are not loaded yet. - throughput_recorder()->UpdateShelfIconList(&model); - EXPECT_TRUE(IsThroughputRecorderBlocked()); - - model.SetIconsLoadedFor({4, 5}); - // All buttons should have icons. - throughput_recorder()->UpdateShelfIconList(&model); - // All loaded icons should trigger login histograms. - EXPECT_FALSE(IsThroughputRecorderBlocked()); - EXPECT_GT(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllShelfIconsLoaded"), - 0); - - GiveItSomeTime(base::Milliseconds(100)); - // Should not report login histogram until login animation starts. - EXPECT_EQ(histogram_tester_.get()->GetTotalSum(metrics_name), 0); - // Shelf metrics should be already reported. Did not specifically start shelf - // animations, but it should be reported immediately when there are no shelf - // animation. - EXPECT_GT(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.ShelfLoginAnimationEnd"), - 0); - - // Start login animation. It should trigger metrics reporting. - RunSimpleAnimation(); - MetricsWaiter(histogram_tester_.get(), metrics_name).Wait(); -} - -TEST_P(LoginUnlockThroughputRecorderLoginAnimationTest, ReportUnlock) { - LoginOwner(); - - EnableTabletMode(GetParam()); - - LockScreenAndAnimate(); - UnlockScreenAndAnimate(); - - MetricsWaiter(histogram_tester_.get(), - GetParam() ? kAshUnlockAnimationDurationTabletMode - : kAshUnlockAnimationDurationClamshellMode) - .Wait(); -} - -using LoginUnlockThroughputRecorderWindowRestoreTest = - LoginUnlockThroughputRecorderTestBase; - -// Boolean parameter controls lacros mode. -INSTANTIATE_TEST_SUITE_P(All, - LoginUnlockThroughputRecorderWindowRestoreTest, - testing::Bool()); - -// Verifies that window restore metrics are reported correctly. -TEST_P(LoginUnlockThroughputRecorderWindowRestoreTest, - ReportWindowRestoreMetrics) { - const bool is_lacros = GetParam(); - - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - LoginOwner(); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - AddScheduledRestoreBrowserWindows({1, 2, 3, 4, 5, 6}, is_lacros); - AddScheduledRestoreNonBrowserWindows({7, 8, 9, 10, 11, 12}); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - // The unexpected windows do not trigger the metrics. - RestoredWindowsCreated({21, 22, 23, 24, 25, 26}); - RestoredWindowsShown({21, 22, 23, 24, 25, 26}); - RestoredWindowsPresented({21, 22, 23, 24, 25, 26}); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - // Window must go through all of the expected steps - // (Created->Shown->Presented). The non-created windows do not trigger - // metrics. - RestoredWindowsShown({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); - RestoredWindowsPresented({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - // Only wait for the expected browser windows: expected window 1 is missing. - RestoredWindowsCreated({2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); - RestoredWindowsShown({2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); - RestoredWindowsPresented({2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - // Last window created. - RestoredWindowsCreated({1}); - EXPECT_TRUE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsCreated")); - GiveItSomeTime(base::Milliseconds(100)); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - EXPECT_FALSE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); - - RestoredWindowsShown({1}); - EXPECT_TRUE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsShown")); - - RestoredWindowsPresented({1}); - EXPECT_TRUE(histogram_tester_.get()->GetTotalSum( - "Ash.LoginSessionRestore.AllBrowserWindowsPresented")); -} - -} // namespace ash
diff --git a/ash/projector/projector_annotation_tray.cc b/ash/projector/projector_annotation_tray.cc index d73175e6..f73f889 100644 --- a/ash/projector/projector_annotation_tray.cc +++ b/ash/projector/projector_annotation_tray.cc
@@ -24,6 +24,7 @@ #include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" +#include "ui/events/event.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/separator.h" @@ -61,7 +62,7 @@ ProjectorTool GetCurrentTool() { auto* controller = Shell::Get()->projector_controller(); - // ProjctorController may not be available yet as the ProjectorAnnotationTray + // `controller` may not be available yet as the `ProjectorAnnotationTray` // is created before it. if (!controller) return kToolNone; @@ -100,6 +101,27 @@ image_view_( tray_container()->AddChildView(std::make_unique<views::ImageView>())), pen_view_(nullptr) { + SetPressedCallback(base::BindRepeating( + [](ProjectorAnnotationTray* projector_annotation_tray, + const ui::Event& event) { + // NOTE: Long press not supported via the `views::Button` callback, it + // is handled via OnGestureEvent override. + if (event.IsMouseEvent() && + event.AsMouseEvent()->IsRightMouseButton()) { + projector_annotation_tray->ShowBubble(); + return; + } + + projector_annotation_tray->ToggleAnnotator(); + }, + base::Unretained(this))); + // Right click should show the bubble. In tablet mode, long press is + // synonymous with right click, gesture long press must be intercepted via + // `OnGestureEvent()` override, as `views::Button` forces long press to show a + // contextual menu. + SetTriggerableEventFlags(ui::EF_LEFT_MOUSE_BUTTON | + ui::EF_RIGHT_MOUSE_BUTTON); + image_view_->SetTooltipText(GetTooltip()); image_view_->SetHorizontalAlignment(views::ImageView::Alignment::kCenter); image_view_->SetVerticalAlignment(views::ImageView::Alignment::kCenter); @@ -111,28 +133,18 @@ ProjectorAnnotationTray::~ProjectorAnnotationTray() = default; -bool ProjectorAnnotationTray::PerformAction(const ui::Event& event) { - ToggleAnnotator(); - return true; -} - -void ProjectorAnnotationTray::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() != ui::ET_MOUSE_PRESSED) { +void ProjectorAnnotationTray::OnGestureEvent(ui::GestureEvent* event) { + // Long Press typically is used to show a contextual menu, but because in + // tablet mode tapping the pod is used to toggle a feature, long press is the + // only available way to show the bubble. + // TODO(crbug/1374368): Put this where we handle other button activations, + // once the `views::Button` code allows it. + if (event->details().type() != ui::ET_GESTURE_LONG_PRESS) { + TrayBackgroundView::OnGestureEvent(event); return; } - if (event->IsRightMouseButton()) { - ShowBubble(); - } else if (event->IsLeftMouseButton()) { - ToggleAnnotator(); - } -} -void ProjectorAnnotationTray::OnGestureEvent(ui::GestureEvent* event) { - if (event->details().type() == ui::ET_GESTURE_LONG_PRESS) { - ShowBubble(); - } else if (event->details().type() == ui::ET_GESTURE_TAP) { - ToggleAnnotator(); - } + ShowBubble(); } void ProjectorAnnotationTray::ClickedOutsideBubble() {
diff --git a/ash/projector/projector_annotation_tray.h b/ash/projector/projector_annotation_tray.h index e11414e..442d018 100644 --- a/ash/projector/projector_annotation_tray.h +++ b/ash/projector/projector_annotation_tray.h
@@ -11,6 +11,15 @@ #include "ash/system/tray/view_click_listener.h" #include "base/scoped_observation.h" +namespace ui { +class GestureEvent; +} // namespace ui + +namespace views { +class ImageView; +class Widget; +} // namespace views + namespace ash { class HoverHighlightView; @@ -34,7 +43,7 @@ ~ProjectorAnnotationTray() override; // TrayBackgroundView: - bool PerformAction(const ui::Event& event) override; + void OnGestureEvent(ui::GestureEvent* event) override; void ClickedOutsideBubble() override; std::u16string GetAccessibleNameForTray() override; void HandleLocaleChange() override; @@ -43,8 +52,6 @@ void ShowBubble() override; TrayBubbleView* GetBubbleView() override; views::Widget* GetBubbleWidget() const override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; void OnThemeChanged() override; // SessionObserver:
diff --git a/ash/projector/projector_ui_controller_unittest.cc b/ash/projector/projector_ui_controller_unittest.cc index 13ed3159..1e440fb 100644 --- a/ash/projector/projector_ui_controller_unittest.cc +++ b/ash/projector/projector_ui_controller_unittest.cc
@@ -24,6 +24,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/test/event_generator.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_observer.h" @@ -206,6 +207,77 @@ /*count=*/1); } +// Tests that right clicking the ProjectorAnnotationTray shows a bubble. +TEST_F(ProjectorUiControllerTest, RightClickShowsBubble) { + controller_->ShowAnnotationTray(Shell::GetPrimaryRootWindow()); + controller_->OnCanvasInitialized(true); + + auto* projector_annotation_tray = Shell::GetPrimaryRootWindowController() + ->GetStatusAreaWidget() + ->projector_annotation_tray(); + + // Right click the tray item, it should show a bubble. + RightClickOn(projector_annotation_tray); + EXPECT_TRUE(projector_annotation_tray->GetBubbleWidget()); +} + +// Tests that long pressing the ProjectorAnnotationTray shows a bubble. +TEST_F(ProjectorUiControllerTest, LongPressShowsBubble) { + controller_->ShowAnnotationTray(Shell::GetPrimaryRootWindow()); + controller_->OnCanvasInitialized(true); + + auto* projector_annotation_tray = Shell::GetPrimaryRootWindowController() + ->GetStatusAreaWidget() + ->projector_annotation_tray(); + + // Long press the tray item, it should show a bubble. + gfx::Point location = + projector_annotation_tray->GetBoundsInScreen().CenterPoint(); + + // Temporarily reconfigure gestures so that the long press takes 2 + // milliseconds. + ui::GestureConfiguration* gesture_config = + ui::GestureConfiguration::GetInstance(); + const int old_long_press_time_in_ms = gesture_config->long_press_time_in_ms(); + const base::TimeDelta old_short_press_time = + gesture_config->short_press_time(); + const int old_show_press_delay_in_ms = + gesture_config->show_press_delay_in_ms(); + gesture_config->set_long_press_time_in_ms(1); + gesture_config->set_short_press_time(base::Milliseconds(1)); + gesture_config->set_show_press_delay_in_ms(1); + + ui::test::EventGenerator* event_generator = GetEventGenerator(); + event_generator->set_current_screen_location(location); + event_generator->PressTouch(); + + // Hold the press down for 2 ms, to trigger a long press. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(2)); + run_loop.Run(); + + gesture_config->set_long_press_time_in_ms(old_long_press_time_in_ms); + gesture_config->set_short_press_time(old_short_press_time); + gesture_config->set_show_press_delay_in_ms(old_show_press_delay_in_ms); + + event_generator->ReleaseTouch(); + + EXPECT_TRUE(projector_annotation_tray->GetBubbleWidget()); +} + +// Tests that tapping the ProjectorAnnotationTray enables annotation. +TEST_F(ProjectorUiControllerTest, TapEnabledAnnotation) { + controller_->ShowAnnotationTray(Shell::GetPrimaryRootWindow()); + controller_->OnCanvasInitialized(true); + + GestureTapOn(Shell::GetPrimaryRootWindowController() + ->GetStatusAreaWidget() + ->projector_annotation_tray()); + + EXPECT_TRUE(controller_->is_annotator_enabled()); +} + TEST_F(ProjectorUiControllerTest, ShowFailureNotification) { base::HistogramTester histogram_tester;
diff --git a/ash/public/cpp/app_list/app_list_color_provider.h b/ash/public/cpp/app_list/app_list_color_provider.h index 94bd32e6..cc418b8 100644 --- a/ash/public/cpp/app_list/app_list_color_provider.h +++ b/ash/public/cpp/app_list/app_list_color_provider.h
@@ -65,7 +65,6 @@ const views::Widget* app_list_widget) const = 0; virtual SkColor GetGridBackgroundCardInactiveColor( const views::Widget* app_list_widget) const = 0; - virtual ui::ColorId GetSeparatorColorId() const = 0; virtual SkColor GetFocusRingColor( const views::Widget* app_list_widget) const = 0; virtual SkColor GetInkDropBaseColor(
diff --git a/ash/public/cpp/app_list/app_list_config.cc b/ash/public/cpp/app_list/app_list_config.cc index 3d42d8e..65462e6 100644 --- a/ash/public/cpp/app_list/app_list_config.cc +++ b/ash/public/cpp/app_list/app_list_config.cc
@@ -237,14 +237,11 @@ } // namespace SharedAppListConfig& SharedAppListConfig::instance() { - static base::NoDestructor<SharedAppListConfig> shared_config; - return *shared_config; + static SharedAppListConfig shared_config; + return shared_config; } -SharedAppListConfig::SharedAppListConfig() - : search_result_title_font_style_(ui::ResourceBundle::BaseFont), - search_result_recommendation_title_font_( - ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(1)) {} +SharedAppListConfig::SharedAppListConfig() = default; int SharedAppListConfig::GetMaxNumOfItemsPerPage() const { return 20;
diff --git a/ash/public/cpp/app_list/app_list_config.h b/ash/public/cpp/app_list/app_list_config.h index b9e9e79..62e175e 100644 --- a/ash/public/cpp/app_list/app_list_config.h +++ b/ash/public/cpp/app_list/app_list_config.h
@@ -33,8 +33,6 @@ size_t max_search_results() const { return max_search_results_; } - size_t max_search_result_tiles() const { return max_search_result_tiles_; } - size_t max_search_result_list_items() const { return max_search_result_list_items_; } @@ -85,14 +83,6 @@ return suggestion_chip_icon_dimension_; } - ui::ResourceBundle::FontStyle search_result_title_font_style() const { - return search_result_title_font_style_; - } - - gfx::FontList search_result_recommendation_title_font() const { - return search_result_recommendation_title_font_; - } - int search_tile_height() const { return search_tile_height_; } // Returns the maximum number of items allowed in a page in the apps grid. @@ -102,7 +92,7 @@ int GetPreferredIconDimension(SearchResultDisplayType display_type) const; private: - friend class base::NoDestructor<SharedAppListConfig>; + friend class SharedAppListConfig; SharedAppListConfig(); // The icon dimension of tile views in apps grid view. @@ -111,9 +101,6 @@ // Maximum number of results to show in the launcher Search UI. const size_t max_search_results_ = 6; - // Max number of search result tiles in the launcher suggestion window. - const size_t max_search_result_tiles_ = 6; - // Max number of search result list items in the launcher suggestion window. const size_t max_search_result_list_items_ = 5; @@ -143,14 +130,6 @@ // The suggestion chip icon dimension. const int suggestion_chip_icon_dimension_ = 20; - // Font style for AppListSearchResultItemViews that are not suggested - // apps. - const ui::ResourceBundle::FontStyle search_result_title_font_style_; - - // Font style for AppListSearchResultTileItemViews that are suggested - // apps. - const gfx::FontList search_result_recommendation_title_font_; - // The height of tiles in search result. const int search_tile_height_ = 92; };
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc index 7fa114c..62b594d 100644 --- a/ash/public/cpp/app_list/app_list_features.cc +++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -50,6 +50,9 @@ BASE_FEATURE(kLauncherPlayStoreSearch, "LauncherPlayStoreSearch", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kAnimateScaleOnTabletModeTransition, + "AnimateScaleOnTabletModeTransition", + base::FEATURE_DISABLED_BY_DEFAULT); bool IsAppRankerEnabled() { return base::FeatureList::IsEnabled(kEnableAppRanker); @@ -129,4 +132,8 @@ base::FeatureList::IsEnabled(kLauncherPlayStoreSearch); } +bool IsAnimateScaleOnTabletModeTransitionEnabled() { + return base::FeatureList::IsEnabled(kAnimateScaleOnTabletModeTransition); +} + } // namespace app_list_features
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h index a2696c56..97de35ee 100644 --- a/ash/public/cpp/app_list/app_list_features.h +++ b/ash/public/cpp/app_list/app_list_features.h
@@ -63,6 +63,10 @@ // Enables Play Store search in the launcher. ASH_PUBLIC_EXPORT BASE_DECLARE_FEATURE(kLauncherPlayStoreSearch); +// Enables new tablet <-> clamshell mode transition animation (scale + opacity +// instead of slide up/down). +ASH_PUBLIC_EXPORT BASE_DECLARE_FEATURE(kAnimateScaleOnTabletModeTransition); + ASH_PUBLIC_EXPORT bool IsAppRankerEnabled(); ASH_PUBLIC_EXPORT bool IsZeroStateAppsRankerEnabled(); ASH_PUBLIC_EXPORT bool IsZeroStateMixedTypesRankerEnabled(); @@ -79,6 +83,7 @@ ASH_PUBLIC_EXPORT base::TimeDelta DynamicSearchUpdateAnimationDuration(); ASH_PUBLIC_EXPORT bool IsCompactBubbleLauncherEnabled(); ASH_PUBLIC_EXPORT bool IsLauncherPlayStoreSearchEnabled(); +ASH_PUBLIC_EXPORT bool IsAnimateScaleOnTabletModeTransitionEnabled(); ASH_PUBLIC_EXPORT std::string AppSearchResultRankerPredictorName(); ASH_PUBLIC_EXPORT std::string CategoricalSearchType();
diff --git a/ash/public/cpp/test/test_app_list_color_provider.cc b/ash/public/cpp/test/test_app_list_color_provider.cc index 545886b..cbddd35f 100644 --- a/ash/public/cpp/test/test_app_list_color_provider.cc +++ b/ash/public/cpp/test/test_app_list_color_provider.cc
@@ -104,10 +104,6 @@ return SkColorSetA(SK_ColorWHITE, 41 /* 16% */); } -ui::ColorId TestAppListColorProvider::GetSeparatorColorId() const { - return ui::kColorAshSystemUIMenuSeparator; -} - SkColor TestAppListColorProvider::GetFocusRingColor( const views::Widget* app_list_widget) const { return gfx::kGoogleBlue600;
diff --git a/ash/public/cpp/test/test_app_list_color_provider.h b/ash/public/cpp/test/test_app_list_color_provider.h index 2ff5c222..7a002052 100644 --- a/ash/public/cpp/test/test_app_list_color_provider.h +++ b/ash/public/cpp/test/test_app_list_color_provider.h
@@ -58,7 +58,6 @@ const views::Widget* app_list_widget) const override; SkColor GetGridBackgroundCardInactiveColor( const views::Widget* app_list_widget) const override; - ui::ColorId GetSeparatorColorId() const override; SkColor GetFocusRingColor( const views::Widget* app_list_widget) const override; SkColor GetInkDropBaseColor(
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc index 5ddea72..18df6440f 100644 --- a/ash/shelf/shelf.cc +++ b/ash/shelf/shelf.cc
@@ -10,7 +10,6 @@ #include "ash/app_list/app_list_controller_impl.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" -#include "ash/metrics/login_unlock_throughput_recorder.h" #include "ash/public/cpp/keyboard/keyboard_controller_observer.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" @@ -19,7 +18,6 @@ #include "ash/root_window_controller.h" #include "ash/shelf/hotseat_widget.h" #include "ash/shelf/login_shelf_widget.h" -#include "ash/shelf/scrollable_shelf_view.h" #include "ash/shelf/shelf_controller.h" #include "ash/shelf/shelf_focus_cycler.h" #include "ash/shelf/shelf_layout_manager.h" @@ -408,8 +406,6 @@ hotseat_transition_metrics_reporter_ = std::make_unique<HotseatWidgetAnimationMetricsReporter>( HotseatWidgetAnimationMetricsReporter::HotseatElementType::kWidget); - Shell::Get()->login_unlock_throughput_recorder()->SetShelfViewIfNotSet( - hotseat_widget_->scrollable_shelf_view()->shelf_view()); } void Shelf::CreateStatusAreaWidget(aura::Window* shelf_container) {
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 696ab55..c417f718 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -1213,6 +1213,8 @@ drag_icon_bounds_in_screen_ = gfx::Rect(); drag_and_drop_shelf_id_ = ShelfID(); is_active_drag_and_drop_host_ = false; + + HandleShelfParty(); } void ShelfView::SwapButtons(views::View* button_to_swap, bool with_next) { @@ -1985,15 +1987,6 @@ return drag_icon_proxy_->GetBoundsInScreen(); } -void ShelfView::AddAnimationObserver(views::BoundsAnimatorObserver* observer) { - bounds_animator_->AddObserver(observer); -} - -void ShelfView::RemoveAnimationObserver( - views::BoundsAnimatorObserver* observer) { - bounds_animator_->RemoveObserver(observer); -} - void ShelfView::AnnounceShelfAutohideBehavior() { std::u16string announcement; switch (shelf_->auto_hide_behavior()) { @@ -2225,6 +2218,8 @@ AnnouncePinUnpinEvent(old_item, /*pinned=*/false); RecordPinUnpinUserAction(/*pinned=*/false); } + + party_.erase(old_item.id); } void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) { @@ -2679,6 +2674,8 @@ } DCHECK(IsItemPinned(item)); DCHECK(!IsItemVisible(item)); + if (item.image.isNull() || item.id == drag_and_drop_shelf_id_) + continue; // Add the item if it is not already partying. const auto insertion_results = party_.try_emplace(item.id); if (insertion_results.second) {
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index c75b823..3cdf669 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -326,9 +326,6 @@ return current_ghost_view_index_; } - void AddAnimationObserver(views::BoundsAnimatorObserver* observer); - void RemoveAnimationObserver(views::BoundsAnimatorObserver* observer); - private: friend class ShelfViewTestAPI;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 007817a..b87835c 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -2333,39 +2333,6 @@ EXPECT_EQ(0, GetHapticTickEventsCount()); } -// Verifies that partying items are hidden from the shelf. -// TODO(crbug/1372295): This test consistently times out. -TEST_P(LtrRtlShelfViewTest, DISABLED_PartyingItemsHiddenFromShelf) { - AddAppShortcut(); - AddAppShortcut(); - AddApp(); - ShelfItem item = model_->items()[1u]; - item.status = STATUS_RUNNING; - model_->Set(1, item); - const gfx::Rect initial_bounds0 = test_api_->GetBoundsByIndex(0); - const gfx::Rect initial_bounds2 = test_api_->GetBoundsByIndex(2); - - // Start shelf party. - model_->ToggleShelfParty(); - { - const std::vector<size_t> not_partying = {1, 3}; - EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); - } - test_api_->RunMessageLoopUntilAnimationsDone(); - EXPECT_TRUE(test_api_->GetBoundsByIndex(0).IsEmpty()); - EXPECT_TRUE(test_api_->GetBoundsByIndex(2).IsEmpty()); - - // End shelf party. - model_->ToggleShelfParty(); - { - const std::vector<size_t> not_partying = {0, 1, 2, 3}; - EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); - } - test_api_->RunMessageLoopUntilAnimationsDone(); - EXPECT_EQ(initial_bounds0, test_api_->GetBoundsByIndex(0)); - EXPECT_EQ(initial_bounds2, test_api_->GetBoundsByIndex(2)); -} - // Test class that tests both context and application menus. class ShelfViewMenuTest : public ShelfViewTest, public testing::WithParamInterface<bool> { @@ -3665,4 +3632,36 @@ test_api_->RunMessageLoopUntilAnimationsDone(); } +// Verifies that partying items are hidden from the shelf. +TEST_P(ShelfPartyTest, PartyingItemsHiddenFromShelf) { + AddAppShortcut(); + AddAppShortcut(); + AddApp(); + ShelfItem item = model_->items()[1u]; + item.status = STATUS_RUNNING; + model_->Set(1, item); + const gfx::Rect initial_bounds0 = test_api_->GetBoundsByIndex(0); + const gfx::Rect initial_bounds2 = test_api_->GetBoundsByIndex(2); + + // Start shelf party. + model_->ToggleShelfParty(); + { + const std::vector<size_t> not_partying = {1, 3}; + EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); + } + task_environment()->FastForwardBy(base::Seconds(1)); + EXPECT_TRUE(test_api_->GetBoundsByIndex(0).IsEmpty()); + EXPECT_TRUE(test_api_->GetBoundsByIndex(2).IsEmpty()); + + // End shelf party. + model_->ToggleShelfParty(); + { + const std::vector<size_t> not_partying = {0, 1, 2, 3}; + EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); + } + test_api_->RunMessageLoopUntilAnimationsDone(); + EXPECT_EQ(initial_bounds0, test_api_->GetBoundsByIndex(0)); + EXPECT_EQ(initial_bounds2, test_api_->GetBoundsByIndex(2)); +} + } // namespace ash
diff --git a/ash/shell.h b/ash/shell.h index 51dfdb29..fd54b4bf 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -738,10 +738,6 @@ void NotifyShelfAlignmentChanged(aura::Window* root_window, ShelfAlignment old_alignment); - LoginUnlockThroughputRecorder* login_unlock_throughput_recorder() { - return login_unlock_throughput_recorder_.get(); - } - private: FRIEND_TEST_ALL_PREFIXES(ExtendedDesktopTest, TestCursor); FRIEND_TEST_ALL_PREFIXES(WindowManagerTest, MouseEventCursors);
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h index aa3eb7d..8a140794 100644 --- a/ash/system/tray/tray_constants.h +++ b/ash/system/tray/tray_constants.h
@@ -74,9 +74,6 @@ // The size of the icons appearing in the material design system tray. constexpr int kTrayIconSize = 16; -// The padding on top of the time tray icon when vertically aligned. -constexpr int kTrayTimeIconTopPadding = 2; - // The padding around network tray icon in dip. constexpr int kTrayNetworkIconPadding = 2; constexpr int kUnifiedTrayNetworkIconPadding = 4;
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index 7723a95..c4e048e 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -222,18 +222,14 @@ notification_icons_controller_->AddNotificationTrayItems(tray_container()); for (TrayItemView* tray_item : notification_icons_controller_->tray_items()) { tray_items_.push_back(tray_item); - AddObservedTrayItem(tray_item); } AddTrayItemToContainer(screen_capture_view_); tray_items_.push_back( notification_icons_controller_->notification_counter_view()); - AddObservedTrayItem( - notification_icons_controller_->notification_counter_view()); tray_items_.push_back(notification_icons_controller_->quiet_mode_view()); - AddObservedTrayItem(notification_icons_controller_->quiet_mode_view()); if (features::IsSnoopingProtectionEnabled()) AddTrayItemToContainer(snooping_protection_view_); @@ -267,12 +263,6 @@ AddTrayItemToContainer(channel_indicator_view_); } - auto vertical_clock_padding = std::make_unique<views::View>(); - vertical_clock_padding->SetPreferredSize(gfx::Size( - 0, features::IsCalendarViewEnabled() ? 0 : kTrayTimeIconTopPadding)); - vertical_clock_padding_ = - tray_container()->AddChildView(std::move(vertical_clock_padding)); - if (!features::IsCalendarViewEnabled()) { AddTrayItemToContainer(time_view_); } @@ -284,12 +274,10 @@ set_use_bounce_in_animation(false); ShelfConfig::Get()->AddObserver(this); - Shell::Get()->AddShellObserver(this); } UnifiedSystemTray::~UnifiedSystemTray() { ShelfConfig::Get()->RemoveObserver(this); - Shell::Get()->RemoveShellObserver(this); DestroyBubbles(); @@ -308,38 +296,6 @@ observers_.RemoveObserver(observer); } -bool UnifiedSystemTray::MoreThanOneVisibleTrayItem() const { - bool one_visible_item = false; - for (TrayItemView* item : tray_items_) { - if (!item->GetVisible()) - continue; - if (one_visible_item) - return true; - one_visible_item = true; - } - return false; -} - -void UnifiedSystemTray::MaybeUpdateVerticalClockPadding() { - const bool padding_is_visible = vertical_clock_padding_->GetVisible(); - - if (shelf()->IsHorizontalAlignment()) { - if (padding_is_visible) - vertical_clock_padding_->SetVisible(false); - return; - } - - // Padding is shown when an icon besides TimeView is visible. - const bool should_show_padding = MoreThanOneVisibleTrayItem(); - if (padding_is_visible != should_show_padding) - vertical_clock_padding_->SetVisible(should_show_padding); -} - -void UnifiedSystemTray::OnViewVisibilityChanged(views::View* observed_view, - views::View* starting_view) { - MaybeUpdateVerticalClockPadding(); -} - bool UnifiedSystemTray::IsBubbleShown() const { return !!bubble_; } @@ -496,11 +452,6 @@ return absl::make_optional(TOGGLE_SYSTEM_TRAY_BUBBLE); } -void UnifiedSystemTray::OnShelfAlignmentChanged(aura::Window* root_window, - ShelfAlignment old_alignment) { - MaybeUpdateVerticalClockPadding(); -} - void UnifiedSystemTray::OnShelfConfigUpdated() { // Ensure the margin is updated correctly depending on whether dense shelf // is currently shown or not. @@ -777,11 +728,6 @@ void UnifiedSystemTray::AddTrayItemToContainer(TrayItemView* tray_item) { tray_items_.push_back(tray_item); tray_container()->AddChildView(tray_item); - AddObservedTrayItem(tray_item); -} - -void UnifiedSystemTray::AddObservedTrayItem(TrayItemView* tray_item) { - tray_items_observations_.AddObservation(tray_item); } void UnifiedSystemTray::DestroyBubbles() {
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index 04aef94..fbfd8fc 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -11,7 +11,6 @@ #include "ash/ash_export.h" #include "ash/public/cpp/accelerators.h" #include "ash/public/cpp/shelf_config.h" -#include "ash/shell_observer.h" #include "ash/system/status_area_widget.h" #include "ash/system/time/time_view.h" #include "ash/system/tray/tray_background_view.h" @@ -19,7 +18,6 @@ #include "ash/system/unified/unified_system_tray_model.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/scoped_multi_source_observation.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -64,7 +62,6 @@ class ASH_EXPORT UnifiedSystemTray : public TrayBackgroundView, public ShelfConfig::Observer, - public ShellObserver, public UnifiedSystemTrayController::Observer { public: class Observer : public base::CheckedObserver { @@ -86,14 +83,6 @@ void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // Adds a padding on top of the vertical clock if there are other visible - // icons in the tray, removes it if the clock is the only visible icon. - void MaybeUpdateVerticalClockPadding(); - - // views::ViewObserver: - void OnViewVisibilityChanged(views::View* observed_view, - views::View* starting_view) override; - // True if the bubble is shown. It does not include slider bubbles, and when // they're shown it still returns false. bool IsBubbleShown() const; @@ -200,10 +189,6 @@ const char* GetClassName() const override; absl::optional<AcceleratorAction> GetAcceleratorAction() const override; - // ShellObserver: - void OnShelfAlignmentChanged(aura::Window* root_window, - ShelfAlignment old_alignment) override; - // ShelfConfig::Observer: void OnShelfConfigUpdated() override; @@ -265,12 +250,6 @@ // The container takes the ownership of |tray_item|. void AddTrayItemToContainer(TrayItemView* tray_item); - // Returns true if there is two or more tray items that are visible. - bool MoreThanOneVisibleTrayItem() const; - - // Add observed tray item views. - void AddObservedTrayItem(TrayItemView* tray_item); - // Destroys the `bubble_` and the `message_center_bubble_`, also handles // removing bubble related observers. void DestroyBubbles(); @@ -312,13 +291,6 @@ // Contains all tray items views added to tray_container(). std::list<TrayItemView*> tray_items_; - base::ScopedMultiSourceObservation<views::View, views::ViewObserver> - tray_items_observations_{this}; - - // Padding owned by the view hierarchy used to separate vertical - // clock from other tray icons. - views::View* vertical_clock_padding_ = nullptr; - base::OneShotTimer timer_; bool first_interaction_recorded_ = false;
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc index d04a346c..4ce2392 100644 --- a/ash/system/unified/unified_system_tray_unittest.cc +++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -87,10 +87,6 @@ ->slider_bubble_controller_->bubble_widget_; } - bool MoreThanOneVisibleTrayItem() const { - return GetPrimaryUnifiedSystemTray()->MoreThanOneVisibleTrayItem(); - } - UnifiedSliderBubbleController::SliderType GetSliderBubbleType() { return GetPrimaryUnifiedSystemTray() ->slider_bubble_controller_->slider_type_; @@ -124,14 +120,6 @@ return GetPrimaryUnifiedSystemTray()->ime_mode_view_; } - std::list<TrayItemView*> tray_items() { - return GetPrimaryUnifiedSystemTray()->tray_items_; - } - - views::View* vertical_clock_padding() { - return GetPrimaryUnifiedSystemTray()->vertical_clock_padding_; - } - private: int id_ = 0; base::test::ScopedFeatureList feature_list_; @@ -280,42 +268,6 @@ EXPECT_EQ(time_bounds.height(), ime_bounds.height()); } -TEST_P(UnifiedSystemTrayTest, VerticalClockPadding) { - // Padding can only be visible if shelf is vertically aligned. - GetPrimaryShelf()->SetAlignment(ShelfAlignment::kLeft); - - // Sets all tray items' visibility to false except TimeView. - for (TrayItemView* item : tray_items()) { - item->SetVisible(item == time_view()); - } - - // Only one visible tray item, padding should not be visible. - EXPECT_FALSE(vertical_clock_padding()->GetVisible()); - - // Sets another tray item visibility to true. - ime_mode_view()->SetVisible(true); - - // Two visible tray items, padding should be visible. - EXPECT_TRUE(vertical_clock_padding()->GetVisible()); -} - -TEST_P(UnifiedSystemTrayTest, VerticalClockPaddingAfterAlignmentChange) { - auto* shelf = GetPrimaryShelf(); - - // Padding can only be visible if shelf is vertically aligned. - shelf->SetAlignment(ShelfAlignment::kLeft); - - // Ensure two tray items are visible, padding should be visible. - time_view()->SetVisible(true); - ime_mode_view()->SetVisible(true); - - EXPECT_TRUE(vertical_clock_padding()->GetVisible()); - - // Padding should not be visible when shelf is horizontal. - shelf->SetAlignment(ShelfAlignment::kBottom); - EXPECT_FALSE(vertical_clock_padding()->GetVisible()); -} - TEST_P(UnifiedSystemTrayTest, FocusMessageCenter) { if (IsQsRevampEnabled()) return;
diff --git a/ash/webui/os_feedback_ui/resources/confirmation_page.js b/ash/webui/os_feedback_ui/resources/confirmation_page.js index 927a7628..c980a05 100644 --- a/ash/webui/os_feedback_ui/resources/confirmation_page.js +++ b/ash/webui/os_feedback_ui/resources/confirmation_page.js
@@ -134,7 +134,7 @@ handleLinkClicked_(e) { e.stopPropagation(); - switch (e.target.id) { + switch (e.currentTarget.id) { case 'diagnostics': this.feedbackServiceProvider_.openDiagnosticsApp(); this.handleEmitMetrics_( @@ -154,7 +154,7 @@ FeedbackAppPostSubmitAction.kOpenChromebookCommunity); break; default: - console.warn('unexpected caller id: ', e.target.id); + console.warn('unexpected caller id: ', e.currentTarget.id); } }
diff --git a/ash/webui/personalization_app/mojom/personalization_app.mojom b/ash/webui/personalization_app/mojom/personalization_app.mojom index 9a67853..77c1f2c1 100644 --- a/ash/webui/personalization_app/mojom/personalization_app.mojom +++ b/ash/webui/personalization_app/mojom/personalization_app.mojom
@@ -167,9 +167,6 @@ // Represents the currently selected wallpaper image. struct CurrentWallpaper { - // URL of the currently selected wallpaper image in data scheme. - url.mojom.Url url; - // Attribution text such as "Photo by John Doe" or the file name of the local // image. array<string> attribution;
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 0a15295..0cba04ec 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -6,6 +6,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/ambient/ambient_client.h" +#include "ash/public/cpp/wallpaper/wallpaper_controller.h" #include "ash/rgb_keyboard/rgb_keyboard_manager.h" #include "ash/shell.h" #include "ash/webui/grit/ash_personalization_app_resources.h" @@ -17,9 +18,12 @@ #include "ash/webui/personalization_app/personalization_app_user_provider.h" #include "ash/webui/personalization_app/personalization_app_wallpaper_provider.h" #include "base/check.h" +#include "base/containers/contains.h" #include "base/strings/strcat.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/strings/grit/chromeos_strings.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/url_constants.h" @@ -259,6 +263,10 @@ source->EnableReplaceI18nInJS(); } +bool ShouldHandleWebUIRequest(const std::string& path) { + return base::StartsWith(path, "wallpaper.png"); +} + } // namespace PersonalizationAppUI::PersonalizationAppUI( @@ -281,6 +289,12 @@ web_ui->GetWebContents()->GetBrowserContext(), kChromeUIPersonalizationAppHost); + // Supply a custom wallpaper image. + source->SetRequestFilter( + base::BindRepeating(&ShouldHandleWebUIRequest), + base::BindRepeating(&PersonalizationAppUI::HandleWebUIRequest, + weak_ptr_factory_.GetWeakPtr())); + source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test chrome://webui-test " @@ -358,6 +372,14 @@ source->AddBoolean("isJellyEnabled", features::IsJellyEnabled()); } +void PersonalizationAppUI::HandleWebUIRequest( + const std::string& path, + content::WebUIDataSource::GotDataCallback callback) { + DCHECK(base::Contains(path, "?key=")) + << "wallpaper key must be provided to prevent browser cache collisions"; + wallpaper_provider_->GetWallpaperAsPngBytes(std::move(callback)); +} + WEB_UI_CONTROLLER_TYPE_IMPL(PersonalizationAppUI) } // namespace ash::personalization_app
diff --git a/ash/webui/personalization_app/personalization_app_ui.h b/ash/webui/personalization_app/personalization_app_ui.h index 71f9e91..378525d 100644 --- a/ash/webui/personalization_app/personalization_app_ui.h +++ b/ash/webui/personalization_app/personalization_app_ui.h
@@ -8,6 +8,8 @@ #include <memory> #include "ash/webui/personalization_app/mojom/personalization_app.mojom-forward.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "ui/webui/mojo_web_ui_controller.h" #include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" @@ -69,6 +71,10 @@ private: void AddBooleans(content::WebUIDataSource* source); + + void HandleWebUIRequest(const std::string& path, + content::WebUIDataSource::GotDataCallback callback); + std::unique_ptr<PersonalizationAppAmbientProvider> ambient_provider_; std::unique_ptr<PersonalizationAppKeyboardBacklightProvider> keyboard_backlight_provider_; @@ -79,6 +85,8 @@ // changes. std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; + base::WeakPtrFactory<PersonalizationAppUI> weak_ptr_factory_{this}; + WEB_UI_CONTROLLER_TYPE_DECL(); };
diff --git a/ash/webui/personalization_app/personalization_app_wallpaper_provider.h b/ash/webui/personalization_app/personalization_app_wallpaper_provider.h index 1517aef..66e6863 100644 --- a/ash/webui/personalization_app/personalization_app_wallpaper_provider.h +++ b/ash/webui/personalization_app/personalization_app_wallpaper_provider.h
@@ -6,6 +6,7 @@ #define ASH_WEBUI_PERSONALIZATION_APP_PERSONALIZATION_APP_WALLPAPER_PROVIDER_H_ #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" +#include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_receiver.h" namespace ash::personalization_app { @@ -17,6 +18,9 @@ virtual void BindInterface( mojo::PendingReceiver<mojom::WallpaperProvider> receiver) = 0; + virtual void GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) = 0; + // Not all users that can view the personalization app can also see google // photos. Users without a gaia account cannot use the photos APIs. virtual bool IsEligibleForGooglePhotos() = 0;
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/utils.ts b/ash/webui/personalization_app/resources/js/wallpaper/utils.ts index e502133..4ae5566 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/utils.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/utils.ts
@@ -121,3 +121,19 @@ } return attribution; } + +/** + * Get a url to download a high quality preview of the current wallpaper. + * Responds with null in case |image| is invalid or null. + */ +export function getWallpaperSrc(image: CurrentWallpaper|null): string|null { + if (!image) { + return null; + } + if (typeof image.key !== 'string' || !image.key) { + console.warn('Invalid image key received'); + return null; + } + // Add a key query parameter to cache bust when the image changes. + return `/wallpaper.png?key=${encodeURIComponent(image.key)}`; +}
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts index 8d3192a..d3216693 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts
@@ -8,7 +8,6 @@ import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js'; import {CurrentWallpaper, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, WallpaperCollection, WallpaperImage} from '../personalization_app.mojom-webui.js'; -import {isPngDataUrl} from '../utils.js'; import {DisplayableImage} from './constants.js'; @@ -449,9 +448,6 @@ */ export function setSelectedImageAction(image: CurrentWallpaper| null): SetSelectedImageAction { - assert( - image === null || isPngDataUrl(image.url), - 'only png data urls are supported'); return { image, name: WallpaperActionName.SET_SELECTED_IMAGE,
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html index 893ce431..45b0696 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html
@@ -84,16 +84,16 @@ <div id="imageContainer" class="photo-images-container clickable" on-click="onClickWallpaper_" on-keypress="onClickWallpaper_"> <div class="photo-images-border"></div> - <img src$="[[image_.url.url]]" - alt$="[[getImageAltDescription_(image_)]]"> + <img alt$="[[getImageAltDescription_(image_)]]" + src$="[[getWallpaperSrc_(image_)]]"> </div> </template> <template is="dom-if" if="[[isPolicyControlled_(image_)]]"> <div id="imageContainer" class="photo-images-container"> <div class="photo-images-border"></div> - <img src$="[[image_.url.url]]" + <img alt$="[[getImageAltDescription_(image_)]]" aria-description="$i18n{managedSetting}" - alt$="[[getImageAltDescription_(image_)]]"> + src$="[[getWallpaperSrc_(image_)]]"> </div> </template> </template>
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.ts index 5fa4c3e..f77a5f3 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.ts
@@ -21,7 +21,7 @@ import {WithPersonalizationStore} from '../personalization_store.js'; import {isNonEmptyArray} from '../utils.js'; -import {getLocalStorageAttribution} from './utils.js'; +import {getLocalStorageAttribution, getWallpaperSrc} from './utils.js'; import {WallpaperObserver} from './wallpaper_observer.js'; import {getTemplate} from './wallpaper_preview_element.html.js'; @@ -67,6 +67,10 @@ PersonalizationRouter.instance().goToRoute(Paths.COLLECTIONS); } + private getWallpaperSrc_(image: CurrentWallpaper|null): string|null { + return getWallpaperSrc(image); + } + private getImageAltDescription_(image: CurrentWallpaper|null): string { if (!image) { return `${this.i18n('currentlySet')} ${
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html index c51805e..e5ac3eff 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html
@@ -72,7 +72,9 @@ <template is="dom-if" if="[[showImage_]]"> <div id="imageContainer" class="preview-image-container"> <div class="preview-image-border"></div> - <img class="preview-image" src$="[[image_.url.url]]" aria-hidden="true"> + <img aria-hidden="true" + class="preview-image" + src$="[[getWallpaperSrc_(image_)]]"> </div> <h2 id="textContainer" class="preview-text-container" aria-live="polite" aria-label$="[[getAriaLabel_(image_, dailyRefreshState_)]]"> <span id="currentlySet" aria-hidden="true">$i18n{currentlySet}</span>
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts index b5c52a4..b05cc8e 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts
@@ -21,7 +21,7 @@ import {WithPersonalizationStore} from '../personalization_store.js'; import {isNonEmptyArray} from '../utils.js'; -import {getLocalStorageAttribution, getWallpaperLayoutEnum} from './utils.js'; +import {getLocalStorageAttribution, getWallpaperLayoutEnum, getWallpaperSrc} from './utils.js'; import {getDailyRefreshState, selectGooglePhotosAlbum, setCurrentWallpaperLayout, setDailyRefreshCollectionId, updateDailyRefreshWallpaper} from './wallpaper_controller.js'; import {getWallpaperProvider} from './wallpaper_interface_provider.js'; import {WallpaperObserver} from './wallpaper_observer.js'; @@ -252,6 +252,10 @@ collectionId! || googlePhotosAlbumId!, dailyRefreshState); } + private getWallpaperSrc_(image: CurrentWallpaper|null): string|null { + return getWallpaperSrc(image); + } + private getCenterAriaPressed_(image: CurrentWallpaper): string { return (!!image && image.layout === WallpaperLayout.kCenter).toString(); }
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.cc b/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.cc index 38cd583..f3b26e0c 100644 --- a/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.cc +++ b/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.cc
@@ -12,6 +12,8 @@ #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" #include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h" #include "base/check_op.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_refptr.h" #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -35,6 +37,11 @@ wallpaper_receiver_.Bind(std::move(receiver)); } +void FakePersonalizationAppWallpaperProvider::GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) { + std::move(callback).Run(base::MakeRefCounted<base::RefCountedBytes>()); +} + bool FakePersonalizationAppWallpaperProvider::IsEligibleForGooglePhotos() { return true; }
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.h b/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.h index 911fad6..11d658783 100644 --- a/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.h +++ b/ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.h
@@ -12,6 +12,7 @@ #include "ash/public/cpp/wallpaper/wallpaper_types.h" #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" #include "base/unguessable_token.h" +#include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -37,6 +38,10 @@ void BindInterface( mojo::PendingReceiver<ash::personalization_app::mojom::WallpaperProvider> receiver) override; + + void GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) override; + bool IsEligibleForGooglePhotos() override; // ash::personalization_app::mojom::WallpaperProvider:
diff --git a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc index fcc9808..e8ebe1e 100644 --- a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc +++ b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
@@ -12,6 +12,7 @@ #include "ash/webui/personalization_app/personalization_app_url_constants.h" #include "ash/webui/personalization_app/personalization_app_user_provider.h" #include "ash/webui/personalization_app/personalization_app_wallpaper_provider.h" +#include "base/memory/scoped_refptr.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "testing/gmock/include/gmock/gmock.h" @@ -118,6 +119,10 @@ ash::personalization_app::mojom::WallpaperProvider> receiver), (override)); bool IsEligibleForGooglePhotos() override { return true; } + void GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) override { + std::move(callback).Run(base::MakeRefCounted<base::RefCountedBytes>()); + } MOCK_METHOD(void, MakeTransparent, (), (override)); MOCK_METHOD(void, MakeOpaque, (), (override)); MOCK_METHOD(void,
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index 71a26a0a..3b50636e 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -1991,7 +1991,7 @@ void DesksController::ReportClosedWindowsCountPerSourceHistogram( DesksCreationRemovalSource source, int windows_closed) const { - std::string desk_removal_source_histogram; + const char* desk_removal_source_histogram = nullptr; switch (source) { case DesksCreationRemovalSource::kButton: desk_removal_source_histogram = kNumberOfWindowsClosedByButton; @@ -2011,9 +2011,9 @@ case DesksCreationRemovalSource::kDesksRestore: case DesksCreationRemovalSource::kEnsureDefaultDesk: break; - NOTREACHED(); } - base::UmaHistogramCounts100(desk_removal_source_histogram, windows_closed); + if (desk_removal_source_histogram) + base::UmaHistogramCounts100(desk_removal_source_histogram, windows_closed); } } // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn index a56c5fc8..d2df03e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -4486,7 +4486,6 @@ "test/android/javatests/src/org/chromium/base/test/util/Feature.java", "test/android/javatests/src/org/chromium/base/test/util/Features.java", "test/android/javatests/src/org/chromium/base/test/util/FeaturesBase.java", - "test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java", "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java", "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferencesContext.java", "test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java",
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java deleted file mode 100644 index 73d88328..0000000 --- a/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.test.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @deprecated Use "@DisabledTest" instead which has identical behavior. - * - * This annotation is for flaky tests. - * <p> - * Tests with this annotation will not be run on any of the normal bots. - * Please note that they might eventually run on a special bot. - */ -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Deprecated -public @interface FlakyTest { - String message() default ""; -}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java index 95d9f46d..774ce60 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
@@ -110,8 +110,31 @@ @LargeTest @Feature("RenderTest") @DisableFeatures({ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE}) + @EnableFeatures({ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES}) @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) - public void testSyncErrorCardForAuthErrorWithTitleFeatureDisabled(boolean nightModeEnabled) + public void testSyncErrorCardForAuthErrorWithTitleFeatureDisabledUpmEnabled( + boolean nightModeEnabled) throws Exception { + mFakeSyncServiceImpl.setAuthError(GoogleServiceAuthError.State.INVALID_GAIA_CREDENTIALS); + mSigninTestRule.addTestAccountThenSigninAndEnableSync(mFakeSyncServiceImpl); + TestThreadUtils.runOnUiThreadBlocking( + () + -> Assert.assertEquals("AUTH_ERROR SyncError should be set", + SyncSettingsUtils.SyncError.AUTH_ERROR, + SyncSettingsUtils.getSyncError())); + + mSettingsActivityTestRule.startSettingsActivity(); + mRenderTestRule.render( + getPersonalizedSyncPromoView(), "sync_error_card_auth_error_with_upm"); + } + + @Test + @LargeTest + @Feature("RenderTest") + @DisableFeatures({ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE, + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES}) + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + public void + testSyncErrorCardForAuthErrorWithTitleFeatureDisabledUpmDisabled(boolean nightModeEnabled) throws Exception { mFakeSyncServiceImpl.setAuthError(GoogleServiceAuthError.State.INVALID_GAIA_CREDENTIALS); mSigninTestRule.addTestAccountThenSigninAndEnableSync(mFakeSyncServiceImpl); @@ -128,9 +151,11 @@ @Test @LargeTest @Feature("RenderTest") - @EnableFeatures({ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE}) + @EnableFeatures({ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE, + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES}) @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) - public void testSyncErrorCardForAuthErrorWithTitleFeatureEnabled(boolean nightModeEnabled) + public void + testSyncErrorCardForAuthErrorWithTitleFeatureEnabledUpmEnabled(boolean nightModeEnabled) throws Exception { mFakeSyncServiceImpl.setAuthError(GoogleServiceAuthError.State.INVALID_GAIA_CREDENTIALS); mSigninTestRule.addTestAccountThenSigninAndEnableSync(mFakeSyncServiceImpl); @@ -141,6 +166,27 @@ SyncSettingsUtils.getSyncError())); mSettingsActivityTestRule.startSettingsActivity(); + mRenderTestRule.render(getPersonalizedSyncPromoView(), + "sync_error_card_auth_error_with_new_title_and_upm"); + } + + @Test + @LargeTest + @Feature("RenderTest") + @EnableFeatures({ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE}) + @DisableFeatures({ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ERROR_MESSAGES}) + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + public void testSyncErrorCardForAuthErrorWithTitleFeatureEnabledUpmDisabled( + boolean nightModeEnabled) throws Exception { + mFakeSyncServiceImpl.setAuthError(GoogleServiceAuthError.State.INVALID_GAIA_CREDENTIALS); + mSigninTestRule.addTestAccountThenSigninAndEnableSync(mFakeSyncServiceImpl); + TestThreadUtils.runOnUiThreadBlocking( + () + -> Assert.assertEquals("AUTH_ERROR SyncError should be set", + SyncSettingsUtils.SyncError.AUTH_ERROR, + SyncSettingsUtils.getSyncError())); + + mSettingsActivityTestRule.startSettingsActivity(); mRenderTestRule.render( getPersonalizedSyncPromoView(), "sync_error_card_auth_error_with_new_title"); }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 4761e2d..9326ff0 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -6925,6 +6925,13 @@ "//chrome/services/printing/public/mojom", "//components/crash/core/common", ] + if (is_win) { + sources += [ + "printing/printer_xml_parser_impl.cc", + "printing/printer_xml_parser_impl.h", + ] + deps += [ "//printing:printing_base" ] + } } if (is_win || enable_print_preview) { deps += [ "//chrome/services/printing/public/mojom" ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3d061b0..708b17e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3352,10 +3352,10 @@ #endif // BUILDFLAG(IS_ANDROID) const FeatureEntry::FeatureParam kUnthrottledNestedTimeout_NestingLevel = { - "nesting", "100"}; + "nesting", "15"}; const FeatureEntry::FeatureVariation kUnthrottledNestedTimeout_Variations[] = { - {"100", &kUnthrottledNestedTimeout_NestingLevel, 1, nullptr}, + {"15", &kUnthrottledNestedTimeout_NestingLevel, 1, nullptr}, }; constexpr FeatureEntry::FeatureParam kLensStandaloneWithSidePanel[] = { @@ -5016,6 +5016,9 @@ {"web-feed-sort", flag_descriptions::kWebFeedSortName, flag_descriptions::kWebFeedSortDescription, kOsAndroid, FEATURE_VALUE_TYPE(feed::kWebFeedSort)}, + {"feed-header-stick-to-top", flag_descriptions::kFeedHeaderStickToTopName, + flag_descriptions::kFeedHeaderStickToTopDescription, kOsAndroid, + FEATURE_VALUE_TYPE(feed::kFeedHeaderStickToTop)}, {"xsurface-metrics-reporting", flag_descriptions::kXsurfaceMetricsReportingName, flag_descriptions::kXsurfaceMetricsReportingDescription, kOsAndroid, @@ -8514,6 +8517,11 @@ kLensInstructionChipVariations, "LensInstructionChipImprovements")}, + {"enable-lens-region-search-static-page", + flag_descriptions::kLensRegionSearchStaticPageName, + flag_descriptions::kLensRegionSearchStaticPageDescription, kOsDesktop, + FEATURE_VALUE_TYPE(lens::features::kLensRegionSearchStaticPage)}, + {"enable-region-search-on-pdf-viewer", flag_descriptions::kEnableRegionSearchOnPdfViewerName, flag_descriptions::kEnableRegionSearchOnPdfViewerDescription, kOsDesktop, @@ -9202,7 +9210,7 @@ flag_descriptions::kIsolatedSandboxedIframesName, flag_descriptions::kIsolatedSandboxedIframesDescription, kOsDesktop, FEATURE_WITH_PARAMS_VALUE_TYPE( - features::kIsolateSandboxedIframes, + blink::features::kIsolateSandboxedIframes, kIsolateSandboxedIframesGroupingVariations, "IsolateSandboxedIframes" /* trial name */)}, #endif
diff --git a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc index 940fb42..72b6edc5 100644 --- a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc +++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
@@ -267,9 +267,14 @@ ::features::IsExperimentalAccessibilityDictationWithPumpkinEnabled(); break; case accessibility_private::AccessibilityFeature:: + ACCESSIBILITY_FEATURE_DICTATIONMORECOMMANDS: + enabled = + ::features::IsExperimentalAccessibilityDictationMoreCommandsEnabled(); + break; + case accessibility_private:: ACCESSIBILITY_FEATURE_SELECTTOSPEAKVOICESWITCHING: - enabled = ::features:: - IsExperimentalAccessibilitySelectToSpeakVoiceSwitchingEnabled(); + enabled = + ::features::IsExperimentalAccessibilitySelectToSpeakVoiceSwitchingEnabled(); break; case accessibility_private::AccessibilityFeature:: ACCESSIBILITY_FEATURE_NONE:
diff --git a/chrome/browser/android/chrome_backup_agent.cc b/chrome/browser/android/chrome_backup_agent.cc index a77391d..8c845a2b 100644 --- a/chrome/browser/android/chrome_backup_agent.cc +++ b/chrome/browser/android/chrome_backup_agent.cc
@@ -20,7 +20,7 @@ // TODO(crbug.com/1305213): The data type toggles shouldn't be individually // listed here. -static_assert(42 == syncer::GetNumModelTypes(), +static_assert(43 == syncer::GetNumModelTypes(), "If the new type has a corresponding pref, add it here"); const char* backed_up_preferences_[] = { autofill::prefs::kAutofillWalletImportEnabled,
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc index 70310bf..cee6d93 100644 --- a/chrome/browser/ash/accessibility/dictation_browsertest.cc +++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -954,6 +954,12 @@ DictationCommandsTest(const DictationCommandsTest&) = delete; DictationCommandsTest& operator=(const DictationCommandsTest&) = delete; + void SetUpCommandLine(base::CommandLine* command_line) override { + DictationTest::SetUpCommandLine(command_line); + scoped_feature_list_.InitAndEnableFeature( + ::features::kExperimentalAccessibilityDictationMoreCommands); + } + void SetUpOnMainThread() override { DictationTest::SetUpOnMainThread(); ToggleDictationWithKeystroke(); @@ -972,6 +978,9 @@ ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &text); return base::UTF16ToUTF8(text); } + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; INSTANTIATE_TEST_SUITE_P( @@ -1153,6 +1162,22 @@ "This is a t."); } +IN_PROC_BROWSER_TEST_P(DictationCommandsTest, DeleteAllTextSimple) { + SendFinalResultAndWaitForTextAreaValue("Hello, world.", "Hello, world."); + SendFinalResultAndWaitForTextAreaValue("delete all", ""); +} + +IN_PROC_BROWSER_TEST_P(DictationCommandsTest, DeleteAllTextMultiLineString) { + std::string text = " Hello, world. \n Hello, world. \n Hello, world. \n"; + SendFinalResultAndWaitForTextAreaValue(text, text); + SendFinalResultAndWaitForTextAreaValue("delete all", ""); +} + +// TODO(crbug.com/1362842) Add a test where +// you disable the MoreCommands Feature Flag +// and ensure that you can't run the Dictation +// Commands under that feature flag + IN_PROC_BROWSER_TEST_P(DictationCommandsTest, DeletePrevSentSimple) { SendFinalResultAndWaitForTextAreaValue("Hello, world.", "Hello, world."); SendFinalResultAndWaitForTextAreaValue("delete the previous sentence", "");
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc index 2616970..7e67100 100644 --- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc +++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
@@ -8,8 +8,6 @@ #include <utility> #include "ash/constants/ash_switches.h" -#include "ash/metrics/login_unlock_throughput_recorder.h" -#include "ash/shell.h" #include "base/bind.h" #include "base/command_line.h" #include "base/metrics/histogram_functions.h" @@ -451,10 +449,6 @@ return; } - LoginUnlockThroughputRecorder* throughput_recorder = - Shell::HasInstance() ? Shell::Get()->login_unlock_throughput_recorder() - : nullptr; - int arc_app_count = 0; int other_app_count = 0; for (const auto& it : restore_data()->app_id_to_launch_list()) { @@ -466,12 +460,6 @@ continue; } - if (throughput_recorder) { - for (const auto& window : it.second) { - throughput_recorder->AddScheduledRestoreWindow( - window.first, it.first, LoginUnlockThroughputRecorder::kBrowser); - } - } ++other_app_count; } VLOG(1) << "There is restore data: Browser("
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util.h b/chrome/browser/ash/crosapi/browser_data_migrator_util.h index fed99c7..ef6b1c8 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_util.h +++ b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
@@ -302,7 +302,7 @@ }; // List of data types in Sync Data that have to stay in Ash and Ash only. -static_assert(42 == syncer::GetNumModelTypes(), +static_assert(43 == syncer::GetNumModelTypes(), "If adding a new sync data type, update the lists below if" " you want to keep the new data type in Ash only."); constexpr syncer::ModelType kAshOnlySyncDataTypes[] = {
diff --git a/chrome/browser/ash/net/network_diagnostics/network_diagnostics_util_unittest.cc b/chrome/browser/ash/net/network_diagnostics/network_diagnostics_util_unittest.cc index d2691e0..137d318 100644 --- a/chrome/browser/ash/net/network_diagnostics/network_diagnostics_util_unittest.cc +++ b/chrome/browser/ash/net/network_diagnostics/network_diagnostics_util_unittest.cc
@@ -7,6 +7,7 @@ #include <string> #include <vector> +#include "base/ranges/algorithm.h" #include "base/strings/string_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,8 +38,7 @@ util::GetRandomHosts(num_hosts, prefix_length); // Ensure |random_hosts| has unique entries. std::sort(random_hosts.begin(), random_hosts.end()); - EXPECT_TRUE(std::adjacent_find(random_hosts.begin(), random_hosts.end()) == - random_hosts.end()); + EXPECT_TRUE(base::ranges::adjacent_find(random_hosts) == random_hosts.end()); } TEST(NetworkDiagnosticsUtilTest, TestGetRandomHostsWithScheme) { @@ -48,8 +48,7 @@ util::GetRandomHostsWithScheme(num_hosts, prefix_length, kHttpsScheme); // Ensure |random_hosts| has unique entries. std::sort(random_hosts.begin(), random_hosts.end()); - EXPECT_TRUE(std::adjacent_find(random_hosts.begin(), random_hosts.end()) == - random_hosts.end()); + EXPECT_TRUE(base::ranges::adjacent_find(random_hosts) == random_hosts.end()); // Ensure hosts in |random_hosts| start with |kHttpsScheme|. for (const auto& host : random_hosts) { EXPECT_TRUE(host.rfind(kHttpsScheme, 0) == 0); @@ -65,8 +64,7 @@ kHttpsScheme); // Ensure |random_hosts| has unique entries. std::sort(random_hosts.begin(), random_hosts.end()); - EXPECT_TRUE(std::adjacent_find(random_hosts.begin(), random_hosts.end()) == - random_hosts.end()); + EXPECT_TRUE(base::ranges::adjacent_find(random_hosts) == random_hosts.end()); // Ensure: // (1) hosts in |random_hosts| start with |kHttpsScheme|. // (2) hosts in |random_hosts| end with |kGenerate204Path|.
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc index 80b0b1b..0080e20 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.cc
@@ -26,9 +26,12 @@ #include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h" #include "base/bind.h" #include "base/files/file_path.h" +#include "base/memory/ref_counted_memory.h" #include "base/notreached.h" #include "base/rand_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/unguessable_token.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/wallpaper/wallpaper_enumerator.h" @@ -47,6 +50,7 @@ #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -59,6 +63,7 @@ #include "ui/aura/window.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "url/gurl.h" @@ -72,7 +77,7 @@ using ash::personalization_app::GetUser; constexpr int kLocalImageThumbnailSizeDip = 256; -constexpr int kCurrentWallpaperThumbnailSizeDip = 512; +constexpr int kCurrentWallpaperThumbnailSizeDip = 1024; const gfx::ImageSkia GetResizedImage(const gfx::ImageSkia& image) { // Resize the image maintaining our aspect ratio. @@ -96,6 +101,19 @@ : base::UnguessableToken::Create().ToString(); } +scoped_refptr<base::RefCountedMemory> ResizeAndEncodeWallpaperImage() { + auto* wallpaper_controller = ash::WallpaperController::Get(); + // Get wallpaper image on worker thread for performance reasons. This avoids + // having to call |image.MakeThreadSafe| in a performance critical path while + // changing wallpaper, and instead calling it in the thread pool. + auto image = wallpaper_controller->GetWallpaperImage(); + image.MakeThreadSafe(); + auto resized = GetResizedImage(image); + scoped_refptr<base::RefCountedMemory> png_bytes = + gfx::Image(resized).As1xPNGBytes(); + return png_bytes; +} + } // namespace PersonalizationAppWallpaperProviderImpl:: @@ -125,6 +143,19 @@ wallpaper_receiver_.Bind(std::move(receiver)); } +void PersonalizationAppWallpaperProviderImpl::GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) { + // |GetWallpaperAsPngBytes| is called in the hot path of switching wallpaper + // on the UI thread right after user makes a new selection. Make sure to do + // resizing and encoding on a task runner to avoid locking up the UI as the + // user's wallpaper is being set. + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, + {base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&ResizeAndEncodeWallpaperImage), std::move(callback)); +} + bool PersonalizationAppWallpaperProviderImpl::IsEligibleForGooglePhotos() { return GetUser(profile_)->HasGaiaAccount(); } @@ -353,7 +384,6 @@ wallpaper_attribution_info_fetcher_.reset(); attribution_weak_ptr_factory_.InvalidateWeakPtrs(); - auto* controller = WallpaperController::Get(); auto* client = WallpaperControllerClientImpl::Get(); absl::optional<ash::WallpaperInfo> info = @@ -365,12 +395,6 @@ return; } - const gfx::ImageSkia& current_wallpaper = controller->GetWallpaperImage(); - const gfx::ImageSkia& current_wallpaper_resized = - GetResizedImage(current_wallpaper); - const GURL& wallpaper_data_url = - GURL(webui::GetBitmapDataUrl(*current_wallpaper_resized.bitmap())); - switch (info->type) { case ash::WallpaperType::kDaily: case ash::WallpaperType::kOnline: { @@ -380,15 +404,13 @@ // look up all collections and match URL. FetchCollections(base::BindOnce( &PersonalizationAppWallpaperProviderImpl::FindAttribution, - attribution_weak_ptr_factory_.GetWeakPtr(), *info, - wallpaper_data_url)); + attribution_weak_ptr_factory_.GetWeakPtr(), *info)); return; } backdrop::Collection collection; collection.set_collection_id(info->collection_id); - FindAttribution(*info, wallpaper_data_url, - std::vector<backdrop::Collection>{collection}); + FindAttribution(*info, std::vector<backdrop::Collection>{collection}); return; } case ash::WallpaperType::kCustomized: { @@ -405,8 +427,7 @@ NotifyWallpaperChanged( ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, std::move(attribution), info->layout, - info->type, key)); + std::move(attribution), info->layout, info->type, key)); return; } @@ -416,8 +437,7 @@ GetAccountId(profile_), info->location, base::BindOnce(&PersonalizationAppWallpaperProviderImpl:: SendGooglePhotosAttribution, - weak_ptr_factory_.GetWeakPtr(), *info, - wallpaper_data_url)); + weak_ptr_factory_.GetWeakPtr(), *info)); return; case ash::WallpaperType::kDefault: case ash::WallpaperType::kDevice: @@ -426,8 +446,8 @@ case ash::WallpaperType::kThirdParty: NotifyWallpaperChanged( ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, /*attribution=*/std::vector<std::string>(), - info->layout, info->type, + /*attribution=*/std::vector<std::string>(), info->layout, + info->type, /*key=*/base::UnguessableToken::Create().ToString())); return; case ash::WallpaperType::kCount: @@ -789,14 +809,13 @@ void PersonalizationAppWallpaperProviderImpl::FindAttribution( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, const absl::optional<std::vector<backdrop::Collection>>& collections) { DCHECK(!wallpaper_attribution_info_fetcher_); if (!collections.has_value() || collections->empty()) { NotifyWallpaperChanged( ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, /*attribution=*/std::vector<std::string>(), - info.layout, info.type, GetOnlineWallpaperKey(info))); + /*attribution=*/std::vector<std::string>(), info.layout, info.type, + GetOnlineWallpaperKey(info))); return; } @@ -808,13 +827,12 @@ wallpaper_attribution_info_fetcher_->Start(base::BindOnce( &PersonalizationAppWallpaperProviderImpl::FindAttributionInCollection, - attribution_weak_ptr_factory_.GetWeakPtr(), info, wallpaper_data_url, - current_index, collections)); + attribution_weak_ptr_factory_.GetWeakPtr(), info, current_index, + collections)); } void PersonalizationAppWallpaperProviderImpl::FindAttributionInCollection( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, std::size_t current_index, const absl::optional<std::vector<backdrop::Collection>>& collections, bool success, @@ -843,7 +861,7 @@ attributions.push_back(attr.text()); NotifyWallpaperChanged( ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, attributions, info.layout, info.type, + attributions, info.layout, info.type, /*key=*/base::NumberToString(backend_image->asset_id()))); wallpaper_attribution_info_fetcher_.reset(); return; @@ -854,8 +872,8 @@ if (current_index >= collections->size()) { NotifyWallpaperChanged( ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, /*attribution=*/std::vector<std::string>(), - info.layout, info.type, GetOnlineWallpaperKey(info))); + /*attribution=*/std::vector<std::string>(), info.layout, info.type, + GetOnlineWallpaperKey(info))); wallpaper_attribution_info_fetcher_.reset(); return; } @@ -864,8 +882,8 @@ collections->at(current_index).collection_id()); fetcher->Start(base::BindOnce( &PersonalizationAppWallpaperProviderImpl::FindAttributionInCollection, - attribution_weak_ptr_factory_.GetWeakPtr(), info, wallpaper_data_url, - current_index, collections)); + attribution_weak_ptr_factory_.GetWeakPtr(), info, current_index, + collections)); // resetting the previous fetcher last because the current method is bound // to a callback owned by the previous fetcher. wallpaper_attribution_info_fetcher_ = std::move(fetcher); @@ -873,7 +891,6 @@ void PersonalizationAppWallpaperProviderImpl::SendGooglePhotosAttribution( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, mojo::StructPtr<ash::personalization_app::mojom::GooglePhotosPhoto> photo, bool success) { // If the fetch for |photo| succeeded but |photo| does not exist, that means @@ -900,7 +917,7 @@ // NOTE: Old clients may not support |dedup_key| when setting Google Photos // wallpaper, so use |location| in such cases for backwards compatibility. NotifyWallpaperChanged(ash::personalization_app::mojom::CurrentWallpaper::New( - wallpaper_data_url, attribution, info.layout, info.type, + attribution, info.layout, info.type, /*key=*/info.dedup_key.value_or(info.location))); }
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h index e1324f63..689d6566 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h
@@ -23,6 +23,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "components/account_id/account_id.h" +#include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -77,6 +78,9 @@ mojo::PendingReceiver<ash::personalization_app::mojom::WallpaperProvider> receiver) override; + void GetWallpaperAsPngBytes( + content::WebUIDataSource::GotDataCallback callback) override; + // Not all users can see google photos. Requires a gaia account to be able to // fetch photos. bool IsEligibleForGooglePhotos() override; @@ -232,12 +236,10 @@ void FindAttribution( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, const absl::optional<std::vector<backdrop::Collection>>& collections); void FindAttributionInCollection( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, std::size_t current_index, const absl::optional<std::vector<backdrop::Collection>>& collections, bool success, @@ -246,7 +248,6 @@ void SendGooglePhotosAttribution( const ash::WallpaperInfo& info, - const GURL& wallpaper_data_url, mojo::StructPtr<ash::personalization_app::mojom::GooglePhotosPhoto> photo, bool success);
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc index cdf4efd..8e544e7 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
@@ -19,6 +19,9 @@ #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" #include "base/callback_helpers.h" #include "base/json/json_reader.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_refptr.h" +#include "base/run_loop.h" #include "base/test/bind.h" #include "base/values.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" @@ -55,6 +58,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/gfx/codec/png_codec.h" namespace ash::personalization_app { @@ -413,7 +417,6 @@ TEST_P(PersonalizationAppWallpaperProviderImplTest, ObserveWallpaperFiresWhenBound) { - // This will create the data url referenced below in expectation. test_wallpaper_controller()->ShowWallpaperImage( CreateSolidImageSkia(/*width=*/1, /*height=*/1, SK_ColorBLACK)); @@ -443,10 +446,6 @@ EXPECT_EQ(ash::WallpaperType::kOnline, current->type); EXPECT_EQ(ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, current->layout); - // Data url of a solid black image scaled up to 512x512. - EXPECT_EQ(webui::GetBitmapDataUrl( - *CreateSolidImageSkia(512, 512, SK_ColorBLACK).bitmap()), - current->url); } TEST_P(PersonalizationAppWallpaperProviderImplTest, SetCurrentWallpaperLayout) { @@ -485,6 +484,33 @@ ResetWallpaperProvider(); } +TEST_P(PersonalizationAppWallpaperProviderImplTest, GetWallpaperAsPngBytes) { + test_wallpaper_controller()->ShowWallpaperImage( + CreateSolidImageSkia(/*width=*/1, /*height=*/1, SK_ColorRED)); + + scoped_refptr<base::RefCountedMemory> png_bytes; + + base::RunLoop loop; + delegate()->GetWallpaperAsPngBytes(base::BindLambdaForTesting( + [quit = loop.QuitClosure(), + &png_bytes](scoped_refptr<base::RefCountedMemory> bytes) { + bytes.swap(png_bytes); + std::move(quit).Run(); + })); + loop.Run(); + + // Png bytes of a solid black image scaled up to 1024x1024. + scoped_refptr<base::RefCountedBytes> expected_png_bytes = + base::MakeRefCounted<base::RefCountedBytes>(); + gfx::PNGCodec::EncodeBGRASkBitmap( + CreateSolidImageSkia(1024, 1024, SK_ColorRED) + .GetRepresentation(/*scale=*/1) + .GetBitmap(), + /*discard_transparency=*/false, &expected_png_bytes->data()); + + EXPECT_TRUE(expected_png_bytes->Equals(png_bytes)); +} + class PersonalizationAppWallpaperProviderImplGooglePhotosTest : public PersonalizationAppWallpaperProviderImplTest { protected:
diff --git a/chrome/browser/creator/android/BUILD.gn b/chrome/browser/creator/android/BUILD.gn index c8afce0..cc84bdb0 100644 --- a/chrome/browser/creator/android/BUILD.gn +++ b/chrome/browser/creator/android/BUILD.gn
@@ -12,10 +12,16 @@ deps = [ ":creator_java_resources", "//base:base_java", + "//chrome/browser/feed/android:feed_java_resources", + "//chrome/browser/feed/android:java", + "//chrome/browser/xsurface:java", + "//components/browser_ui/styles/android:java", + "//components/browser_ui/widget/android:java", "//content/public/android:content_main_dex_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_appcompat_appcompat_java", "//third_party/androidx:androidx_appcompat_appcompat_resources_java", + "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//ui/android:ui_no_recycler_view_java", "//url:gurl_java", ] @@ -27,6 +33,8 @@ sources = [ "java/res/drawable/profile_background.xml", "java/res/layout/creator_activity.xml", + "java/res/values/dimens.xml", + "java/res/values/ids.xml", "java/res/values/styles.xml", ] deps = [
diff --git a/chrome/browser/creator/android/java/res/values/dimens.xml b/chrome/browser/creator/android/java/res/values/dimens.xml new file mode 100644 index 0000000..c94fbaf --- /dev/null +++ b/chrome/browser/creator/android/java/res/values/dimens.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2022 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Content Previews dimensions. --> + <dimen name="content_previews_padding">16dp</dimen> +</resources>
diff --git a/chrome/browser/creator/android/java/res/values/ids.xml b/chrome/browser/creator/android/java/res/values/ids.xml new file mode 100644 index 0000000..d776e90 --- /dev/null +++ b/chrome/browser/creator/android/java/res/values/ids.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- +Copyright 2022 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources> + <!-- Id to use for Content Previews RecyclerView. --> + <item type="id" name="creator_feed_stream_recycler_view" /> +</resources>
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java index 291441da..f9f158f 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
@@ -6,27 +6,95 @@ import android.app.Activity; import android.view.LayoutInflater; -import android.view.View; +import android.view.ViewGroup; + +import androidx.recyclerview.widget.RecyclerView; + +import org.chromium.chrome.browser.feed.FeedSurfaceScopeDependencyProvider; +import org.chromium.chrome.browser.feed.FeedSurfaceTracker; +import org.chromium.chrome.browser.feed.NativeViewListRenderer; +import org.chromium.chrome.browser.feed.NtpListContentManager; +import org.chromium.chrome.browser.xsurface.HybridListRenderer; +import org.chromium.chrome.browser.xsurface.ProcessScope; +import org.chromium.chrome.browser.xsurface.SurfaceScope; +import org.chromium.components.browser_ui.styles.SemanticColorUtils; + +import java.util.ArrayList; +import java.util.List; /** * Sets up the Coordinator for Cormorant Creator surface. It is based on the doc at * https://chromium.googlesource.com/chromium/src/+/HEAD/docs/ui/android/mvc_simple_list_tutorial.md */ public class CreatorCoordinator { + private static final String NATIVE_CONTENT_ID = "0"; + private CreatorMediator mMediator; private Activity mActivity; - private final View mView; + private NtpListContentManager mContentManager; + private RecyclerView mRecyclerView; + private HybridListRenderer mHybridListRenderer; + private SurfaceScope mSurfaceScope; + private FeedSurfaceScopeDependencyProvider mDependencyProvider; + + private final ViewGroup mViewGroup; public CreatorCoordinator(Activity activity) { mActivity = activity; + mRecyclerView = setUpView(); + List<NtpListContentManager.FeedContent> contentPreviewsList = new ArrayList<>(); + + // Add empty state to Content Manager + contentPreviewsList.add(new NtpListContentManager.NativeViewContent( + getLateralPaddingsPx(), NATIVE_CONTENT_ID, R.layout.no_content_v2)); + mContentManager.addContents(0, contentPreviewsList); // Inflate the XML. - mView = LayoutInflater.from(mActivity).inflate(R.layout.creator_activity, null); + mViewGroup = + (ViewGroup) LayoutInflater.from(mActivity).inflate(R.layout.creator_activity, null); + mViewGroup.addView(mRecyclerView); mMediator = new CreatorMediator(mActivity); } - public View getView() { - return mView; + public ViewGroup getView() { + return mViewGroup; + } + + private RecyclerView setUpView() { + // TODO(crbug.com/1374744): Refactor NTP naming out of the general Feed code. + mContentManager = new NtpListContentManager(); + ProcessScope processScope = FeedSurfaceTracker.getInstance().getXSurfaceProcessScope(); + + if (processScope != null) { + mDependencyProvider = + new FeedSurfaceScopeDependencyProvider(mActivity, mActivity, false); + mSurfaceScope = processScope.obtainSurfaceScope(mDependencyProvider); + } else { + mDependencyProvider = null; + mSurfaceScope = null; + } + + if (mSurfaceScope != null) { + mHybridListRenderer = mSurfaceScope.provideListRenderer(); + } else { + mHybridListRenderer = new NativeViewListRenderer(mActivity); + } + + RecyclerView view; + if (mHybridListRenderer != null) { + view = (RecyclerView) mHybridListRenderer.bind( + mContentManager, /* mViewportView */ null, /* useStaggeredLayout */ false); + view.setId(R.id.creator_feed_stream_recycler_view); + view.setClipToPadding(false); + view.setBackgroundColor(SemanticColorUtils.getDefaultBgColor(mActivity)); + } else { + view = null; + } + return view; + } + + private int getLateralPaddingsPx() { + return mActivity.getResources().getDimensionPixelSize(R.dimen.content_previews_padding); } }
diff --git a/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.cc b/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.cc index b5c8450..e85586e1 100644 --- a/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.cc +++ b/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.cc
@@ -46,10 +46,3 @@ address, port); return extensions::SocketsManifestData::CheckRequest(extension, param); } - -bool ChromeDirectSocketsDelegate::ShouldSkipPostResolveChecks( - content::RenderFrameHost* frame) const { - // chrome.sockets.* doesn't have any restrictions on resolved addresses, so we - // may skip these checks. - return IsExtensionFrame(frame); -}
diff --git a/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.h b/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.h index 3fb4421f..174b2d8 100644 --- a/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.h +++ b/chrome/browser/direct_sockets/chrome_direct_sockets_delegate.h
@@ -15,7 +15,6 @@ const std::string& address, uint16_t port, blink::mojom::DirectSocketProtocolType protocol) const override; - bool ShouldSkipPostResolveChecks(content::RenderFrameHost*) const override; }; #endif // CHROME_BROWSER_DIRECT_SOCKETS_CHROME_DIRECT_SOCKETS_DELEGATE_H_
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceScopeDependencyProvider.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceScopeDependencyProvider.java index 564887d..c1f38013 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceScopeDependencyProvider.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceScopeDependencyProvider.java
@@ -20,7 +20,8 @@ /** * Provides activity, darkmode and logging context for a single surface. */ -class FeedSurfaceScopeDependencyProvider implements SurfaceScopeDependencyProvider, ScrollListener { +public class FeedSurfaceScopeDependencyProvider + implements SurfaceScopeDependencyProvider, ScrollListener { private static final String TAG = "Feed"; private final Activity mActivity; private final Context mActivityContext;
diff --git a/chrome/browser/first_party_sets/first_party_sets_policy_service.cc b/chrome/browser/first_party_sets/first_party_sets_policy_service.cc index d2404db..bce556a 100644 --- a/chrome/browser/first_party_sets/first_party_sets_policy_service.cc +++ b/chrome/browser/first_party_sets/first_party_sets_policy_service.cc
@@ -51,29 +51,17 @@ : browser_context_(browser_context) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(browser_context); - Init([](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - content::FirstPartySetsHandler::GetInstance()->GetContextConfigForPolicy( - GetOverridesPolicyForProfile(prefs), std::move(callback)); - }); + Init(); } FirstPartySetsPolicyService::~FirstPartySetsPolicyService() = default; -void FirstPartySetsPolicyService::InitForTesting( - base::FunctionRef< - void(PrefService*, - base::OnceCallback<void(net::FirstPartySetsContextConfig)>)> - get_config) { +void FirstPartySetsPolicyService::InitForTesting() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - Init(get_config); + Init(); } -void FirstPartySetsPolicyService::Init( - base::FunctionRef< - void(PrefService*, - base::OnceCallback<void(net::FirstPartySetsContextConfig)>)> - get_config) { +void FirstPartySetsPolicyService::Init() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!base::FeatureList::IsEnabled(features::kFirstPartySets)) { OnReadyToNotifyDelegates(net::FirstPartySetsContextConfig(), @@ -98,14 +86,15 @@ // dynamically refresh, and all the delegates for `context` will have the same // policy and thus the same config. PrefService* prefs = profile->GetPrefs(); - get_config(prefs, base::BindOnce( - &FirstPartySetsPolicyService::OnProfileConfigReady, - weak_factory_.GetWeakPtr(), - // We should only clear site data if First-Party Sets is - // enabled when the service is created, to allow users - // to play with the FPS enabled setting without - // affecting user experience during the browser session. - GetEnabledPolicyForProfile(prefs))); + content::FirstPartySetsHandler::GetInstance()->GetContextConfigForPolicy( + GetOverridesPolicyForProfile(prefs), + base::BindOnce(&FirstPartySetsPolicyService::OnProfileConfigReady, + weak_factory_.GetWeakPtr(), + // We should only clear site data if First-Party Sets is + // enabled when the service is created, to allow users + // to play with the FPS enabled setting without + // affecting user experience during the browser session. + GetEnabledPolicyForProfile(prefs))); } void FirstPartySetsPolicyService::AddRemoteAccessDelegate(
diff --git a/chrome/browser/first_party_sets/first_party_sets_policy_service.h b/chrome/browser/first_party_sets/first_party_sets_policy_service.h index 2d995457..8ab0653 100644 --- a/chrome/browser/first_party_sets/first_party_sets_policy_service.h +++ b/chrome/browser/first_party_sets/first_party_sets_policy_service.h
@@ -14,8 +14,6 @@ #include "mojo/public/cpp/bindings/remote_set.h" #include "services/network/public/mojom/first_party_sets_access_delegate.mojom.h" -class PrefService; - namespace content { class BrowserContext; } // namespace content @@ -76,16 +74,11 @@ // factory for FirstPartySetsPolicyService instances in tests, so every // instance calls into the prod logic to eagerly initialize itself. This // method allows tests to wait for that eager initialization to complete, then - // reset state, and re-run initialization via `InitForTesting`. + // reset state, and re-run initialization via `Init`. void WaitForFirstInitCompleteForTesting(base::OnceClosure callback); - // Testing-only method that allows injecting different logic to get the - // config. - void InitForTesting( - base::FunctionRef< - void(PrefService*, - base::OnceCallback<void(net::FirstPartySetsContextConfig)>)> - get_config); + // Exposes `Init` for use in tests. + void InitForTesting(); // Returns true when this instance has received the config thus has been fully // initialized. @@ -122,11 +115,8 @@ } private: - // Initialize this instance by getting the config via `get_config` if needed. - void Init(base::FunctionRef< - void(PrefService*, - base::OnceCallback<void(net::FirstPartySetsContextConfig)>)> - get_config); + // Initialize this instance by getting the config if needed. + void Init(); // Sets the `config_` member and provides it to all delegates via NotifyReady. void OnReadyToNotifyDelegates(net::FirstPartySetsContextConfig config,
diff --git a/chrome/browser/first_party_sets/first_party_sets_policy_service_unittest.cc b/chrome/browser/first_party_sets/first_party_sets_policy_service_unittest.cc index 81278fe..02cd1fe 100644 --- a/chrome/browser/first_party_sets/first_party_sets_policy_service_unittest.cc +++ b/chrome/browser/first_party_sets/first_party_sets_policy_service_unittest.cc
@@ -19,6 +19,7 @@ #include "net/base/schemeful_site.h" #include "net/first_party_sets/first_party_set_entry.h" #include "net/first_party_sets/first_party_sets_context_config.h" +#include "net/first_party_sets/global_first_party_sets.h" #include "services/network/public/mojom/first_party_sets_access_delegate.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -146,8 +147,11 @@ void SetUp() override { DefaultFirstPartySetsPolicyServiceTest::SetUp(); - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting({}); + content::FirstPartySetsHandler::GetInstance()->SetInstanceForTesting( + &first_party_sets_handler_); + first_party_sets_handler_.SetGlobalSets({}); + SetContextConfig(net::FirstPartySetsContextConfig()); + SetCacheFilter(net::FirstPartySetsCacheFilter()); profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); @@ -175,15 +179,30 @@ // tests if the factory has already created a service for the testing // profile being used. service_->ResetForTesting(); + content::FirstPartySetsHandler::GetInstance()->SetInstanceForTesting( + nullptr); profile_manager_->DeleteAllTestingProfiles(); profile_manager_.reset(); } + void SetContextConfig(net::FirstPartySetsContextConfig config) { + first_party_sets_handler_.SetContextConfig(std::move(config)); + } + + void SetCacheFilter(net::FirstPartySetsCacheFilter cache_filter) { + first_party_sets_handler_.SetCacheFilter(std::move(cache_filter)); + } + + void SetGlobalSets(net::GlobalFirstPartySets global_sets) { + first_party_sets_handler_.SetGlobalSets(std::move(global_sets)); + } + protected: Profile* profile() { return profile_; } FirstPartySetsPolicyService* service() { return service_; } private: + MockFirstPartySetsHandler first_party_sets_handler_; std::unique_ptr<TestingProfileManager> profile_manager_; Profile* profile_; base::test::ScopedFeatureList features_; @@ -196,15 +215,12 @@ } TEST_F(FirstPartySetsPolicyServiceTest, IsSiteInManagedSet_SiteNotInConfig) { - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig( - {{net::SchemefulSite(GURL("https://example.test")), - {net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://primary.test")), - net::SiteType::kAssociated, absl::nullopt)}}})); - }); + SetContextConfig(net::FirstPartySetsContextConfig( + {{net::SchemefulSite(GURL("https://example.test")), + {net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://primary.test")), + net::SiteType::kAssociated, absl::nullopt)}}})); + service()->InitForTesting(); EXPECT_FALSE(service()->IsSiteInManagedSet( net::SchemefulSite(GURL("https://not-example.test")))); @@ -215,13 +231,9 @@ IsSiteInManagedSet_SiteInConfig_AsDeletion) { net::SchemefulSite example_site = net::SchemefulSite(GURL("https://example.test")); - service()->InitForTesting( - [example_site]( - PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig( - {{example_site, {absl::nullopt}}})); - }); + SetContextConfig( + net::FirstPartySetsContextConfig({{example_site, {absl::nullopt}}})); + service()->InitForTesting(); EXPECT_FALSE(service()->IsSiteInManagedSet(example_site)); env().RunUntilIdle(); } @@ -230,16 +242,12 @@ IsSiteInManagedSet_SiteInConfig_AsModification) { net::SchemefulSite example_site = net::SchemefulSite(GURL("https://example.test")); - service()->InitForTesting( - [example_site]( - PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig( - {{example_site, - {net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://primary.test")), - net::SiteType::kAssociated, absl::nullopt)}}})); - }); + SetContextConfig(net::FirstPartySetsContextConfig( + {{example_site, + {net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://primary.test")), + net::SiteType::kAssociated, absl::nullopt)}}})); + service()->InitForTesting(); EXPECT_TRUE(service()->IsSiteInManagedSet(example_site)); env().RunUntilIdle(); } @@ -253,18 +261,13 @@ // Create Global First-Party Sets with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate1.test"} - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - net::GlobalFirstPartySets( - {{associate1_site, - {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, - 0)}}}, - {})); + SetGlobalSets(net::GlobalFirstPartySets( + {{associate1_site, + {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, + 0)}}}, + {})); // Simulate the profile set overrides are empty. - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); // Simulate First-Party Sets disabled by the feature. features.InitAndDisableFeature(features::kFirstPartySets); @@ -286,18 +289,13 @@ // Create Global First-Party Sets with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate1.test"} - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - net::GlobalFirstPartySets( - {{associate1_site, - {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, - 0)}}}, - {})); + SetGlobalSets(net::GlobalFirstPartySets( + {{associate1_site, + {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, + 0)}}}, + {})); // Simulate the profile set overrides are empty. - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); // Simulate First-Party Sets disabled by the preference. features.InitAndEnableFeature(features::kFirstPartySets); @@ -330,7 +328,7 @@ // Simulate the global First-Party Sets with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate1.test"} - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( + SetGlobalSets( net::GlobalFirstPartySets({{associate1_site, {associate1_entry}}}, {})); // Verify that FindEntry returns empty if both sources of sets aren't ready @@ -338,11 +336,7 @@ EXPECT_FALSE(service()->FindEntry(associate1_site)); // Simulate the profile set overrides are empty. - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); // Verify that FindEntry finally returns associate1's entry. EXPECT_EQ(service()->FindEntry(associate1_site).value(), associate1_entry); @@ -372,15 +366,11 @@ // Simulate the global First-Party Sets with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate.test"} - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( + SetGlobalSets( net::GlobalFirstPartySets({{associate_site, {associate_entry}}}, {})); // Simulate the profile set overrides are empty. - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); // The queries that occur before global sets are ready should be // counted in our metric. @@ -416,15 +406,11 @@ // Simulate the global First-Party Sets with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate.test"} - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( + SetGlobalSets( net::GlobalFirstPartySets({{associate_site, {associate_entry}}}, {})); // Simulate the profile set overrides are empty. - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); // Simulate 3 FindEntry queries which all are answered successfully. EXPECT_EQ(service()->FindEntry(associate_site).value(), associate_entry); @@ -456,12 +442,9 @@ net::FirstPartySetEntry test_entry(test_primary, net::SiteType::kPrimary, absl::nullopt); net::FirstPartySetsContextConfig test_config({{test_primary, {test_entry}}}); + SetContextConfig(test_config.Clone()); - service()->InitForTesting( - [&](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(test_config.Clone()); - }); + service()->InitForTesting(); EXPECT_CALL(mock_delegate, NotifyReady(CarryingConfig(std::ref(test_config)))) .Times(1); @@ -471,11 +454,7 @@ TEST_F(FirstPartySetsPolicyServicePrefObserverTest, OnFirstPartySetsEnabledChanged_Default_WithConfig) { - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); EXPECT_CALL(mock_delegate, SetEnabled(_)).Times(0); EXPECT_CALL(mock_delegate, NotifyReady(_)).Times(1); @@ -493,11 +472,7 @@ TEST_F(FirstPartySetsPolicyServicePrefObserverTest, OnFirstPartySetsEnabledChanged_Disables_WithConfig) { - service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); service()->OnFirstPartySetsEnabledChanged(false); EXPECT_CALL(mock_delegate, SetEnabled(false)).Times(1); @@ -522,12 +497,9 @@ net::FirstPartySetEntry test_entry(test_primary, net::SiteType::kPrimary, absl::nullopt); net::FirstPartySetsContextConfig test_config({{test_primary, {test_entry}}}); + SetContextConfig(test_config.Clone()); - service()->InitForTesting( - [&](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(test_config.Clone()); - }); + service()->InitForTesting(); service()->OnFirstPartySetsEnabledChanged(true); // Ensure access delegate is called with SetEnabled(true) and NotifyReady is @@ -551,39 +523,7 @@ env().RunUntilIdle(); } -class FirstPartySetsPolicyServiceWithMockHandlerTest - : public FirstPartySetsPolicyServiceTest { - public: - FirstPartySetsPolicyServiceWithMockHandlerTest() = default; - - void SetUp() override { - FirstPartySetsPolicyServiceTest::SetUp(); - - content::FirstPartySetsHandler::GetInstance()->SetInstanceForTesting( - &first_party_sets_handler_); - } - - void TearDown() override { - FirstPartySetsPolicyServiceTest::TearDown(); - first_party_sets_handler_.ResetForTesting(); - content::FirstPartySetsHandler::GetInstance()->SetInstanceForTesting( - nullptr); - } - - void SetContextConfig(net::FirstPartySetsContextConfig config) { - first_party_sets_handler_.SetContextConfig(std::move(config)); - } - void SetCacheFilter(net::FirstPartySetsCacheFilter cache_filter) { - first_party_sets_handler_.SetCacheFilter(std::move(cache_filter)); - } - - private: - MockFirstPartySetsHandler first_party_sets_handler_; - base::test::ScopedFeatureList features_; -}; - -TEST_F(FirstPartySetsPolicyServiceWithMockHandlerTest, - NotifiesReadyWithConfigAndCacheFilter) { +TEST_F(FirstPartySetsPolicyServiceTest, NotifiesReadyWithConfigAndCacheFilter) { net::SchemefulSite test_primary(GURL("https://a.test")); net::FirstPartySetEntry test_entry(test_primary, net::SiteType::kPrimary, absl::nullopt); @@ -592,11 +532,7 @@ /*browser_run_id=*/1); SetContextConfig(test_config.Clone()); SetCacheFilter(test_cache_filter.Clone()); - service()->InitForTesting( - [&](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(test_config.Clone()); - }); + service()->InitForTesting(); EXPECT_CALL(mock_delegate, NotifyReady(CarryingConfigAndCacheFilter( @@ -644,11 +580,7 @@ IsPrefEnabled()); base::RunLoop run_loop; service()->RegisterThrottleResumeCallback(run_loop.QuitClosure()); - service()->InitForTesting( - [&](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + service()->InitForTesting(); run_loop.Run(); }
diff --git a/chrome/browser/first_party_sets/mock_first_party_sets_handler.cc b/chrome/browser/first_party_sets/mock_first_party_sets_handler.cc index 2139a94e..06674c1 100644 --- a/chrome/browser/first_party_sets/mock_first_party_sets_handler.cc +++ b/chrome/browser/first_party_sets/mock_first_party_sets_handler.cc
@@ -7,7 +7,9 @@ #include <string> #include "base/callback.h" +#include "base/feature_list.h" #include "base/types/optional_util.h" +#include "content/public/common/content_features.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" #include "net/first_party_sets/first_party_sets_context_config.h" #include "net/first_party_sets/global_first_party_sets.h" @@ -26,15 +28,11 @@ const base::Version& version, base::File sets_file) {} -void MockFirstPartySetsHandler::SetGlobalSetsForTesting( - net::GlobalFirstPartySets global_sets) { - global_sets_ = std::move(global_sets); -} - absl::optional<net::FirstPartySetEntry> MockFirstPartySetsHandler::FindEntry( const net::SchemefulSite& site, const net::FirstPartySetsContextConfig& config) const { - if (!global_sets_.has_value()) { + if (!global_sets_.has_value() || + !base::FeatureList::IsEnabled(features::kFirstPartySets)) { return absl::nullopt; } return global_sets_->FindEntry(site, config); @@ -68,9 +66,15 @@ net::FirstPartySetsContextConfig config) { config_ = std::move(config); } + void MockFirstPartySetsHandler::SetCacheFilter( net::FirstPartySetsCacheFilter cache_filter) { cache_filter_ = std::move(cache_filter); } +void MockFirstPartySetsHandler::SetGlobalSets( + net::GlobalFirstPartySets global_sets) { + global_sets_ = std::move(global_sets); +} + } // namespace first_party_sets
diff --git a/chrome/browser/first_party_sets/mock_first_party_sets_handler.h b/chrome/browser/first_party_sets/mock_first_party_sets_handler.h index a452bff..80d30c0 100644 --- a/chrome/browser/first_party_sets/mock_first_party_sets_handler.h +++ b/chrome/browser/first_party_sets/mock_first_party_sets_handler.h
@@ -40,7 +40,6 @@ void SetPublicFirstPartySets(const base::Version& version, base::File sets_file) override; void ResetForTesting() override; - void SetGlobalSetsForTesting(net::GlobalFirstPartySets global_sets) override; absl::optional<net::FirstPartySetEntry> FindEntry( const net::SchemefulSite& site, const net::FirstPartySetsContextConfig& config) const override; @@ -59,8 +58,11 @@ // Helper functions for tests to set up context. void SetContextConfig(net::FirstPartySetsContextConfig config); + void SetCacheFilter(net::FirstPartySetsCacheFilter cache_filter); + void SetGlobalSets(net::GlobalFirstPartySets global_sets); + private: absl::optional<net::GlobalFirstPartySets> global_sets_; absl::optional<net::FirstPartySetsContextConfig> config_;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 60256f3..75c5e56 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2604,6 +2604,11 @@ "expiry_milestone": 110 }, { + "name": "enable-lens-region-search-static-page", + "owners": ["juanmojica@google.com", "stanfield@google.com", "lens-chrome@google.com"], + "expiry_milestone": 110 + }, + { "name": "enable-lens-standalone", "owners": [ "stanfield@google.com", "benwgold@google.com", "juanmojica@google.com" ], "expiry_milestone": 107 @@ -3637,6 +3642,11 @@ "expiry_milestone": 115 }, { + "name": "feed-header-stick-to-top", + "owners": [ "//chrome/android/feed/OWNERS", "chili@chromium.org" ], + "expiry_milestone": 115 + }, + { "name": "feed-interactive-refresh", "owners": [ "//chrome/android/feed/OWNERS", "jianli@chromium.org" ], "expiry_milestone": 99 @@ -3831,7 +3841,7 @@ { "name": "forced-colors", "owners": [ "almaher@microsoft.com" ], - "expiry_milestone": 108 + "expiry_milestone": 111 }, { "name": "fractional-scroll-offsets", @@ -4448,7 +4458,7 @@ { "name": "lightweight-reactions-android", "owners": [ "gujen", "sophey", "chrome-with-friends-robots@google.com" ], - "expiry_milestone": 108 + "expiry_milestone": 110 }, { "name": "link-capturing-auto-display-intent-picker",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 6c64833c..2da78cd 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1850,6 +1850,12 @@ "Enable an entry point to Google Lens to allow users to search what they " "see using their mobile camera."; +const char kLensRegionSearchStaticPageName[] = + "Use a static page with the Lens region search feature."; +const char kLensRegionSearchStaticPageDescription[] = + "Enables use of a static page in a new tab when using the Lens region " + "search feature."; + const char kLensOnQuickActionSearchWidgetName[] = "Google Lens in Chrome's Quick Action Search Widget"; const char kLensOnQuickActionSearchWidgetDescription[] = @@ -3713,6 +3719,10 @@ "Enables showing a callout to help users return to the top of the feeds " "quickly."; +const char kFeedHeaderStickToTopName[] = "Feed header stick to top"; +const char kFeedHeaderStickToTopDescription[] = + "Stick feed header to top on scroll."; + const char kFeedInteractiveRefreshName[] = "Refresh feeds"; const char kFeedInteractiveRefreshDescription[] = "Enables refreshing feeds triggered by the users.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index fbcb38f..3ca7adc9 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1035,6 +1035,9 @@ extern const char kLensCameraAssistedSearchName[]; extern const char kLensCameraAssistedSearchDescription[]; +extern const char kLensRegionSearchStaticPageName[]; +extern const char kLensRegionSearchStaticPageDescription[]; + extern const char kLensOnQuickActionSearchWidgetName[]; extern const char kLensOnQuickActionSearchWidgetDescription[]; @@ -2096,6 +2099,9 @@ extern const char kFeedBackToTopName[]; extern const char kFeedBackToTopDescription[]; +extern const char kFeedHeaderStickToTopName[]; +extern const char kFeedHeaderStickToTopDescription[]; + extern const char kFeedInteractiveRefreshName[]; extern const char kFeedInteractiveRefreshDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index eba24e5..aa9beec 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -142,6 +142,7 @@ &feature_guide::features::kSkipCheckForLowEngagedUsers, &feed::kFeedBackToTop, &feed::kFeedClearImageMemoryCache, + &feed::kFeedHeaderStickToTop, &feed::kFeedImageMemoryCacheSizePercentage, &feed::kFeedInteractiveRefresh, &feed::kFeedLoadingPlaceholder, @@ -804,7 +805,7 @@ BASE_FEATURE(kIsVoiceSearchEnabledCache, "IsVoiceSearchEnabledCache", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kKitKatSupported, "KitKatSupported",
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index c50054a..0f29b42 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -359,6 +359,7 @@ public static final String FEATURE_NOTIFICATION_GUIDE = "FeatureNotificationGuide"; public static final String FEED_BACK_TO_TOP = "FeedBackToTop"; public static final String FEED_CLEAR_IMAGE_MEMORY_CACHE = "FeedClearImageMemoryCache"; + public static final String FEED_HEADER_STICK_TO_TOP = "FeedHeaderStickToTop"; public static final String FEED_IMAGE_MEMORY_CACHE_SIZE_PERCENTAGE = "FeedImageMemoryCacheSizePercentage"; public static final String FEED_INTERACTIVE_REFRESH = "FeedInteractiveRefresh";
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.h b/chrome/browser/media/router/mojo/media_router_mojo_impl.h index ebd1e9b..9793082 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.h
@@ -259,7 +259,7 @@ absl::optional<std::vector<MediaRoute>> cached_route_list_; // Per-MRP lists of routes for the query. - // TODO(crbug.com/761493): Consider making MRP ID an attribute of + // TODO(crbug.com/1374496): Consider making MRP ID an attribute of // MediaRoute, so that we can simplify these into vectors. base::flat_map<mojom::MediaRouteProviderId, std::vector<MediaRoute>> providers_to_routes_;
diff --git a/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc b/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc index 62f443c..cfbb1629f 100644 --- a/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc +++ b/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc
@@ -13,12 +13,18 @@ #include "base/rand_util.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/content_settings/core/common/content_settings_types.h" +#include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/public/features.h" #include "components/performance_manager/public/graph/page_node.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" +#if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" +#endif // !BUILDFLAG(IS_ANDROID) + namespace performance_manager::metrics { PageTimelineMonitor::PageTimelineMonitor() @@ -93,8 +99,39 @@ curr_info->time_of_last_foreground_millisecond_update = now; } + bool is_active_tab = false; + bool has_notification_permission = false; + bool is_capturing_media = false; + bool is_connected_to_device = false; + + const auto* page_live_state_data = + PageLiveStateDecorator::Data::FromPageNode(page_node); + if (page_live_state_data) { + is_active_tab = page_live_state_data->IsActiveTab(); + has_notification_permission = + page_live_state_data->IsContentSettingTypeAllowed( + ContentSettingsType::NOTIFICATIONS); + is_capturing_media = page_live_state_data->IsCapturingVideo() || + page_live_state_data->IsCapturingAudio() || + page_live_state_data->IsBeingMirrored() || + page_live_state_data->IsCapturingWindow() || + page_live_state_data->IsCapturingDisplay(); + is_connected_to_device = + page_live_state_data->IsConnectedToUSBDevice() || + page_live_state_data->IsConnectedToBluetoothDevice(); + } + ukm::builders::PerformanceManager_PageTimelineState(source_id) .SetSliceId(slice_id) +#if !BUILDFLAG(IS_ANDROID) + .SetHighEfficiencyMode( + user_tuning::UserPerformanceTuningManager::GetInstance() + ->IsHighEfficiencyModeActive()) + .SetBatterySaverMode( + user_tuning::UserPerformanceTuningManager::GetInstance() + ->IsBatterySaverActive()) +#endif // !BUILDFLAG(IS_ANDROID) + .SetIsActiveTab(is_active_tab) .SetTimeSinceLastSlice(ukm::GetSemanticBucketMinForDurationTiming( time_since_last_slice.InMilliseconds())) .SetTimeSinceCreation(ukm::GetSemanticBucketMinForDurationTiming( @@ -107,6 +144,11 @@ curr_info->total_foreground_milliseconds)) .SetChangedFaviconOrTitleInBackground( curr_info->updated_title_or_favicon_in_background) + .SetHasNotificationPermission(has_notification_permission) + .SetIsCapturingMedia(is_capturing_media) + .SetIsConnectedToDevice(is_connected_to_device) + .SetIsPlayingAudio(page_node->IsAudible()) + .SetResidentSetSize(page_node->EstimateResidentSetSize()) .Record(ukm::UkmRecorder::Get()); } }
diff --git a/chrome/browser/performance_manager/metrics/page_timeline_monitor.h b/chrome/browser/performance_manager/metrics/page_timeline_monitor.h index 6d5bc1e..87b9266 100644 --- a/chrome/browser/performance_manager/metrics/page_timeline_monitor.h +++ b/chrome/browser/performance_manager/metrics/page_timeline_monitor.h
@@ -19,9 +19,6 @@ // Periodically reports tab state via UKM, to enable analysis of usage patterns // over time. -// -// TODO(crbug.com/1367052): Report whether high-efficiency mode and/or -// battery-saver mode are enabled. class PageTimelineMonitor : public PageNode::ObserverDefaultImpl, public GraphOwned { public:
diff --git a/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc b/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc index 7d4d956..9ab9d643 100644 --- a/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc +++ b/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc
@@ -8,14 +8,22 @@ #include "base/bind.h" #include "base/memory/raw_ptr.h" #include "build/build_config.h" +#include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h" +#include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/public/mojom/lifecycle.mojom-shared.h" +#include "components/performance_manager/public/user_tuning/prefs.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" +#include "components/prefs/testing_pref_service.h" #include "components/ukm/test_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h" +#endif // !BUILDFLAG(IS_ANDROID) + namespace performance_manager::metrics { class PageTimelineMonitorUnitTest : public GraphTestHarness { @@ -35,9 +43,17 @@ monitor_ = monitor.get(); graph()->PassToGraph(std::move(monitor)); test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); +#if !BUILDFLAG(IS_ANDROID) + performance_manager::user_tuning::prefs::RegisterLocalStatePrefs( + local_state_.registry()); + environment_.SetUp(&local_state_); +#endif // !BUILDFLAG(IS_ANDROID) } void TearDown() override { +#if !BUILDFLAG(IS_ANDROID) + environment_.TearDown(); +#endif // !BUILDFLAG(IS_ANDROID) test_ukm_recorder_.reset(); GraphTestHarness::TearDown(); } @@ -53,6 +69,13 @@ private: std::unique_ptr<ukm::TestUkmRecorder> test_ukm_recorder_; + +#if !BUILDFLAG(IS_ANDROID) + // The UserPerformanceTuningManager doesn't exist on Android + TestingPrefServiceSimple local_state_; + performance_manager::user_tuning::TestUserPerformanceTuningManagerEnvironment + environment_; +#endif // !BUILDFLAG(IS_ANDROID) }; TEST_F(PageTimelineMonitorUnitTest, TestPageTimeline) { @@ -162,4 +185,157 @@ mojom::LifecycleState::kFrozen); } +TEST_F(PageTimelineMonitorUnitTest, TestHasNotificationsPermission) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + + PageLiveStateDecorator::Data* data = + PageLiveStateDecorator::Data::GetOrCreateForPageNode( + mock_graph.page.get()); + data->SetContentSettingsForTesting( + {{ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW}}); + + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], + "HasNotificationPermission", 1); + + data->SetContentSettingsForTesting( + {{ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK}}); + + TriggerCollectSlice(); + entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 2UL); + + test_ukm_recorder()->ExpectEntryMetric(entries[1], + "HasNotificationPermission", 0); +} + +TEST_F(PageTimelineMonitorUnitTest, TestCapturingMedia) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + + PageLiveStateDecorator::Data* data = + PageLiveStateDecorator::Data::GetOrCreateForPageNode( + mock_graph.page.get()); + data->SetIsCapturingVideoForTesting(false); + + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], "IsCapturingMedia", 0); + + data->SetIsCapturingVideoForTesting(true); + TriggerCollectSlice(); + entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 2UL); + test_ukm_recorder()->ExpectEntryMetric(entries[1], "IsCapturingMedia", 1); +} + +TEST_F(PageTimelineMonitorUnitTest, TestConnectedToDevice) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + + PageLiveStateDecorator::Data* data = + PageLiveStateDecorator::Data::GetOrCreateForPageNode( + mock_graph.page.get()); + data->SetIsConnectedToUSBDeviceForTesting(false); + + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], "IsConnectedToDevice", 0); + + data->SetIsConnectedToUSBDeviceForTesting(true); + TriggerCollectSlice(); + entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 2UL); + test_ukm_recorder()->ExpectEntryMetric(entries[1], "IsConnectedToDevice", 1); +} + +TEST_F(PageTimelineMonitorUnitTest, TestAudible) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + + mock_graph.page->SetIsAudible(false); + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], "IsPlayingAudio", 0); + + mock_graph.page->SetIsAudible(true); + TriggerCollectSlice(); + entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 2UL); + test_ukm_recorder()->ExpectEntryMetric(entries[1], "IsPlayingAudio", 1); +} + +TEST_F(PageTimelineMonitorUnitTest, TestIsActiveTab) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + + PageLiveStateDecorator::Data* data = + PageLiveStateDecorator::Data::GetOrCreateForPageNode( + mock_graph.page.get()); + data->SetIsActiveTabForTesting(false); + + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], "IsActiveTab", 0); + + data->SetIsActiveTabForTesting(true); + TriggerCollectSlice(); + entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 2UL); + test_ukm_recorder()->ExpectEntryMetric(entries[1], "IsActiveTab", 1); +} + +TEST_F(PageTimelineMonitorUnitTest, TestResidentSetSize) { + MockSinglePageInSingleProcessGraph mock_graph(graph()); + ukm::SourceId mock_source_id = ukm::NoURLSourceId(); + mock_graph.page->SetType(performance_manager::PageType::kTab); + mock_graph.page->SetUkmSourceId(mock_source_id); + mock_graph.page->SetIsVisible(true); + mock_graph.page->SetLifecycleStateForTesting(mojom::LifecycleState::kRunning); + mock_graph.frame->SetResidentSetKbEstimate(123); + + TriggerCollectSlice(); + auto entries = test_ukm_recorder()->GetEntriesByName( + ukm::builders::PerformanceManager_PageTimelineState::kEntryName); + EXPECT_EQ(entries.size(), 1UL); + test_ukm_recorder()->ExpectEntryMetric(entries[0], "ResidentSetSize", 123); +} + } // namespace performance_manager::metrics
diff --git a/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h b/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h index 4945450..cf90cb37 100644 --- a/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h +++ b/chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h
@@ -133,6 +133,9 @@ void SetTemporaryBatterySaverDisabledForSession(bool disabled); bool IsBatterySaverModeDisabledForSession() const; + // Returns true if High Efficiency mode is currently enabled. + bool IsHighEfficiencyModeActive() const; + // Returns true if Battery Saver Mode interventions are active. If any state // transitions cause an observer notification, this is guaranteed to reflect // the *new* value when the observers are notified so the UI layer can make
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc index 50e432e..6965bea5 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc
@@ -113,6 +113,11 @@ return battery_saver_mode_disabled_for_session_; } +bool UserPerformanceTuningManager::IsHighEfficiencyModeActive() const { + return pref_change_registrar_.prefs()->GetBoolean( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); +} + bool UserPerformanceTuningManager::IsBatterySaverActive() const { return battery_saver_mode_enabled_; }
diff --git a/chrome/browser/printing/print_backend_service_manager.cc b/chrome/browser/printing/print_backend_service_manager.cc index bf35239a..2f590a66 100644 --- a/chrome/browser/printing/print_backend_service_manager.cc +++ b/chrome/browser/printing/print_backend_service_manager.cc
@@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <utility> #include "base/bind.h" #include "base/containers/flat_map.h" @@ -29,6 +30,9 @@ #if BUILDFLAG(IS_WIN) #include "base/win/win_util.h" +#include "chrome/browser/printing/printer_xml_parser_impl.h" +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "printing/backend/win_helper.h" #include "printing/printed_page_win.h" #include "ui/views/win/hwnd_util.h" @@ -152,6 +156,13 @@ remote_id); if (new_timeout.has_value()) UpdateServiceIdleTimeoutByRemoteId(remote_id, new_timeout.value()); + +#if BUILDFLAG(IS_WIN) + if (base::FeatureList::IsEnabled(features::kReadPrinterCapabilitiesWithXps) && + query_clients_.empty()) { + xml_parser_.reset(); + } +#endif // BUILDFLAG(IS_WIN) } void PrintBackendServiceManager::EnumeratePrinters( @@ -648,6 +659,17 @@ // Initialize the new service for the desired locale. service->Init(g_browser_process->GetApplicationLocale()); + +#if BUILDFLAG(IS_WIN) + // Bind PrintBackendService with a Remote that allows pass-through requests + // to an XML parser. + if (base::FeatureList::IsEnabled( + features::kReadPrinterCapabilitiesWithXps)) { + if (!xml_parser_) + xml_parser_ = std::make_unique<PrinterXmlParserImpl>(); + service->BindPrinterXmlParser(xml_parser_->GetRemote()); + } +#endif // BUILDFLAG(IS_WIN) } return service;
diff --git a/chrome/browser/printing/print_backend_service_manager.h b/chrome/browser/printing/print_backend_service_manager.h index 69a55088..68861abf 100644 --- a/chrome/browser/printing/print_backend_service_manager.h +++ b/chrome/browser/printing/print_backend_service_manager.h
@@ -35,6 +35,10 @@ namespace printing { +#if BUILDFLAG(IS_WIN) +class PrinterXmlParserImpl; +#endif // BUILDFLAG(IS_WIN) + class PrintedPage; class PrintBackendServiceManager { @@ -427,6 +431,12 @@ const ClientsSet& query_with_ui_clients, const PrintClientsMap& print_document_clients); +#if BUILDFLAG(IS_WIN) + // Printer XML Parser implementation used to allow Print Backend Service to + // send XML parse requests to the browser process. + std::unique_ptr<PrinterXmlParserImpl> xml_parser_; +#endif // BUILDFLAG(IS_WIN) + // Bundles of remotes for the Print Backend Service and their corresponding // wrapping hosts, to manage these sets until they disconnect. The sandboxed // and unsandboxed services are kept separate.
diff --git a/chrome/browser/printing/print_backend_service_test_impl.cc b/chrome/browser/printing/print_backend_service_test_impl.cc index 9bd6d02..65286269 100644 --- a/chrome/browser/printing/print_backend_service_test_impl.cc +++ b/chrome/browser/printing/print_backend_service_test_impl.cc
@@ -14,6 +14,14 @@ #include "chrome/browser/printing/print_backend_service_manager.h" #include "printing/backend/test_print_backend.h" +#if BUILDFLAG(IS_WIN) +#include <memory> + +#include "chrome/browser/printing/printer_xml_parser_impl.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "printing/printing_features.h" +#endif // BUILDFLAG(IS_WIN) + namespace printing { #if BUILDFLAG(IS_WIN) @@ -169,6 +177,15 @@ receiver_.reset(); } +#if BUILDFLAG(IS_WIN) +mojo::PendingRemote<mojom::PrinterXmlParser> +PrintBackendServiceTestImpl::GetPrinterXmlParserRemote() { + if (!xml_parser_) + xml_parser_ = std::make_unique<PrinterXmlParserImpl>(); + return xml_parser_->GetRemote(); +} +#endif // BUILDFLAG(IS_WIN) + // static std::unique_ptr<PrintBackendServiceTestImpl> PrintBackendServiceTestImpl::LaunchForTesting( @@ -183,6 +200,11 @@ new PrintBackendServiceTestImpl(std::move(receiver), std::move(backend))); service->Init(/*locale=*/std::string()); +#if BUILDFLAG(IS_WIN) + if (base::FeatureList::IsEnabled(features::kReadPrinterCapabilitiesWithXps)) + service->BindPrinterXmlParser(service->GetPrinterXmlParserRemote()); +#endif // BUILDFLAG(IS_WIN) + // Register this test version of print backend service to be used instead of // launching instances out-of-process on-demand. if (sandboxed) {
diff --git a/chrome/browser/printing/print_backend_service_test_impl.h b/chrome/browser/printing/print_backend_service_test_impl.h index 807a8f3..da877410 100644 --- a/chrome/browser/printing/print_backend_service_test_impl.h +++ b/chrome/browser/printing/print_backend_service_test_impl.h
@@ -20,6 +20,8 @@ #if BUILDFLAG(IS_WIN) #include "base/containers/queue.h" #include "base/memory/read_only_shared_memory_region.h" +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom-forward.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "printing/mojom/print.mojom.h" #endif @@ -33,6 +35,7 @@ namespace printing { #if BUILDFLAG(IS_WIN) +class PrinterXmlParserImpl; struct RenderPrintedPageData; #endif @@ -98,6 +101,8 @@ void set_rendering_delayed_until_page(uint32_t page_number) { rendering_delayed_until_page_number_ = page_number; } + + mojo::PendingRemote<mojom::PrinterXmlParser> GetPrinterXmlParserRemote(); #endif private: @@ -127,6 +132,9 @@ // The queue of pages whose rendering processing is being delayed. base::queue<std::unique_ptr<RenderPrintedPageData>> delayed_rendering_pages_; + + // Used to parse XPS XML capabilities. + std::unique_ptr<PrinterXmlParserImpl> xml_parser_; #endif scoped_refptr<TestPrintBackend> test_print_backend_;
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index 47fcd1e..a70cd643 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -271,7 +271,7 @@ fail_on_use_default_settings_ = true; } -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) void SetCancelErrorOnAskUserForSettings() { cancel_on_ask_user_for_settings_ = true; } @@ -291,7 +291,7 @@ bool access_denied_errors_for_render_document_ = false; bool access_denied_errors_for_document_done_ = false; bool fail_on_use_default_settings_ = false; -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) bool cancel_on_ask_user_for_settings_ = false; #endif int new_document_called_count_ = 0; @@ -2741,7 +2741,7 @@ test_printing_context_factory()->SetFailErrorOnUseDefaultSettings(); } -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) void PrimeForCancelInAskUserForSettings() { test_printing_context_factory()->SetCancelErrorOnAskUserForSettings(); } @@ -2789,7 +2789,7 @@ return use_default_settings_result_; } -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) mojom::ResultCode ask_user_for_settings_result() const { return ask_user_for_settings_result_; } @@ -2874,7 +2874,7 @@ CheckForQuit(); } -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) void OnDidAskUserForSettings(mojom::ResultCode result) { ask_user_for_settings_result_ = result; CheckForQuit(); @@ -2945,7 +2945,7 @@ raw_ptr<PrintJob> print_job_ = nullptr; bool reset_errors_after_check_ = true; mojom::ResultCode use_default_settings_result_ = mojom::ResultCode::kFailed; -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) mojom::ResultCode ask_user_for_settings_result_ = mojom::ResultCode::kFailed; #endif mojom::ResultCode start_printing_result_ = mojom::ResultCode::kFailed; @@ -3386,9 +3386,7 @@ EXPECT_EQ(print_job_destruction_count(), 1); } -// TODO(crbug.com/809738) Extend to Linux once Wayland can be made to support -// a system be modal against an application window in the browser process. -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest, StartBasicPrint) { AddPrinter("printer1"); @@ -3403,24 +3401,53 @@ ASSERT_TRUE(web_contents); SetUpPrintViewManager(web_contents); +#if BUILDFLAG(IS_WIN) // The test will get the default settings followed by asking the user for // settings. After that a print job will be started, with a page getting // rendered, and finally the document done notification. Wait for the one // print job to be destroyed to ensure printing finished cleanly before // completing the test. This results in a total of 6 calls. SetNumExpectedMessages(/*num=*/6); +#else + // The test sequence for this is: + // - Get the default settings. + // - Ask the user for settings. Due to issues with displaying a system dialog + // from the utility process, there is no callback to capture the request for + // user supplied settings. + // - A print job is started. + // - The document is rendered. + // - Receive document done notification. + // - Wait for the one print job to be destroyed, to ensure printing finished + // cleanly before completing the test. + // This results in a total of 5 calls. + // TODO(crbug.com/1374188) Update this expectation once + // `AskUserForSettings()` is able to be pushed OOP for Linux. + SetNumExpectedMessages(/*num=*/5); +#endif StartBasicPrint(web_contents); WaitUntilCallbackReceived(); EXPECT_EQ(use_default_settings_result(), mojom::ResultCode::kSuccess); + // macOS and Linux currently have to invoke a system dialog from within the + // browser process. There is not a callback to capture the result in these + // cases. + // TODO(crbug.com/1374188) Re-enable this check against + // `ask_user_for_settings_result()` once `AskForUserSettings()` is able to be + // pushed OOP for Linux. +#if BUILDFLAG(IS_WIN) EXPECT_EQ(ask_user_for_settings_result(), mojom::ResultCode::kSuccess); +#endif EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess); +#if BUILDFLAG(IS_WIN) // TODO(crbug.com/1008222) Include Windows coverage of // RenderPrintedDocument() once XPS print pipeline is added. EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kSuccess); EXPECT_EQ(render_printed_page_count(), 1); +#else + EXPECT_EQ(render_printed_document_result(), mojom::ResultCode::kSuccess); +#endif EXPECT_EQ(document_done_result(), mojom::ResultCode::kSuccess); EXPECT_EQ(print_job_destruction_count(), 1); } @@ -3459,8 +3486,18 @@ EXPECT_FALSE(print_backend_service_use_detected()); } +// macOS and Linux currently have to invoke a system dialog from within the +// browser process. There is not a callback to capture the result in these +// cases. +// TODO(crbug.com/1374188) Re-enable for Linux once `AskForUserSettings()` is +// able to be pushed OOP for Linux. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +#define MAYBE_StartBasicPrintCancel DISABLED_StartBasicPrintCancel +#else +#define MAYBE_StartBasicPrintCancel StartBasicPrintCancel +#endif IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest, - StartBasicPrintCancel) { + MAYBE_StartBasicPrintCancel) { AddPrinter("printer1"); SetPrinterNameForSubsequentContexts("printer1"); PrimeForCancelInAskUserForSettings(); @@ -3510,17 +3547,18 @@ // Now initiate a system print that would exist concurrently with that. StartBasicPrint(web_contents); - // On Windows, concurrent system print is not allowed. - // TODO(crbug.com/809738): Demonstrate that Linux allows multiple system - // prints at a time. const absl::optional<bool>& result = print_view_manager->print_now_result(); ASSERT_TRUE(result.has_value()); + // With the exception of Linux, concurrent system print is not allowed. +#if BUILDFLAG(IS_LINUX) + EXPECT_TRUE(*result); +#else EXPECT_FALSE(*result); +#endif // Cleanup before test shutdown. PrintBackendServiceManager::GetInstance().UnregisterClient(*client_id); } -#endif // BUILDFLAG(IS_WIN) // https://crbug.com/1320681 flaky. IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest, @@ -3549,6 +3587,7 @@ EXPECT_EQ(use_default_settings_result(), mojom::ResultCode::kFailed); EXPECT_EQ(print_job_construction_count(), 1); } +#endif // BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) #endif // BUILDFLAG(ENABLE_OOP_PRINTING) @@ -3757,13 +3796,11 @@ INSTANTIATE_TEST_SUITE_P(All, ContentAnalysisPrintBrowserTest, testing::Bool()); -// This test suite doesn't run on CrOS since it doesn't support non-print -// preview scripted printing. -#if !BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) INSTANTIATE_TEST_SUITE_P(All, ContentAnalysisScriptedPreviewlessPrintBrowserTest, testing::Bool()); -#endif // !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_CHROMEOS) +#endif // BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) #endif // BUILDFLAG(ENABLE_PRINT_SCANNING)
diff --git a/chrome/browser/printing/printer_xml_parser_impl.cc b/chrome/browser/printing/printer_xml_parser_impl.cc new file mode 100644 index 0000000..de0efa8b --- /dev/null +++ b/chrome/browser/printing/printer_xml_parser_impl.cc
@@ -0,0 +1,60 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/printing/printer_xml_parser_impl.h" + +#include <memory> +#include <utility> + +#include "base/callback.h" +#include "base/values.h" +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "printing/mojom/print.mojom.h" +#include "services/data_decoder/public/cpp/data_decoder.h" + +namespace printing { + +namespace { + +void XmlPrinterCapabilitiesParsed( + PrinterXmlParserImpl::ParseXmlCallback callback, + data_decoder::DataDecoder::ValueOrError value_or_error) { + if (!value_or_error.has_value()) { + std::move(callback).Run( + mojom::PrinterCapabilitiesValueResult::NewResultCode( + mojom::ResultCode::kFailed)); + return; + } + std::move(callback).Run( + mojom::PrinterCapabilitiesValueResult::NewCapabilities( + std::move(value_or_error.value()))); +} + +} // namespace + +PrinterXmlParserImpl::PrinterXmlParserImpl() = default; + +PrinterXmlParserImpl::~PrinterXmlParserImpl() = default; + +void PrinterXmlParserImpl::ParseXmlForPrinterCapabilities( + const std::string& capabilities_xml, + ParseXmlCallback callback) { + if (!decoder_) + decoder_ = std::make_unique<data_decoder::DataDecoder>(); + decoder_->ParseXml( + capabilities_xml, + data_decoder::mojom::XmlParser::WhitespaceBehavior::kIgnore, + base::BindOnce(&XmlPrinterCapabilitiesParsed, std::move(callback))); +} + +mojo::PendingRemote<mojom::PrinterXmlParser> PrinterXmlParserImpl::GetRemote() { + mojo::PendingRemote<mojom::PrinterXmlParser> pending_remote; + receivers_.Add(this, pending_remote.InitWithNewPipeAndPassReceiver()); + return pending_remote; +} + +} // namespace printing
diff --git a/chrome/browser/printing/printer_xml_parser_impl.h b/chrome/browser/printing/printer_xml_parser_impl.h new file mode 100644 index 0000000..a31055be --- /dev/null +++ b/chrome/browser/printing/printer_xml_parser_impl.h
@@ -0,0 +1,40 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PRINTING_PRINTER_XML_PARSER_IMPL_H_ +#define CHROME_BROWSER_PRINTING_PRINTER_XML_PARSER_IMPL_H_ + +#include <memory> + +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "printing/mojom/print.mojom.h" +#include "services/data_decoder/public/cpp/data_decoder.h" + +namespace printing { + +class PrinterXmlParserImpl : public mojom::PrinterXmlParser { + public: + using ParseXmlCallback = + base::OnceCallback<void(mojom::PrinterCapabilitiesValueResultPtr)>; + + PrinterXmlParserImpl(); + PrinterXmlParserImpl(const PrinterXmlParserImpl&) = delete; + PrinterXmlParserImpl& operator=(const PrinterXmlParserImpl&) = delete; + ~PrinterXmlParserImpl() override; + + void ParseXmlForPrinterCapabilities(const std::string& capabilities_xml, + ParseXmlCallback callback) override; + + mojo::PendingRemote<mojom::PrinterXmlParser> GetRemote(); + + private: + mojo::ReceiverSet<mojom::PrinterXmlParser> receivers_; + std::unique_ptr<data_decoder::DataDecoder> decoder_; +}; + +} // namespace printing + +#endif // PRINTING_PRINTER_XML_PARSER_IMPL_H_
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc index a992b690..e8c5c966 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/first_party_sets/first_party_sets_policy_service.h" +#include "chrome/browser/first_party_sets/mock_first_party_sets_handler.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/chrome_features.h" @@ -683,9 +684,19 @@ void SetUp() override { CreateService(); + content::FirstPartySetsHandler::SetInstanceForTesting( + &mock_first_party_sets_handler_); + mock_first_party_sets_handler().SetCacheFilter( + net::FirstPartySetsCacheFilter()); + mock_first_party_sets_handler().SetContextConfig( + net::FirstPartySetsContextConfig()); SetGlobalFirstPartySetsAndWait(); } + void TearDown() override { + content::FirstPartySetsHandler::SetInstanceForTesting(nullptr); + } + virtual std::unique_ptr< privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate> GetMockDelegate() { @@ -752,6 +763,9 @@ browsing_topics::MockBrowsingTopicsService* mock_browsing_topics_service() { return &mock_browsing_topics_service_; } + first_party_sets::MockFirstPartySetsHandler& mock_first_party_sets_handler() { + return mock_first_party_sets_handler_; + } first_party_sets::FirstPartySetsPolicyService* first_party_sets_policy_service() { return &first_party_sets_policy_service_; @@ -763,8 +777,7 @@ #endif void SetGlobalFirstPartySetsAndWait() { - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting({}); + mock_first_party_sets_handler_.SetGlobalSets({}); base::RunLoop run_loop; first_party_sets_policy_service_.WaitForFirstInitCompleteForTesting( run_loop.QuitClosure()); @@ -779,6 +792,7 @@ base::test::ScopedFeatureList feature_list_; TestInterestGroupManager test_interest_group_manager_; browsing_topics::MockBrowsingTopicsService mock_browsing_topics_service_; + first_party_sets::MockFirstPartySetsHandler mock_first_party_sets_handler_; first_party_sets::FirstPartySetsPolicyService first_party_sets_policy_service_ = first_party_sets::FirstPartySetsPolicyService( @@ -2129,16 +2143,10 @@ content_settings::CookieControlsMode::kOff))); prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - global_sets.Clone()); - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone()); + + first_party_sets_policy_service()->InitForTesting(); // We shouldn't get associate1's owner since FPS is disabled. EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl), absl::nullopt); @@ -2177,16 +2185,9 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); + mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone()); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - global_sets.Clone()); - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + first_party_sets_policy_service()->InitForTesting(); // We shouldn't get associate1's owner since FPS is disabled. EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl), absl::nullopt); @@ -2227,16 +2228,9 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); + mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone()); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - global_sets.Clone()); - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + first_party_sets_policy_service()->InitForTesting(); // We shouldn't get associate1's owner since FPS is disabled. EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl), @@ -2278,16 +2272,8 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - global_sets.Clone()); - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone()); + first_party_sets_policy_service()->InitForTesting(); // We shouldn't get associate1's owner since FPS is disabled. EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl), @@ -2330,16 +2316,9 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(false)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); + mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone()); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - global_sets.Clone()); - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig()); - }); + first_party_sets_policy_service()->InitForTesting(); // We shouldn't get associate1's owner since FPS is disabled. EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl), @@ -2413,32 +2392,26 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - // Simulate that the Global First-Party Sets are ready with the following set: // { primary: "https://primary.test", // associatedSites: ["https://associate1.test", "https://associate2.test"] } - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - net::GlobalFirstPartySets( - {{associate1_site, - {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, - 0)}}, - {associate2_site, - {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, - 1)}}}, - {})); + mock_first_party_sets_handler().SetGlobalSets(net::GlobalFirstPartySets( + {{associate1_site, + {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, 0)}}, + {associate2_site, + {net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, + 1)}}}, + {})); // Simulate that associate2 is removed from the Global First-Party Sets for // this profile. - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run(net::FirstPartySetsContextConfig( - net::FirstPartySetsContextConfig::OverrideSets{ - {net::SchemefulSite(GURL("https://associate2.test")), - {absl::nullopt}}})); - }); + mock_first_party_sets_handler().SetContextConfig( + net::FirstPartySetsContextConfig( + net::FirstPartySetsContextConfig::OverrideSets{ + {net::SchemefulSite(GURL("https://associate2.test")), + {absl::nullopt}}})); + + first_party_sets_policy_service()->InitForTesting(); // Verify that primary owns associate1, but no longer owns associate2. EXPECT_EQ( @@ -2539,9 +2512,6 @@ prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled, std::make_unique<base::Value>(true)); - // Reset test state to reflect required state above. - content::FirstPartySetsHandler::GetInstance()->ResetForTesting(); - // Simulate that the Global First-Party Sets are ready with the following // set: // { primary: "https://youtube-primary.test", @@ -2551,26 +2521,23 @@ GURL youtube_gurl("https://youtube.com"); net::SchemefulSite youtube_site(youtube_gurl); - content::FirstPartySetsHandler::GetInstance()->SetGlobalSetsForTesting( - net::GlobalFirstPartySets( - {{youtube_site, - {net::FirstPartySetEntry(youtube_primary_site, - net::SiteType::kAssociated, 0)}}}, - {})); + mock_first_party_sets_handler().SetGlobalSets(net::GlobalFirstPartySets( + {{youtube_site, + {net::FirstPartySetEntry(youtube_primary_site, + net::SiteType::kAssociated, 0)}}}, + {})); // Simulate that https://google.de is moved into a new First-Party Set for // this profile. - first_party_sets_policy_service()->InitForTesting( - [](PrefService* prefs, - base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) { - std::move(callback).Run( - net::FirstPartySetsContextConfig(net::FirstPartySetsContextConfig( - net::FirstPartySetsContextConfig::OverrideSets{ - {net::SchemefulSite(GURL("https://google.de")), - {net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://new-primary.test")), - net::SiteType::kAssociated, 0)}}}))); - }); + mock_first_party_sets_handler().SetContextConfig( + net::FirstPartySetsContextConfig( + net::FirstPartySetsContextConfig::OverrideSets{ + {net::SchemefulSite(GURL("https://google.de")), + {net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://new-primary.test")), + net::SiteType::kAssociated, 0)}}})); + + first_party_sets_policy_service()->InitForTesting(); // Expect queries to be resolved based on the FPS sample sets. EXPECT_GT(privacy_sandbox_service()->GetSampleFirstPartySets().size(), 0u);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index a4c41a8..6760b10 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -247,6 +247,7 @@ #if BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "chrome/browser/lens/region_search/lens_region_search_controller.h" +#include "chrome/browser/ui/lens/lens_side_panel_helper.h" #include "chrome/grit/theme_resources.h" #include "ui/base/resource/resource_bundle.h" #endif @@ -3638,9 +3639,14 @@ int event_flags, bool is_google_default_search_provider) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) + Browser* browser = GetBrowser(); + CHECK(browser); + if (lens::features::IsLensRegionSearchStaticPageEnabled()) { + lens::OpenLensStaticPage(browser); + return; + } + if (!lens_region_search_controller_) { - Browser* browser = GetBrowser(); - CHECK(browser); WebContents* web_contents = source_web_contents_; if (base::FeatureList::IsEnabled( lens::features::kEnableRegionSearchOnPdfViewer)) {
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index f185ec8..e3fdecd2 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -53,7 +53,10 @@ "whats_new:resources", ] if (is_chrome_branded) { - public_deps += [ "media_router/cast_feedback:resources" ] + public_deps += [ + "lens:resources", + "media_router/cast_feedback:resources", + ] } }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js index b6ffdee..3696654 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
@@ -100,5 +100,8 @@ // Move the cursor to the previous sentence. NAV_PREV_SENT: 26, + // Deletes all text in the input box. + DELETE_ALL_TEXT: 27, + // Any new actions should match with Voice Access's semantic tags. };
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/repeatable_key_press_macro.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/repeatable_key_press_macro.js index 9722f96..73e06f97 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/repeatable_key_press_macro.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/repeatable_key_press_macro.js
@@ -247,3 +247,16 @@ LocaleInfo.isRTLLocale() ? KeyCode.RIGHT : KeyCode.LEFT, {ctrl: true}); } } + +/** Macro to delete all text in input field. */ +export class DeleteAllText extends RepeatableKeyPressMacro { + constructor() { + super(MacroName.DELETE_ALL_TEXT, 1); + } + + /** @override */ + doKeyPress() { + EventGenerator.sendKeyPress(KeyCode.A, {ctrl: true}); + EventGenerator.sendKeyPress(KeyCode.BACK); + } +}
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/pumpkin_parse_strategy.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/pumpkin_parse_strategy.js index e5854b2f..a3e63cf 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/pumpkin_parse_strategy.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/pumpkin_parse_strategy.js
@@ -200,6 +200,8 @@ text = argument.value; } } + // TODO(crbug.com/1362842) Add all macros under the DictationMoreCommands + // to this switch statement. switch (tag) { case MacroName.INPUT_TEXT_VIEW: return new InputTextViewMacro(text, this.getInputController()); @@ -255,6 +257,9 @@ // Try to get results from Pumpkin. // TODO(crbug.com/1264544): Could increase the hypotheses count from 1 // when we are ready to implement disambiguation. + // TODO(crbug.com/1362842) Add logic to check whether + // DictationMoreCommands is enabled or not before + // running the macros hidden within that flag. const taggerResults = this.pumpkinTagger_.tagAndGetNBestHypotheses(text, 1); if (taggerResults && taggerResults.hypothesisList.length > 0) {
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/simple_parse_strategy.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/simple_parse_strategy.js index eaa1a5d0..2dabfbc 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/simple_parse_strategy.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/simple_parse_strategy.js
@@ -237,9 +237,17 @@ messageId: 'dictation_command_nav_prev_sent', build: NavPrevSentMacro, }, + [MacroName.DELETE_ALL_TEXT]: { + messageId: 'dictation_command_delete_all_text', + build: RepeatableKeyPress.DeleteAllText, + }, }; } } +// TODO(crbug.com/1362842) Do not release any Macros +// hidden under the DictationMoreCommands Flag +// using the simple_parse_strategy, rather +// move them over to the pumpkin_parse_strategy /** A parsing strategy that utilizes SimpleMacroFactory. */ export class SimpleParseStrategy extends ParseStrategy { @@ -252,6 +260,13 @@ * @private {!Map<MacroName, !SimpleMacroFactory>} */ this.macroFactoryMap_ = new Map(); + + /** @private {boolean} */ + this.isMoreCommandsFeatureEnabled_ = false; + + /** @private {!Array<!MacroName>}*/ + this.moreCommandsSet_ = [MacroName.DELETE_ALL_TEXT]; + this.initialize_(); } @@ -267,6 +282,13 @@ this.macroFactoryMap_.set( name, new SimpleMacroFactory(name, this.getInputController())); } + + const moreCommandsFeature = chrome.accessibilityPrivate.AccessibilityFeature + .DICTATION_MORE_COMMANDS; + chrome.accessibilityPrivate.isFeatureEnabled( + moreCommandsFeature, enabled => { + this.isMoreCommandsFeatureEnabled_ = enabled; + }); } /** @override */ @@ -280,12 +302,30 @@ this.initialize_(); } + /** + * @param {Macro} macro + * @return {boolean} + * @private + */ + shouldAddMacro_(macro) { + if (!macro) { + return false; + } + + const isNewCommand = this.moreCommandsSet_.includes(macro.getMacroName()); + if (!isNewCommand) { + return true; + } + + return this.isMoreCommandsFeatureEnabled_; + } + /** @override */ async parse(text) { const macros = []; for (const [name, factory] of this.macroFactoryMap_) { const macro = factory.createMacro(text); - if (macro) { + if (this.shouldAddMacro_(macro)) { macros.push(macro); } }
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/dictation_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/dictation_strings.grdp index 9b5ccab..6fb98ded 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/dictation_strings.grdp +++ b/chrome/browser/resources/chromeos/accessibility/strings/dictation_strings.grdp
@@ -78,4 +78,7 @@ <message name="DICTATION_COMMAND_NAV_PREV_SENT" desc="A spoken command to move the cursor to the previous sentence." is_accessibility_with_no_ui="true"> move to the previous sentence </message> + <message name="DICTATION_COMMAND_DELETE_ALL_TEXT" desc="A spoken command to delete all text in the input field." is_accessibility_with_no_ui="true"> + delete all + </message> </grit-part>
diff --git a/chrome/browser/resources/lens/BUILD.gn b/chrome/browser/resources/lens/BUILD.gn new file mode 100644 index 0000000..8ae57c93 --- /dev/null +++ b/chrome/browser/resources/lens/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import("//build/config/chrome_build.gni") +import("//chrome/browser/resources/tools/build_webui.gni") + +assert(toolkit_views) +assert(is_chrome_branded) + +build_webui("build") { + grd_prefix = "lens" + static_files = [ "lens.html" ] + non_web_component_files = [ "app.ts" ] + ts_use_local_config = false +}
diff --git a/chrome/browser/resources/lens/DIR_METADATA b/chrome/browser/resources/lens/DIR_METADATA new file mode 100644 index 0000000..749bdad --- /dev/null +++ b/chrome/browser/resources/lens/DIR_METADATA
@@ -0,0 +1,4 @@ +monorail { + component: "UI>Browser" +} +team_email: "lens-chrome-eng+bugs@google.com"
diff --git a/chrome/browser/resources/lens/OWNERS b/chrome/browser/resources/lens/OWNERS new file mode 100644 index 0000000..f6009d23 --- /dev/null +++ b/chrome/browser/resources/lens/OWNERS
@@ -0,0 +1 @@ +file://components/lens/OWNERS
diff --git a/chrome/browser/resources/lens/app.ts b/chrome/browser/resources/lens/app.ts new file mode 100644 index 0000000..d2e09d1 --- /dev/null +++ b/chrome/browser/resources/lens/app.ts
@@ -0,0 +1,7 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +document.addEventListener('DOMContentLoaded', function() { + console.info('Content loaded.'); +});
diff --git a/chrome/browser/resources/lens/lens.html b/chrome/browser/resources/lens/lens.html new file mode 100644 index 0000000..339a59e --- /dev/null +++ b/chrome/browser/resources/lens/lens.html
@@ -0,0 +1,12 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<head> + <meta charset="utf-8"> +</head> +<body> + <pre> + Placeholder text + </pre> + <script type="module" src="app.js"></script> +</body> +</html>
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 6785c150..4a27d27 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -405,6 +405,7 @@ ":deep_linking_behavior", ":find_shortcut_behavior", ":global_scroll_target_behavior", + ":icon", ":lazy_load", ":metrics_recorder", ":os_icons", @@ -526,6 +527,9 @@ ] } +js_library("icon") { +} + js_library("personalization_search_handler") { deps = [ "//ash/webui/personalization_app/search:mojo_bindings_webui_js" ] }
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts index 5585ffe..8ca94560 100644 --- a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts +++ b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts
@@ -24,11 +24,10 @@ import {loadTimeData} from '../../i18n_setup.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './date_time_page.html.js'; import {TimeZoneBrowserProxy, TimeZoneBrowserProxyImpl} from './timezone_browser_proxy.js'; @@ -38,11 +37,10 @@ [ DeepLinkingBehavior, PrefsBehavior, - RouteObserverBehavior, ], - I18nMixin(WebUIListenerMixin(PolymerElement))) as { + RouteObserverMixin(I18nMixin(WebUIListenerMixin(PolymerElement)))) as { new (): PolymerElement & DeepLinkingBehaviorInterface & - PrefsBehaviorInterface & RouteObserverBehaviorInterface & + PrefsBehaviorInterface & RouteObserverMixinInterface & I18nMixinInterface & WebUIListenerMixinInterface, };
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts index 01f2e46..0f55cf5 100644 --- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts +++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_subpage.ts
@@ -19,11 +19,10 @@ import {SettingsDropdownMenuElement} from '../../controls/settings_dropdown_menu.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {TimeZoneAutoDetectMethod} from './date_time_types.js'; import {TimeZoneBrowserProxy, TimeZoneBrowserProxyImpl} from './timezone_browser_proxy.js'; @@ -37,17 +36,17 @@ }; } -const TimezoneSubpageElementBase = mixinBehaviors( - [ - DeepLinkingBehavior, - PrefsBehavior, - RouteObserverBehavior, - ], - WebUIListenerMixin(PolymerElement)) as { - new (): PolymerElement & DeepLinkingBehaviorInterface & - PrefsBehaviorInterface & RouteObserverBehaviorInterface & - WebUIListenerMixinInterface, -}; +const TimezoneSubpageElementBase = + mixinBehaviors( + [ + DeepLinkingBehavior, + PrefsBehavior, + ], + RouteObserverMixin(WebUIListenerMixin(PolymerElement))) as { + new (): PolymerElement & DeepLinkingBehaviorInterface & + PrefsBehaviorInterface & RouteObserverMixinInterface & + WebUIListenerMixinInterface, + }; class TimezoneSubpageElement extends TimezoneSubpageElementBase { static get is() { @@ -87,7 +86,7 @@ } /** - * RouteObserverBehavior + * RouteObserverMixin * Called when the timezone subpage is hit. Child accounts need parental * approval to modify their timezone, this method starts this process on the * C++ side, and timezone setting will be disable. Once it is complete the
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page.ts b/chrome/browser/resources/settings/chromeos/device_page/device_page.ts index 1f93fa7..db28856 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/device_page.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/device_page.ts
@@ -24,11 +24,10 @@ import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {WebUIListenerMixin, WebUIListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Router} from '../../router.js'; +import {RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './device_page.html.js'; import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl} from './device_page_browser_proxy.js'; @@ -39,12 +38,12 @@ }; } +// TODO(crbug/1315757) Remove need to typecast and intersect mixin interfaces +// once RouteObserverMixin is converted to TS const SettingsDevicePageElementBase = - mixinBehaviors( - [RouteObserverBehavior], - I18nMixin(WebUIListenerMixin(PolymerElement))) as { - new (): PolymerElement & I18nMixinInterface & - WebUIListenerMixinInterface & RouteObserverBehaviorInterface, + RouteObserverMixin(I18nMixin(WebUIListenerMixin(PolymerElement))) as { + new (): PolymerElement & WebUIListenerMixinInterface & + I18nMixinInterface & RouteObserverMixinInterface, }; class SettingsDevicePageElement extends SettingsDevicePageElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/device_page/pointers.ts b/chrome/browser/resources/settings/chromeos/device_page/pointers.ts index 6558eabe..47e3ac5 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/pointers.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/pointers.ts
@@ -19,21 +19,19 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './pointers.html.js'; -const SettingsPointersElementBase = - mixinBehaviors( - [DeepLinkingBehavior, PrefsBehavior, RouteObserverBehavior], - PolymerElement) as { - new (): PolymerElement & DeepLinkingBehaviorInterface & - PrefsBehaviorInterface & RouteObserverBehaviorInterface, - }; +const SettingsPointersElementBase = mixinBehaviors( + [DeepLinkingBehavior, PrefsBehavior], + RouteObserverMixin(PolymerElement)) as { + new (): PolymerElement & DeepLinkingBehaviorInterface & + PrefsBehaviorInterface & RouteObserverMixinInterface, +}; class SettingsPointersElement extends SettingsPointersElementBase { static get is() {
diff --git a/chrome/browser/resources/settings/chromeos/device_page/stylus.ts b/chrome/browser/resources/settings/chromeos/device_page/stylus.ts index 8987d02..9495f8f0 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/stylus.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/stylus.ts
@@ -20,12 +20,11 @@ import {microTask, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {assertExists} from '../assert_extras.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl, NoteAppInfo, NoteAppLockScreenSupport} from './device_page_browser_proxy.js'; import {getTemplate} from './stylus.html.js'; @@ -40,10 +39,10 @@ 'collection/promotion_30023cb_stylus_apps'; const SettingsStylusElementBase = - mixinBehaviors( - [DeepLinkingBehavior, RouteObserverBehavior], PolymerElement) as { + mixinBehaviors([DeepLinkingBehavior], RouteObserverMixin(PolymerElement)) as + { new (): PolymerElement & DeepLinkingBehaviorInterface & - RouteObserverBehaviorInterface, + RouteObserverMixinInterface, }; class SettingsStylusElement extends SettingsStylusElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.ts b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.ts index 973e5cd3..9eb716e 100644 --- a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.ts +++ b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.ts
@@ -22,13 +22,12 @@ import {SettingsToggleButtonElement} from '../../controls/settings_toggle_button.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {cast, castExists} from '../assert_extras.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {GoogleAssistantBrowserProxy, GoogleAssistantBrowserProxyImpl} from './google_assistant_browser_proxy.js'; import {getTemplate} from './google_assistant_page.html.js'; @@ -68,12 +67,11 @@ [ DeepLinkingBehavior, PrefsBehavior, - RouteObserverBehavior, ], - WebUIListenerMixin(I18nMixin(PolymerElement))) as { + RouteObserverMixin(WebUIListenerMixin(I18nMixin(PolymerElement)))) as { new (): PolymerElement & I18nMixinInterface & WebUIListenerMixinInterface & DeepLinkingBehaviorInterface & - PrefsBehaviorInterface & RouteObserverBehaviorInterface, + PrefsBehaviorInterface & RouteObserverMixinInterface, }; class SettingsGoogleAssistantPageElement extends
diff --git a/chrome/browser/resources/settings/chromeos/icon.js b/chrome/browser/resources/settings/chromeos/icon.js new file mode 100644 index 0000000..ee53d5e --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/icon.js
@@ -0,0 +1,85 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Note: This file is deprecated in favor of the TypeScript version at + * ui/webui/resources/js/icon.ts. icon.ts should be used by all TypeScript + * files, and can also be used by any JS file that is not using closure + * compiler for typechecking. + */ + +/** + * @return {!Array<number>} The scale factors supported by this platform for + * webui resources. + */ +function getSupportedScaleFactors() { + // 1 is supported to match code in ResourceBundle::InitSharedInstance() that + // supports SCALE_FACTOR_100P on all non-iOS platforms. + // All desktop platforms including Ash support zooming which also updates the + // renderer's device scale factors (a.k.a devicePixelRatio), and these + // platforms have high DPI assets for 2x. Let the renderer pick the closest + // image for the current device scale factor. + return [1, 2]; +} + +/** + * Generates a CSS url string. + * @param {string} s The URL to generate the CSS url for. + * @return {string} The CSS url string. + */ +export function getUrlForCss(s) { + // http://www.w3.org/TR/css3-values/#uris + // Parentheses, commas, whitespace characters, single quotes (') and double + // quotes (") appearing in a URI must be escaped with a backslash + const s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); + return `url("${s2}")`; +} + +/** + * Generates a CSS -webkit-image-set for a chrome:// url. + * An entry in the image set is added for each of getSupportedScaleFactors(). + * The scale-factor-specific url is generated by replacing the first instance + * of 'scalefactor' in |path| with the numeric scale factor. + * + * @param {string} path The URL to generate an image set for. + * 'scalefactor' should be a substring of |path|. + * @return {string} The CSS -webkit-image-set. + */ +function getImageSet(path) { + const supportedScaleFactors = getSupportedScaleFactors(); + + const replaceStartIndex = path.indexOf('SCALEFACTOR'); + if (replaceStartIndex < 0) { + return getUrlForCss(path); + } + + let s = ''; + for (let i = 0; i < supportedScaleFactors.length; ++i) { + const scaleFactor = supportedScaleFactors[i]; + const pathWithScaleFactor = path.substr(0, replaceStartIndex) + + scaleFactor + path.substr(replaceStartIndex + 'scalefactor'.length); + + s += getUrlForCss(pathWithScaleFactor) + ' ' + scaleFactor + 'x'; + + if (i !== supportedScaleFactors.length - 1) { + s += ', '; + } + } + return '-webkit-image-set(' + s + ')'; +} + +/** + * Returns the URL of the image, or an image set of URLs for the provided + * path. Resources in chrome://theme have multiple supported scale factors. + * + * @param {string} path The path of the image. + * @return {string} The url, or an image set of URLs. + */ +export function getImage(path) { + const chromeThemePath = 'chrome://theme'; + const isChromeThemeUrl = + (path.slice(0, chromeThemePath.length) === chromeThemePath); + return isChromeThemeUrl ? getImageSet(path + '@SCALEFACTORx') : + getUrlForCss(path); +}
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/kerberos_page/BUILD.gn index bd13cbd..8bb804f 100644 --- a/chrome/browser/resources/settings/chromeos/kerberos_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/kerberos_page/BUILD.gn
@@ -21,6 +21,7 @@ deps = [ ":kerberos_accounts_browser_proxy", "..:deep_linking_behavior", + "..:icon", "..:metrics_recorder", "..:os_route", "..:route_observer_behavior", @@ -30,7 +31,6 @@ "//ash/webui/common/resources:web_ui_listener_behavior", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js:icon", ] externs_list = [
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js index 767cf48..1e4ea58 100644 --- a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js +++ b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.js
@@ -19,7 +19,6 @@ import './kerberos_add_account_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {getImage} from 'chrome://resources/js/icon.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -27,6 +26,7 @@ import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; import {Route, Router} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; +import {getImage} from '../icon.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {Account} from '../os_people_page/account_manager_browser_proxy.js'; import {routes} from '../os_route.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts index 6297a7b..a6d4165b 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts +++ b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts
@@ -25,12 +25,11 @@ import {loadTimeData} from '../../i18n_setup.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {castExists} from '../assert_extras.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, browserChannelToI18nId, ChannelInfo, VersionInfo} from './about_page_browser_proxy.js'; import {getTemplate} from './detailed_build_info.html.js'; @@ -48,12 +47,11 @@ [ DeepLinkingBehavior, PrefsBehavior, - RouteObserverBehavior, ], - I18nMixin(WebUIListenerMixin(PolymerElement))) as { + RouteObserverMixin(I18nMixin(WebUIListenerMixin(PolymerElement)))) as { new (): PolymerElement & DeepLinkingBehaviorInterface & WebUIListenerMixinInterface & I18nMixinInterface & - PrefsBehaviorInterface & RouteObserverBehaviorInterface, + PrefsBehaviorInterface & RouteObserverMixinInterface, }; class SettingsDetailedBuildInfoElement extends SettingsDetailedBuildInfoBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts index 0643230..243b19e0 100644 --- a/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_files_page/os_files_page.ts
@@ -16,18 +16,17 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_files_page.html.js'; const OsSettingsFilesPageElementBase = - mixinBehaviors( - [DeepLinkingBehavior, RouteObserverBehavior], PolymerElement) as { - new (): DeepLinkingBehaviorInterface & RouteObserverBehaviorInterface & - PolymerElement, + mixinBehaviors([DeepLinkingBehavior], RouteObserverMixin(PolymerElement)) as + { + new (): PolymerElement & DeepLinkingBehaviorInterface & + RouteObserverMixinInterface, }; class OsSettingsFilesPageElement extends OsSettingsFilesPageElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.ts b/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.ts index 7b5a618..9202a6e 100644 --- a/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_files_page/smb_shares_page.ts
@@ -11,18 +11,18 @@ import '../../settings_shared.css.js'; import '../../settings_vars.css.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './smb_shares_page.html.js'; -const SettingsSmbSharesPageElementBase = - mixinBehaviors([RouteObserverBehavior], PolymerElement) as { - new (): PolymerElement & RouteObserverBehaviorInterface, - }; +// TODO(crbug/1315757) Remove need to typecast and intersect mixin interfaces +// once RouteObserverMixin is converted to TS +const SettingsSmbSharesPageElementBase = RouteObserverMixin(PolymerElement) as { + new (): PolymerElement & RouteObserverMixinInterface, +}; class SettingsSmbSharesPageElement extends SettingsSmbSharesPageElementBase { static get is() { @@ -51,7 +51,7 @@ private showAddSmbDialog_: boolean; /** - * Overridden from RouteObserverBehavior. + * Overridden from RouteObserverMixin. */ override currentRouteChanged(route: Route) { if (route === routes.SMB_SHARES) {
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn index 944d364..6429132 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
@@ -36,6 +36,7 @@ deps = [ ":account_manager_browser_proxy", "..:deep_linking_behavior", + "..:icon", "..:metrics_recorder", "..:os_route", "..:route_observer_behavior", @@ -44,7 +45,6 @@ "//ash/webui/common/resources:web_ui_listener_behavior", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js:icon", ] externs_list = [ @@ -128,6 +128,7 @@ ":lock_state_behavior", ":os_sync_controls", "..:deep_linking_behavior", + "..:icon", "..:os_page_visibility", "..:os_route", "..:route_observer_behavior", @@ -139,7 +140,6 @@ "//ash/webui/common/resources/quick_unlock:lock_screen_constants", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert", - "//ui/webui/resources/js:icon", "//ui/webui/resources/js:load_time_data.m", ] externs_list =
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js index 53c5a53..5443be0 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
@@ -18,7 +18,6 @@ import '../../settings_shared.css.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {getImage} from 'chrome://resources/js/icon.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -26,6 +25,7 @@ import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; import {Route} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; +import {getImage} from '../icon.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; import {ParentalControlsBrowserProxy, ParentalControlsBrowserProxyImpl} from '../parental_controls_page/parental_controls_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js index 1d46ef6..30a3096 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
@@ -33,7 +33,6 @@ import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; import {assert} from 'chrome://resources/js/assert.js'; import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; -import {getImage} from 'chrome://resources/js/icon.js'; import {afterNextRender, flush, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; @@ -42,6 +41,7 @@ import {SyncBrowserProxyImpl} from '../../people_page/sync_browser_proxy.js'; import {Route, Router} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; +import {getImage} from '../icon.js'; import {OSPageVisibility} from '../os_page_visibility.js'; import {routes} from '../os_route.js'; import {SettingsParentalControlsPageElement} from '../parental_controls_page/parental_controls_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.ts b/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.ts index d6248cf..46042da 100644 --- a/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.ts
@@ -16,10 +16,9 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_reset_page.html.js'; @@ -30,10 +29,10 @@ } const OsSettingsResetPageElementBase = - mixinBehaviors( - [DeepLinkingBehavior, RouteObserverBehavior], PolymerElement) as { + mixinBehaviors([DeepLinkingBehavior], RouteObserverMixin(PolymerElement)) as + { new (): PolymerElement & DeepLinkingBehaviorInterface & - RouteObserverBehaviorInterface, + RouteObserverMixinInterface, }; class OsSettingsResetPageElement extends OsSettingsResetPageElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.ts b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.ts index 4470b02..b06f9569 100644 --- a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.ts
@@ -27,19 +27,18 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_search_page.html.js'; const OsSettingsSearchPageElementBase = mixinBehaviors( - [DeepLinkingBehavior, RouteObserverBehavior], - I18nMixin(PolymerElement)) as { + [DeepLinkingBehavior], RouteObserverMixin(I18nMixin(PolymerElement))) as + { new (): PolymerElement & I18nMixinInterface & - DeepLinkingBehaviorInterface & RouteObserverBehaviorInterface, + DeepLinkingBehaviorInterface & RouteObserverMixinInterface, }; class OsSettingsSearchPageElement extends OsSettingsSearchPageElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts index 414753e8..edef082 100644 --- a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts +++ b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts
@@ -25,22 +25,21 @@ import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {castExists} from '../assert_extras.js'; import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './search_subpage.html.js'; const SettingsSearchSubpageElementBase = mixinBehaviors( - [DeepLinkingBehavior, PrefsBehavior, RouteObserverBehavior], - I18nMixin(PolymerElement)) as { + [DeepLinkingBehavior, PrefsBehavior], + RouteObserverMixin(I18nMixin(PolymerElement))) as { new (): PolymerElement & DeepLinkingBehaviorInterface & I18nMixinInterface & PrefsBehaviorInterface & - RouteObserverBehaviorInterface, + RouteObserverMixinInterface, }; class SettingsSearchSubpageElement extends SettingsSearchSubpageElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 1ad40de8f..dc1b84c 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -137,6 +137,7 @@ "chromeos/global_scroll_target_behavior.js", "chromeos/google_assistant_page/google_assistant_browser_proxy.ts", "chromeos/guest_os/guest_os_browser_proxy.js", + "chromeos/icon.js", "chromeos/internet_page/cellular_setup_settings_delegate.js", "chromeos/internet_page/internet_page_browser_proxy.js", "chromeos/kerberos_page/kerberos_accounts_browser_proxy.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts index f372cc33..7341116 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts
@@ -17,14 +17,13 @@ import '../../settings_shared.css.js'; import '../../settings_vars.css.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {assertExists} from '../assert_extras.js'; import {OSPageVisibility} from '../os_page_visibility.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_settings_main.html.js'; @@ -39,10 +38,11 @@ }; } -const OsSettingsMainElementBase = - mixinBehaviors([RouteObserverBehavior], PolymerElement) as { - new (): PolymerElement & RouteObserverBehaviorInterface, - }; +// TODO(crbug/1315757) Remove need to typecast and intersect mixin interfaces +// once RouteObserverMixin is converted to TS +const OsSettingsMainElementBase = RouteObserverMixin(PolymerElement) as { + new (): PolymerElement & RouteObserverMixinInterface, +}; class OsSettingsMainElement extends OsSettingsMainElementBase { static get is() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.ts b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.ts index 385b0edc..457a6ef 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.ts
@@ -17,12 +17,11 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {IronCollapseElement} from 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js'; import {IronSelectorElement} from 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {castExists} from '../assert_extras.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_settings_menu.html.js'; @@ -34,10 +33,11 @@ }; } -const OsSettingsMenuElementBase = - mixinBehaviors([RouteObserverBehavior], PolymerElement) as { - new (): PolymerElement & RouteObserverBehaviorInterface, - }; +// TODO(crbug/1315757) Remove need to typecast and intersect mixin interfaces +// once RouteObserverMixin is converted to TS +const OsSettingsMenuElementBase = RouteObserverMixin(PolymerElement) as { + new (): PolymerElement & RouteObserverMixinInterface, +}; class OsSettingsMenuElement extends OsSettingsMenuElementBase { static get is() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts index 8ab15d404..ceae6a7 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts
@@ -22,23 +22,22 @@ import '../../prefs/prefs.js'; import '../../settings_vars.css.js'; -import {CrContainerShadowBehavior} from 'chrome://resources/ash/common/cr_container_shadow_behavior.js'; +import {CrContainerShadowMixin, CrContainerShadowMixinInterface} from 'chrome://resources/cr_elements/cr_container_shadow_mixin.js'; import {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js'; import {FindShortcutMixin, FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {listenOnce} from 'chrome://resources/js/util.js'; -import {Debouncer, DomIf, microTask, mixinBehaviors, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {Debouncer, DomIf, microTask, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; import {SettingsPrefsElement} from '../../prefs/prefs.js'; -import {Route, Router} from '../../router.js'; +import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {castExists} from '../assert_extras.js'; import {setGlobalScrollTarget} from '../global_scroll_target_behavior.js'; import {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSettingChange} from '../metrics_recorder.js'; import {OSPageVisibility, osPageVisibility} from '../os_page_visibility.js'; import {OsToolbarElement} from '../os_toolbar/os_toolbar.js'; import {PrefToSettingMetricConverter} from '../pref_to_setting_metric_converter.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {getTemplate} from './os_settings_ui.html.js'; @@ -72,17 +71,16 @@ }; } +// TODO(crbug/1315757) Remove need to typecast and intersect mixin interfaces +// once RouteObserverMixin is converted to TS const OsSettingsUiElementBase = - mixinBehaviors( - [ - CrContainerShadowBehavior, - // Calls currentRouteChanged() in attached(),so ensure other behaviors - // run their attached() first. - RouteObserverBehavior, - ], - FindShortcutMixin(PolymerElement)) as { - new (): PolymerElement & CrContainerShadowBehavior & - FindShortcutMixinInterface & RouteObserverBehaviorInterface, + // RouteObserverMixin calls currentRouteChanged() in + // connectedCallback(), so ensure other mixins/behaviors run their + // connectedCallback() first. + RouteObserverMixin( + FindShortcutMixin(CrContainerShadowMixin(PolymerElement))) as { + new (): PolymerElement & FindShortcutMixinInterface & + CrContainerShadowMixinInterface & RouteObserverMixinInterface, }; class OsSettingsUiElement extends OsSettingsUiElementBase {
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index 28124e1a..bfda629 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -82,6 +82,10 @@ } const element = document.createElement(htmlTag); + const direction = chrome.readAnything.getTextDirection(nodeId); + if (direction) { + element.setAttribute('dir', direction); + } const url = chrome.readAnything.getUrl(nodeId); if (url) { element.setAttribute('href', url);
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts index 7a8d604a..04ae40a 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
@@ -38,6 +38,9 @@ // the selected text. function getTextContent(nodeId: number): string; + // Returns the text direction of the AXNode for the provided AXNodeID. + function getTextDirection(nodeId: number): string; + // Returns the url of the AXNode for the provided AXNodeID. function getUrl(nodeId: number): string;
diff --git a/chrome/browser/resources/tab_strip/drag_manager.ts b/chrome/browser/resources/tab_strip/drag_manager.ts index 05d7e6e9..06c2ae71 100644 --- a/chrome/browser/resources/tab_strip/drag_manager.ts +++ b/chrome/browser/resources/tab_strip/drag_manager.ts
@@ -69,7 +69,7 @@ placeTabGroupElement(element: TabGroupElement, index: number): void; - shouldPreventDrag(): boolean; + shouldPreventDrag(isDraggingTab: boolean): boolean; } type DragManagerDelegateElement = DragManagerDelegate&HTMLElement; @@ -470,7 +470,7 @@ return; } - if (this.delegate_.shouldPreventDrag()) { + if (this.delegate_.shouldPreventDrag(isTabElement(draggedItem))) { event.preventDefault(); return; }
diff --git a/chrome/browser/resources/tab_strip/tab_list.ts b/chrome/browser/resources/tab_strip/tab_list.ts index 7909f39..4b9ce7b 100644 --- a/chrome/browser/resources/tab_strip/tab_list.ts +++ b/chrome/browser/resources/tab_strip/tab_list.ts
@@ -778,12 +778,17 @@ this.animateScrollPosition_(scrollBy); } - shouldPreventDrag(): boolean { - // Do not allow dragging if there's only 1 tab with no tab group, or only 1 - // tab group with no other tabs outside of the tab group. - return (this.pinnedTabsElement_.childElementCount + - this.unpinnedTabsElement_.childElementCount) === - 1; + shouldPreventDrag(isDraggingTab: boolean): boolean { + if (isDraggingTab) { + // Do not allow dragging a tab if there's only 1 tab. + return this.$all('tabstrip-tab').length === 1; + } else { + // Do not allow dragging the tab group with no others outside of the tab + // group. In this case there is only 1 pinned and unpinned top level + // element, which is the dragging tab group itself. + return (this.pinnedTabsElement_.childElementCount + + this.unpinnedTabsElement_.childElementCount) === 1; + } } private tabThumbnailUpdated_(tabId: number, imgData: string) {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc index 1a5bd4b..0c9daa6 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -962,6 +962,26 @@ EXPECT_EQ("token2", reuse_lookup.verdict_token()) << t; t++; } + + { + auto response = std::make_unique<LoginReputationClientResponse>(); + response->set_verdict_token("token3"); + response->set_verdict_type(LoginReputationClientResponse::PHISHING); + service_->MaybeLogPasswordReuseLookupEvent( + web_contents(), RequestOutcome::RESPONSE_ALREADY_CACHED, + PasswordType::PRIMARY_ACCOUNT_PASSWORD, response.get()); + ASSERT_EQ(t + 1, GetUserEventService()->GetRecordedUserEvents().size()) + << t; + PasswordReuseLookup reuse_lookup = GetUserEventService() + ->GetRecordedUserEvents()[t] + .gaia_password_reuse_event() + .reuse_lookup(); + EXPECT_EQ(PasswordReuseLookup::CACHE_HIT, reuse_lookup.lookup_result()) + << t; + EXPECT_EQ(PasswordReuseLookup::PHISHING, reuse_lookup.verdict()) << t; + EXPECT_EQ("token3", reuse_lookup.verdict_token()) << t; + t++; + } } TEST_F(ChromePasswordProtectionServiceTest, VerifyGetDefaultChangePasswordURL) {
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_config_unittest.cc b/chrome/browser/segmentation_platform/segmentation_platform_config_unittest.cc index 981be8bf..d08dece 100644 --- a/chrome/browser/segmentation_platform/segmentation_platform_config_unittest.cc +++ b/chrome/browser/segmentation_platform/segmentation_platform_config_unittest.cc
@@ -17,27 +17,14 @@ namespace segmentation_platform { -using ::base::test::ScopedFeatureList; - class SegmentationPlatformConfigTest : public testing::Test { public: SegmentationPlatformConfigTest() = default; ~SegmentationPlatformConfigTest() override = default; - void SetUp() override { - Test::SetUp(); - scoped_feature_list_ = std::make_unique<ScopedFeatureList>(); - } - - void TearDown() override { - Test::TearDown(); - scoped_feature_list_.reset(); - } - void EnableFeaturesWithParams( - const std::vector<ScopedFeatureList::FeatureAndParams>& - enabled_features) { - scoped_feature_list_->InitWithFeaturesAndParameters(enabled_features, {}); + const std::vector<base::test::FeatureRefAndParams>& enabled_features) { + scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features, {}); // Activate each field trial so that these trials are considered as Active // groups. the FieldTrialList currently does not consider force enabled // trials as "active" by default. @@ -51,7 +38,7 @@ } protected: - std::unique_ptr<ScopedFeatureList> scoped_feature_list_; + base::test::ScopedFeatureList scoped_feature_list_; }; TEST_F(SegmentationPlatformConfigTest, GetSegmentationPlatformConfig) { @@ -63,15 +50,14 @@ } TEST_F(SegmentationPlatformConfigTest, EmptyFeatures) { - ScopedFeatureList scoped_feature_list_; std::vector<std::unique_ptr<Config>> configs; AppendConfigsFromExperiments(configs); EXPECT_TRUE(configs.empty()); } TEST_F(SegmentationPlatformConfigTest, BadFormat) { - std::vector<ScopedFeatureList::FeatureAndParams> features; - features.push_back(ScopedFeatureList::FeatureAndParams( + std::vector<base::test::FeatureRefAndParams> features; + features.push_back(base::test::FeatureRefAndParams( features::kSegmentationPlatformLowEngagementFeature, {{"segmentation_platform_add_config_param", "bad_json"}})); EnableFeaturesWithParams(features); @@ -119,14 +105,14 @@ proto::SegmentId:: OPTIMIZATION_TARGET_NOTIFICATION_PERMISSION_PREDICTIONS}; - std::vector<ScopedFeatureList::FeatureAndParams> features; - features.push_back(ScopedFeatureList::FeatureAndParams( + std::vector<base::test::FeatureRefAndParams> features; + features.push_back(base::test::FeatureRefAndParams( features::kSegmentationPlatformLowEngagementFeature, {{"segmentation_platform_add_config_param", "bad_json"}})); - features.push_back(ScopedFeatureList::FeatureAndParams( + features.push_back(base::test::FeatureRefAndParams( features::kSegmentationPlatformFeedSegmentFeature, {{"segmentation_platform_add_config_param", kValidConfig1}})); - features.push_back(ScopedFeatureList::FeatureAndParams( + features.push_back(base::test::FeatureRefAndParams( features::kShoppingUserSegmentFeature, {{"segmentation_platform_add_config_param", kValidConfig2}})); EnableFeaturesWithParams(features);
diff --git a/chrome/browser/sessions/DEPS b/chrome/browser/sessions/DEPS index ee77d5b..7878abe 100644 --- a/chrome/browser/sessions/DEPS +++ b/chrome/browser/sessions/DEPS
@@ -8,8 +8,4 @@ # Tests may depend upon views. "+chrome/browser/ui/views", ], - "session_restore\.cc": [ - "+ash/shell.h", - "+ash/metrics/login_unlock_throughput_recorder.h", - ], }
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index f49871b..f71a402e 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc
@@ -92,11 +92,7 @@ #include "extensions/common/extension_set.h" #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/metrics/login_unlock_throughput_recorder.h" -#include "ash/shell.h" #include "chrome/browser/ash/boot_times_recorder.h" -#include "components/app_restore/window_properties.h" -#include "ui/compositor/layer.h" #endif using content::NavigationController; @@ -118,50 +114,6 @@ // Pointers to SessionRestoreImpls which are currently restoring the session. std::set<SessionRestoreImpl*>* active_session_restorers = nullptr; -#if BUILDFLAG(IS_CHROMEOS_ASH) -void StartRecordingRestoredWindowsMetrics( - const std::vector<std::unique_ptr<sessions::SessionWindow>>& windows) { - // Ash is not always initialized in unit tests. - if (!ash::Shell::HasInstance()) - return; - - ash::LoginUnlockThroughputRecorder* throughput_recorder = - ash::Shell::Get()->login_unlock_throughput_recorder(); - - for (const auto& w : windows) { - if (w->type == sessions::SessionWindow::TYPE_NORMAL) { - throughput_recorder->AddScheduledRestoreWindow( - w->window_id.id(), w->app_name, - ash::LoginUnlockThroughputRecorder::kBrowser); - } - } -} - -void ReportRestoredWindowCreated(aura::Window* window) { - // Ash is not always initialized in unit tests. - if (!ash::Shell::HasInstance()) - return; - - const int32_t restore_window_id = - window->GetProperty(app_restore::kRestoreWindowIdKey); - - // Restored window IDs are always non-zero. - if (restore_window_id == 0) - return; - - ash::LoginUnlockThroughputRecorder* throughput_recorder = - ash::Shell::Get()->login_unlock_throughput_recorder(); - throughput_recorder->OnRestoredWindowCreated(restore_window_id); - aura::Window* root_window = window->GetRootWindow(); - if (root_window) { - ui::Compositor* compositor = root_window->layer()->GetCompositor(); - throughput_recorder->OnBeforeRestoredWindowShown(restore_window_id, - compositor); - } -} - -#endif - } // namespace // SessionRestoreImpl --------------------------------------------------------- @@ -463,11 +415,6 @@ if (!read_error_) read_error_ = read_error; -#if BUILDFLAG(IS_CHROMEOS_ASH) - if (!read_error_) - StartRecordingRestoredWindowsMetrics(windows); -#endif - // Copy windows into windows_ so that we can combine both app and browser // windows together before doing a one-pass restore. std::copy(std::make_move_iterator(windows.begin()), @@ -629,7 +576,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::BootTimesRecorder::Get()->AddLoginTimeMarker( "SessionRestore-CreateRestoredBrowser-End", false); - ReportRestoredWindowCreated(browser->window()->GetNativeWindow()); #endif }
diff --git a/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc b/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc index ceb6f0c..9244c679 100644 --- a/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc +++ b/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc
@@ -20,6 +20,7 @@ #include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/blink/public/common/features.h" #include "url/gurl.h" class TestMemoryDetails : public MetricsMemoryDetails { @@ -75,13 +76,13 @@ // BrowsingInstances. if (enable_isolate_sandboxed_iframes_) { feature_list_.InitWithFeatures( - /* enable_features */ {features::kIsolateSandboxedIframes, + /* enable_features */ {blink::features::kIsolateSandboxedIframes, features::kDisableProcessReuse}, /* disable_features */ {features::kSpareRendererForSitePerProcess}); } else { feature_list_.InitWithFeatures( /* enable_features */ {features::kDisableProcessReuse}, - /* disable_features */ {features::kIsolateSandboxedIframes, + /* disable_features */ {blink::features::kIsolateSandboxedIframes, features::kSpareRendererForSitePerProcess}); } }
diff --git a/chrome/browser/sync/sync_service_factory_unittest.cc b/chrome/browser/sync/sync_service_factory_unittest.cc index 7e22ca7b..33714acf 100644 --- a/chrome/browser/sync/sync_service_factory_unittest.cc +++ b/chrome/browser/sync/sync_service_factory_unittest.cc
@@ -84,7 +84,7 @@ // Returns the collection of default datatypes. syncer::ModelTypeSet DefaultDatatypes() { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled)."); @@ -96,6 +96,9 @@ // ChromeSyncClient types. datatypes.Put(syncer::READING_LIST); datatypes.Put(syncer::SECURITY_EVENTS); + if (base::FeatureList::IsEnabled(syncer::kSyncSegmentationDataType)) { + datatypes.Put(syncer::SEGMENTATION); + } #if BUILDFLAG(ENABLE_SUPERVISED_USERS) datatypes.Put(syncer::SUPERVISED_USER_SETTINGS);
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 b943f862..01bc140d 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
@@ -28,7 +28,7 @@ namespace { syncer::ModelTypeSet AllowedTypesInStandaloneTransportMode() { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "Add new types below if they run in transport mode"); // Only some special allowlisted types (and control types) are allowed in // standalone transport mode.
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java index 5770f64..be61137 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
@@ -171,6 +171,11 @@ TextView passwordText = view.findViewById(R.id.password); passwordText.setText(credential.getPassword()); passwordText.setTransformationMethod(new PasswordTransformationMethod()); + + String contentDescription = view.getContext().getString( + R.string.touch_to_fill_password_credential_accessibility_description, + credential.getFormattedUsername()); + view.setContentDescription(contentDescription); } else if (propertyKey == SHOW_SUBMIT_BUTTON) { // Whether Touch To Fill should auto-submit a form doesn't affect the credentials list. } else { @@ -202,6 +207,10 @@ usernameText.setText(credential.getUsername()); TextView descriptionText = view.findViewById(R.id.webauthn_credential_context); descriptionText.setText(R.string.touch_to_fill_sheet_webauthn_credential_context); + String contentDescription = view.getContext().getString( + R.string.touch_to_fill_passkey_credential_accessibility_description, + credential.getUsername()); + view.setContentDescription(contentDescription); } else if (propertyKey == SHOW_WEBAUTHN_SUBMIT_BUTTON) { // Ignore. } else {
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd index 7de9939f..654e3a8 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd +++ b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
@@ -232,6 +232,12 @@ <message name="IDS_TOUCH_TO_FILL_SHEET_WEBAUTHN_CREDENTIAL_CONTEXT" desc="Context string for second line of a Passkey on the Touch To Fill sheet, beneath the username."> Use your screen lock </message> + <message name="IDS_TOUCH_TO_FILL_PASSWORD_CREDENTIAL_ACCESSIBILITY_DESCRIPTION" desc="Content description for a password credential item on the sheet list. This is not visually displayed, but is audibly read by screen readers for accessibility purposes."> + Password for <ph name="USERNAME">%1$s<ex>John.Doe@example.com</ex></ph>. + </message> + <message name="IDS_TOUCH_TO_FILL_PASSKEY_CREDENTIAL_ACCESSIBILITY_DESCRIPTION" desc="Content description for a passkey credential item on the sheet list. This is not visually displayed, but is audibly read by screen readers for accessibility purposes."> + Passkey for <ph name="USERNAME">%1$s<ex>John.Doe@example.com</ex></ph>, use your screen lock. + </message> </messages> </release> </grit>
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSKEY_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1 b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSKEY_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..4cac228 --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSKEY_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +dfa6a8d96285248a2f2ffd64dc81dfd446a411d3 \ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSWORD_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1 b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSWORD_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..05e94f0 --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_PASSWORD_CREDENTIAL_ACCESSIBILITY_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +ebf05b0512c6da1827e834248575e35ef980c870 \ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java index c8c9dce..b4fb53259 100644 --- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java +++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
@@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; @@ -26,6 +27,7 @@ import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.ON_CLICK_MANAGE; import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.VISIBLE; +import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.WebAuthnCredentialProperties.WEBAUTHN_CREDENTIAL; import static java.util.Arrays.asList; @@ -53,6 +55,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties; import org.chromium.chrome.browser.touch_to_fill.data.Credential; +import org.chromium.chrome.browser.touch_to_fill.data.WebAuthnCredential; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; @@ -81,6 +84,7 @@ new Credential("", "***", "No Username", "m.example.xyz", true, false, 0); private static final Credential BOB = new Credential("Bob", "***", "Bob", "mobile.example.xyz", true, false, 0); + private static final WebAuthnCredential CAM = new WebAuthnCredential("Cam", "12345"); private static final Credential NIK = new Credential("Nik", "***", "Nik", "group.xyz", false, true, 0); @@ -435,6 +439,41 @@ verify(mDismissHandler).onResult(BottomSheetController.StateChangeReason.NONE); } + @Test + @MediumTest + public void testPasswordCredentialAccessibilityDescription() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mModel.get(SHEET_ITEMS).addAll(Collections.singletonList(buildCredentialItem(ANA))); + mModel.set(VISIBLE, true); + }); + + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + assertNotNull(getCredentials().getChildAt(0)); + assertEquals(getCredentials().getChildAt(0).getContentDescription(), + getActivity().getString( + R.string.touch_to_fill_password_credential_accessibility_description, + ANA.getFormattedUsername())); + } + + @Test + @MediumTest + public void testPasskeyCredentialAccessibilityDescription() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mModel.get(SHEET_ITEMS) + .addAll(Collections.singletonList(buildWebAuthnCredentialItem(CAM))); + mModel.set(VISIBLE, true); + }); + + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + assertNotNull(getCredentials().getChildAt(0)); + assertEquals(getCredentials().getChildAt(0).getContentDescription(), + getActivity().getString( + R.string.touch_to_fill_passkey_credential_accessibility_description, + CAM.getUsername())); + } + private ChromeActivity getActivity() { return mActivityTestRule.getActivity(); } @@ -469,6 +508,14 @@ TouchToFillProperties.ItemType.CREDENTIAL, credential, mCredentialCallback, false); } + private MVCListAdapter.ListItem buildWebAuthnCredentialItem(WebAuthnCredential credential) { + return new MVCListAdapter.ListItem(TouchToFillProperties.ItemType.WEBAUTHN_CREDENTIAL, + new PropertyModel + .Builder(TouchToFillProperties.WebAuthnCredentialProperties.ALL_KEYS) + .with(WEBAUTHN_CREDENTIAL, credential) + .build()); + } + private MVCListAdapter.ListItem buildConfirmationButton( Credential credential, boolean showSubmitButton) { return buildSheetItem(TouchToFillProperties.ItemType.FILL_BUTTON, credential,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 4a3990d..9ed442c5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1762,6 +1762,13 @@ ] } + if (toolkit_views && is_chrome_branded) { + sources += [ + "webui/lens/lens_ui.cc", + "webui/lens/lens_ui.h", + ] + } + deps += [ "//base", "//build:chromeos_buildflags",
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/optional_button_layout.xml b/chrome/browser/ui/android/toolbar/java/res/layout/optional_button_layout.xml index 8337c5de..14606bf 100644 --- a/chrome/browser/ui/android/toolbar/java/res/layout/optional_button_layout.xml +++ b/chrome/browser/ui/android/toolbar/java/res/layout/optional_button_layout.xml
@@ -35,6 +35,8 @@ android:layout_marginStart="40dp" android:gravity="center" android:visibility="gone" + android:maxLines="1" + android:ellipsize="end" android:textAppearance="@style/TextAppearance.TextLarge.Primary"/> <org.chromium.ui.widget.ChromeImageView android:layout_width="40dp"
diff --git a/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml b/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml index 4471383..1a3aa3c 100644 --- a/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml +++ b/chrome/browser/ui/android/toolbar/java/res/values/dimens.xml
@@ -19,6 +19,7 @@ <!-- Toolbar Phone - padding of the optional button when menu button is present --> <dimen name="toolbar_phone_optional_button_padding">12dp</dimen> + <dimen name="toolbar_phone_optional_button_action_chip_max_width">175dp</dimen> <!-- Home Button Menu dimensions--> <dimen name="home_button_list_menu_width">222dp</dimen>
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/BaseButtonDataProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/BaseButtonDataProvider.java index 5877f91e..c97ed1f 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/BaseButtonDataProvider.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/BaseButtonDataProvider.java
@@ -36,6 +36,7 @@ private ModalDialogManagerObserver mModalDialogObserver; private boolean mShouldShowOnIncognitoTabs; + private @StringRes int mActionChipResourceId; /** * Creates a new instance of {@code BaseButtonDataProvider}. @@ -122,6 +123,16 @@ mButtonData.updateIPHCommandBuilder(getIphCommandBuilder(tab)); } + private void maybeSetActionChipResourceId() { + if (!mButtonData.getButtonSpec().isDynamicAction() || !FeatureList.isInitialized() + || !AdaptiveToolbarFeatures.shouldShowActionChip() + || mButtonData.getButtonSpec().getActionChipLabelResId() != Resources.ID_NULL) { + return; + } + + mButtonData.updateActionChipResourceId(mActionChipResourceId); + } + /** * Sets whether the button should be shown on incognito tabs, default is false. */ @@ -130,6 +141,15 @@ } /** + * Sets a string resource ID to be used when the action chip variant is enabled, only used on + * dynamic actions. + * @param actionChipResourceId A string resource to use as the action chip label. + */ + protected void setActionChipResourceId(@StringRes int actionChipResourceId) { + mActionChipResourceId = actionChipResourceId; + } + + /** * Gets an {@link IPHCommandBuilder} builder instance to use on this button. Only called when * native is initialized and when there's no IPHCommandBuilder set. * @param tab Current tab. @@ -155,6 +175,7 @@ public ButtonData get(Tab tab) { mButtonData.setCanShow(shouldShowButton(tab)); maybeSetIphCommandBuilder(tab); + maybeSetActionChipResourceId(); return mButtonData; }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java index e1e8544d..11382b94 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsChecker.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.toolbar; +import android.os.Handler; + import androidx.annotation.NonNull; import org.chromium.base.Callback; @@ -19,15 +21,19 @@ private final ViewResourceAdapter mViewResourceAdapter; @NonNull private final ObservableSupplier<Integer> mConstraintsSupplier; + @NonNull + private final Handler mHandler; /** * @param viewResourceAdapter The target to notify when a capture is needed. * @param constraintsSupplier The underlying supplier for the state of constraints. + * @param handler Handler to post deferred tasks to. */ public ConstraintsChecker(@NonNull ViewResourceAdapter viewResourceAdapter, - @NonNull ObservableSupplier<Integer> constraintsSupplier) { + @NonNull ObservableSupplier<Integer> constraintsSupplier, @NonNull Handler handler) { mViewResourceAdapter = viewResourceAdapter; mConstraintsSupplier = constraintsSupplier; + mHandler = handler; } /** @@ -53,7 +59,7 @@ public void onResult(Integer result) { if (!areControlsLocked()) { mConstraintsSupplier.removeObserver(this); - mViewResourceAdapter.onResourceRequested(); + mHandler.post(() -> mViewResourceAdapter.onResourceRequested()); } } } \ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsCheckerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsCheckerTest.java index 673ecf8e..ebaa559 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsCheckerTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ConstraintsCheckerTest.java
@@ -5,9 +5,13 @@ package org.chromium.chrome.browser.toolbar; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.os.Handler; + import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,13 +34,22 @@ @Mock private ViewResourceAdapter mViewResourceAdapter; + @Mock + private Handler mHandler; private ObservableSupplierImpl mConstraintsSupplier = new ObservableSupplierImpl(); @Test public void testScheduleRequestResourceOnUnlock() { + doAnswer((invocation) -> { + Runnable runnable = (Runnable) invocation.getArguments()[0]; + runnable.run(); + return null; + }) + .when(mHandler) + .post(any(Runnable.class)); ConstraintsChecker constraintsChecker = - new ConstraintsChecker(mViewResourceAdapter, mConstraintsSupplier); + new ConstraintsChecker(mViewResourceAdapter, mConstraintsSupplier, mHandler); constraintsChecker.scheduleRequestResourceOnUnlock(); mConstraintsSupplier.set(BrowserControlsState.SHOWN); verify(mViewResourceAdapter, times(0)).onResourceRequested(); @@ -51,7 +64,7 @@ @Test public void testAreControlsLocked() { ConstraintsChecker constraintsChecker = - new ConstraintsChecker(mViewResourceAdapter, mConstraintsSupplier); + new ConstraintsChecker(mViewResourceAdapter, mConstraintsSupplier, mHandler); assertEquals(true, constraintsChecker.areControlsLocked()); mConstraintsSupplier.set(BrowserControlsState.SHOWN);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java index 9651936..32f1b93 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java
@@ -8,6 +8,8 @@ import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.Rect; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; import androidx.annotation.NonNull; @@ -120,6 +122,7 @@ */ public void setConstraintsSupplier(ObservableSupplier<Integer> constraintsSupplier) { assert mConstraintsChecker == null; - mConstraintsChecker = new ConstraintsChecker(getResourceAdapter(), constraintsSupplier); + mConstraintsChecker = new ConstraintsChecker( + getResourceAdapter(), constraintsSupplier, new Handler(Looper.getMainLooper())); } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java index 3aefd75..3deb1485 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
@@ -584,12 +584,16 @@ mActionChipLabel.setVisibility(VISIBLE); mBackground.setVisibility(VISIBLE); - // TODO(salg): Add a check to avoid expanding too much. float actionChipLabelTextWidth = mActionChipLabel.getPaint().measureText(mActionChipLabelString); - int expandedStateWidthPx = - (int) (mCollapsedStateWidthPx + actionChipLabelTextWidth + mExpandedStatePaddingPx); + int maxExpandedStateWidthPx = getResources().getDimensionPixelSize( + R.dimen.toolbar_phone_optional_button_action_chip_max_width); + + int expandedStateWidthPx = Math.min( + (int) (mCollapsedStateWidthPx + actionChipLabelTextWidth + mExpandedStatePaddingPx), + maxExpandedStateWidthPx); + setWidth(expandedStateWidthPx); mState = State.RUNNING_ACTION_CHIP_EXPANSION_TRANSITION;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewTest.java index b81bf609..92a7b1f 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonViewTest.java
@@ -36,6 +36,7 @@ import androidx.appcompat.content.res.AppCompatResources; +import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -666,4 +667,27 @@ // visibility many times should begin a new animation. verify(mMockBeginDelayedTransition, times(2)).onResult(any()); } + + @Test + public void testUpdateButton_actionChipWidthIsRestricted() { + ButtonDataImpl buttonData = getDataForPriceTrackingActionChip(); + // Set a string that's too long as an action chip label. Real code measures the number of + // pixels this will take on screen, but robolectric just uses the character count, so use + // any string with more than 150 characters. + buttonData.updateActionChipResourceId(R.string.sign_in_managed_account_description); + + int maxActionChipWidth = mOptionalButtonView.getResources().getDimensionPixelSize( + R.dimen.toolbar_phone_optional_button_action_chip_max_width); + + ViewGroup transitionRoot = mock(ViewGroup.class); + mOptionalButtonView.setTransitionRoot(transitionRoot); + + mOptionalButtonView.updateButtonWithAnimation(buttonData); + mOptionalButtonView.onTransitionStart(null); + mOptionalButtonView.onTransitionEnd(null); + + // Button shouldn't be wider than the established maximum. + Assert.assertThat(mOptionalButtonView.getLayoutParams().width, + Matchers.lessThanOrEqualTo(maxActionChipWidth)); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java index 876408f..51308db 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
@@ -11,6 +11,8 @@ import android.graphics.Region; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -237,7 +239,8 @@ assert mConstraintsObserver == null; if (constraintsSupplier != null) { - mConstraintsObserver = new ConstraintsChecker(this, constraintsSupplier); + mConstraintsObserver = new ConstraintsChecker( + this, constraintsSupplier, new Handler(Looper.getMainLooper())); } assert mTabSupplier == null;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java index 955cfc81..c28a563 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
@@ -18,6 +18,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.UmaRecorderHolder; @@ -218,6 +219,7 @@ // BOTH should cause a new onResourceRequested call. mConstraintsSupplier.set(BrowserControlsState.BOTH); + ShadowLooper.idleMainLooper(); Assert.assertEquals(1, onResourceRequestedCount.get()); // The constraints should no longer block isDirty/captures.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 5c92c4f..d9b5e3ec 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1522,6 +1522,7 @@ @Override public void draw(Canvas canvas) { + if (mDestroyChecker.isDestroyed()) return; // If capturing a texture of the toolbar, ensure the alpha is set prior to draw(...) being // called. The alpha is being used prior to getting to draw(...), so updating the value // after this point was having no affect.
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc index 568ca547..589f64e8 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller.cc
@@ -12,7 +12,6 @@ #include "ash/components/arc/arc_util.h" #include "ash/constants/app_types.h" #include "ash/constants/ash_pref_names.h" -#include "ash/metrics/login_unlock_throughput_recorder.h" #include "ash/public/cpp/multi_user_window_manager.h" #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_model.h" @@ -130,26 +129,6 @@ return standard_image; } -// Report shelf buttons initialized to LoginUnlockThroughputRecorder. -void ReportInitShelfIconList(const ash::ShelfModel* model) { - // Shell is not always initializaed in tests. - if (!ash::Shell::HasInstance()) - return; - - ash::Shell::Get()->login_unlock_throughput_recorder()->InitShelfIconList( - model); -} - -// Report shelf buttons updated to LoginUnlockThroughputRecorder. -void ReportUpdateShelfIconList(const ash::ShelfModel* model) { - // Shell is not always initializaed in tests. - if (!ash::Shell::HasInstance()) - return; - - ash::Shell::Get()->login_unlock_throughput_recorder()->UpdateShelfIconList( - model); -} - } // namespace // A class to get events from ChromeOS when a user gets changed or added. @@ -337,7 +316,6 @@ if (browser_status_monitor_) { browser_status_monitor_->Initialize(); } - ReportInitShelfIconList(model_); } ash::ShelfID ChromeShelfController::CreateAppItem( @@ -487,8 +465,6 @@ new_item.id.app_id, image); model_->Set(model_->ItemIndexByID(shelf_id), new_item); } - - ReportUpdateShelfIconList(model_); } void ChromeShelfController::UpdateItemImage(const std::string& app_id) { @@ -711,7 +687,6 @@ model_->GetItemIndexForType(ash::TYPE_UNPINNED_BROWSER_SHORTCUT); if (item_index >= 0) { model_->RemoveItemAt(item_index); - ReportUpdateShelfIconList(model_); return; } } @@ -737,8 +712,6 @@ browser_item.status = browser_status; model_->Set(browser_index, browser_item); - - ReportUpdateShelfIconList(model_); } void ChromeShelfController::SetShelfIDForBrowserWindowContents( @@ -823,8 +796,6 @@ model_->RemoveItemAt(index); model_->AddAt(index, item, std::make_unique<AppShortcutShelfItemController>(item.id)); - - ReportUpdateShelfIconList(model_); } void ChromeShelfController::PinAppAtIndex(const std::string& app_id, @@ -839,8 +810,6 @@ model_->AddAt(target_index, item, std::make_unique<AppShortcutShelfItemController>(item.id)); - - ReportUpdateShelfIconList(model_); } int ChromeShelfController::PinnedItemIndexByAppID(const std::string& app_id) { @@ -1131,8 +1100,6 @@ model_->Set(index, item); // It's possible we're waiting on more than one item, so don't break. } - - ReportUpdateShelfIconList(model_); } /////////////////////////////////////////////////////////////////////////////// @@ -1174,8 +1141,6 @@ const int index = model_->ItemIndexByID(id); if (index >= 0 && index < model_->item_count()) model_->RemoveItemAt(index); - - ReportUpdateShelfIconList(model_); } void ChromeShelfController::PinRunningAppInternal( @@ -1308,8 +1273,6 @@ } UpdatePolicyPinnedAppsFromPrefs(); - - ReportUpdateShelfIconList(model_); } bool ChromeShelfController::EnsureAppPinnedInModelAtIndex( @@ -1367,8 +1330,6 @@ item.pinned_by_policy = pinned_by_policy; model_->Set(model_index, item); } - - ReportUpdateShelfIconList(model_); } ash::ShelfItemStatus ChromeShelfController::GetAppState( @@ -1412,8 +1373,6 @@ item.app_status = ShelfControllerHelper::GetAppStatus( latest_active_profile_, item_delegate->shelf_id().app_id); model_->AddAt(index, item, std::move(item_delegate)); - - ReportUpdateShelfIconList(model_); return item.id; } @@ -1443,8 +1402,6 @@ model_->Add(browser_shortcut, std::make_unique<BrowserShortcutShelfItemController>(model_)); } - - ReportUpdateShelfIconList(model_); } int ChromeShelfController::FindInsertionPoint() { @@ -1611,8 +1568,6 @@ // Update the pin position preference as needed. if (ShouldSyncItemWithReentrancy(item)) SyncPinPosition(item.id); - - ReportUpdateShelfIconList(model_); } void ChromeShelfController::ShelfItemRemoved(int index, @@ -1639,6 +1594,4 @@ SyncPinPosition(item.id); else if (ShouldSyncItemWithReentrancy(old_item) && !ItemTypeIsPinned(item)) shelf_prefs_->RemovePinPosition(profile(), old_item.id); - - ReportUpdateShelfIconList(model_); }
diff --git a/chrome/browser/ui/lens/lens_side_panel_helper.h b/chrome/browser/ui/lens/lens_side_panel_helper.h index 9637f6a..d87a812 100644 --- a/chrome/browser/ui/lens/lens_side_panel_helper.h +++ b/chrome/browser/ui/lens/lens_side_panel_helper.h
@@ -25,6 +25,9 @@ void OpenLensSidePanel(Browser* browser, const content::OpenURLParams& url_params); +// Opens the Lens region search feature in a new tab with a WebUI page. +void OpenLensStaticPage(Browser* browser); + // Check if the lens URL is a valid results page. This is done by checking if // the URL has a payload parameter. bool IsValidLensResultUrl(const GURL& url);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 1a3e5076..09144bcb 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1038,7 +1038,7 @@ // Ensure that the indices are nonempty, sorted, and unique. DCHECK_GT(indices.size(), 0u); DCHECK(base::ranges::is_sorted(indices)); - DCHECK(std::adjacent_find(indices.begin(), indices.end()) == indices.end()); + DCHECK(base::ranges::adjacent_find(indices) == indices.end()); // The odds of |new_group| colliding with an existing group are astronomically // low. If there is a collision, a DCHECK will fail in |AddToNewGroupImpl()|, @@ -1058,7 +1058,7 @@ // Ensure that the indices are sorted and unique. DCHECK(base::ranges::is_sorted(indices)); - DCHECK(std::adjacent_find(indices.begin(), indices.end()) == indices.end()); + DCHECK(base::ranges::adjacent_find(indices) == indices.end()); CHECK(ContainsIndex(*(indices.begin()))); CHECK(ContainsIndex(*(indices.rbegin())));
diff --git a/chrome/browser/ui/views/lens/lens_side_panel_helper.cc b/chrome/browser/ui/views/lens/lens_side_panel_helper.cc index 7c142ab..9746fddc 100644 --- a/chrome/browser/ui/views/lens/lens_side_panel_helper.cc +++ b/chrome/browser/ui/views/lens/lens_side_panel_helper.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/views/lens/lens_side_panel_controller.h" #include "chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" +#include "chrome/common/webui_url_constants.h" #include "components/lens/lens_entrypoints.h" #include "components/lens/lens_features.h" #include "components/lens/lens_rendering_environment.h" @@ -119,4 +120,16 @@ return web_contents; } +void OpenLensStaticPage(Browser* browser) { + // TODO(juanmojica): Expand this function to simulate the current region + // search experience in the new tab. + DCHECK(browser); + GURL url(chrome::kChromeUILensURL); + content::OpenURLParams params( + url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false); + params.initiator_origin = url::Origin::Create(url); + browser->OpenURL(params); +} + } // namespace lens
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc index 31e2d57e..621c7a1 100644 --- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc +++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc
@@ -65,7 +65,7 @@ return promo_controller; } - PageActionIconView* GetPageActionIconView() { + PageActionIconView* GetHighEfficiencyChipView() { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); return browser_view->GetLocationBarView() @@ -73,9 +73,10 @@ ->GetIconView(PageActionIconType::kHighEfficiency); } - void PressButton(views::Button* button) { + void ClickHighEfficiencyChip() { views::test::InteractionTestUtilSimulatorViews::PressButton( - button, ui::test::InteractionTestUtil::InputType::kMouse); + GetHighEfficiencyChipView(), + ui::test::InteractionTestUtil::InputType::kMouse); } void SetTabDiscardState(bool is_discarded) { @@ -100,8 +101,31 @@ waiter.WaitIfNeededAndGet(); } + user_education::HelpBubbleView* GetHelpBubbleView() { + return GetFeaturePromoController() + ->promo_bubble_for_testing() + ->AsA<user_education::HelpBubbleViews>() + ->bubble_view(); + } + + void ClickIPHCancelButton() { + views::test::WidgetDestroyedWaiter waiter(GetHelpBubbleView()->GetWidget()); + views::test::InteractionTestUtilSimulatorViews::PressButton( + GetHelpBubbleView()->GetDefaultButtonForTesting(), + ui::test::InteractionTestUtil::InputType::kMouse); + waiter.Wait(); + } + + void ClickIPHSettingsButton() { + views::test::WidgetDestroyedWaiter waiter(GetHelpBubbleView()->GetWidget()); + views::test::InteractionTestUtilSimulatorViews::PressButton( + GetHelpBubbleView()->GetNonDefaultButtonForTesting(0), + ui::test::InteractionTestUtil::InputType::kMouse); + waiter.Wait(); + } + views::InkDropState GetInkDropState() { - return views::InkDrop::Get(GetPageActionIconView()) + return views::InkDrop::Get(GetHighEfficiencyChipView()) ->GetInkDrop() ->GetTargetInkDropState(); } @@ -111,17 +135,13 @@ }; IN_PROC_BROWSER_TEST_F(HighEfficiencyChipViewBrowserTest, - PromoCustomActionClicked) { + NavigatesOnIPHSettingsLinkClicked) { auto lock = BrowserFeaturePromoController::BlockActiveWindowCheckForTesting(); - auto* const promo_controller = GetFeaturePromoController(); EXPECT_FALSE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); SetTabDiscardState(true); - PageActionIconView* icon = GetPageActionIconView(); - EXPECT_TRUE(icon->GetVisible()); - WaitForIPHToShow(); EXPECT_TRUE(GetFeaturePromoController()->IsPromoActive( @@ -129,11 +149,7 @@ content::TestNavigationObserver navigation_observer( browser()->tab_strip_model()->GetWebContentsAt(0)); - auto* promo_bubble = promo_controller->promo_bubble_for_testing() - ->AsA<user_education::HelpBubbleViews>() - ->bubble_view(); - auto* custom_action_button = promo_bubble->GetNonDefaultButtonForTesting(0); - PressButton(custom_action_button); + ClickIPHSettingsButton(); navigation_observer.Wait(); GURL expected(chrome::kChromeUIPerformanceSettingsURL); @@ -141,56 +157,40 @@ } IN_PROC_BROWSER_TEST_F(HighEfficiencyChipViewBrowserTest, - PromoDismissesOnChipClick) { + PromoDismissesOnCancelClick) { auto lock = BrowserFeaturePromoController::BlockActiveWindowCheckForTesting(); SetTabDiscardState(true); - PageActionIconView* icon = GetPageActionIconView(); WaitForIPHToShow(); EXPECT_TRUE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); - PressButton(icon); + ClickHighEfficiencyChip(); // Expect the bubble to be open and the promo to be closed. EXPECT_FALSE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); - EXPECT_NE(icon->GetBubble(), nullptr); + EXPECT_NE(GetHighEfficiencyChipView()->GetBubble(), nullptr); } IN_PROC_BROWSER_TEST_F(HighEfficiencyChipViewBrowserTest, ShowAndHideInkDropWithPromo) { auto lock = BrowserFeaturePromoController::BlockActiveWindowCheckForTesting(); - auto* const promo_controller = GetFeaturePromoController(); EXPECT_FALSE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); SetTabDiscardState(true); - PageActionIconView* icon = GetPageActionIconView(); - EXPECT_TRUE(icon->GetVisible()); - WaitForIPHToShow(); EXPECT_TRUE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); - EXPECT_EQ(GetInkDropState(), views::InkDropState::ACTIVATED); - auto* promo_bubble = promo_controller->promo_bubble_for_testing() - ->AsA<user_education::HelpBubbleViews>() - ->bubble_view(); + ClickIPHCancelButton(); - views::test::WidgetDestroyedWaiter waiter(promo_bubble->GetWidget()); - auto* default_action_button = promo_bubble->GetDefaultButtonForTesting(); - PressButton(default_action_button); - waiter.Wait(); - - EXPECT_FALSE(browser()->window()->IsFeaturePromoActive( + EXPECT_FALSE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); - - views::InkDropState current_state = GetInkDropState(); - EXPECT_TRUE(current_state == views::InkDropState::HIDDEN || - current_state == views::InkDropState::DEACTIVATED); + EXPECT_TRUE(GetInkDropState() == views::InkDropState::DEACTIVATED); }
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc index 455907a..646a985 100644 --- a/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc +++ b/chrome/browser/ui/views/side_panel/lens/lens_side_panel_coordinator_browsertest.cc
@@ -432,6 +432,7 @@ IN_PROC_BROWSER_TEST_F(SearchImageWithSidePanel3PDseDisabled, ImageSearchFor3PDSEWithValidImageOpensInNewTab) { + SetupImageSearchEngine(); SetupAndLoadValidImagePage(); // Ensures that the lens side panel coordinator is open and is valid when @@ -458,6 +459,7 @@ IN_PROC_BROWSER_TEST_F(SearchImageWithSidePanel3PDseDisabled, ImageSearchForLensWithValidImageOpensInSidePanel) { + SetupImageSearchEngine(); SetupUnifiedSidePanel(); EXPECT_TRUE(GetUnifiedSidePanel()->GetVisible());
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index ede9f17..1f0c418 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -396,6 +396,10 @@ #include "chrome/browser/ui/webui/media_router/cast_feedback_ui.h" #endif +#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) +#include "chrome/browser/ui/webui/lens/lens_ui.h" +#endif + #if BUILDFLAG(PLATFORM_CFM) #include "chrome/browser/ui/webui/ash/chromebox_for_meetings/network_settings_dialog.h" #endif // BUILDFLAG(PLATFORM_CFM) @@ -1354,6 +1358,12 @@ return &NewWebUI<PrivacySandboxDialogUI>; #endif // !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) + if (url.host_piece() == chrome::kChromeUILensHost) { + return &NewWebUI<LensUI>; + } +#endif + return nullptr; }
diff --git a/chrome/browser/ui/webui/lens/DIR_METADATA b/chrome/browser/ui/webui/lens/DIR_METADATA new file mode 100644 index 0000000..749bdad --- /dev/null +++ b/chrome/browser/ui/webui/lens/DIR_METADATA
@@ -0,0 +1,4 @@ +monorail { + component: "UI>Browser" +} +team_email: "lens-chrome-eng+bugs@google.com"
diff --git a/chrome/browser/ui/webui/lens/OWNERS b/chrome/browser/ui/webui/lens/OWNERS new file mode 100644 index 0000000..6e913aa --- /dev/null +++ b/chrome/browser/ui/webui/lens/OWNERS
@@ -0,0 +1,2 @@ +file://components/lens/OWNERS +
diff --git a/chrome/browser/ui/webui/lens/lens_ui.cc b/chrome/browser/ui/webui/lens/lens_ui.cc new file mode 100644 index 0000000..fa20353 --- /dev/null +++ b/chrome/browser/ui/webui/lens/lens_ui.cc
@@ -0,0 +1,25 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/lens/lens_ui.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/lens_resources.h" +#include "chrome/grit/lens_resources_map.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +LensUI::LensUI(content::WebUI* web_ui) : WebUIController(web_ui) { + // Set up the chrome://lens source. + content::WebUIDataSource* html_source = + content::WebUIDataSource::CreateAndAdd(Profile::FromWebUI(web_ui), + chrome::kChromeUILensHost); + webui::SetupWebUIDataSource( + html_source, base::make_span(kLensResources, kLensResourcesSize), + IDR_LENS_LENS_HTML); +} + +LensUI::~LensUI() = default;
diff --git a/chrome/browser/ui/webui/lens/lens_ui.h b/chrome/browser/ui/webui/lens/lens_ui.h new file mode 100644 index 0000000..0bc6a6fa --- /dev/null +++ b/chrome/browser/ui/webui/lens/lens_ui.h
@@ -0,0 +1,16 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_LENS_LENS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_LENS_LENS_UI_H_ + +#include "content/public/browser/web_ui_controller.h" + +// The WebUI for chrome://lens +class LensUI : public content::WebUIController { + public: + explicit LensUI(content::WebUI* web_ui); + ~LensUI() override; +}; +#endif // CHROME_BROWSER_UI_WEBUI_LENS_LENS_UI_H_
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_app_from_command_line_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/install_isolated_app_from_command_line_browsertest.cc index bd70ac5..346f478 100644 --- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_app_from_command_line_browsertest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_app_from_command_line_browsertest.cc
@@ -76,5 +76,6 @@ const WebApp* web_app = GetWebAppRegistrar().GetAppById(app_id); EXPECT_THAT(web_app->isolation_data().has_value(), IsTrue()); } + } // namespace } // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory.cc index 45e2a23..cee7da70 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_factory.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h" #include "chrome/browser/web_applications/isolation_data.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/url_constants.h" @@ -140,6 +141,7 @@ LOG(ERROR) << error_message; return; } + web_contents->ForEachRenderFrameHostWithAction( [frame_tree_node_id, &error_message](content::RenderFrameHost* render_frame_host) { @@ -194,8 +196,8 @@ IsolatedWebAppURLLoader(const IsolatedWebAppURLLoader&) = delete; IsolatedWebAppURLLoader& operator=(const IsolatedWebAppURLLoader&) = delete; - - ~IsolatedWebAppURLLoader() override = default; + IsolatedWebAppURLLoader(IsolatedWebAppURLLoader&&) = delete; + IsolatedWebAppURLLoader& operator=(IsolatedWebAppURLLoader&&) = delete; private: void OnResponseRead( @@ -348,63 +350,79 @@ return; } + auto forward_request_to_isolation_data_content = + [&](const IsolationData& isolation_data) { + if (!IsSupportedHttpMethod(resource_request.method)) { + CompleteWithGeneratedHtmlResponse( + mojo::Remote<network::mojom::URLLoaderClient>( + std::move(loader_client)), + net::HTTP_METHOD_NOT_ALLOWED, /*body=*/absl::nullopt); + return; + } + + absl::visit( + base::Overloaded{ + [&](const IsolationData::InstalledBundle& content) { + auto* isolated_web_app_reader_registry = + IsolatedWebAppReaderRegistryFactory::GetForProfile( + profile_); + if (!isolated_web_app_reader_registry) { + LogErrorAndFail( + "Support for Isolated Web Apps is not enabled.", + std::move(loader_client)); + return; + } + mojo::MakeSelfOwnedReceiver( + std::make_unique<IsolatedWebAppURLLoader>( + isolated_web_app_reader_registry, content.path, + *web_bundle_id, std::move(loader_client), + resource_request, frame_tree_node_id_), + mojo::PendingReceiver<network::mojom::URLLoader>( + std::move(loader_receiver))); + }, + [&](const IsolationData::DevModeBundle& content) { + // TODO: Implement dev mode bundles. + CompleteWithGeneratedHtmlResponse( + mojo::Remote<network::mojom::URLLoaderClient>( + std::move(loader_client)), + net::HTTP_NOT_FOUND, /*body=*/absl::nullopt); + }, + [&](const IsolationData::DevModeProxy& content) { + HandleDevModeProxy(*url_info, content, + std::move(loader_receiver), + resource_request, std::move(loader_client), + traffic_annotation); + }}, + isolation_data.content); + }; + + absl::optional<IsolationData> pending_install_isolation_data = + IsolatedWebAppPendingInstallInfo::FromWebContents( + *content::WebContents::FromFrameTreeNodeId(frame_tree_node_id_)) + .isolation_data(); + if (pending_install_isolation_data.has_value()) { + if (resource_request.url.path() == kInstallPagePath && + IsSupportedHttpMethod(resource_request.method)) { + CompleteWithGeneratedHtmlResponse( + mojo::Remote<network::mojom::URLLoaderClient>( + std::move(loader_client)), + net::HTTP_OK, kInstallPageContent); + return; + } + + forward_request_to_isolation_data_content(*pending_install_isolation_data); + return; + } + base::expected<std::reference_wrapper<const WebApp>, std::string> iwa = FindIsolatedWebApp(profile_, *url_info); + if (!iwa.has_value()) { LogErrorAndFail(iwa.error(), std::move(loader_client)); return; } - if (!IsSupportedHttpMethod(resource_request.method)) { - CompleteWithGeneratedHtmlResponse( - mojo::Remote<network::mojom::URLLoaderClient>(std::move(loader_client)), - net::HTTP_METHOD_NOT_ALLOWED, /*body=*/absl::nullopt); - return; - } - - // TODO(crbug.com/1333966): Check that the app is being installed before - // returning the auto-generated installation page. - if (resource_request.url.path() == kInstallPagePath) { - CompleteWithGeneratedHtmlResponse( - mojo::Remote<network::mojom::URLLoaderClient>(std::move(loader_client)), - net::HTTP_OK, kInstallPageContent); - return; - } - - IsolationData isolation_data = iwa->get().isolation_data().value(); - absl::visit( - base::Overloaded{ - [&](const IsolationData::InstalledBundle& content) { - auto* isolated_web_app_reader_registry = - IsolatedWebAppReaderRegistryFactory::GetForProfile(profile_); - if (!isolated_web_app_reader_registry) { - LogErrorAndFail("Support for Isolated Web Apps is not enabled.", - std::move(loader_client)); - return; - } - - auto loader = std::make_unique<IsolatedWebAppURLLoader>( - isolated_web_app_reader_registry, content.path, *web_bundle_id, - std::move(loader_client), resource_request, - frame_tree_node_id_); - mojo::MakeSelfOwnedReceiver( - std::move(std::move(loader)), - mojo::PendingReceiver<network::mojom::URLLoader>( - std::move(loader_receiver))); - }, - [&loader_client](const IsolationData::DevModeBundle& content) { - // TODO: Implement dev mode bundles. - CompleteWithGeneratedHtmlResponse( - mojo::Remote<network::mojom::URLLoaderClient>( - std::move(loader_client)), - net::HTTP_NOT_FOUND, /*body=*/absl::nullopt); - }, - [&](const IsolationData::DevModeProxy& content) { - HandleDevModeProxy(*url_info, content, std::move(loader_receiver), - resource_request, std::move(loader_client), - traffic_annotation); - }}, - isolation_data.content); + forward_request_to_isolation_data_content(*iwa->get().isolation_data()); } void IsolatedWebAppURLLoaderFactory::OnProfileWillBeDestroyed( @@ -439,19 +457,20 @@ network::ResourceRequest proxy_request(resource_request); proxy_request.url = proxy_url; - content::StoragePartition* iwa_partition = profile_->GetStoragePartition( + content::StoragePartition* storage_partition = profile_->GetStoragePartition( url_info.storage_partition_config(profile_), /*can_create=*/false); - if (iwa_partition == nullptr) { + if (storage_partition == nullptr) { LogErrorAndFail(base::StrCat({"Storage not found for Isolated Web App: ", resource_request.url.spec()}), std::move(loader_client)); return; } - iwa_partition->GetURLLoaderFactoryForBrowserProcess()->CreateLoaderAndStart( - std::move(loader_receiver), - /*request_id=*/0, network::mojom::kURLLoadOptionNone, proxy_request, - std::move(loader_client), traffic_annotation); + storage_partition->GetURLLoaderFactoryForBrowserProcess() + ->CreateLoaderAndStart(std::move(loader_receiver), + /*request_id=*/0, + network::mojom::kURLLoadOptionNone, proxy_request, + std::move(loader_client), traffic_annotation); } void IsolatedWebAppURLLoaderFactory::LogErrorAndFail(
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc index 4f183eb7..4f818ec 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc
@@ -12,6 +12,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h" #include "chrome/browser/web_applications/isolation_data.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" #include "chrome/browser/web_applications/test/web_app_test.h" @@ -23,6 +24,7 @@ #include "components/web_package/test_support/signed_web_bundles/web_bundle_signer.h" #include "components/web_package/web_bundle_builder.h" #include "content/public/browser/storage_partition_config.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/test/simple_url_loader_test_helper.h" #include "content/public/test/url_loader_interceptor.h" @@ -149,10 +151,7 @@ void RegisterWebApp(std::unique_ptr<WebApp> web_app, bool create_storage_partition = true) { if (create_storage_partition) { - auto url_info = IsolatedWebAppUrlInfo::Create(web_app->scope()); - profile()->GetStoragePartition( - url_info->storage_partition_config(profile()), - /*can_create=*/true); + CreateStoragePartitionForUrl(web_app->scope()); } provider()->GetRegistrarMutable().registry().emplace(web_app->app_id(), @@ -160,9 +159,9 @@ } void CreateFactory() { - int dummy_frame_tree_node_id = 42; factory_.Bind(IsolatedWebAppURLLoaderFactory::Create( - dummy_frame_tree_node_id, profile())); + web_contents()->GetPrimaryMainFrame()->GetFrameTreeNodeId(), + profile())); } int CreateLoaderAndRun(std::unique_ptr<network::ResourceRequest> request) { @@ -187,6 +186,30 @@ return loader->NetError(); } + void CreateStoragePartitionForUrl(const GURL& url) { + base::expected<IsolatedWebAppUrlInfo, std::string> url_info = + IsolatedWebAppUrlInfo::Create(url); + if (!url_info.has_value()) { + CHECK(false) << "Can't create url info for url " << url + << ", error: " << url_info.error(); + } + + content::StoragePartition* current_storage_partition = + profile()->GetStoragePartition( + url_info->storage_partition_config(profile()), + /*can_create=*/false); + + CHECK(current_storage_partition == nullptr) + << "Partition already exists for url: " << url; + + content::StoragePartition* new_storage_partition = + profile()->GetStoragePartition( + url_info->storage_partition_config(profile()), + /*can_create=*/true); + + CHECK(new_storage_partition != nullptr); + } + const ScopedUrlHandler& url_handler() { CHECK(url_handler_); return *url_handler_; @@ -304,7 +327,7 @@ } TEST_F(IsolatedWebAppURLLoaderFactoryTest, - PostRequestsReturnMethodNotSupported) { + PostRequestsReturnMethodNotSupportedWhenAppIsInstalled) { RegisterWebApp(CreateIsolatedWebApp(kAppStartUrl, IsolationData{IsolationData::DevModeProxy{ .proxy_url = kProxyUrl.spec()}})); @@ -322,12 +345,39 @@ IsHttpStatusCode(net::HTTP_METHOD_NOT_ALLOWED)); } -TEST_F(IsolatedWebAppURLLoaderFactoryTest, - PostRequestsFailWithErrFailedIfAppNotInstalled) { +TEST_F( + IsolatedWebAppURLLoaderFactoryTest, + PostRequestsReturnMethodNotSupportedWhenAppIsInstalledAndThereIsPendingInstall) { + RegisterWebApp(CreateIsolatedWebApp( + kAppStartUrl, IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://installed-app-proxy-url.com"}})); + + IsolatedWebAppPendingInstallInfo::FromWebContents(*web_contents()) + .set_isolation_data(IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://pending-install-proxy-url.com"}}); + CreateFactory(); auto request = std::make_unique<network::ResourceRequest>(); - request->method = net::HttpRequestHeaders::kPostMethod; + const char* kUnsupportedHttpMethod = net::HttpRequestHeaders::kPostMethod; + request->method = kUnsupportedHttpMethod; + request->url = kAppStartUrl; + int status = CreateLoaderAndRun(std::move(request)); + + EXPECT_THAT(status, IsNetError(net::OK)); + ASSERT_THAT(ResponseInfo(), NotNull()); + EXPECT_THAT(ResponseInfo()->headers->response_code(), + IsHttpStatusCode(net::HTTP_METHOD_NOT_ALLOWED)); +} + +TEST_F(IsolatedWebAppURLLoaderFactoryTest, + RequestWithUnsupportedHttpMethodFailWithErrFailedIfAppNotInstalled) { + CreateFactory(); + + auto request = std::make_unique<network::ResourceRequest>(); + + const char* kUnsupportedHttpMethod = net::HttpRequestHeaders::kPostMethod; + request->method = kUnsupportedHttpMethod; request->url = kAppStartUrl; int status = CreateLoaderAndRun(std::move(request)); @@ -455,7 +505,8 @@ Eq(GURL("http://example.com/foo/bar.html"))); } -TEST_F(IsolatedWebAppURLLoaderFactoryTest, GeneratedInstallPageIsReturned) { +TEST_F(IsolatedWebAppURLLoaderFactoryTest, + DoNotReturnGeneratedPageWhenNotInstallingApplication) { RegisterWebApp(CreateIsolatedWebApp(kAppStartUrl, IsolationData{IsolationData::DevModeProxy{ .proxy_url = "http://example.com"}})); @@ -465,6 +516,31 @@ auto request = std::make_unique<network::ResourceRequest>(); request->url = GURL("isolated-app://" + kWebBundleId + "/.well-known/_generated_install_page.html"); + + int status = CreateLoaderAndRun(std::move(request)); + + EXPECT_THAT(status, IsNetError(net::OK)); + EXPECT_THAT( + url_handler().intercepted_url(), + Eq("http://example.com/.well-known/_generated_install_page.html")); +} + +TEST_F(IsolatedWebAppURLLoaderFactoryTest, + ReturnGeneratedPageWhenInstallingApplication) { + IsolatedWebAppPendingInstallInfo::FromWebContents(*web_contents()) + .set_isolation_data(IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://some-proxy-url.com"}}); + + RegisterWebApp(CreateIsolatedWebApp(kAppStartUrl, + IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://example.com"}})); + + CreateFactory(); + + auto request = std::make_unique<network::ResourceRequest>(); + request->url = GURL("isolated-app://" + kWebBundleId + + "/.well-known/_generated_install_page.html"); + int status = CreateLoaderAndRun(std::move(request)); EXPECT_THAT(status, IsNetError(net::OK)); @@ -475,7 +551,53 @@ } TEST_F(IsolatedWebAppURLLoaderFactoryTest, - GeneratedInstallPageIsNotReturnedForNonIwa) { + RequestsRedirectedToPendingInstallIsolationDataWhenAppIsInstalled) { + IsolatedWebAppPendingInstallInfo::FromWebContents(*web_contents()) + .set_isolation_data(IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://some-proxy-url.com"}}); + + RegisterWebApp(CreateIsolatedWebApp(kAppStartUrl, + IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://example.com"}})); + + CreateFactory(); + + auto request = std::make_unique<network::ResourceRequest>(); + request->url = GURL("isolated-app://" + kWebBundleId + + "/some-resource-for-testing.html"); + + int status = CreateLoaderAndRun(std::move(request)); + + EXPECT_THAT(status, IsNetError(net::OK)); + EXPECT_THAT( + url_handler().intercepted_url(), + Eq(GURL("http://some-proxy-url.com/some-resource-for-testing.html"))); +} + +TEST_F(IsolatedWebAppURLLoaderFactoryTest, + RequestsRedirectedToPendingInstallIsolationDataWhenAppIsNotInstalled) { + CreateStoragePartitionForUrl(GURL("isolated-app://" + kWebBundleId)); + + IsolatedWebAppPendingInstallInfo::FromWebContents(*web_contents()) + .set_isolation_data(IsolationData{IsolationData::DevModeProxy{ + .proxy_url = "http://some-proxy-url.com"}}); + + CreateFactory(); + + auto request = std::make_unique<network::ResourceRequest>(); + request->url = GURL("isolated-app://" + kWebBundleId + + "/some-resource-for-testing.html"); + + int status = CreateLoaderAndRun(std::move(request)); + + EXPECT_THAT(status, IsNetError(net::OK)); + EXPECT_THAT( + url_handler().intercepted_url(), + Eq(GURL("http://some-proxy-url.com/some-resource-for-testing.html"))); +} + +TEST_F(IsolatedWebAppURLLoaderFactoryTest, + GeneratedInstallPageIsNotReturnedForNonInstallingApp) { RegisterWebApp(CreateWebApp(kAppStartUrl)); CreateFactory();
diff --git a/chrome/browser/win/conflicts/installed_applications_unittest.cc b/chrome/browser/win/conflicts/installed_applications_unittest.cc index f1b6d7c..ae494e1 100644 --- a/chrome/browser/win/conflicts/installed_applications_unittest.cc +++ b/chrome/browser/win/conflicts/installed_applications_unittest.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/win/conflicts/installed_applications.h" -#include <algorithm> #include <map> +#include "base/ranges/algorithm.h" #include "base/strings/stringprintf.h" #include "base/test/test_reg_util_win.h" #include "base/win/registry.h" @@ -397,13 +397,10 @@ auto applications = installed_applications().applications_; std::sort(std::begin(applications), std::end(applications)); EXPECT_EQ(std::end(applications), - std::adjacent_find(std::begin(applications), std::end(applications), - [](const auto& lhs, const auto& rhs) { - return std::tie(lhs.name, lhs.registry_root, - lhs.registry_key_path, - lhs.registry_wow64_access) == - std::tie(rhs.name, rhs.registry_root, - rhs.registry_key_path, - rhs.registry_wow64_access); - })); + base::ranges::adjacent_find( + applications, std::equal<>(), [](const auto& app) { + return std::tie(app.name, app.registry_root, + app.registry_key_path, + app.registry_wow64_access); + })); }
diff --git a/chrome/browser/win/conflicts/module_blocklist_cache_util_unittest.cc b/chrome/browser/win/conflicts/module_blocklist_cache_util_unittest.cc index 0af2cdd09..2db9d15 100644 --- a/chrome/browser/win/conflicts/module_blocklist_cache_util_unittest.cc +++ b/chrome/browser/win/conflicts/module_blocklist_cache_util_unittest.cc
@@ -52,8 +52,8 @@ // Sort the entries and make sure each module is unique. std::sort(entries.begin(), entries.end(), internal::ModuleLess()); - CHECK(std::adjacent_find(entries.begin(), entries.end(), - internal::ModuleEqual()) == entries.end()); + CHECK(base::ranges::adjacent_find(entries, internal::ModuleEqual()) == + entries.end()); return entries; }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 01d48837..883d8a80 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1665748375-b2b65b3edd4aa54d39584ec37f17a02b534c6a88.profdata +chrome-linux-main-1665770398-17d4f7bea9fcc7d745ba4f47c559f834a80ec320.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index a6075393..324fd7d 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1664819315-34a4cf7009d4c6f71f01d59b264c8857d33d762e.profdata +chrome-mac-arm-main-1665770398-c2ca4d7140879c329be52f41540880b88c5e6fea.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 069b275..40e18e1 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1665748375-fdaca138baf43e64fc055e9a634fed17cf608280.profdata +chrome-mac-main-1665770398-3e2cbb4cbec67c24aa069dcf24f9a5316ce169a2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 2484d07..b704373 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1665725711-7a5ece51c21f206817e2bbc0fdf1b1588c007956.profdata +chrome-win32-main-1665770398-e5491636ea29ef2e4a2a0d4123cb4c9b39977e3f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 9fadd49..c0e6f11 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1665748375-fe5d46e806b458fcf6d095059fa61765fe504a88.profdata +chrome-win64-main-1665770398-60ea39db78e2e9990263a15c0195420700de507e.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index c298d35..c5eb50b 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -217,6 +217,11 @@ "//chrome/browser/resources/media_router/cast_feedback:resources", ] } + + if (is_chrome_branded && toolkit_views) { + sources += [ "$root_gen_dir/chrome/lens_resources.pak" ] + deps += [ "//chrome/browser/resources/lens:resources" ] + } } if (is_chromeos_ash) { sources += [
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json index 28393334..8d119adc 100644 --- a/chrome/common/extensions/api/accessibility_private.json +++ b/chrome/common/extensions/api/accessibility_private.json
@@ -234,7 +234,7 @@ { "id": "AccessibilityFeature", "type": "string", - "enum": [ "enhancedNetworkVoices", "googleTtsLanguagePacks", "dictationPumpkinParsing", "selectToSpeakVoiceSwitching"], + "enum": [ "enhancedNetworkVoices", "googleTtsLanguagePacks", "dictationPumpkinParsing", "selectToSpeakVoiceSwitching", "dictationMoreCommands"], "description": "Subset of accessibility features." }, {
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index cc945d1..c7f9465 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -619,6 +619,11 @@ const char kChromeUICastFeedbackHost[] = "cast-feedback"; #endif +#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) +const char kChromeUILensURL[] = "chrome://lens/"; +const char kChromeUILensHost[] = "lens"; +#endif + // Extension sub pages. const char kExtensionConfigureCommandsSubPage[] = "configureCommands";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 276f7a7..31a4c4c 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -542,6 +542,11 @@ extern const char kChromeUICastFeedbackHost[]; #endif +#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING) +extern const char kChromeUILensURL[]; +extern const char kChromeUILensHost[]; +#endif + // Extensions sub pages. extern const char kExtensionConfigureCommandsSubPage[];
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index 533da31c..e3f4235 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -105,6 +105,17 @@ html_tag); } +void SetAXNodeDataTextDirection(v8::Isolate* isolate, + gin::Dictionary* v8_dict, + ui::AXNodeData* ax_node_data) { + v8::Local<v8::Value> v8_direction; + v8_dict->Get("direction", &v8_direction); + int direction; + gin::ConvertFromV8(isolate, v8_direction, &direction); + ax_node_data->AddIntAttribute(ax::mojom::IntAttribute::kTextDirection, + direction); +} + void SetAXNodeDataUrl(v8::Isolate* isolate, gin::Dictionary* v8_dict, ui::AXNodeData* ax_node_data) { @@ -183,6 +194,7 @@ SetAXNodeDataChildIds(isolate, &v8_node_dict, &ax_node_data); SetAXNodeDataHtmlTag(isolate, &v8_node_dict, &ax_node_data); SetAXNodeDataLanguage(isolate, &v8_node_dict, &ax_node_data); + SetAXNodeDataTextDirection(isolate, &v8_node_dict, &ax_node_data); SetAXNodeDataUrl(isolate, &v8_node_dict, &ax_node_data); snapshot.nodes.push_back(ax_node_data); } @@ -213,13 +225,13 @@ ReadAnythingAppController* ReadAnythingAppController::Install( content::RenderFrame* render_frame) { v8::Isolate* isolate = blink::MainThreadIsolate(); - v8::MicrotasksScope microtask_scope(isolate, - v8::MicrotasksScope::kDoNotRunMicrotasks); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = render_frame->GetWebFrame()->MainWorldScriptContext(); if (context.IsEmpty()) return nullptr; + v8::MicrotasksScope microtask_scope(isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); @@ -325,6 +337,8 @@ .SetProperty("letterSpacing", &ReadAnythingAppController::LetterSpacing) .SetProperty("lineSpacing", &ReadAnythingAppController::LineSpacing) .SetMethod("getChildren", &ReadAnythingAppController::GetChildren) + .SetMethod("getTextDirection", + &ReadAnythingAppController::GetTextDirection) .SetMethod("getHtmlTag", &ReadAnythingAppController::GetHtmlTag) .SetMethod("getLanguage", &ReadAnythingAppController::GetLanguage) .SetMethod("getTextContent", &ReadAnythingAppController::GetTextContent) @@ -415,6 +429,30 @@ return text_content; } +std::string ReadAnythingAppController::GetTextDirection( + ui::AXNodeID ax_node_id) { + ui::AXNode* ax_node = GetAXNode(ax_node_id); + if (!ax_node) + return std::string(); + + auto text_direction = static_cast<ax::mojom::WritingDirection>( + ax_node->GetIntAttribute(ax::mojom::IntAttribute::kTextDirection)); + + // Vertical writing is displayed horizontally with "auto". + switch (text_direction) { + case ax::mojom::WritingDirection::kLtr: + return "ltr"; + case ax::mojom::WritingDirection::kRtl: + return "rtl"; + case ax::mojom::WritingDirection::kTtb: + return "auto"; + case ax::mojom::WritingDirection::kBtt: + return "auto"; + default: + return std::string(); + } +} + std::string ReadAnythingAppController::GetUrl(ui::AXNodeID ax_node_id) { ui::AXNode* ax_node = GetAXNode(ax_node_id); if (!ax_node)
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h index 527cc5d..2a33fea3 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.h +++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -82,6 +82,7 @@ std::string GetHtmlTag(ui::AXNodeID ax_node_id); std::string GetLanguage(ui::AXNodeID ax_node_id); std::string GetTextContent(ui::AXNodeID ax_node_id); + std::string GetTextDirection(ui::AXNodeID ax_node_id); std::string GetUrl(ui::AXNodeID ax_node_id); void OnConnected();
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc index 878bbc3..7d9ed7e 100644 --- a/chrome/renderer/cart/commerce_hint_agent.cc +++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -501,6 +501,9 @@ const GURL& navigation_url(frame->GetDocument().Url()); const GURL& url = request.Url(); + if (CommerceHintAgent::ShouldSkipAddToCartRequest(navigation_url, url)) { + return false; + } bool is_add_to_cart = false; if (navigation_url.DomainIs("dickssportinggoods.com")) { is_add_to_cart = CommerceHintAgent::IsAddToCart(url.spec()); @@ -532,10 +535,6 @@ return true; } - if (CommerceHintAgent::ShouldSkipAddToCartRequest(navigation_url, url)) { - return false; - } - if (IsCartHeuristicsImprovementEnabled()) { if (navigation_url.DomainIs("abebooks.com")) return false; @@ -1170,11 +1169,17 @@ bool CommerceHintAgent::ShouldSkipAddToCartRequest(const GURL& navigation_url, const GURL& request_url) { + const std::string& navigation_domain = eTLDPlusOne(navigation_url); + const re2::RE2* pattern = + commerce_heuristics::CommerceHeuristicsData::GetInstance() + .GetSkipAddToCartPatternForDomain(navigation_domain); + if (pattern) { + return PartialMatch(request_url.spec().substr(0, kLengthLimit), *pattern); + } const std::map<std::string, std::string>& skip_string_map = GetSkipAddToCartMapping(); static base::NoDestructor<std::map<std::string, std::unique_ptr<re2::RE2>>> skip_regex_map; - const std::string& navigation_domain = eTLDPlusOne(navigation_url); if (skip_string_map.find(navigation_domain) == skip_string_map.end()) { return false; }
diff --git a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc index 5687c26..b08ec0c6 100644 --- a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc +++ b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
@@ -504,6 +504,27 @@ ExpectUKMCount(XHREntry::kEntryName, "IsAddToCart", 1); } +IN_PROC_BROWSER_TEST_F(CommerceHintAgentTest, SkipAddToCart_FromComponent) { + bool is_populated = + commerce_hint_service_->InitializeCommerceHeuristicsForTesting( + base::Version("0.0.0.1"), R"###( + { + "guitarcenter.com": { + "skip_add_to_cart_regex": "dummy-request" + } + } + )###", + "{}", "", ""); + DCHECK(is_populated); + + NavigateToURL("https://www.guitarcenter.com/"); + SendXHR("/add-to-cart", "product: 123"); + WaitForUmaCount("Commerce.Carts.AddToCartByURL", 1); + + SendXHR("/add-to-cart/dummy-request-url", "product: 123"); + WaitForUmaCount("Commerce.Carts.AddToCartByURL", 1); +} + // TODO(https://crbug/1310497, https://crbug.com/1362442): This test is flaky // on ChromeOS and Linux Asan. #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/renderer/net/net_error_page_controller.cc b/chrome/renderer/net/net_error_page_controller.cc index 20d0993..6424315 100644 --- a/chrome/renderer/net/net_error_page_controller.cc +++ b/chrome/renderer/net/net_error_page_controller.cc
@@ -24,13 +24,14 @@ base::WeakPtr<Delegate> delegate) { v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); - v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Context> context = render_frame->GetWebFrame()->MainWorldScriptContext(); if (context.IsEmpty()) return; + v8::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); gin::Handle<NetErrorPageController> controller = gin::CreateHandle(
diff --git a/chrome/renderer/supervised_user/supervised_user_error_page_controller.cc b/chrome/renderer/supervised_user/supervised_user_error_page_controller.cc index da71ced..f5da744d 100644 --- a/chrome/renderer/supervised_user/supervised_user_error_page_controller.cc +++ b/chrome/renderer/supervised_user/supervised_user_error_page_controller.cc
@@ -33,13 +33,14 @@ base::WeakPtr<SupervisedUserErrorPageControllerDelegate> delegate) { v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); - v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Context> context = render_frame->GetWebFrame()->MainWorldScriptContext(); if (context.IsEmpty()) return; + v8::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); gin::Handle<SupervisedUserErrorPageController> controller = gin::CreateHandle(
diff --git a/chrome/services/printing/print_backend_service_impl.cc b/chrome/services/printing/print_backend_service_impl.cc index 4c3b12b..7589844 100644 --- a/chrome/services/printing/print_backend_service_impl.cc +++ b/chrome/services/printing/print_backend_service_impl.cc
@@ -51,6 +51,9 @@ #if BUILDFLAG(IS_WIN) #include "base/containers/queue.h" #include "base/win/win_util.h" +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" #include "printing/emf_win.h" #include "printing/printed_page_win.h" #include "ui/gfx/geometry/rect.h" @@ -734,6 +737,13 @@ std::move(callback))); } +#if BUILDFLAG(IS_WIN) +void PrintBackendServiceImpl::BindPrinterXmlParser( + mojo::PendingRemote<mojom::PrinterXmlParser> remote) { + xml_parser_remote_.Bind(std::move(remote)); +} +#endif // BUILDFLAG(IS_WIN) + void PrintBackendServiceImpl::OnDidStartPrintingReadyDocument( DocumentHelper& document_helper, mojom::ResultCode result) {
diff --git a/chrome/services/printing/print_backend_service_impl.h b/chrome/services/printing/print_backend_service_impl.h index ca339999..cfd95ee 100644 --- a/chrome/services/printing/print_backend_service_impl.h +++ b/chrome/services/printing/print_backend_service_impl.h
@@ -27,6 +27,12 @@ #include "printing/printing_context.h" #include "ui/gfx/native_widget_types.h" +#if BUILDFLAG(IS_WIN) +#include "chrome/services/printing/public/mojom/printer_xml_parser.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#endif // BUILDFLAG(IS_WIN) + #if !BUILDFLAG(ENABLE_OOP_PRINTING) #error "Out-of-process printing must be enabled." #endif @@ -122,6 +128,10 @@ // mojom::PrintBackendService implementation: void Init(const std::string& locale) override; +#if BUILDFLAG(IS_WIN) + void BindPrinterXmlParser( + mojo::PendingRemote<mojom::PrinterXmlParser> remote) override; +#endif // BUILDFLAG(IS_WIN) void Poke() override; void EnumeratePrinters( mojom::PrintBackendService::EnumeratePrintersCallback callback) override; @@ -218,6 +228,10 @@ std::vector<std::unique_ptr<DocumentHelper>> documents_; mojo::Receiver<mojom::PrintBackendService> receiver_; + +#if BUILDFLAG(IS_WIN) + mojo::Remote<mojom::PrinterXmlParser> xml_parser_remote_; +#endif // BUILDFLAG(IS_WIN) }; } // namespace printing
diff --git a/chrome/services/printing/public/mojom/BUILD.gn b/chrome/services/printing/public/mojom/BUILD.gn index 5c17796..759524f1 100644 --- a/chrome/services/printing/public/mojom/BUILD.gn +++ b/chrome/services/printing/public/mojom/BUILD.gn
@@ -46,6 +46,9 @@ "//printing/mojom:printing_context", "//ui/gfx/geometry/mojom", ] + if (is_win) { + sources += [ "printer_xml_parser.mojom" ] + } } cpp_typemaps = [
diff --git a/chrome/services/printing/public/mojom/print_backend_service.mojom b/chrome/services/printing/public/mojom/print_backend_service.mojom index 912330b..bf5e1de0 100644 --- a/chrome/services/printing/public/mojom/print_backend_service.mojom +++ b/chrome/services/printing/public/mojom/print_backend_service.mojom
@@ -13,6 +13,9 @@ import "sandbox/policy/mojom/sandbox.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; +[EnableIf=is_win] +import "chrome/services/printing/public/mojom/printer_xml_parser.mojom"; + // The default printer name, or the `ResultCode` if there was an error when // trying to retrieve this data. union DefaultPrinterNameResult { @@ -91,6 +94,11 @@ // interface to the underlying data source. Init(string locale); + // Binds an interface that is used to communicate with the browser process + // to parse XML in a separate process. + [EnableIf=is_win] + BindPrinterXmlParser(pending_remote<PrinterXmlParser> remote); + // TODO(crbug.com/1225111) Message with no arguments and no reply that is // useful to ensure that an idle timeout change takes effect. Poke();
diff --git a/chrome/services/printing/public/mojom/printer_xml_parser.mojom b/chrome/services/printing/public/mojom/printer_xml_parser.mojom new file mode 100644 index 0000000..18abced4 --- /dev/null +++ b/chrome/services/printing/public/mojom/printer_xml_parser.mojom
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module printing.mojom; + +import "mojo/public/mojom/base/values.mojom"; +import "printing/mojom/print.mojom"; + +// The capabilities of a printer as a `base::Value`, or the `ResultCode` if +// there was an error when trying to retrieve this data. +union PrinterCapabilitiesValueResult { + mojo_base.mojom.Value capabilities; + ResultCode result_code; +}; + +// An interface that is used by printing utility services to send XML parse +// requests to the browser process. The browser process can then facilitate +// safely parsing the XML. +interface PrinterXmlParser { + // Receives an XML string of printer capabilities and responds with a + // base::Value of the parsed XML or ResultCode if there was an error + // retrieving the data. + [Sync] + ParseXmlForPrinterCapabilities(string capabilities_xml) => + (PrinterCapabilitiesValueResult value_result); +};
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js index ff265ae5..2c5784e 100644 --- a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js +++ b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
@@ -264,6 +264,15 @@ assertEquals(1, feedbackServiceProvider.getOpenDiagnosticsAppCallCount()); verifyRecordPostSubmitActionCalled( true, FeedbackAppPostSubmitAction.kOpenDiagnosticsApp); + + // Make sure that the label and the sub-label are clickable too. + const label = link.querySelector('.label'); + label.click(); + assertEquals(2, feedbackServiceProvider.getOpenDiagnosticsAppCallCount()); + + const subLabel = link.querySelector('.sub-label'); + subLabel.click(); + assertEquals(3, feedbackServiceProvider.getOpenDiagnosticsAppCallCount()); }); // Test clicking explore app link. @@ -280,6 +289,15 @@ assertEquals(1, feedbackServiceProvider.getOpenExploreAppCallCount()); verifyRecordPostSubmitActionCalled( true, FeedbackAppPostSubmitAction.kOpenExploreApp); + + // Make sure that the label and the sub-label are clickable too. + const label = link.querySelector('.label'); + label.click(); + assertEquals(2, feedbackServiceProvider.getOpenExploreAppCallCount()); + + const subLabel = link.querySelector('.sub-label'); + subLabel.click(); + assertEquals(3, feedbackServiceProvider.getOpenExploreAppCallCount()); }); // Test clicking openChromebookHelp link. @@ -312,6 +330,15 @@ url, 'https://support.google.com/chromebook/?hl=en#topic=3399709'); verifyRecordPostSubmitActionCalled( true, FeedbackAppPostSubmitAction.kOpenChromebookCommunity); + + // Make sure that the label and the sub-label are clickable too. + const label = link.querySelector('.label'); + label.click(); + assertEquals(2, windowOpenCalled); + + const subLabel = link.querySelector('.sub-label'); + subLabel.click(); + assertEquals(3, windowOpenCalled); }); // Test that we only record the user's first action on confirmation page.
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts index acbbb1e4..49911a4 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.ts
@@ -104,7 +104,6 @@ layout: WallpaperLayout.kCenter, key: '1', type: WallpaperType.kOnline, - url: {url: 'data:image/png;base64somedataurl/0'}, }; }
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts index bf1479c..e51df833 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts
@@ -26,7 +26,6 @@ layout: WallpaperLayout.kCenter, key: 'testing', type: WallpaperType.kCustomized, - url: {url: 'data://testing'}, }; const pendingSelectedCustomImage:
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts index 3a76ca9..d1e341f 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts
@@ -86,7 +86,11 @@ await waitAfterNextRender(wallpaperPreviewElement); const img = wallpaperPreviewElement.shadowRoot!.querySelector('img'); - assertEquals(wallpaperProvider.currentWallpaper.url.url, img!.src); + assertEquals( + `chrome://personalization/wallpaper.png?key=${ + wallpaperProvider.currentWallpaper.key}`, + img!.src, + 'current wallpaper key is appended to url as query parameter'); }); test('shows placeholders when image fails to load', async () => {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts index f5e6c31b..73fc488 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts
@@ -91,7 +91,10 @@ await waitAfterNextRender(wallpaperSelectedElement); const img = wallpaperSelectedElement.shadowRoot!.querySelector('img'); - assertEquals(wallpaperProvider.currentWallpaper.url.url, img!.src); + assertEquals( + `chrome://personalization/wallpaper.png?key=${ + wallpaperProvider.currentWallpaper.key}`, + img!.src, 'sets current wallpaper key appended to url'); const textContainerElements = wallpaperSelectedElement.shadowRoot!.querySelectorAll( @@ -142,17 +145,22 @@ const img = wallpaperSelectedElement.shadowRoot!.querySelector('img') as HTMLImageElement; - assertEquals(wallpaperProvider.currentWallpaper.url.url, img.src); + assertEquals( + `chrome://personalization/wallpaper.png?key=${ + wallpaperProvider.currentWallpaper.key}`, + img!.src, 'sets current wallpaper key appended to url'); + personalizationStore.data.wallpaper.currentSelected = { - url: {url: 'data:image/png;base64_some_new_data'}, - attribution: ['New attribution'], - assetId: BigInt(100), + ...personalizationStore.data.wallpaper.currentSelected, + key: 'new_key', }; personalizationStore.notifyObservers(); await waitAfterNextRender(wallpaperSelectedElement); - assertEquals('data:image/png;base64_some_new_data', img.src); + assertEquals( + `chrome://personalization/wallpaper.png?key=new_key`, img.src, + 'updates wallpaper key query parameter'); }); test('shows placeholders when image fails to load', async () => { @@ -181,20 +189,6 @@ null, wallpaperSelectedElement.shadowRoot!.querySelector('img')); }); - test('shows image url with data scheme', async () => { - personalizationStore.data.wallpaper.currentSelected = { - url: {url: 'data:image/png;base64,abc='}, - attribution: [], - assetId: BigInt(100), - }; - personalizationStore.data.wallpaper.loading.selected = false; - wallpaperSelectedElement = initElement(WallpaperSelected); - await waitAfterNextRender(wallpaperSelectedElement); - - const img = wallpaperSelectedElement.shadowRoot!.querySelector('img'); - assertEquals('data:image/png;base64,abc=', img!.src); - }); - test('shows daily refresh option on the collection view', async () => { personalizationStore.data.wallpaper.currentSelected = { url: {url: 'data:image/png;base64,abc='}, @@ -335,7 +329,6 @@ test('shows attribution for device default wallpaper', async () => { const currentSelected: CurrentWallpaper = { - url: {url: 'url'}, attribution: ['testing attribution'], layout: WallpaperLayout.kStretch, type: WallpaperType.kDefault,
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts index 4d6777d..63161a01 100644 --- a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
@@ -608,4 +608,146 @@ const expected: string = '<div><p>ello</p><p>World</p><p>Fr</p></div>'; assertContainerInnerHTML(expected); }); + + test('updateContent textDirection', () => { + // root htmlTag='#document' id=1 + // ++paragraph htmlTag='p' id=2 direction='ltr' + // ++++staticText name='This is left to right writing' id=3 + // ++paragraph htmlTag='p' id=4 direction='rtl' + // ++++staticText name='This is right to left writing' id=4 + const axTree = { + rootId: 1, + nodes: [ + { + id: 1, + role: 'rootWebArea', + htmlTag: '#document', + childIds: [2, 4], + }, + { + id: 2, + role: 'paragraph', + htmlTag: 'p', + direction: 1, + childIds: [3], + }, + { + id: 3, + role: 'staticText', + name: 'This is left to right writing', + }, + { + id: 4, + role: 'paragraph', + htmlTag: 'p', + direction: 2, + childIds: [5], + }, + { + id: 5, + role: 'staticText', + name: 'This is right to left writing', + }, + ], + }; + chrome.readAnything.setContentForTesting(axTree, [2, 4]); + const expected: string = '<p dir="ltr">This is left to right writing</p>' + + '<p dir="rtl">This is right to left writing</p>'; + assertContainerInnerHTML(expected); + }); + + test('updateContent textDirection parentNodeDiffDir', () => { + // root htmlTag='#document' id=1 + // ++paragraph htmlTag='p' id=2 direction='ltr' + // ++++staticText name='This is ltr' id=3 + // ++++link htmlTag='a' url='http://www.google.com/' id=4 direction='rtl' + // ++++++staticText name='This link is rtl' id=5 + const axTree = { + rootId: 1, + nodes: [ + { + id: 1, + role: 'rootWebArea', + htmlTag: '#document', + childIds: [2], + }, + { + id: 2, + role: 'paragraph', + htmlTag: 'p', + direction: 1, + childIds: [3, 4], + }, + { + id: 3, + role: 'staticText', + name: 'This is ltr', + }, + { + id: 4, + role: 'link', + htmlTag: 'a', + direction: 2, + url: 'http://www.google.com/', + childIds: [5], + }, + { + id: 5, + role: 'staticText', + name: 'This link is rtl', + }, + ], + }; + chrome.readAnything.setContentForTesting(axTree, [2]); + const expected: string = + '<p dir="ltr">This is ltr<a dir="rtl" href="http://www.google.com/">This link is rtl</a></p>'; + assertContainerInnerHTML(expected); + }); + + test('updateContent textDirection verticalDir', () => { + // root htmlTag='#document' id=1 + // ++paragraph htmlTag='p' id=2 direction='ttb' + // ++++staticText name='This should be auto' id=3 + // ++paragraph htmlTag='p' id=4 direction='btt' + // ++++staticText name='This should be also be auto' id=4 + const axTree = { + rootId: 1, + nodes: [ + { + id: 1, + role: 'rootWebArea', + htmlTag: '#document', + childIds: [2, 4], + }, + { + id: 2, + role: 'paragraph', + htmlTag: 'p', + direction: 3, + childIds: [3], + }, + { + id: 3, + role: 'staticText', + name: 'This should be auto', + }, + { + id: 4, + role: 'paragraph', + htmlTag: 'p', + direction: 4, + childIds: [5], + }, + { + id: 5, + role: 'staticText', + name: 'This should be also be auto', + }, + ], + }; + chrome.readAnything.setContentForTesting(axTree, [2, 4]); + const expected: string = '<p dir="auto">This should be auto</p>' + + '<p dir="auto">This should be also be auto</p>'; + assertContainerInnerHTML(expected); + }); });
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.ts b/chrome/test/data/webui/tab_strip/tab_list_test.ts index d60ba37..e33c7cd 100644 --- a/chrome/test/data/webui/tab_strip/tab_list_test.ts +++ b/chrome/test/data/webui/tab_strip/tab_list_test.ts
@@ -994,15 +994,15 @@ }); test('PreventsDraggingWhenOnlyOneTab', () => { - assertFalse(tabList.shouldPreventDrag()); + assertFalse(tabList.shouldPreventDrag(/*isDraggingTab=*/ true)); const tabElements = getUnpinnedTabs(); tabElements[1]!.remove(); tabElements[2]!.remove(); - assertTrue(tabList.shouldPreventDrag()); + assertTrue(tabList.shouldPreventDrag(/*isDraggingTab=*/ true)); }); test('PreventsDraggingWhenOnlyOneTabGroup', async () => { - // Create a tab group with 2 tabs. + // Create a tab group with 1 tab. const appendedTab = createTab({ groupId: 'group0', id: 3, @@ -1011,6 +1011,22 @@ }); callbackRouter.tabCreated(appendedTab); await flushTasks(); + + // Remove all tabs outside the tab group. + const tabElements = getUnpinnedTabs(); + tabElements[0]!.remove(); + tabElements[1]!.remove(); + tabElements[2]!.remove(); + + // At this point there's only 1 tab in 1 tab group. + + // Dragging a tab is not allowed. + assertTrue(tabList.shouldPreventDrag(/*isDraggingTab=*/ true)); + + // Dragging a tab group is not allowed. + assertTrue(tabList.shouldPreventDrag(/*isDraggingTab=*/ false)); + + // Add another tab in the same tab group. const appendedTabInSameGroup = createTab({ groupId: 'group0', id: 4, @@ -1019,13 +1035,13 @@ }); callbackRouter.tabCreated(appendedTabInSameGroup); await flushTasks(); - assertFalse(tabList.shouldPreventDrag()); - // Remove all tabs outside the tab group. - const tabElements = getUnpinnedTabs(); - tabElements[0]!.remove(); - tabElements[1]!.remove(); - tabElements[2]!.remove(); - assertTrue(tabList.shouldPreventDrag()); + // At this point there are 2 tabs in 1 tab group; + + // Dragging a tab is still allowed. + assertFalse(tabList.shouldPreventDrag(/*isDraggingTab=*/ true)); + + // Dragging a tab group is not allowed. + assertTrue(tabList.shouldPreventDrag(/*isDraggingTab=*/ false)); }); });
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc index 281a8b27..49f74e8f 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -214,10 +214,11 @@ if (!test_provider_->HasRoutes()) return; - // FIXME: There can't be a good reason to use the observer API to check for - // routes asynchronously, which is fragile. However, some browser tests rely - // on this behavior. Either add a callback parameter to TerminateRoute, or - // add pass callback to the TestProvider to run when all routes are gone. + // TODO(crbug.com/1374499): There can't be a good reason to use the observer + // API to check for routes asynchronously, which is fragile. However, some + // browser tests rely on this behavior. Either add a callback parameter to + // TerminateRoute, or add pass callback to the TestProvider to run when all + // routes are gone. base::RunLoop run_loop; NoRoutesObserver no_routes_observer( MediaRouterFactory::GetApiForBrowserContext(
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index 91305ef..292dfef 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -369,9 +369,7 @@ Uninstall(); } -// TODO(crbug.com/1345407): this test is disabled temporarily. Reenable after -// the build that adds `IUpdater::FetchPolicies` is published to CIPD. -TEST_F(IntegrationTest, DISABLED_OverinstallWorking) { +TEST_F(IntegrationTest, OverinstallWorking) { SetupRealUpdaterLowerVersion(); EXPECT_TRUE(WaitForUpdaterExit()); ExpectVersionNotActive(kUpdaterVersion); @@ -385,13 +383,7 @@ Uninstall(); } -// TODO(crbug.com/1359334): Flaky on Win10. -#if BUILDFLAG(IS_WIN) -#define MAYBE_OverinstallBroken DISABLED_OverinstallBroken -#else -#define MAYBE_OverinstallBroken OverinstallBroken -#endif -TEST_F(IntegrationTest, MAYBE_OverinstallBroken) { +TEST_F(IntegrationTest, OverinstallBroken) { SetupRealUpdaterLowerVersion(); EXPECT_TRUE(WaitForUpdaterExit()); DeleteUpdaterDirectory();
diff --git a/chromeos/metrics/login_event_recorder.cc b/chromeos/metrics/login_event_recorder.cc index 388f6c339..b6cf00b 100644 --- a/chromeos/metrics/login_event_recorder.cc +++ b/chromeos/metrics/login_event_recorder.cc
@@ -106,10 +106,6 @@ total_hist->AddTime(total); std::string output = base::StringPrintf("%s: %.2f", uma_name.c_str(), total.InSecondsF()); - if (uma_name == "BootTime.Login2" || uma_name == "BootTime.LoginNewUser") { - UMA_HISTOGRAM_CUSTOM_TIMES("Ash.Tast.BootTime.Login2", total, - base::Milliseconds(1), base::Seconds(300), 100); - } base::Time prev = first; // Convert base::Time to base::TimeTicks for tracing. auto time2timeticks = [](const base::Time& ts) {
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 0fc7416..59a3cae8 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-108-5335.0-1665395930-benchmark-108.0.5355.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-108-5335.0-1665395930-benchmark-108.0.5359.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index b8215a2..e3fc160 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-108-5335.0-1665395359-benchmark-108.0.5355.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-108-5335.0-1665395359-benchmark-108.0.5359.0-r1-redacted.afdo.xz
diff --git a/components/breadcrumbs/DIR_METADATA b/components/breadcrumbs/DIR_METADATA new file mode 100644 index 0000000..030c855 --- /dev/null +++ b/components/breadcrumbs/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail { + component: "Internals>CrashReporting" +}
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java index 2b9eb67f..df41bc1 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java
@@ -398,7 +398,6 @@ private boolean isNewAllSitesUiEnabled() { // Only in the "All sites" mode and with the flag enabled. return mCategory.getType() == SiteSettingsCategory.Type.ALL_SITES - && SiteSettingsFeatureList.isEnabled( - SiteSettingsFeatureList.SITE_DATA_IMPROVEMENTS); + && SiteSettingsUtil.isSiteDataImprovementEnabled(); } }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java index 0d72530..7cd3d5c 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java
@@ -4,9 +4,7 @@ package org.chromium.components.browser_ui.site_settings; -import android.content.Context; import android.os.Bundle; -import android.text.format.Formatter; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; @@ -81,12 +79,11 @@ private void setUpClearDataPreference() { ClearWebsiteStorage preference = findPreference(PREF_CLEAR_DATA); - long usage = mSiteGroup.getTotalUsage(); - if (usage > 0) { - Context context = preference.getContext(); - preference.setTitle( - String.format(context.getString(R.string.origin_settings_storage_usage_brief), - Formatter.formatShortFileSize(context, usage))); + long storage = mSiteGroup.getTotalUsage(); + int cookies = mSiteGroup.getNumberOfCookies(); + if (storage > 0 || cookies > 0) { + preference.setTitle(SiteSettingsUtil.generateStorageUsageText( + preference.getContext(), storage, cookies)); // TODO(crbug.com/1342991): Get clearingApps information from underlying sites. preference.setDataForDisplay(mSiteGroup.getDomainAndRegistry(), /*clearingApps=*/false); // TODO(crbug.com/1342991): Disable the preference if all underlying origins have
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index 85fb1f7..70235b23 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -524,13 +524,20 @@ private void setUpClearDataPreference() { ClearWebsiteStorage preference = findPreference(PREF_CLEAR_DATA); long usage = mSite.getTotalUsage(); - if (usage > 0) { + int cookies = mSite.getNumberOfCookies(); + // Only take cookies into account when the new UI is enabled. + if (usage > 0 || (SiteSettingsUtil.isSiteDataImprovementEnabled() && cookies > 0)) { boolean appFound = getSiteSettingsDelegate().getOriginsWithInstalledApp().contains( mSite.getAddress().getOrigin()); Context context = preference.getContext(); - preference.setTitle( - String.format(context.getString(R.string.origin_settings_storage_usage_brief), - Formatter.formatShortFileSize(context, usage))); + if (SiteSettingsUtil.isSiteDataImprovementEnabled()) { + preference.setTitle( + SiteSettingsUtil.generateStorageUsageText(context, usage, cookies)); + } else { + preference.setTitle(String.format( + context.getString(R.string.origin_settings_storage_usage_brief), + Formatter.formatShortFileSize(context, usage))); + } preference.setDataForDisplay(mSite.getTitle(), appFound); if (WebsitePreferenceBridge.isCookieDeletionDisabled( getSiteSettingsDelegate().getBrowserContextHandle(), @@ -545,7 +552,7 @@ private void setupResetSitePreference() { Preference preference = findPreference(PREF_RESET_SITE); int titleResId; - if (SiteSettingsFeatureList.isEnabled(SiteSettingsFeatureList.SITE_DATA_IMPROVEMENTS)) { + if (SiteSettingsUtil.isSiteDataImprovementEnabled()) { titleResId = mHideNonPermissionPreferences ? R.string.page_info_permissions_reset : R.string.website_reset_full; } else {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsUtil.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsUtil.java index aa5b7f5..3090b6a 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsUtil.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsUtil.java
@@ -4,6 +4,9 @@ package org.chromium.components.browser_ui.site_settings; +import android.content.Context; +import android.text.format.Formatter; + import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -76,4 +79,34 @@ } return ContentSettingsType.DEFAULT; } + + /** + * @return whether the flag for the improved UI for "All sites" and "Site settings" is enabled. + */ + public static boolean isSiteDataImprovementEnabled() { + return SiteSettingsFeatureList.isEnabled(SiteSettingsFeatureList.SITE_DATA_IMPROVEMENTS); + } + + /** + * @param context A {@link Context} object to pull strings out of. + * @param storage The amount of storage (in bytes) used by the entry. + * @param cookies The number of cookies associated with the entry. + * @return A string to display in the UI to show and clear storage and cookies. + */ + public static String generateStorageUsageText(Context context, long storage, int cookies) { + String result = ""; + if (storage > 0) { + result = String.format(context.getString(R.string.origin_settings_storage_usage_brief), + Formatter.formatShortFileSize(context, storage)); + } + if (cookies > 0) { + String cookie_str = context.getResources().getQuantityString( + R.plurals.cookies_count, cookies, cookies); + result = result.isEmpty() + ? cookie_str + : String.format(context.getString(R.string.summary_with_one_bullet), result, + cookie_str); + } + return result; + } }
diff --git a/components/commerce/core/commerce_heuristics_data.cc b/components/commerce/core/commerce_heuristics_data.cc index a07ddf14..d64b12e 100644 --- a/components/commerce/core/commerce_heuristics_data.cc +++ b/components/commerce/core/commerce_heuristics_data.cc
@@ -18,6 +18,7 @@ constexpr char kMerchantCartURLRegexType[] = "cart_url_regex"; constexpr char kMerchantCheckoutURLRegexType[] = "checkout_url_regex"; constexpr char kMerchantPurchaseURLRegexType[] = "purchase_url_regex"; +constexpr char kSkipAddToCartRegexType[] = "skip_add_to_cart_regex"; // CommerceGlobalHeuristics types. constexpr char kSkipProductPatternType[] = "sensitive_product_regex"; @@ -90,6 +91,7 @@ domain_cart_url_pattern_mapping_.clear(); domain_checkout_url_pattern_mapping_.clear(); domain_purchase_url_pattern_mapping_.clear(); + domain_skip_add_to_cart_pattern_mapping_.clear(); return true; } @@ -177,6 +179,13 @@ kMerchantPurchaseURLRegexType, domain); } +const re2::RE2* CommerceHeuristicsData::GetSkipAddToCartPatternForDomain( + const std::string& domain) { + return GetCommerceHintHeuristicsRegex( + domain_skip_add_to_cart_pattern_mapping_, kSkipAddToCartRegexType, + domain); +} + std::string CommerceHeuristicsData::GetProductIDExtractionJSON() { return product_id_json_; }
diff --git a/components/commerce/core/commerce_heuristics_data.h b/components/commerce/core/commerce_heuristics_data.h index ae9356c..49f4d9ab 100644 --- a/components/commerce/core/commerce_heuristics_data.h +++ b/components/commerce/core/commerce_heuristics_data.h
@@ -88,6 +88,10 @@ // `domain`. const re2::RE2* GetPurchasePageURLPatternForDomain(const std::string& domain); + // Try to get the pattern regex used to match against XHR request URL to see + // if the request should be ignored for AddToCart detection in `domain`. + const re2::RE2* GetSkipAddToCartPatternForDomain(const std::string& domain); + // Get the JSON data with product ID extraction heuristics. std::string GetProductIDExtractionJSON(); @@ -132,6 +136,8 @@ domain_checkout_url_pattern_mapping_; std::map<std::string, std::unique_ptr<re2::RE2>> domain_purchase_url_pattern_mapping_; + std::map<std::string, std::unique_ptr<re2::RE2>> + domain_skip_add_to_cart_pattern_mapping_; std::string product_id_json_; std::string cart_extraction_script_; };
diff --git a/components/commerce/core/commerce_heuristics_data_unittest.cc b/components/commerce/core/commerce_heuristics_data_unittest.cc index 0ef8836f..04197e8e 100644 --- a/components/commerce/core/commerce_heuristics_data_unittest.cc +++ b/components/commerce/core/commerce_heuristics_data_unittest.cc
@@ -21,7 +21,8 @@ "checkout_url_regex" : "bar.com/([^/]+/)?checkout" }, "baz.com": { - "purchase_url_regex" : "baz.com/([^/]+/)?purchase" + "purchase_url_regex" : "baz.com/([^/]+/)?purchase", + "skip_add_to_cart_regex": "dummy-request-url" } } )###"; @@ -95,6 +96,9 @@ EXPECT_EQ( *hint_heuristics->FindDict("baz.com")->FindString("purchase_url_regex"), "baz.com/([^/]+/)?purchase"); + EXPECT_EQ(*hint_heuristics->FindDict("baz.com")->FindString( + "skip_add_to_cart_regex"), + "dummy-request-url"); auto* global_heuristics = GetGlobalHeuristics(); EXPECT_EQ(global_heuristics->size(), 9u); EXPECT_TRUE(global_heuristics->contains("sensitive_product_regex")); @@ -271,6 +275,16 @@ "baz.com/([^/]+/)?purchase"); } +TEST_F(CommerceHeuristicsDataTest, TestGetSkipAddToCartPatternForDomain) { + auto& data = commerce_heuristics::CommerceHeuristicsData::GetInstance(); + + ASSERT_TRUE(data.PopulateDataFromComponent( + kHintHeuristicsJSONData, kGlobalHeuristicsJSONData, "", "")); + + EXPECT_EQ(data.GetSkipAddToCartPatternForDomain("baz.com")->pattern(), + "dummy-request-url"); +} + TEST_F(CommerceHeuristicsDataTest, TestRepopulateHintData) { auto& data = commerce_heuristics::CommerceHeuristicsData::GetInstance();
diff --git a/components/drive/OWNERS b/components/drive/OWNERS index 4ad89d4..6f2bdb8f 100644 --- a/components/drive/OWNERS +++ b/components/drive/OWNERS
@@ -1,5 +1 @@ -# Primary file://chrome/browser/sync_file_system/OWNERS - -# Secondary -file://ash/projector/OWNERS
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc index 9ee52ae0..067fe06 100644 --- a/components/exo/pointer.cc +++ b/components/exo/pointer.cc
@@ -67,13 +67,8 @@ bool SameLocation(const gfx::PointF& location_in_target, const gfx::PointF& location) { - // In general, it is good practice to compare floats using an epsilon. - // In particular, the mouse location_f() could differ between the - // MOUSE_PRESSED and MOUSE_RELEASED events. At MOUSE_RELEASED, it will have a - // targeter() already cached, while at MOUSE_PRESSED, it will have to - // calculate it passing through all the hierarchy of windows, and that could - // generate rounding error. std::numeric_limits<float>::epsilon() is not big - // enough to catch this rounding error. + // TODO(crbug.com/1354573): This is no longer necessary. Switch to + // std::numeric_limits<float>::eplison(). gfx::Vector2dF offset = location_in_target - location; return offset.LengthSquared() < (2 * kLocatedEventEpsilonSquared); } @@ -381,7 +376,8 @@ aura::Env::GetInstance()->AddPreTargetHandler( this, ui::EventTarget::Priority::kSystem); - location_when_pointer_capture_enabled_ = gfx::ToRoundedPoint(location_); + location_when_pointer_capture_enabled_ = + gfx::ToRoundedPoint(location_in_root_); if (ShouldMoveToCenter()) MoveCursorToCenterOfActiveDisplay(); @@ -464,7 +460,7 @@ } if (surface == focus_surface_) { - SetFocus(nullptr, gfx::PointF(), 0); + SetFocus(nullptr, gfx::PointF(), gfx::PointF(), 0); was_correctly_subscribed = true; } else if (surface == root_surface()) { UpdatePointerSurface(nullptr); @@ -488,12 +484,13 @@ gfx::PointF location_in_target; Surface* target = GetEffectiveTargetForEvent(event, &location_in_target); + gfx::PointF location_in_root = event->root_location_f(); // Update focus if target is different than the current pointer focus. - if (target != focus_surface_) - SetFocus(target, location_in_target, event->button_flags()); - - gfx::PointF location_in_root = GetLocationInRoot(target, location_in_target); + if (target != focus_surface_) { + SetFocus(target, location_in_root, location_in_target, + event->button_flags()); + } if (!focus_surface_) return; @@ -516,9 +513,9 @@ // so to avoid generating mouse event jitter we consider the location of // these events to be the same as |location| if floored values match. bool same_location = !event->IsSynthesized() - ? SameLocation(location_in_root, location_) + ? SameLocation(location_in_root, location_in_root_) : gfx::ToFlooredPoint(location_in_root) == - gfx::ToFlooredPoint(location_); + gfx::ToFlooredPoint(location_in_root_); // Ordinal motion is sent only on platforms that support it, which is // indicated by the presence of a flag. @@ -561,7 +558,7 @@ } if (needs_frame) delegate_->OnPointerFrame(); - location_ = location_in_root; + location_in_root_ = location_in_root; } } switch (event->type()) { @@ -717,7 +714,6 @@ //////////////////////////////////////////////////////////////////////////////// // aura::client::DragDropClientObserver overrides: void Pointer::OnDragStarted() { -#if BUILDFLAG(IS_CHROMEOS_ASH) // Drag 'n drop operations driven by sources different than pointer/mouse // should have not effect here. WMHelper* helper = WMHelper::GetInstance(); @@ -727,12 +723,10 @@ return; } - SetFocus(nullptr, gfx::PointF(), 0); -#endif + SetFocus(nullptr, gfx::PointF(), gfx::PointF(), 0); } void Pointer::OnDragCompleted(const ui::DropTargetEvent& event) { -#if BUILDFLAG(IS_CHROMEOS_ASH) // Drag 'n drop operations driven by sources different than pointer/mouse // should have not effect here. WMHelper* helper = WMHelper::GetInstance(); @@ -757,9 +751,10 @@ gfx::PointF location_in_target; auto* target = GetEffectiveTargetForEvent(&event, &location_in_target); - if (target) - SetFocus(target, location_in_target, /*button_flags=*/0); -#endif + if (target) { + SetFocus(target, event.root_location_f(), location_in_target, + /*button_flags=*/0); + } } //////////////////////////////////////////////////////////////////////////////// @@ -836,7 +831,8 @@ } void Pointer::SetFocus(Surface* surface, - const gfx::PointF& location, + const gfx::PointF& root_location, + const gfx::PointF& surface_location, int button_flags) { DCHECK(!surface || delegate_->CanAcceptPointerEventsForSurface(surface)); // First generate a leave event if we currently have a target in focus. @@ -852,9 +848,9 @@ } // Second generate an enter event if focus moved to a new surface. if (surface) { - delegate_->OnPointerEnter(surface, location, button_flags); + delegate_->OnPointerEnter(surface, surface_location, button_flags); delegate_->OnPointerFrame(); - location_ = GetLocationInRoot(surface, location); + location_in_root_ = root_location; focus_surface_ = surface; if (!focus_surface_->HasSurfaceObserver(this)) focus_surface_->AddSurfaceObserver(this); @@ -996,23 +992,13 @@ } } -gfx::PointF Pointer::GetLocationInRoot(Surface* target, - gfx::PointF location_in_target) { - if (!target || !target->window()) - return location_in_target; - aura::Window* w = target->window(); - gfx::PointF p(location_in_target.x(), location_in_target.y()); - aura::Window::ConvertPointToTarget(w, w->GetRootWindow(), &p); - return gfx::PointF(p.x(), p.y()); -} - bool Pointer::ShouldMoveToCenter() { if (!capture_window_) return false; gfx::Rect rect = capture_window_->GetRootWindow()->bounds(); rect.Inset(gfx::Insets::VH(rect.height() / 6, rect.width() / 6)); - return !rect.Contains(location_.x(), location_.y()); + return !rect.Contains(location_in_root_.x(), location_in_root_.y()); } void Pointer::MoveCursorToCenterOfActiveDisplay() { @@ -1031,7 +1017,7 @@ if (!relative_pointer_delegate_) return false; - gfx::Vector2dF delta = location_in_root - location_; + gfx::Vector2dF delta = location_in_root - location_in_root_; relative_pointer_delegate_->OnPointerRelativeMotion( time_stamp, delta, ordinal_motion.has_value() ? ordinal_motion.value() : delta);
diff --git a/components/exo/pointer.h b/components/exo/pointer.h index 20f92d9..099bc00 100644 --- a/components/exo/pointer.h +++ b/components/exo/pointer.h
@@ -157,7 +157,8 @@ // Change pointer focus to |surface|. void SetFocus(Surface* surface, - const gfx::PointF& location, + const gfx::PointF& root_location, + const gfx::PointF& surface_location, int button_flags); // Updates the root_surface in |SurfaceTreeHost| from which the cursor @@ -175,10 +176,6 @@ // Update |cursor_| to |cursor_bitmap_| transformed for the current display. void UpdateCursor(); - // Convert the given |location_in_target| to coordinates in the root window. - gfx::PointF GetLocationInRoot(Surface* target, - gfx::PointF location_in_target); - // Called to check if cursor should be moved to the center of the window when // sending relative movements. bool ShouldMoveToCenter(); @@ -225,8 +222,8 @@ // The current focus surface for the pointer. Surface* focus_surface_ = nullptr; - // The location of the pointer in the current focus surface. - gfx::PointF location_; + // The location of the pointer in the root window. + gfx::PointF location_in_root_; // The location of the pointer when pointer capture is first enabled. absl::optional<gfx::Point> location_when_pointer_capture_enabled_;
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 63c5e6e2..d5b4a9fc 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -9,7 +9,6 @@ #include "ash/constants/ash_constants.h" #include "ash/display/screen_orientation_controller.h" #include "ash/frame/non_client_frame_view_ash.h" -#include "ash/metrics/login_unlock_throughput_recorder.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/rounded_corner_utils.h" #include "ash/public/cpp/shelf_types.h" @@ -653,9 +652,6 @@ DCHECK(!widget_); restore_session_id_.emplace(restore_session_id); restore_window_id_.emplace(restore_window_id); - ash::LoginUnlockThroughputRecorder* throughput_recorder = - ash::Shell::Get()->login_unlock_throughput_recorder(); - throughput_recorder->OnRestoredWindowCreated(restore_window_id); } void ShellSurfaceBase::SetRestoreInfoWithWindowIdSource( @@ -1812,17 +1808,6 @@ needs_layout_on_show_ = false; } - if (restore_window_id_.has_value()) { - ash::LoginUnlockThroughputRecorder* throughput_recorder = - ash::Shell::Get()->login_unlock_throughput_recorder(); - - aura::Window* root_window = host_window()->GetRootWindow(); - if (root_window) { - ui::Compositor* compositor = root_window->layer()->GetCompositor(); - throughput_recorder->OnBeforeRestoredWindowShown( - restore_window_id_.value(), compositor); - } - } widget_->Show(); if (has_grab_) StartCapture();
diff --git a/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc b/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc index f8e6392a..e3c03194 100644 --- a/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc +++ b/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc
@@ -224,6 +224,9 @@ "ContentSuggestions.Feed.WebFeed.FollowCount.AfterFollow", 1, 1); histograms.ExpectUniqueSample( "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", 0, 1); + histograms.ExpectUniqueSample( + "ContentSuggestions.Feed.WebFeed.NewFollow.ChangeReason", + WebFeedChangeReason::WEB_PAGE_MENU, 1); } TEST_F(FeedApiSubscriptionsTest, FollowWebFeedAbortOnClearAll) {
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc index c0dc933..941d52e2 100644 --- a/components/feed/core/v2/metrics_reporter.cc +++ b/components/feed/core/v2/metrics_reporter.cc
@@ -1102,6 +1102,14 @@ base::UmaHistogramBoolean( "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", result.web_feed_metadata.is_recommended); + if (result.change_reason) { + // Because WebFeedChangeReason_MAX is not an enum value, we can't use + // UmaHistogramEnumeration, but UmaHistogramExactLinear is equivalent. + base::UmaHistogramExactLinear( + "ContentSuggestions.Feed.WebFeed.NewFollow.ChangeReason", + static_cast<int>(result.change_reason), + feedwire::webfeed::WebFeedChangeReason_MAX + 1); + } } }
diff --git a/components/feed/core/v2/public/web_feed_subscriptions.h b/components/feed/core/v2/public/web_feed_subscriptions.h index 033f6211..02cac4c5 100644 --- a/components/feed/core/v2/public/web_feed_subscriptions.h +++ b/components/feed/core/v2/public/web_feed_subscriptions.h
@@ -24,6 +24,8 @@ WebFeedMetadata web_feed_metadata; // Number of subscriptions the user has after the Follow operation. int subscription_count = 0; + // The change reason from the request. + feedwire::webfeed::WebFeedChangeReason change_reason; }; // Follow a web feed given information about a web page. Calls `callback` when // complete. The callback parameter reports whether the url is now considered
diff --git a/components/feed/core/v2/web_feed_subscription_coordinator.cc b/components/feed/core/v2/web_feed_subscription_coordinator.cc index 0770071..f6eaafb 100644 --- a/components/feed/core/v2/web_feed_subscription_coordinator.cc +++ b/components/feed/core/v2/web_feed_subscription_coordinator.cc
@@ -304,6 +304,7 @@ index_.IsRecommended(result.followed_web_feed_id); callback_result.request_status = result.request_status; callback_result.subscription_count = index_.SubscriptionCount(); + callback_result.change_reason = result.change_reason; feed_stream_->GetMetricsReporter().OnFollowAttempt(followed_with_id, callback_result); std::move(callback).Run(std::move(callback_result));
diff --git a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc index 8785fa0b..fcf87c74 100644 --- a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc +++ b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.cc
@@ -108,6 +108,7 @@ result.request_status = status; result.web_feed_info = subscribed_web_feed_info_; result.followed_web_feed_id = subscribed_web_feed_info_.web_feed_id(); + result.change_reason = request_.change_reason; std::move(callback_).Run(std::move(result)); TaskComplete(); }
diff --git a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.h b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.h index fb362bd8..b2ff2fb 100644 --- a/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.h +++ b/components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.h
@@ -26,7 +26,7 @@ WebFeedPageInformation page_info; std::string web_feed_id; feedwire::webfeed::WebFeedChangeReason change_reason = feedwire::webfeed:: - WebFeedChangeReason ::WEB_FEED_CHANGE_REASON_UNSPECIFIED; + WebFeedChangeReason::WEB_FEED_CHANGE_REASON_UNSPECIFIED; // Whether the subscription request will be stored and retried if failed. bool durable = false; }; @@ -37,6 +37,9 @@ // is its ID. std::string followed_web_feed_id; feedstore::WebFeedInfo web_feed_info; + // The change reason from the request. + feedwire::webfeed::WebFeedChangeReason change_reason = feedwire::webfeed:: + WebFeedChangeReason::WEB_FEED_CHANGE_REASON_UNSPECIFIED; }; SubscribeToWebFeedTask(FeedStream* stream, const OperationToken& operation_token,
diff --git a/components/feed/feed_feature_list.cc b/components/feed/feed_feature_list.cc index e3fbe7a..527974c 100644 --- a/components/feed/feed_feature_list.cc +++ b/components/feed/feed_feature_list.cc
@@ -73,6 +73,9 @@ BASE_FEATURE(kReliabilityLogging, "FeedReliabilityLogging", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kFeedHeaderStickToTop, + "FeedHeaderStickToTop", + base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kFeedInteractiveRefresh, "FeedInteractiveRefresh", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/feed/feed_feature_list.h b/components/feed/feed_feature_list.h index 332bf065..edce9f13 100644 --- a/components/feed/feed_feature_list.h +++ b/components/feed/feed_feature_list.h
@@ -57,6 +57,9 @@ // Whether to log reliability events. BASE_DECLARE_FEATURE(kReliabilityLogging); +// Feature that enables sticky header when users scroll down. +BASE_DECLARE_FEATURE(kFeedHeaderStickToTop); + // Feature that enables refreshing feeds triggered by the users. BASE_DECLARE_FEATURE(kFeedInteractiveRefresh);
diff --git a/components/guest_view/renderer/guest_view_container.cc b/components/guest_view/renderer/guest_view_container.cc index 6a214a9..889d4c0 100644 --- a/components/guest_view/renderer/guest_view_container.cc +++ b/components/guest_view/renderer/guest_view_container.cc
@@ -173,8 +173,9 @@ return; v8::Context::Scope context_scope(context); - v8::MicrotasksScope microtasks( - destruction_isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::MicrotasksScope microtasks(destruction_isolate_, + context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); callback->Call(context, context->Global(), 0 /* argc */, nullptr) .FromMaybe(v8::Local<v8::Value>()); @@ -242,8 +243,9 @@ v8::Integer::New(element_resize_isolate_, new_size.height())}; v8::Context::Scope context_scope(context); - v8::MicrotasksScope microtasks( - element_resize_isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::MicrotasksScope microtasks(element_resize_isolate_, + context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); callback->Call(context, context->Global(), argc, argv) .FromMaybe(v8::Local<v8::Value>());
diff --git a/components/guest_view/renderer/guest_view_request.cc b/components/guest_view/renderer/guest_view_request.cc index 00443c3..2816577 100644 --- a/components/guest_view/renderer/guest_view_request.cc +++ b/components/guest_view/renderer/guest_view_request.cc
@@ -80,7 +80,7 @@ return; v8::Context::Scope context_scope(context); - v8::MicrotasksScope microtasks(isolate_, + v8::MicrotasksScope microtasks(isolate_, context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); callback->Call(context, context->Global(), argc, argv.get())
diff --git a/components/history/core/browser/expire_history_backend.cc b/components/history/core/browser/expire_history_backend.cc index 785d36e..6a286cad 100644 --- a/components/history/core/browser/expire_history_backend.cc +++ b/components/history/core/browser/expire_history_backend.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include <algorithm> #include <functional> #include <limits> #include <memory> @@ -21,6 +20,7 @@ #include "base/location.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" +#include "base/ranges/algorithm.h" #include "base/task/sequenced_task_runner.h" #include "build/build_config.h" #include "components/favicon/core/favicon_database.h" @@ -262,10 +262,8 @@ // `times` must be in reverse chronological order and have no // duplicates, i.e. each member must be earlier than the one before // it. - DCHECK( - std::adjacent_find( - times.begin(), times.end(), std::less_equal<base::Time>()) == - times.end()); + DCHECK(base::ranges::adjacent_find(times, std::less_equal<base::Time>()) == + times.end()); if (!main_db_) return;
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc index 4751673..37f9fd86 100644 --- a/components/lens/lens_features.cc +++ b/components/lens/lens_features.cc
@@ -50,6 +50,10 @@ "EnableImageSearchSidePanelFor3PDse", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kLensRegionSearchStaticPage, + "LensRegionSearchStaticPage", + base::FEATURE_DISABLED_BY_DEFAULT); + const base::FeatureParam<bool> kEnableUKMLoggingForRegionSearch{ &kLensStandalone, "region-search-enable-ukm-logging", true}; @@ -221,5 +225,9 @@ return kEnablePersistentBubble.Get(); } +bool IsLensRegionSearchStaticPageEnabled() { + return base::FeatureList::IsEnabled(kLensRegionSearchStaticPage); +} + } // namespace features } // namespace lens
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h index 5ec19da..cb31a61 100644 --- a/components/lens/lens_features.h +++ b/components/lens/lens_features.h
@@ -44,6 +44,9 @@ // engines BASE_DECLARE_FEATURE(kEnableImageSearchSidePanelFor3PDse); +// Enables launching the region search experience in a new tab with WebUI. +BASE_DECLARE_FEATURE(kLensRegionSearchStaticPage); + // Enables using `Google` as the visual search provider instead of `Google // Lens`. extern const base::FeatureParam<bool> kUseGoogleAsVisualSearchProvider; @@ -174,6 +177,9 @@ // Returns whether we should use an alternative instruction chip string. extern bool UseAltChipString(); + +// Returns whether we should use a WebUI static page for region search. +extern bool IsLensRegionSearchStaticPageEnabled(); } // namespace features } // namespace lens
diff --git a/components/local_state/DIR_METADATA b/components/local_state/DIR_METADATA new file mode 100644 index 0000000..1c5b27e --- /dev/null +++ b/components/local_state/DIR_METADATA
@@ -0,0 +1,5 @@ +monorail { + component: "Internals>Metrics>Variations" +} + +team_email: "chromium-dev@chromium.org"
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc index f7cdcbd..6347206 100644 --- a/components/omnibox/browser/in_memory_url_index_unittest.cc +++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -7,7 +7,6 @@ #include <stddef.h> #include <stdint.h> -#include <algorithm> #include <fstream> #include <memory> #include <numeric> @@ -21,6 +20,7 @@ #include "base/i18n/case_conversion.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" +#include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -723,9 +723,8 @@ // Each next group should fill almost everything, while the previous group // should occupy what's left. - auto* error_position = std::adjacent_find( - std::begin(item_groups), std::end(item_groups), - [&](const ItemGroup& previous, const ItemGroup& current) { + auto* error_position = base::ranges::adjacent_find( + item_groups, [&](const ItemGroup& previous, const ItemGroup& current) { auto ids = GetHistoryIdsUpTo(current.max_id); EXPECT_TRUE(GetPrivateData()->TrimHistoryIdsPool(&ids));
diff --git a/components/omnibox/browser/scored_history_match.cc b/components/omnibox/browser/scored_history_match.cc index f853e91d..bb2c625f 100644 --- a/components/omnibox/browser/scored_history_match.cc +++ b/components/omnibox/browser/scored_history_match.cc
@@ -6,13 +6,13 @@ #include <math.h> -#include <algorithm> #include <utility> #include <vector> #include "base/check_op.h" #include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -634,11 +634,8 @@ auto visits_end = visits.begin() + std::min(visits.size(), max_visits_to_score_); // Visits should be in newest to oldest order. - DCHECK(std::adjacent_find( - visits.begin(), visits_end, - [](const history::VisitInfo& a, const history::VisitInfo& b) { - return a.first < b.first; - }) == visits_end); + DCHECK(base::ranges::adjacent_find(visits.begin(), visits_end, std::less<>(), + &history::VisitInfo::first) == visits_end); for (auto i = visits.begin(); i != visits_end; ++i) { const bool is_page_transition_typed = ui::PageTransitionCoreTypeIs(i->second, ui::PAGE_TRANSITION_TYPED);
diff --git a/components/password_manager/core/browser/generation/password_generator.cc b/components/password_manager/core/browser/generation/password_generator.cc index 5aec52d..d6544e0f 100644 --- a/components/password_manager/core/browser/generation/password_generator.cc +++ b/components/password_manager/core/browser/generation/password_generator.cc
@@ -4,7 +4,6 @@ #include "components/password_manager/core/browser/generation/password_generator.h" -#include <algorithm> #include <limits> #include <map> #include <utility> @@ -12,6 +11,7 @@ #include "base/check.h" #include "base/rand_util.h" +#include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/proto/password_requirements.pb.h" @@ -80,10 +80,9 @@ // sequences of '-' or '_' that are joined into long strokes on the screen // in many fonts. bool IsDifficultToRead(const std::u16string& password) { - return std::adjacent_find(password.begin(), password.end(), - [](auto a, auto b) { - return a == b && (a == '-' || a == '_'); - }) != password.end(); + return base::ranges::adjacent_find(password, [](auto a, auto b) { + return a == b && (a == '-' || a == '_'); + }) != password.end(); } // Generates a password according to |spec| and tries to maximze the entropy
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index 24294f8..f33819af 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -384,10 +384,11 @@ v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); - v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Context> context = frame_->MainWorldScriptContext(); DCHECK(!context.IsEmpty()); + v8::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); v8::Local<v8::Object> global = context->Global();
diff --git a/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc b/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc index 79ecbcbc..fc0d72f4 100644 --- a/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc +++ b/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc
@@ -24,13 +24,14 @@ content::RenderFrame* render_frame) { v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); - v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Context> context = render_frame->GetWebFrame()->MainWorldScriptContext(); if (context.IsEmpty()) return; + v8::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); gin::Handle<SecurityInterstitialPageController> controller =
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc index 42e0b316..41f925f25 100644 --- a/components/sync/base/features.cc +++ b/components/sync/base/features.cc
@@ -56,6 +56,10 @@ "SyncResetPollIntervalOnStart", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kSyncSegmentationDataType, + "SyncSegmentationDataType", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kSyncSendInterestedDataTypes, "SyncSendInterestedDataTypes", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/sync/base/features.h b/components/sync/base/features.h index ab9dc96..fbdeac4 100644 --- a/components/sync/base/features.h +++ b/components/sync/base/features.h
@@ -72,6 +72,9 @@ BASE_DECLARE_FEATURE(kSyncResetPollIntervalOnStart); +// If enabled, Segmentation data type will be synced. +BASE_DECLARE_FEATURE(kSyncSegmentationDataType); + // If enabled, interested data types, excluding Wallet and Offer, will be sent // to the Sync Server as part of DeviceInfo. BASE_DECLARE_FEATURE(kSyncSendInterestedDataTypes);
diff --git a/components/sync/base/model_type.cc b/components/sync/base/model_type.cc index a9ceb99..c0eaae1 100644 --- a/components/sync/base/model_type.cc +++ b/components/sync/base/model_type.cc
@@ -73,8 +73,8 @@ "Autofill Wallet Offer", sync_pb::EntitySpecifics::kAutofillOfferFieldNumber, ModelTypeForHistograms::kAutofillWalletOffer}, - {AUTOFILL_WALLET_USAGE, "AUTOFILL_WALLET_USAGE", - "autofill_wallet_usage", "Autofill Wallet Usage", + {AUTOFILL_WALLET_USAGE, "AUTOFILL_WALLET_USAGE", "autofill_wallet_usage", + "Autofill Wallet Usage", sync_pb::EntitySpecifics::kAutofillWalletUsageFieldNumber, ModelTypeForHistograms::kAutofillWalletUsage}, {THEMES, "THEME", "themes", "Themes", @@ -137,6 +137,9 @@ {USER_CONSENTS, "USER_CONSENT", "user_consent", "User Consents", sync_pb::EntitySpecifics::kUserConsentFieldNumber, ModelTypeForHistograms::kUserConsents}, + {SEGMENTATION, "SEGMENTATION", "segmentation", "Segmentation", + sync_pb::EntitySpecifics::kSegmentationFieldNumber, + ModelTypeForHistograms::kSegmentation}, {SEND_TAB_TO_SELF, "SEND_TAB_TO_SELF", "send_tab_to_self", "Send Tab To Self", sync_pb::EntitySpecifics::kSendTabToSelfFieldNumber, ModelTypeForHistograms::kSendTabToSelf}, @@ -184,7 +187,7 @@ static_assert(std::size(kModelTypeInfoMap) == GetNumModelTypes(), "kModelTypeInfoMap should have GetNumModelTypes() elements"); -static_assert(42 == syncer::GetNumModelTypes(), +static_assert(43 == syncer::GetNumModelTypes(), "When adding a new type, update enum SyncModelTypes in enums.xml " "and suffix SyncModelType in histograms.xml."); @@ -318,6 +321,9 @@ case CONTACT_INFO: specifics->mutable_contact_info(); break; + case SEGMENTATION: + specifics->mutable_segmentation(); + break; } } @@ -348,7 +354,7 @@ } ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "When adding new protocol types, the following type lookup " "logic must be updated."); if (specifics.has_bookmark()) @@ -431,6 +437,8 @@ return CONTACT_INFO; if (specifics.has_autofill_wallet_usage()) return AUTOFILL_WALLET_USAGE; + if (specifics.has_segmentation()) + return SEGMENTATION; // This client version doesn't understand |specifics|. DVLOG(1) << "Unknown datatype in sync proto."; @@ -438,7 +446,7 @@ } ModelTypeSet EncryptableUserTypes() { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "If adding an unencryptable type, remove from " "encryptable_user_types below."); ModelTypeSet encryptable_user_types = UserTypes();
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h index ed145e8..0e2e0149 100644 --- a/components/sync/base/model_type.h +++ b/components/sync/base/model_type.h
@@ -112,6 +112,8 @@ USER_EVENTS, // Commit only user consents. USER_CONSENTS, + // Segmentation data. + SEGMENTATION, // Tabs sent between devices. SEND_TAB_TO_SELF, // Commit only security events. @@ -238,7 +240,8 @@ kPrintersAuthorizationServers = 52, kContactInfo = 53, kAutofillWalletUsage = 54, - kMaxValue = kAutofillWalletUsage + kSegmentation = 55, + kMaxValue = kSegmentation }; // Used to mark the type of EntitySpecifics that has no actual data.
diff --git a/components/sync/base/user_selectable_type.cc b/components/sync/base/user_selectable_type.cc index 76bbe59..96cf28bd 100644 --- a/components/sync/base/user_selectable_type.cc +++ b/components/sync/base/user_selectable_type.cc
@@ -33,7 +33,7 @@ constexpr char kWifiConfigurationsTypeName[] = "wifiConfigurations"; UserSelectableTypeInfo GetUserSelectableTypeInfo(UserSelectableType type) { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "Almost always when adding a new ModelType, you must tie it to " "a UserSelectableType below (new or existing) so the user can " "disable syncing of that data. Today you must also update the " @@ -45,9 +45,12 @@ case UserSelectableType::kBookmarks: return {kBookmarksTypeName, BOOKMARKS, {BOOKMARKS}}; case UserSelectableType::kPreferences: + // TODO(crbug.com/1369259): Add GetPreconditionState() logic to check + // history state as a precondition for SEGMENTATION. return {kPreferencesTypeName, PREFERENCES, - {PREFERENCES, DICTIONARY, PRIORITY_PREFERENCES, SEARCH_ENGINES}}; + {PREFERENCES, DICTIONARY, PRIORITY_PREFERENCES, SEARCH_ENGINES, + SEGMENTATION}}; case UserSelectableType::kPasswords: return {kPasswordsTypeName, PASSWORDS, {PASSWORDS}}; case UserSelectableType::kAutofill:
diff --git a/components/sync/driver/sync_user_settings_impl.cc b/components/sync/driver/sync_user_settings_impl.cc index 57254a2..3c1b2c87 100644 --- a/components/sync/driver/sync_user_settings_impl.cc +++ b/components/sync/driver/sync_user_settings_impl.cc
@@ -268,7 +268,7 @@ #endif types.RetainAll(registered_model_types_); - static_assert(42 == GetNumModelTypes(), + static_assert(43 == GetNumModelTypes(), "If adding a new sync data type, update the list below below if" " you want to disable the new data type for local sync."); types.PutAll(ControlTypes()); @@ -277,6 +277,7 @@ types.Remove(AUTOFILL_WALLET_OFFER); types.Remove(AUTOFILL_WALLET_USAGE); types.Remove(SECURITY_EVENTS); + types.Remove(SEGMENTATION); types.Remove(SEND_TAB_TO_SELF); types.Remove(SHARING_MESSAGE); types.Remove(USER_CONSENTS);
diff --git a/components/sync/engine/cycle/data_type_tracker.cc b/components/sync/engine/cycle/data_type_tracker.cc index 790a92a..106f205 100644 --- a/components/sync/engine/cycle/data_type_tracker.cc +++ b/components/sync/engine/cycle/data_type_tracker.cc
@@ -30,6 +30,9 @@ constexpr base::TimeDelta kDefaultLocalChangeNudgeDelayForSessions = base::Seconds(11); +constexpr base::TimeDelta kDefaultLocalChangeNudgeDelayForSegmentations = + base::Seconds(11); + // Nudge delay for remote invalidations. Common to all data types. constexpr base::TimeDelta kRemoteInvalidationDelay = base::Milliseconds(250); @@ -56,6 +59,11 @@ // custom nudge delay, tuned for a reasonable trade-off between traffic // and freshness. return kDefaultLocalChangeNudgeDelayForSessions; + case SEGMENTATION: + // There are multiple segmentations computed during start-up within + // seconds. Applies a custom nudge delay, so that they are batched into + // one commit. + return kDefaultLocalChangeNudgeDelayForSegmentations; case BOOKMARKS: case PREFERENCES: // Types with sometimes automatic changes get longer delays to allow more @@ -146,6 +154,7 @@ case PRINTERS_AUTHORIZATION_SERVERS: case READING_LIST: case USER_CONSENTS: + case SEGMENTATION: case SEND_TAB_TO_SELF: case SECURITY_EVENTS: case WIFI_CONFIGURATIONS:
diff --git a/components/sync/protocol/proto_value_conversions.cc b/components/sync/protocol/proto_value_conversions.cc index 26361e5..f4bb0d8 100644 --- a/components/sync/protocol/proto_value_conversions.cc +++ b/components/sync/protocol/proto_value_conversions.cc
@@ -138,12 +138,14 @@ void VisitBytes(const P& parent_proto, const char* field_name, const std::string& field) { - value_->Set(field_name, BytesToValue(field)); + value_->GetDict().Set( + field_name, + base::Base64Encode(base::as_bytes(base::make_span(field)))); } template <class P, class E> void VisitEnum(const P& parent_proto, const char* field_name, E field) { - value_->Set(field_name, EnumToValue(field)); + value_->GetDict().Set(field_name, ProtoEnumToString(field)); } template <class P, class F> @@ -155,7 +157,7 @@ for (const auto& field : repeated_field) { list.Append(base::Value::FromUniquePtrValue(ToValue(field))); } - value_->Set(field_name, std::make_unique<base::Value>(std::move(list))); + value_->GetDict().Set(field_name, std::move(list)); } } @@ -168,7 +170,7 @@ for (const auto& field : repeated_field) { list.Append(base::Value::FromUniquePtrValue(ToValue(field))); } - value_->Set(field_name, std::make_unique<base::Value>(std::move(list))); + value_->GetDict().Set(field_name, std::move(list)); } } @@ -260,17 +262,6 @@ return value; } - static std::unique_ptr<base::Value> BytesToValue(const std::string& bytes) { - std::string bytes_base64; - base::Base64Encode(bytes, &bytes_base64); - return std::make_unique<base::Value>(bytes_base64); - } - - template <class E> - static std::unique_ptr<base::Value> EnumToValue(E value) { - return std::make_unique<base::Value>(ProtoEnumToString(value)); - } - std::unique_ptr<base::Value> ToValue(const std::string& value) const { return std::make_unique<base::Value>(value); } @@ -301,7 +292,8 @@ // Needs to be here to see all ToValue() overloads above. template <class P, class F> void VisitImpl(P&, const char* field_name, const F& field) { - value_->Set(field_name, ToValue(field)); + value_->GetDict().Set(field_name, + base::Value::FromUniquePtrValue(ToValue(field))); } const ProtoValueConversionOptions options_;
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc index 409fc51..30d9c11 100644 --- a/components/sync/protocol/proto_value_conversions_unittest.cc +++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -64,7 +64,7 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(encrypted) -static_assert(42 == syncer::GetNumModelTypes(), +static_assert(43 == syncer::GetNumModelTypes(), "When adding a new field, add a DEFINE_SPECIFICS_TO_VALUE_TEST " "for your field below, and optionally a test for the specific " "conversions.");
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index b47302d..1f1f9166 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -534,7 +534,7 @@ } VISIT_PROTO_FIELDS(const sync_pb::EntitySpecifics& proto) { - static_assert(42 == GetNumModelTypes(), + static_assert(43 == GetNumModelTypes(), "When adding a new protocol type, you will likely need to add " "it here as well."); VISIT(encrypted);
diff --git a/components/translate/core/browser/translate_language_list.cc b/components/translate/core/browser/translate_language_list.cc index 088cc236..1e1753e 100644 --- a/components/translate/core/browser/translate_language_list.cc +++ b/components/translate/core/browser/translate_language_list.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include <algorithm> #include <iterator> #include "base/bind.h" @@ -14,6 +13,7 @@ #include "base/json/json_reader.h" #include "base/lazy_instance.h" #include "base/notreached.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" @@ -185,8 +185,7 @@ DCHECK( std::is_sorted(supported_languages_.begin(), supported_languages_.end())); DCHECK(supported_languages_.end() == - std::adjacent_find(supported_languages_.begin(), - supported_languages_.end())); + base::ranges::adjacent_find(supported_languages_)); if (update_is_disabled) return; @@ -362,8 +361,7 @@ DCHECK( std::is_sorted(supported_languages_.begin(), supported_languages_.end())); DCHECK(supported_languages_.end() == - std::adjacent_find(supported_languages_.begin(), - supported_languages_.end())); + base::ranges::adjacent_find(supported_languages_)); NotifyEvent(__LINE__, base::JoinString(supported_languages_, ", ")); return true;
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index b71d40d..e4cc6d8 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -314,16 +314,11 @@ OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane = nullptr; if (output_surface_->IsDisplayedAsOverlayPlane()) { - // OutputSurface::GetOverlayMailbox() returns the mailbox for the last - // used buffer, which is most likely different from the one being used - // this frame. However, for the purpose of testing the overlay - // configuration, the mailbox for ANY buffer from BufferQueue is good - // enough because they're all created with identical properties. current_frame()->output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay( device_viewport_size, surface_resource_size, frame_buffer_format, frame_color_space, frame_has_alpha, 1.0f /*opacity*/, - output_surface_->GetOverlayMailbox()); + GetPrimaryPlaneOverlayTestingMailbox()); primary_plane = &(current_frame()->output_surface_plane.value()); } @@ -1121,4 +1116,9 @@ return gfx::Rect(); } +gpu::Mailbox DirectRenderer::GetPrimaryPlaneOverlayTestingMailbox() { + NOTREACHED(); + return gpu::Mailbox(); +} + } // namespace viz
diff --git a/components/viz/service/display/direct_renderer.h b/components/viz/service/display/direct_renderer.h index 5b47646..733a7d6e8 100644 --- a/components/viz/service/display/direct_renderer.h +++ b/components/viz/service/display/direct_renderer.h
@@ -180,6 +180,10 @@ // 0 < n <= capabilities_.number_of_buffers. virtual void EnsureMinNumberOfBuffers(int n) {} + // Gets a mailbox that can be used for overlay testing the primary plane. This + // does not need to be the next mailbox that will be swapped. + virtual gpu::Mailbox GetPrimaryPlaneOverlayTestingMailbox(); + // Return the bounding rect of previously drawn delegated ink trail. gfx::Rect GetDelegatedInkTrailDamageRect();
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index daab4044..758999e 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -2718,6 +2718,9 @@ #elif defined(USE_OZONE) // Only Wayland uses this code path. for (auto& overlay : current_frame()->overlay_list) { + if (overlay.is_root_render_pass) { + continue; + } if (overlay.rpdq) { PrepareRenderPassOverlay(&overlay); locks.emplace_back(overlay.mailbox); @@ -3711,6 +3714,23 @@ } } +gpu::Mailbox SkiaRenderer::GetPrimaryPlaneOverlayTestingMailbox() { + // For the purpose of testing the overlay configuration, the mailbox for ANY + // buffer from BufferQueue is good enough because they're all created with + // identical properties. + // At the time we're testing overlays we don't yet know which mailbox will be + // presented this frame so we'll just use the last swapped buffer. (We might + // present a new frame's mailbox, or if we empty-swap we'll present the + // previous frame's mailbox.) + if (buffer_queue_) { + return buffer_queue_->GetLastSwappedBuffer(); + } else { + // OutputSurface::GetOverlayMailbox() returns the mailbox for the last + // swapped buffer. + return skia_output_surface_->GetOverlayMailbox(); + } +} + #if defined(USE_OZONE) const gpu::Mailbox SkiaRenderer::GetImageMailboxForColor( const SkColor4f& color) {
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index c6f95a3..b38120b 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -75,6 +75,7 @@ gfx::Rect GetCurrentFramebufferDamage() const override; void Reshape(const OutputSurface::ReshapeParams& reshape_params) override; void EnsureMinNumberOfBuffers(int n) override; + gpu::Mailbox GetPrimaryPlaneOverlayTestingMailbox() override; protected: bool CanPartialSwap() override;
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc index 6f2f0c6..2b760087 100644 --- a/components/viz/service/display_embedder/buffer_queue.cc +++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -158,6 +158,29 @@ return buffer; } +gpu::Mailbox BufferQueue::GetLastSwappedBuffer() { + // The last swapped buffer will generally be in displayed_buffer_, as long as + // SwapBuffersComplete() has been called at least once for a non-empty swap + // since the last Reshape(). + if (displayed_buffer_) { + return displayed_buffer_->mailbox; + } + + // If displayed_buffer_ is null then any available buffer will do. + if (!available_buffers_.empty()) { + return available_buffers_.back()->mailbox; + } + + // If there's nothing displayed or available, then we should have no buffers + // allocated because Reshape() hasn't been called yet, so a zero-mailbox is + // returned. + // If any buffers are in flight at this point then BufferQueue is being used + // incorrectly. We should not be Swap()ing all available buffers before + // receiving any SwapBuffersComplete() calls. + DCHECK(in_flight_buffers_.empty()); + return gpu::Mailbox(); +} + void BufferQueue::EnsureMinNumberOfBuffers(size_t n) { if (n <= number_of_buffers_) { return;
diff --git a/components/viz/service/display_embedder/buffer_queue.h b/components/viz/service/display_embedder/buffer_queue.h index 78843b1..4381440 100644 --- a/components/viz/service/display_embedder/buffer_queue.h +++ b/components/viz/service/display_embedder/buffer_queue.h
@@ -49,6 +49,8 @@ // target for compositing). gpu::Mailbox GetCurrentBuffer(); + gpu::Mailbox GetLastSwappedBuffer(); + // Returns a rectangle whose contents may have changed since the current // buffer was last submitted and needs to be redrawn. For partial swap, // only the contents outside this rectangle can be considered valid and do not
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc index 908eb944..cce12c8f 100644 --- a/components/viz/service/display_embedder/buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -504,4 +504,53 @@ SendDamagedFrame(small_damage); } +TEST_F(BufferQueueTest, GetLastSwappedBuffer) { + // No images allocated, so zero-mailbox is returned. + EXPECT_TRUE(buffer_queue_->GetLastSwappedBuffer().IsZero()); + + // After reshape we'll get the last buffer in the queue. + EXPECT_TRUE(buffer_queue_->Reshape(screen_size, kBufferQueueColorSpace, + kBufferQueueFormat)); + gpu::Mailbox last_swapped1 = buffer_queue_->GetLastSwappedBuffer(); + EXPECT_FALSE(last_swapped1.IsZero()); + + // The last swapped buffer won't change until calling SwapBuffersComplete. + gpu::Mailbox mailbox1 = buffer_queue_->GetCurrentBuffer(); + EXPECT_NE(last_swapped1, mailbox1); + EXPECT_EQ(last_swapped1, buffer_queue_->GetLastSwappedBuffer()); + buffer_queue_->SwapBuffers(screen_rect); + EXPECT_EQ(last_swapped1, buffer_queue_->GetLastSwappedBuffer()); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox1); + + // Swap another frame. Last swapped only updates after SwapBuffersComplete(). + gpu::Mailbox mailbox2 = buffer_queue_->GetCurrentBuffer(); + buffer_queue_->SwapBuffers(screen_rect); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox1); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox2); + + // Swap a third frame. Last swapped only updates after SwapBuffersComplete(). + gpu::Mailbox mailbox3 = buffer_queue_->GetCurrentBuffer(); + // The third mailbox is the first one we got from GetLastSwappedBuffer(). + EXPECT_EQ(mailbox3, last_swapped1); + buffer_queue_->SwapBuffers(screen_rect); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox2); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox3); + + // Empty swap, Last swapped stays the same. + buffer_queue_->SwapBuffers(gfx::Rect()); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox3); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox3); + + // Swap a fourth frame. Last swapped only updates after SwapBuffersComplete(). + EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mailbox1); + buffer_queue_->SwapBuffers(screen_rect); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox3); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mailbox1); +} + } // namespace viz
diff --git a/components/webapps/browser/features.cc b/components/webapps/browser/features.cc index b18c71b..8222b62 100644 --- a/components/webapps/browser/features.cc +++ b/components/webapps/browser/features.cc
@@ -62,7 +62,7 @@ // Enables showing a detailed install dialog for user installs. BASE_FEATURE(kDesktopPWAsDetailedInstallDialog, "DesktopPWAsDetailedInstallDialog", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables sending the beforeinstallprompt without a service worker check. BASE_FEATURE(kSkipServiceWorkerForInstallPrompt,
diff --git a/components/zucchini/imposed_ensemble_matcher.cc b/components/zucchini/imposed_ensemble_matcher.cc index 36afad6..09c09f0 100644 --- a/components/zucchini/imposed_ensemble_matcher.cc +++ b/components/zucchini/imposed_ensemble_matcher.cc
@@ -4,12 +4,12 @@ #include "components/zucchini/imposed_ensemble_matcher.h" -#include <algorithm> #include <sstream> #include <utility> #include "base/bind.h" #include "base/logging.h" +#include "base/ranges/algorithm.h" #include "components/zucchini/io_utils.h" namespace zucchini { @@ -67,9 +67,8 @@ }); // Check for overlaps in "new" file. - if (std::adjacent_find( - matches_.begin(), matches_.end(), - [](const ElementMatch& match1, const ElementMatch& match2) { + if (base::ranges::adjacent_find( + matches_, [](const ElementMatch& match1, const ElementMatch& match2) { return match1.new_element.hi() > match2.new_element.lo(); }) != matches_.end()) { return kOverlapInNew;
diff --git a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc index 4e27e196..2f919ab 100644 --- a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc +++ b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
@@ -5,12 +5,10 @@ #include <algorithm> #include <vector> -#include "base/bind.h" #include "base/command_line.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram.h" -#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" #include "content/browser/direct_sockets/direct_sockets_service_impl.h" @@ -68,81 +66,12 @@ constexpr char kLocalhostAddress[] = "127.0.0.1"; -constexpr char kPermissionDeniedHistogramName[] = - "DirectSockets.PermissionDeniedFailures"; - constexpr char kTCPNetworkFailuresHistogramName[] = "DirectSockets.TCPNetworkFailures"; constexpr char kUDPNetworkFailuresHistogramName[] = "DirectSockets.UDPNetworkFailures"; -const std::string kIPv4_tests[] = { - // 0.0.0.0/8 - "0.0.0.0", "0.255.255.255", - // 10.0.0.0/8 - "10.0.0.0", "10.255.255.255", - // 100.64.0.0/10 - "100.64.0.0", "100.127.255.255", - // 127.0.0.0/8 - "127.0.0.0", "127.255.255.255", - // 169.254.0.0/16 - "169.254.0.0", "169.254.255.255", - // 172.16.0.0/12 - "172.16.0.0", "172.31.255.255", - // 192.0.2.0/24 - "192.0.2.0", "192.0.2.255", - // 192.88.99.0/24 - "192.88.99.0", "192.88.99.255", - // 192.168.0.0/16 - "192.168.0.0", "192.168.255.255", - // 198.18.0.0/15 - "198.18.0.0", "198.19.255.255", - // 198.51.100.0/24 - "198.51.100.0", "198.51.100.255", - // 203.0.113.0/24 - "203.0.113.0", "203.0.113.255", - // 224.0.0.0/8 - 255.0.0.0/8 - "224.0.0.0", "255.255.255.255"}; - -const std::string kIPv6_tests[] = { - // 0000::/8. - // Skip testing ::ffff:/96 explicitly since it will be tested through - // mapping Ipv4 Addresses. - "0:0:0:0:0:0:0:0", "ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 0100::/8 - "100:0:0:0:0:0:0:0", "1ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 0200::/7 - "200:0:0:0:0:0:0:0", "3ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 0400::/6 - "400:0:0:0:0:0:0:0", "7ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 0800::/5 - "800:0:0:0:0:0:0:0", "fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 1000::/4 - "1000:0:0:0:0:0:0:0", "1fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 4000::/3 - "4000:0:0:0:0:0:0:0", "5fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 6000::/3 - "6000:0:0:0:0:0:0:0", "7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // 8000::/3 - "8000:0:0:0:0:0:0:0", "9fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // c000::/3 - "c000:0:0:0:0:0:0:0", "dfff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // e000::/4 - "e000:0:0:0:0:0:0:0", "efff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // f000::/5 - "f000:0:0:0:0:0:0:0", "f7ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // f800::/6 - "f800:0:0:0:0:0:0:0", "fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // fc00::/7 - "fc00:0:0:0:0:0:0:0", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // fe00::/9 - "fe00:0:0:0:0:0:0:0", "fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // fe80::/10 - "fe80:0:0:0:0:0:0:0", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - // fec0::/10 - "fec0:0:0:0:0:0:0:0", "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"}; - class MockOpenNetworkContext : public content::test::MockNetworkContext { public: explicit MockOpenNetworkContext(net::Error result) : result_(result) {} @@ -291,78 +220,6 @@ ::testing::HasSubstr("keepAliveDelay must be no less than")); } -class DirectSocketsOpenCannotConnectBrowserTest - : public DirectSocketsOpenBrowserTest, - public testing::WithParamInterface<ProtocolType> { - public: - static std::vector<std::string> ProduceAllTestParams() { - std::vector<std::string> params; - std::copy(std::begin(kIPv4_tests), std::end(kIPv4_tests), - std::back_inserter(params)); - std::transform(std::begin(kIPv4_tests), std::end(kIPv4_tests), - std::back_inserter(params), - [](const std::string& ip_address) { - net::IPAddress address; - EXPECT_TRUE(address.AssignFromIPLiteral(ip_address)); - net::IPAddress mapped_address = - net::ConvertIPv4ToIPv4MappedIPv6(address); - return base::StrCat({"[", mapped_address.ToString(), "]"}); - }); - std::transform(std::begin(kIPv6_tests), std::end(kIPv6_tests), - std::back_inserter(params), - [](const std::string& ip_address) { - return base::StrCat({"[", ip_address, "]"}); - }); - return params; - } - - void RunTest() { - const auto protocol = GetParam(); - const std::string type = protocol == ProtocolType::kTcp ? "Tcp" : "Udp"; - const std::string expected_result = base::StringPrintf( - "open%s failed: NetworkError: Network Error.", type.c_str()); - - const std::string example_hostname = "mail.example.com"; - const std::string script = - protocol == ProtocolType::kTcp - ? base::StringPrintf("openTcp('%s', 993)", example_hostname.c_str()) - : base::StringPrintf( - "openUdp({ remoteAddress: '%s', remotePort: 993 })", - example_hostname.c_str()); - - for (const auto& address : ProduceAllTestParams()) { - const std::string mapping_rules = base::StringPrintf( - "MAP %s %s", example_hostname.c_str(), address.c_str()); - - MockOpenNetworkContext mock_network_context(net::OK); - mock_network_context.set_host_mapping_rules(mapping_rules); - DirectSocketsServiceImpl::SetNetworkContextForTesting( - &mock_network_context); - - base::HistogramTester histogram_tester; - histogram_tester.ExpectBucketCount( - kPermissionDeniedHistogramName, - blink::mojom::DirectSocketFailureType::kResolvingToNonPublic, 0); - - EXPECT_EQ(expected_result, EvalJs(shell(), script)); - - histogram_tester.ExpectBucketCount( - kPermissionDeniedHistogramName, - blink::mojom::DirectSocketFailureType::kResolvingToNonPublic, 1); - } - } -}; - -IN_PROC_BROWSER_TEST_P(DirectSocketsOpenCannotConnectBrowserTest, - Open_CannotConnectNonPublic) { - RunTest(); -} - -INSTANTIATE_TEST_SUITE_P( - /*empty*/, - DirectSocketsOpenCannotConnectBrowserTest, - testing::Values(ProtocolType::kTcp, ProtocolType::kUdp)); - IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, OpenTcp_OptionsOne) { base::HistogramTester histogram_tester; histogram_tester.ExpectUniqueSample(kTCPNetworkFailuresHistogramName,
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc index f9777e33..62bfde2 100644 --- a/content/browser/direct_sockets/direct_sockets_service_impl.cc +++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -5,27 +5,25 @@ #include "content/browser/direct_sockets/direct_sockets_service_impl.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "content/browser/direct_sockets/direct_udp_socket_impl.h" #include "content/browser/direct_sockets/resolve_host_and_open_socket.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/direct_sockets_delegate.h" -#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/document_service.h" #include "content/public/browser/storage_partition.h" -#include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" #include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/tcp_socket.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom-shared.h" +#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h" namespace content { @@ -57,11 +55,13 @@ } bool IsFrameSufficientlyIsolated(content::RenderFrameHost* frame) { - return frame->GetWebExposedIsolationLevel() >= - content::RenderFrameHost::WebExposedIsolationLevel:: - kMaybeIsolatedApplication && - frame->IsFeatureEnabled( - blink::mojom::PermissionsPolicyFeature::kDirectSockets); + if (frame->GetWebExposedIsolationLevel() >= + content::RenderFrameHost::WebExposedIsolationLevel:: + kMaybeIsolatedApplication) { + return true; + } + + return false; } network::mojom::TCPConnectedSocketOptionsPtr CreateTCPConnectedSocketOptions( @@ -112,23 +112,29 @@ } // namespace -DirectSocketsServiceImpl::DirectSocketsServiceImpl(RenderFrameHost* frame_host) - : WebContentsObserver(WebContents::FromRenderFrameHost(frame_host)), - frame_host_(frame_host) {} +DirectSocketsServiceImpl::DirectSocketsServiceImpl( + RenderFrameHost* render_frame_host, + mojo::PendingReceiver<blink::mojom::DirectSocketsService> receiver) + : DocumentService(*render_frame_host, std::move(receiver)) {} DirectSocketsServiceImpl::~DirectSocketsServiceImpl() = default; // static void DirectSocketsServiceImpl::CreateForFrame( - RenderFrameHost* frame, + RenderFrameHost* render_frame_host, mojo::PendingReceiver<blink::mojom::DirectSocketsService> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!IsFrameSufficientlyIsolated(frame)) { + if (!render_frame_host->IsFeatureEnabled( + blink::mojom::PermissionsPolicyFeature::kDirectSockets)) { + mojo::ReportBadMessage( + "Permissions policy blocks access to Direct Sockets."); + } + if (!IsFrameSufficientlyIsolated(render_frame_host)) { + mojo::ReportBadMessage( + "Frame is not sufficiently isolated to use Direct Sockets."); return; } - mojo::MakeSelfOwnedReceiver( - base::WrapUnique(new DirectSocketsServiceImpl(frame)), - std::move(receiver)); + new DirectSocketsServiceImpl(render_frame_host, std::move(receiver)); } content::DirectSocketsDelegate* DirectSocketsServiceImpl::GetDelegate() { @@ -140,37 +146,26 @@ mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver, mojo::PendingRemote<network::mojom::SocketObserver> observer, OpenTcpSocketCallback callback) { - if (!IsFrameSufficientlyIsolated(frame_host_)) { - mojo::ReportBadMessage("Insufficient isolation to open socket"); - return; - } - - if (!GetNetworkContext()) { - mojo::ReportBadMessage("Invalid request to open socket"); - return; - } + const std::string remote_host = options->remote_hostname; + const uint16_t remote_port = options->remote_port; if (auto* delegate = GetDelegate(); - delegate && - !delegate->ValidateAddressAndPort( - frame_host_, options->remote_hostname, options->remote_port, - blink::mojom::DirectSocketProtocolType::kTcp)) { + delegate && !delegate->ValidateAddressAndPort( + &render_frame_host(), remote_host, remote_port, + blink::mojom::DirectSocketProtocolType::kTcp)) { std::move(callback).Run(net::ERR_ACCESS_DENIED, absl::nullopt, absl::nullopt, mojo::ScopedDataPipeConsumerHandle(), mojo::ScopedDataPipeProducerHandle()); return; } - const std::string remote_host = options->remote_hostname; - const uint16_t remote_port = options->remote_port; - - auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); ResolveHostAndOpenSocket::Create( - weak_ptr, remote_host, remote_port, + remote_host, remote_port, base::BindOnce(&DirectSocketsServiceImpl::OnResolveCompleteForTcpSocket, - weak_ptr, std::move(options), std::move(receiver), - std::move(observer), std::move(callback))) - ->Start(); + weak_ptr_factory_.GetWeakPtr(), std::move(options), + std::move(receiver), std::move(observer), + std::move(callback))) + ->Start(GetNetworkContext()); } void DirectSocketsServiceImpl::OpenUdpSocket( @@ -178,42 +173,25 @@ mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver, mojo::PendingRemote<network::mojom::UDPSocketListener> listener, OpenUdpSocketCallback callback) { - if (!IsFrameSufficientlyIsolated(frame_host_)) { - mojo::ReportBadMessage("Insufficient isolation to open socket"); - return; - } - - if (!GetNetworkContext()) { - mojo::ReportBadMessage("Invalid request to open socket"); - return; - } + const std::string remote_host = options->remote_hostname; + const uint16_t remote_port = options->remote_port; if (auto* delegate = GetDelegate(); - delegate && - !delegate->ValidateAddressAndPort( - frame_host_, options->remote_hostname, options->remote_port, - blink::mojom::DirectSocketProtocolType::kUdp)) { + delegate && !delegate->ValidateAddressAndPort( + &render_frame_host(), remote_host, remote_port, + blink::mojom::DirectSocketProtocolType::kUdp)) { std::move(callback).Run(net::ERR_ACCESS_DENIED, absl::nullopt, absl::nullopt); return; } - const std::string remote_host = options->remote_hostname; - const uint16_t remote_port = options->remote_port; - - auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); ResolveHostAndOpenSocket::Create( - weak_ptr, remote_host, remote_port, + remote_host, remote_port, base::BindOnce(&DirectSocketsServiceImpl::OnResolveCompleteForUdpSocket, - weak_ptr, std::move(options), std::move(receiver), - std::move(listener), std::move(callback))) - ->Start(); -} - -// static -net::MutableNetworkTrafficAnnotationTag -DirectSocketsServiceImpl::MutableTrafficAnnotation() { - return net::MutableNetworkTrafficAnnotationTag{TrafficAnnotation()}; + weak_ptr_factory_.GetWeakPtr(), std::move(options), + std::move(receiver), std::move(listener), + std::move(callback))) + ->Start(GetNetworkContext()); } // static @@ -227,38 +205,12 @@ GetNetworkContextForTesting() = network_context; } -void DirectSocketsServiceImpl::RenderFrameDeleted( - RenderFrameHost* render_frame_host) { - if (render_frame_host == frame_host_) { - frame_host_ = nullptr; - } -} - -void DirectSocketsServiceImpl::RenderFrameHostChanged( - RenderFrameHost* old_host, - RenderFrameHost* new_host) { - if (old_host == frame_host_) { - frame_host_ = nullptr; - } -} - -void DirectSocketsServiceImpl::WebContentsDestroyed() { - frame_host_ = nullptr; -} - network::mojom::NetworkContext* DirectSocketsServiceImpl::GetNetworkContext() const { - if (GetNetworkContextForTesting()) - return GetNetworkContextForTesting(); - - if (!frame_host_) - return nullptr; - - return frame_host_->GetStoragePartition()->GetNetworkContext(); -} - -RenderFrameHost* DirectSocketsServiceImpl::GetFrameHost() const { - return frame_host_; + if (auto* network_context = GetNetworkContextForTesting()) { + return network_context; + } + return render_frame_host().GetStoragePartition()->GetNetworkContext(); } void DirectSocketsServiceImpl::OnResolveCompleteForTcpSocket( @@ -275,19 +227,15 @@ return; } - auto* network_context = GetNetworkContext(); - if (!network_context) { - return; - } - DCHECK(resolved_addresses && !resolved_addresses->empty()); absl::optional<net::IPEndPoint> local_addr = GetLocalAddress(*options); - network_context->CreateTCPConnectedSocket( + GetNetworkContext()->CreateTCPConnectedSocket( std::move(local_addr), *resolved_addresses, CreateTCPConnectedSocketOptions(std::move(options)), - DirectSocketsServiceImpl::MutableTrafficAnnotation(), std::move(socket), - std::move(observer), std::move(callback)); + net::MutableNetworkTrafficAnnotationTag{ + DirectSocketsServiceImpl::TrafficAnnotation()}, + std::move(socket), std::move(observer), std::move(callback)); } void DirectSocketsServiceImpl::OnResolveCompleteForUdpSocket( @@ -303,16 +251,11 @@ return; } - auto* network_context = GetNetworkContext(); - if (!network_context) { - return; - } - DCHECK(resolved_addresses && !resolved_addresses->empty()); net::IPEndPoint peer_addr = resolved_addresses->front(); auto direct_udp_socket = std::make_unique<DirectUDPSocketImpl>( - network_context, std::move(listener)); + GetNetworkContext(), std::move(listener)); direct_udp_socket->Connect( resolved_addresses->front(), CreateUDPSocketOptions(std::move(options)),
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.h b/content/browser/direct_sockets/direct_sockets_service_impl.h index 9c2837a..6d2fad8 100644 --- a/content/browser/direct_sockets/direct_sockets_service_impl.h +++ b/content/browser/direct_sockets/direct_sockets_service_impl.h
@@ -8,9 +8,8 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "content/public/browser/direct_sockets_delegate.h" +#include "content/public/browser/document_service.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents_observer.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" @@ -24,10 +23,11 @@ namespace content { +class DirectSocketsDelegate; + // Implementation of the DirectSocketsService Mojo service. class CONTENT_EXPORT DirectSocketsServiceImpl - : public blink::mojom::DirectSocketsService, - public WebContentsObserver { + : public DocumentService<blink::mojom::DirectSocketsService> { public: ~DirectSocketsServiceImpl() override; @@ -49,23 +49,17 @@ mojo::PendingRemote<network::mojom::UDPSocketListener> listener, OpenUdpSocketCallback callback) override; - // WebContentsObserver: - void RenderFrameDeleted(RenderFrameHost* render_frame_host) override; - void RenderFrameHostChanged(RenderFrameHost* old_host, - RenderFrameHost* new_host) override; - void WebContentsDestroyed() override; - - network::mojom::NetworkContext* GetNetworkContext() const; - RenderFrameHost* GetFrameHost() const; - - static net::MutableNetworkTrafficAnnotationTag MutableTrafficAnnotation(); static net::NetworkTrafficAnnotationTag TrafficAnnotation(); // Testing: static void SetNetworkContextForTesting(network::mojom::NetworkContext*); private: - explicit DirectSocketsServiceImpl(RenderFrameHost*); + DirectSocketsServiceImpl( + RenderFrameHost*, + mojo::PendingReceiver<blink::mojom::DirectSocketsService> receiver); + + network::mojom::NetworkContext* GetNetworkContext() const; void OnResolveCompleteForTcpSocket( blink::mojom::DirectSocketOptionsPtr, @@ -83,7 +77,6 @@ int result, const absl::optional<net::AddressList>& resolved_addresses); - raw_ptr<RenderFrameHost> frame_host_; mojo::UniqueReceiverSet<blink::mojom::DirectUDPSocket> direct_udp_socket_receivers_;
diff --git a/content/browser/direct_sockets/direct_udp_socket_impl.cc b/content/browser/direct_sockets/direct_udp_socket_impl.cc index f19414a..f975091 100644 --- a/content/browser/direct_sockets/direct_udp_socket_impl.cc +++ b/content/browser/direct_sockets/direct_udp_socket_impl.cc
@@ -5,6 +5,7 @@ #include "content/browser/direct_sockets/direct_udp_socket_impl.h" #include "content/browser/direct_sockets/direct_sockets_service_impl.h" +#include "net/traffic_annotation/network_traffic_annotation.h" namespace content { @@ -40,7 +41,8 @@ return; } remote_->Send(std::move(data), - DirectSocketsServiceImpl::MutableTrafficAnnotation(), + net::MutableNetworkTrafficAnnotationTag{ + DirectSocketsServiceImpl::TrafficAnnotation()}, std::move(callback)); }
diff --git a/content/browser/direct_sockets/resolve_host_and_open_socket.cc b/content/browser/direct_sockets/resolve_host_and_open_socket.cc index bb23d60..7d9908e 100644 --- a/content/browser/direct_sockets/resolve_host_and_open_socket.cc +++ b/content/browser/direct_sockets/resolve_host_and_open_socket.cc
@@ -5,24 +5,15 @@ #include "content/browser/direct_sockets/resolve_host_and_open_socket.h" #include "base/functional/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/metrics/histogram_functions.h" #include "build/build_config.h" -#include "content/browser/direct_sockets/direct_sockets_service_impl.h" -#include "content/public/browser/direct_sockets_delegate.h" #include "content/public/browser/render_frame_host.h" #include "net/base/address_list.h" -#include "net/base/ip_address.h" -#include "net/base/ip_endpoint.h" #include "net/net_buildflags.h" #include "services/network/public/mojom/network_context.mojom.h" namespace content { namespace { -constexpr char kPermissionDeniedHistogramName[] = - "DirectSockets.PermissionDeniedFailures"; - #if BUILDFLAG(ENABLE_MDNS) bool ResemblesMulticastDNSName(const std::string& hostname) { return base::EndsWith(hostname, ".local") || @@ -30,64 +21,37 @@ } #endif // !BUILDFLAG(ENABLE_MDNS) -bool IsRawIPAddress(const std::string& address) { - net::IPAddress ip; - return ip.AssignFromIPLiteral(address); -} - -bool ContainNonPubliclyRoutableAddress(const net::AddressList& addresses) { - DCHECK(!addresses.empty()); - return !base::ranges::all_of(addresses, &net::IPAddress::IsPubliclyRoutable, - &net::IPEndPoint::address); -} - -RenderFrameHost* GetFrameHostFromService( - base::WeakPtr<DirectSocketsServiceImpl> service) { - if (!service) { - return nullptr; - } - return service->GetFrameHost(); -} - } // namespace -ResolveHostAndOpenSocket::ResolveHostAndOpenSocket( - base::WeakPtr<DirectSocketsServiceImpl> service, - const std::string& host, - uint16_t port, - OpenSocketCallback callback) - : service_(service), - host_(host), - port_(port), - callback_(std::move(callback)) {} +ResolveHostAndOpenSocket::ResolveHostAndOpenSocket(const std::string& host, + uint16_t port, + OpenSocketCallback callback) + : host_(host), port_(port), callback_(std::move(callback)) {} ResolveHostAndOpenSocket::~ResolveHostAndOpenSocket() = default; // static ResolveHostAndOpenSocket* ResolveHostAndOpenSocket::Create( - base::WeakPtr<DirectSocketsServiceImpl> service, - const std::string& host, + const std::string& address, uint16_t port, OpenSocketCallback callback) { - return new ResolveHostAndOpenSocket(std::move(service), host, port, - std::move(callback)); + return new ResolveHostAndOpenSocket(address, port, std::move(callback)); } -void ResolveHostAndOpenSocket::Start() { - auto* network_context = service_->GetNetworkContext(); - DCHECK(network_context); +void ResolveHostAndOpenSocket::Start( + network::mojom::NetworkContext* network_context) { DCHECK(!receiver_.is_bound()); DCHECK(!resolver_.is_bound()); - network_context->CreateHostResolver(/*config_overrides=*/absl::nullopt, - resolver_.BindNewPipeAndPassReceiver()); + network_context->CreateHostResolver( + /*config_overrides=*/absl::nullopt, + resolver_.BindNewPipeAndPassReceiver()); network::mojom::ResolveHostParametersPtr parameters = network::mojom::ResolveHostParameters::New(); #if BUILDFLAG(ENABLE_MDNS) if (ResemblesMulticastDNSName(host_)) { parameters->source = net::HostResolverSource::MULTICAST_DNS; - is_mdns_name_ = true; } #endif // !BUILDFLAG(ENABLE_MDNS) // Intentionally using a HostPortPair because scheme isn't specified. @@ -111,36 +75,8 @@ endpoint_results_with_metadata) { DCHECK(receiver_.is_bound()); receiver_.reset(); + resolver_.reset(); - auto* frame = GetFrameHostFromService(service_); - if (!frame) { - OpenSocket(net::ERR_UNEXPECTED, {}); - return; - } - - if (auto* delegate = DirectSocketsServiceImpl::GetDelegate(); - delegate && delegate->ShouldSkipPostResolveChecks(frame)) { - OpenSocket(result, resolved_addresses); - return; - } - - // Reject hostnames that resolve to non-public exception unless a raw IP - // address or a *.local hostname is entered by the user. - if (!IsRawIPAddress(host_) && !is_mdns_name_ && resolved_addresses && - ContainNonPubliclyRoutableAddress(*resolved_addresses)) { - base::UmaHistogramEnumeration( - kPermissionDeniedHistogramName, - blink::mojom::DirectSocketFailureType::kResolvingToNonPublic); - OpenSocket(net::ERR_NETWORK_ACCESS_DENIED, {}); - return; - } - - OpenSocket(result, resolved_addresses); -} - -void ResolveHostAndOpenSocket::OpenSocket( - int result, - const absl::optional<net::AddressList>& resolved_addresses) { std::move(callback_).Run(result, resolved_addresses); delete this; }
diff --git a/content/browser/direct_sockets/resolve_host_and_open_socket.h b/content/browser/direct_sockets/resolve_host_and_open_socket.h index 0d778ce..7f4b414 100644 --- a/content/browser/direct_sockets/resolve_host_and_open_socket.h +++ b/content/browser/direct_sockets/resolve_host_and_open_socket.h
@@ -5,7 +5,6 @@ #ifndef CONTENT_BROWSER_DIRECT_SOCKETS_RESOLVE_HOST_AND_OPEN_SOCKET_H_ #define CONTENT_BROWSER_DIRECT_SOCKETS_RESOLVE_HOST_AND_OPEN_SOCKET_H_ -#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -13,12 +12,14 @@ #include "net/dns/public/host_resolver_results.h" #include "services/network/public/cpp/resolve_host_client_base.h" +namespace network::mojom { +class NetworkContext; +} // namespace network::mojom + namespace content { -class DirectSocketsServiceImpl; - -// Resolves the host/port pair provided in options. Upon completion invokes the -// supplied callback and deletes |this|. +// Resolves the host/port pair provided on creation. After resolver signals +// completion via OnComplete(), fires the supplied callback and deletes itself. class CONTENT_EXPORT ResolveHostAndOpenSocket : public network::ResolveHostClientBase { public: @@ -28,17 +29,14 @@ ~ResolveHostAndOpenSocket() override; - static ResolveHostAndOpenSocket* Create( - base::WeakPtr<DirectSocketsServiceImpl>, - const std::string& host, - uint16_t port, - OpenSocketCallback); + static ResolveHostAndOpenSocket* Create(const std::string& host, + uint16_t port, + OpenSocketCallback); - void Start(); + void Start(network::mojom::NetworkContext*); private: - ResolveHostAndOpenSocket(base::WeakPtr<DirectSocketsServiceImpl>, - const std::string& host, + ResolveHostAndOpenSocket(const std::string& host, uint16_t port, OpenSocketCallback); @@ -48,18 +46,11 @@ const absl::optional<net::HostResolverEndpointResults>& endpoint_results_with_metadata) override; - void OpenSocket(int result, - const absl::optional<net::AddressList>& resolved_addresses); - - base::WeakPtr<DirectSocketsServiceImpl> service_; - const std::string host_; uint16_t port_; OpenSocketCallback callback_; - bool is_mdns_name_ = false; - mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this}; mojo::Remote<network::mojom::HostResolver> resolver_; };
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl.cc b/content/browser/first_party_sets/first_party_sets_handler_impl.cc index ee262ed..5568647 100644 --- a/content/browser/first_party_sets/first_party_sets_handler_impl.cc +++ b/content/browser/first_party_sets/first_party_sets_handler_impl.cc
@@ -222,12 +222,6 @@ db_helper_.Reset(); } -void FirstPartySetsHandlerImpl::SetGlobalSetsForTesting( - net::GlobalFirstPartySets global_sets) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - global_sets_ = std::move(global_sets); -} - void FirstPartySetsHandlerImpl::GetPersistedGlobalSetsForTesting( const std::string& browser_context_id, base::OnceCallback<void(absl::optional<net::GlobalFirstPartySets>)>
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl.h b/content/browser/first_party_sets/first_party_sets_handler_impl.h index 5ea1af2..bc69f225 100644 --- a/content/browser/first_party_sets/first_party_sets_handler_impl.h +++ b/content/browser/first_party_sets/first_party_sets_handler_impl.h
@@ -111,7 +111,6 @@ void SetPublicFirstPartySets(const base::Version& version, base::File sets_file) override; void ResetForTesting() override; - void SetGlobalSetsForTesting(net::GlobalFirstPartySets global_sets) override; absl::optional<net::FirstPartySetEntry> FindEntry( const net::SchemefulSite& site, const net::FirstPartySetsContextConfig& config) const override;
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc index 29c2078..fc279464 100644 --- a/content/browser/interest_group/interest_group_auction.cc +++ b/content/browser/interest_group/interest_group_auction.cc
@@ -1091,7 +1091,7 @@ DCHECK(!bidding_and_scoring_phase_callback_); DCHECK(!reporting_phase_callback_); DCHECK(!final_auction_result_); - DCHECK(!top_bid_); + DCHECK(!auction_leader_.top_bid); DCHECK_EQ(pending_component_seller_worklet_requests_, 0u); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "bidding_and_scoring_phase", @@ -1139,16 +1139,17 @@ DCHECK(!bidding_and_scoring_phase_callback_); DCHECK(!reporting_phase_callback_); DCHECK(!final_auction_result_); - DCHECK(top_bid_); + DCHECK(auction_leader_.top_bid); // This should only be called on top-level auctions. DCHECK(!parent_); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "reporting_phase", trace_id_); InterestGroupAuctionReporter::WinningBidInfo winning_bid_info; - winning_bid_info.storage_interest_group = &top_bid_->bid->bid_state->bidder; - winning_bid_info.render_url = top_bid_->bid->render_url; - winning_bid_info.ad_components = top_bid_->bid->ad_components; + winning_bid_info.storage_interest_group = + &auction_leader_.top_bid->bid->bid_state->bidder; + winning_bid_info.render_url = auction_leader_.top_bid->bid->render_url; + winning_bid_info.ad_components = auction_leader_.top_bid->bid->ad_components; // Need the bid from the bidder itself. If the bid was from a component // auction, then `top_bid_->bid` will be the bid from the component auction, // which the component seller worklet may have modified, and thus the wrong @@ -1157,22 +1158,23 @@ // the bid was from the top-level auction, and the original top bid from the // component auction, otherwise, so will always be the bid returned by the // winning bidder's generateBid() method. - winning_bid_info.bid = top_bid_->bid->auction->top_bid()->bid->bid; - winning_bid_info.bid_duration = top_bid_->bid->bid_duration; + winning_bid_info.bid = + auction_leader_.top_bid->bid->auction->top_bid()->bid->bid; + winning_bid_info.bid_duration = auction_leader_.top_bid->bid->bid_duration; winning_bid_info.bidding_signals_data_version = - top_bid_->bid->bidding_signals_data_version; + auction_leader_.top_bid->bid->bidding_signals_data_version; InterestGroupAuctionReporter::SellerWinningBidInfo top_level_seller_winning_bid_info; top_level_seller_winning_bid_info.auction_config = config_; - top_level_seller_winning_bid_info.bid = top_bid_->bid->bid; - top_level_seller_winning_bid_info.score = top_bid_->score; + top_level_seller_winning_bid_info.bid = auction_leader_.top_bid->bid->bid; + top_level_seller_winning_bid_info.score = auction_leader_.top_bid->score; top_level_seller_winning_bid_info.highest_scoring_other_bid = - highest_scoring_other_bid_; + auction_leader_.highest_scoring_other_bid; top_level_seller_winning_bid_info.highest_scoring_other_bid_owner = - highest_scoring_other_bid_owner_; + auction_leader_.highest_scoring_other_bid_owner; top_level_seller_winning_bid_info.scoring_signals_data_version = - top_bid_->scoring_signals_data_version; + auction_leader_.top_bid->scoring_signals_data_version; top_level_seller_winning_bid_info.trace_id = trace_id_; // Populate the SellerWinningBidInfo for the component auction that the @@ -1187,25 +1189,27 @@ // SellerWinningBidInfos. absl::optional<InterestGroupAuctionReporter::SellerWinningBidInfo> component_seller_winning_bid_info; - if (top_bid_->bid->auction != this) { - const InterestGroupAuction* component_auction = top_bid_->bid->auction; + if (auction_leader_.top_bid->bid->auction != this) { + const InterestGroupAuction* component_auction = + auction_leader_.top_bid->bid->auction; component_seller_winning_bid_info.emplace(); component_seller_winning_bid_info->auction_config = component_auction->config_; component_seller_winning_bid_info->bid = - component_auction->top_bid_->bid->bid; + component_auction->auction_leader_.top_bid->bid->bid; component_seller_winning_bid_info->score = - component_auction->top_bid_->score; + component_auction->auction_leader_.top_bid->score; component_seller_winning_bid_info->highest_scoring_other_bid = - component_auction->highest_scoring_other_bid_; + component_auction->auction_leader_.highest_scoring_other_bid; component_seller_winning_bid_info->highest_scoring_other_bid_owner = - component_auction->highest_scoring_other_bid_owner_; + component_auction->auction_leader_.highest_scoring_other_bid_owner; component_seller_winning_bid_info->scoring_signals_data_version = - component_auction->top_bid_->scoring_signals_data_version; + component_auction->auction_leader_.top_bid + ->scoring_signals_data_version; component_seller_winning_bid_info->trace_id = component_auction->trace_id_; component_seller_winning_bid_info->component_auction_modified_bid_params = - component_auction->top_bid_->component_auction_modified_bid_params - ->Clone(); + component_auction->auction_leader_.top_bid + ->component_auction_modified_bid_params->Clone(); } reporting_phase_callback_ = std::move(reporting_phase_callback); @@ -1369,14 +1373,15 @@ // `debug_win_report_urls`. BidState* winner = nullptr; if (final_auction_result_ == AuctionResult::kSuccess && - top_bid_->bid->auction == this) { - winner = top_bid_->bid->bid_state; + auction_leader_.top_bid->bid->auction == this) { + winner = auction_leader_.top_bid->bid->bid_state; } // `signals` includes post auction signals from current auction. PostAuctionSignals signals; - signals.winning_bid = top_bid_ ? top_bid_->bid->bid : 0.0; - signals.highest_scoring_other_bid = highest_scoring_other_bid_; + signals.winning_bid = + auction_leader_.top_bid ? auction_leader_.top_bid->bid->bid : 0.0; + signals.highest_scoring_other_bid = auction_leader_.highest_scoring_other_bid; // `top_level_signals` includes post auction signals from top-level auction. // Will only will be used in debug report URLs of top-level seller and // component sellers. @@ -1386,27 +1391,31 @@ if (parent_) { top_level_signals = PostAuctionSignals(); top_level_signals->winning_bid = - parent_->top_bid_ ? parent_->top_bid_->bid->bid : 0.0; + parent_->auction_leader_.top_bid + ? parent_->auction_leader_.top_bid->bid->bid + : 0.0; } - if (!top_bid_) { - DCHECK_EQ(highest_scoring_other_bid_, 0); - DCHECK(!highest_scoring_other_bid_owner_.has_value()); + if (!auction_leader_.top_bid) { + DCHECK_EQ(auction_leader_.highest_scoring_other_bid, 0); + DCHECK(!auction_leader_.highest_scoring_other_bid_owner.has_value()); } for (const auto& buyer_helper : buyer_helpers_) { const url::Origin& owner = buyer_helper->owner(); - if (top_bid_) - signals.made_winning_bid = owner == top_bid_->bid->interest_group->owner; - - if (highest_scoring_other_bid_owner_.has_value()) { - DCHECK_GT(highest_scoring_other_bid_, 0); - signals.made_highest_scoring_other_bid = - owner == highest_scoring_other_bid_owner_.value(); + if (auction_leader_.top_bid) { + signals.made_winning_bid = + owner == auction_leader_.top_bid->bid->interest_group->owner; } - if (parent_ && parent_->top_bid_) { + + if (auction_leader_.highest_scoring_other_bid_owner.has_value()) { + DCHECK_GT(auction_leader_.highest_scoring_other_bid, 0); + signals.made_highest_scoring_other_bid = + owner == auction_leader_.highest_scoring_other_bid_owner.value(); + } + if (parent_ && parent_->auction_leader_.top_bid) { top_level_signals->made_winning_bid = - owner == parent_->top_bid_->bid->interest_group->owner; + owner == parent_->auction_leader_.top_bid->bid->interest_group->owner; } buyer_helper->TakeDebugReportUrls(winner, signals, top_level_signals, @@ -1463,8 +1472,8 @@ InterestGroupAuction::ScoredBid* InterestGroupAuction::top_bid() { DCHECK(all_bids_scored_); - DCHECK(top_bid_); - return top_bid_.get(); + DCHECK(auction_leader_.top_bid); + return auction_leader_.top_bid.get(); } absl::optional<uint16_t> InterestGroupAuction::GetBuyerExperimentId( @@ -1489,6 +1498,9 @@ return absl::nullopt; } +InterestGroupAuction::LeaderInfo::LeaderInfo() = default; +InterestGroupAuction::LeaderInfo::~LeaderInfo() = default; + void InterestGroupAuction::OnInterestGroupRead( std::vector<StorageInterestGroup> interest_groups) { ++num_owners_loaded_; @@ -1848,8 +1860,8 @@ errors_.insert(errors_.end(), errors.begin(), errors.end()); - // Use separate fields for component and top-level seller reports, so both can - // send debug reports. + // Use separate fields for component and top-level seller reports, so both + // can send debug reports. if (bid->auction == this) { bid->bid_state->seller_debug_loss_report_url = std::move(debug_loss_report_url); @@ -1866,88 +1878,101 @@ } // A score <= 0 means the seller rejected the bid. - if (score <= 0) { - // Need to delete `bid` because OnBiddingAndScoringComplete() may delete - // this, which leaves danging pointers on the stack. While this is safe to - // do (nothing has access to `bid` to dereference them), it makes the - // dangling pointer tooling sad. - bid.reset(); - MaybeCompleteBiddingAndScoringPhase(); - return; + if (score > 0) { + UpdateAuctionLeaders(std::move(bid), score, + std::move(component_auction_modified_bid_params), + data_version, has_data_version, auction_leader_); } + // Need to delete `bid` because OnBiddingAndScoringComplete() may delete + // this, which leaves danging pointers on the stack. While this is safe to + // do (nothing has access to `bid` to dereference them), it makes the + // dangling pointer tooling sad. + bid.reset(); + MaybeCompleteBiddingAndScoringPhase(); +} + +void InterestGroupAuction::UpdateAuctionLeaders( + std::unique_ptr<Bid> bid, + double score, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr + component_auction_modified_bid_params, + uint32_t data_version, + bool has_data_version, + LeaderInfo& leader_info) { bool is_top_bid = false; const url::Origin& owner = bid->interest_group->owner; - if (!top_bid_ || score > top_bid_->score) { + if (!leader_info.top_bid || score > leader_info.top_bid->score) { // If there's no previous top bidder, or the bidder has the highest score, // need to replace the previous top bidder. is_top_bid = true; - if (top_bid_) { - OnNewHighestScoringOtherBid(top_bid_->score, top_bid_->bid->bid, - &top_bid_->bid->interest_group->owner); + if (leader_info.top_bid) { + OnNewHighestScoringOtherBid( + leader_info.top_bid->score, leader_info.top_bid->bid->bid, + &leader_info.top_bid->bid->interest_group->owner, leader_info); } - num_top_bids_ = 1; - at_most_one_top_bid_owner_ = true; - } else if (score == top_bid_->score) { + leader_info.num_top_bids = 1; + leader_info.at_most_one_top_bid_owner = true; + } else if (score == leader_info.top_bid->score) { // If there's a tie, replace the top-bidder with 1-in-`num_top_bids_` // chance. This is the select random value from a stream with fixed // storage problem. - ++num_top_bids_; - if (1 == base::RandInt(1, num_top_bids_)) + ++leader_info.num_top_bids; + if (1 == base::RandInt(1, leader_info.num_top_bids)) is_top_bid = true; - if (owner != top_bid_->bid->interest_group->owner) - at_most_one_top_bid_owner_ = false; + if (owner != leader_info.top_bid->bid->interest_group->owner) + leader_info.at_most_one_top_bid_owner = false; // If the top bid is being replaced, need to add the old top bid as a second // highest bid. Otherwise, need to add the current bid as a second highest // bid. double new_highest_scoring_other_bid = - is_top_bid ? top_bid_->bid->bid : bid->bid; - OnNewHighestScoringOtherBid( - score, new_highest_scoring_other_bid, - at_most_one_top_bid_owner_ ? &bid->interest_group->owner : nullptr); - } else if (score >= second_highest_score_) { + is_top_bid ? leader_info.top_bid->bid->bid : bid->bid; + OnNewHighestScoringOtherBid(score, new_highest_scoring_other_bid, + leader_info.at_most_one_top_bid_owner + ? &bid->interest_group->owner + : nullptr, + leader_info); + } else if (score >= leader_info.second_highest_score) { // Also use this bid (the most recent one) as highest scoring other bid if // there's a tie for second highest score. - OnNewHighestScoringOtherBid(score, bid->bid, &owner); + OnNewHighestScoringOtherBid(score, bid->bid, &owner, leader_info); } if (is_top_bid) { - top_bid_ = std::make_unique<ScoredBid>( + leader_info.top_bid = std::make_unique<ScoredBid>( score, has_data_version ? data_version : absl::optional<uint32_t>(), std::move(bid), std::move(component_auction_modified_bid_params)); } - - bid.reset(); - MaybeCompleteBiddingAndScoringPhase(); } void InterestGroupAuction::OnNewHighestScoringOtherBid( double score, double bid_value, - const url::Origin* owner) { + const url::Origin* owner, + LeaderInfo& leader_info) { // Current (the most recent) bid becomes highest scoring other bid. - if (score > second_highest_score_) { - highest_scoring_other_bid_ = bid_value; - num_second_highest_bids_ = 1; + if (score > leader_info.second_highest_score) { + leader_info.highest_scoring_other_bid = bid_value; + leader_info.num_second_highest_bids = 1; // Owner may be false if this is one of the bids tied for first place. if (!owner) { - highest_scoring_other_bid_owner_.reset(); + leader_info.highest_scoring_other_bid_owner.reset(); } else { - highest_scoring_other_bid_owner_ = *owner; + leader_info.highest_scoring_other_bid_owner = *owner; } - second_highest_score_ = score; + leader_info.second_highest_score = score; return; } - DCHECK_EQ(score, second_highest_score_); - if (!owner || *owner != highest_scoring_other_bid_owner_) - highest_scoring_other_bid_owner_.reset(); - ++num_second_highest_bids_; + DCHECK_EQ(score, leader_info.second_highest_score); + if (!owner || *owner != leader_info.highest_scoring_other_bid_owner) + leader_info.highest_scoring_other_bid_owner.reset(); + ++leader_info.num_second_highest_bids; // In case of a tie, randomly pick one. This is the select random value from a // stream with fixed storage problem. - if (1 == base::RandInt(1, num_second_highest_bids_)) - highest_scoring_other_bid_ = bid_value; + if (1 == base::RandInt(1, leader_info.num_second_highest_bids)) + leader_info.highest_scoring_other_bid = bid_value; } absl::optional<base::TimeDelta> InterestGroupAuction::PerBuyerTimeout( @@ -1983,7 +2008,7 @@ // If there's no winning bid, fail with kAllBidsRejected if there were any // bids. Otherwise, fail with kNoBids. - if (!top_bid_) { + if (!auction_leader_.top_bid) { if (any_bid_made_) { OnBiddingAndScoringComplete(AuctionResult::kAllBidsRejected); } else { @@ -2036,8 +2061,10 @@ for (auto& component_auction : component_auctions_) { // Leave the state of the winning component auction alone, if the winning // bid is from a component auction. - if (top_bid_ && top_bid_->bid->auction == component_auction.get()) + if (auction_leader_.top_bid && + auction_leader_.top_bid->bid->auction == component_auction.get()) { continue; + } if (component_auction->final_auction_result_) continue; component_auction->final_auction_result_ = @@ -2069,8 +2096,10 @@ // TODO(mmenke): Extract relevant data from `this` when creating the Reporter, // and have it handle reporting only if auction results are loaded in a frame, // or if there's no result. - if (top_bid_) - top_bid_->bid->auction->final_auction_result_ = AuctionResult::kSuccess; + if (auction_leader_.top_bid) { + auction_leader_.top_bid->bid->auction->final_auction_result_ = + AuctionResult::kSuccess; + } // Close all pipes, as they're no longer needed. ClosePipes();
diff --git a/content/browser/interest_group/interest_group_auction.h b/content/browser/interest_group/interest_group_auction.h index cc91bd24..7096451 100644 --- a/content/browser/interest_group/interest_group_auction.h +++ b/content/browser/interest_group/interest_group_auction.h
@@ -467,6 +467,36 @@ // interest groups of a particular buyer, etc). class BuyerHelper; + struct LeaderInfo { + LeaderInfo(); + ~LeaderInfo(); + + LeaderInfo(const LeaderInfo&) = delete; + LeaderInfo& operator=(LeaderInfo&) = delete; + + // The highest scoring bid so far. Null if no bid has been accepted yet. + std::unique_ptr<ScoredBid> top_bid; + // Number of bidders with the same score as `top_bidder`. + size_t num_top_bids = 0; + // Number of bidders with the same score as `second_highest_score`. If the + // second highest score matches the highest score, this does not include the + // top bid. + size_t num_second_highest_bids = 0; + + // The numeric value of the bid that got the second highest score. When + // there's a tie for the second highest score, one of the second highest + // scoring bids is randomly chosen. + double highest_scoring_other_bid = 0.0; + double second_highest_score = 0.0; + // Whether all bids of the highest score are from the same interest group + // owner. + bool at_most_one_top_bid_owner = true; + // Will be null in the end if there are interest groups having the second + // highest score with different owners. That includes the top bid itself, in + // the case there's a tie for the top bid. + absl::optional<url::Origin> highest_scoring_other_bid_owner; + }; + // --------------------------------- // Load interest group phase methods // --------------------------------- @@ -567,12 +597,24 @@ PrivateAggregationRequests pa_requests, const std::vector<std::string>& errors) override; + // Compares `bid` with current auction leaders in `leader_info`, updating + // `leader_info` if needed. + void UpdateAuctionLeaders( + std::unique_ptr<Bid> bid, + double score, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr + component_auction_modified_bid_params, + uint32_t data_version, + bool has_data_version, + LeaderInfo& leader_info); + // Invoked when the bid becomes the new highest scoring other bid, to handle // calculation of post auction signals. `owner` is nullptr in the event the // bid is tied with the top bid, and they have different origins. void OnNewHighestScoringOtherBid(double score, double bid_value, - const url::Origin* owner); + const url::Origin* owner, + LeaderInfo& leader_info); absl::optional<base::TimeDelta> PerBuyerTimeout(const BidState* state); absl::optional<base::TimeDelta> SellerTimeout(); @@ -727,27 +769,7 @@ std::vector<std::pair<blink::InterestGroupKey, double>> post_auction_priority_updates_; - // The highest scoring bid so far. Null if no bid has been accepted yet. - std::unique_ptr<ScoredBid> top_bid_; - // Number of bidders with the same score as `top_bidder`. - size_t num_top_bids_ = 0; - // Number of bidders with the same score as `second_highest_score_`. If the - // second highest score matches the highest score, this does not include the - // top bid. - size_t num_second_highest_bids_ = 0; - - // The numeric value of the bid that got the second highest score. When - // there's a tie for the second highest score, one of the second highest - // scoring bids is randomly chosen. - double highest_scoring_other_bid_ = 0.0; - double second_highest_score_ = 0.0; - // Whether all bids of the highest score are from the same interest group - // owner. - bool at_most_one_top_bid_owner_ = true; - // Will be null in the end if there are interest groups having the second - // highest score with different owners. That includes the top bid itself, in - // the case there's a tie for the top bid. - absl::optional<url::Origin> highest_scoring_other_bid_owner_; + LeaderInfo auction_leader_; // Holds a reference to the SellerWorklet used by the auction. std::unique_ptr<AuctionWorkletManager::WorkletHandle> seller_worklet_handle_;
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 14dfb45..25a9534 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -3495,8 +3495,8 @@ // if two or more such documents share a site/origin. Using // navigation_id_ means that each new NavigationRequest (and thus each // document) will get a different value. - if (features::kIsolateSandboxedIframesGroupingParam.Get() == - features::IsolateSandboxedIframesGrouping::kPerDocument) { + if (blink::features::kIsolateSandboxedIframesGroupingParam.Get() == + blink::features::IsolateSandboxedIframesGrouping::kPerDocument) { url_info_init.WithUniqueSandboxId(navigation_id_); } }
diff --git a/content/browser/site_info.cc b/content/browser/site_info.cc index 1314683..ff5cf87b 100644 --- a/content/browser/site_info.cc +++ b/content/browser/site_info.cc
@@ -24,6 +24,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "third_party/blink/public/common/features.h" namespace content { @@ -845,8 +846,8 @@ // origin, as we should be using the full origin for the SiteInstance, but // we don't need to track the origin like we do for OriginAgentCluster. if (real_url_info.is_sandboxed && - features::kIsolateSandboxedIframesGroupingParam.Get() == - features::IsolateSandboxedIframesGrouping::kPerOrigin) { + blink::features::kIsolateSandboxedIframesGroupingParam.Get() == + blink::features::IsolateSandboxedIframesGrouping::kPerOrigin) { return origin.GetURL(); }
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index f591ec3e..3c57b5c 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -31,6 +31,7 @@ #include "content/public/common/url_utils.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "third_party/blink/public/common/chrome_debug_urls.h" +#include "third_party/blink/public/common/features.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value.h" #include "url/origin.h" @@ -1117,8 +1118,8 @@ // known to have the same value. if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() || (real_src_url_info.is_sandboxed && - features::kIsolateSandboxedIframesGroupingParam.Get() == - features::IsolateSandboxedIframesGrouping::kPerOrigin)) { + blink::features::kIsolateSandboxedIframesGroupingParam.Get() == + blink::features::IsolateSandboxedIframesGrouping::kPerOrigin)) { return src_origin == dest_origin; }
diff --git a/content/browser/site_per_process_oopsif_browsertest.cc b/content/browser/site_per_process_oopsif_browsertest.cc index 9196ca1de..e901391 100644 --- a/content/browser/site_per_process_oopsif_browsertest.cc +++ b/content/browser/site_per_process_oopsif_browsertest.cc
@@ -12,6 +12,7 @@ #include "content/public/test/test_frame_navigation_observer.h" #include "content/test/render_document_feature.h" #include "net/dns/mock_host_resolver.h" +#include "third_party/blink/public/common/features.h" namespace content { @@ -24,8 +25,8 @@ public ::testing::WithParamInterface<bool> { public: SrcdocIsolatedSandboxedIframeTest() { - feature_list_.InitWithFeatureState(features::kIsolateSandboxedIframes, - GetParam()); + feature_list_.InitWithFeatureState( + blink::features::kIsolateSandboxedIframes, GetParam()); } void SetUpOnMainThread() override { @@ -50,7 +51,8 @@ : public SitePerProcessBrowserTest { public: SitePerProcessIsolatedSandboxedIframeTest() { - feature_list_.InitAndEnableFeature(features::kIsolateSandboxedIframes); + feature_list_.InitAndEnableFeature( + blink::features::kIsolateSandboxedIframes); } private: @@ -61,7 +63,8 @@ : public SitePerProcessBrowserTest { public: SitePerProcessNotIsolatedSandboxedIframeTest() { - feature_list_.InitAndDisableFeature(features::kIsolateSandboxedIframes); + feature_list_.InitAndDisableFeature( + blink::features::kIsolateSandboxedIframes); } private: @@ -75,7 +78,8 @@ public: SitePerProcessPerOriginIsolatedSandboxedIframeTest() { feature_list_.InitWithFeaturesAndParameters( - {{features::kIsolateSandboxedIframes, {{"grouping", "per-origin"}}}}, + {{blink::features::kIsolateSandboxedIframes, + {{"grouping", "per-origin"}}}}, {/* disabled_features */}); } @@ -87,7 +91,8 @@ : public SitePerProcessIsolatedSandboxedIframeTest { public: SitePerProcessIsolatedSandboxWithoutStrictSiteIsolationBrowserTest() { - feature_list_.InitAndEnableFeature(features::kIsolateSandboxedIframes); + feature_list_.InitAndEnableFeature( + blink::features::kIsolateSandboxedIframes); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -150,7 +155,8 @@ public: SitePerProcessPerDocumentIsolatedSandboxedIframeTest() { feature_list_.InitWithFeaturesAndParameters( - {{features::kIsolateSandboxedIframes, {{"grouping", "per-document"}}}}, + {{blink::features::kIsolateSandboxedIframes, + {{"grouping", "per-document"}}}}, {/* disabled_features */}); }
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index fe77d59..f0048908 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -2613,7 +2613,8 @@ attribution_manager->ClearData( begin, end, generic_filter, filter_builder, remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL, - CreateTaskCompletionClosure(TracingDataType::kConversions)); + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + CreateTaskCompletionClosure(TracingDataType::kConversions))); } else if (storage_key.IsFirstPartyContext()) { // Attribution Reporting API doesn't support cross-site data deletion. std::unique_ptr<BrowsingDataFilterBuilder> effective_filter_builder = @@ -2623,7 +2624,8 @@ attribution_manager->ClearData( begin, end, generic_filter, effective_filter_builder.get(), remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL, - CreateTaskCompletionClosure(TracingDataType::kConversions)); + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + CreateTaskCompletionClosure(TracingDataType::kConversions))); } } @@ -2638,7 +2640,8 @@ // `CookiesTreeModel`. aggregation_service->ClearData( begin, end, generic_filter, - CreateTaskCompletionClosure(TracingDataType::kAggregationService)); + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + CreateTaskCompletionClosure(TracingDataType::kAggregationService))); } if (private_aggregation_manager &&
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index 860e005..d8cd60b 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -18,6 +18,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/path_service.h" +#include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/strings/pattern.h" #include "base/strings/stringprintf.h" @@ -1004,8 +1005,8 @@ const std::vector<double>& progresses = delegate->progresses; // All updates should be in order ... - if (std::adjacent_find(progresses.begin(), progresses.end(), - std::greater<>()) != progresses.end()) { + if (base::ranges::adjacent_find(progresses, std::greater<>()) != + progresses.end()) { ADD_FAILURE() << "Progress values should be in order: " << ::testing::PrintToString(progresses); } @@ -1025,8 +1026,8 @@ const std::vector<double>& progresses = delegate->progresses; // All updates should be in order ... - if (std::adjacent_find(progresses.begin(), progresses.end(), - std::greater<>()) != progresses.end()) { + if (base::ranges::adjacent_find(progresses, std::greater<>()) != + progresses.end()) { ADD_FAILURE() << "Progress values should be in order: " << ::testing::PrintToString(progresses); }
diff --git a/content/public/browser/direct_sockets_delegate.h b/content/public/browser/direct_sockets_delegate.h index 3d4424e..ee608cb 100644 --- a/content/public/browser/direct_sockets_delegate.h +++ b/content/public/browser/direct_sockets_delegate.h
@@ -28,9 +28,6 @@ const std::string& address, uint16_t port, blink::mojom::DirectSocketProtocolType) const = 0; - - // If yes, skips post-resolve checks for Direct TCP/UDP sockets. - virtual bool ShouldSkipPostResolveChecks(content::RenderFrameHost*) const = 0; }; } // namespace content
diff --git a/content/public/browser/first_party_sets_handler.h b/content/public/browser/first_party_sets_handler.h index 15a5206..3cdcbe4 100644 --- a/content/public/browser/first_party_sets_handler.h +++ b/content/public/browser/first_party_sets_handler.h
@@ -19,7 +19,6 @@ class FirstPartySetEntry; class FirstPartySetsCacheFilter; class FirstPartySetsContextConfig; -class GlobalFirstPartySets; class SchemefulSite; } @@ -140,10 +139,6 @@ // Resets the state on the instance for testing. virtual void ResetForTesting() = 0; - // Allows tests to override the post-initalization global First-Party Sets. - virtual void SetGlobalSetsForTesting( - net::GlobalFirstPartySets global_sets) = 0; - // Looks up `site` in the global First-Party Sets and `config` to find its // associated FirstPartySetEntry. //
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc index 16f994d..35725be 100644 --- a/content/public/browser/site_isolation_policy.cc +++ b/content/public/browser/site_isolation_policy.cc
@@ -25,6 +25,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "third_party/blink/public/common/features.h" #include "url/origin.h" namespace content { @@ -141,7 +142,8 @@ // static bool SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() { return !IsSiteIsolationDisabled(SiteIsolationMode::kPartialSiteIsolation) && - base::FeatureList::IsEnabled(features::kIsolateSandboxedIframes); + base::FeatureList::IsEnabled( + blink::features::kIsolateSandboxedIframes); } // static
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 5b754837..0ca55f1 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -524,24 +524,6 @@ base::FEATURE_DISABLED_BY_DEFAULT); const char kIsolateOriginsFieldTrialParamName[] = "OriginsList"; -// Allow process isolation of iframes with the 'sandbox' attribute set. Whether -// or not such an iframe will be isolated may depend on options specified with -// the attribute. Note: At present, only iframes with origin-restricted -// sandboxes are isolated. -BASE_FEATURE(kIsolateSandboxedIframes, - "IsolateSandboxedIframes", - base::FEATURE_DISABLED_BY_DEFAULT); -const base::FeatureParam<IsolateSandboxedIframesGrouping>::Option - isolated_sandboxed_iframes_grouping_types[] = { - {IsolateSandboxedIframesGrouping::kPerSite, "per-site"}, - {IsolateSandboxedIframesGrouping::kPerOrigin, "per-origin"}, - {IsolateSandboxedIframesGrouping::kPerDocument, "per-document"}}; -const base::FeatureParam<IsolateSandboxedIframesGrouping> - kIsolateSandboxedIframesGroupingParam{ - &kIsolateSandboxedIframes, "grouping", - IsolateSandboxedIframesGrouping::kPerSite, - &isolated_sandboxed_iframes_grouping_types}; - // Enables the TC39 Array grouping proposal. BASE_FEATURE(kJavaScriptArrayGrouping, "JavaScriptArrayGrouping",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 1e543fa..e10cdf16 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -110,22 +110,6 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kIsolateFencedFrames); CONTENT_EXPORT BASE_DECLARE_FEATURE(kIsolateOrigins); CONTENT_EXPORT extern const char kIsolateOriginsFieldTrialParamName[]; -CONTENT_EXPORT BASE_DECLARE_FEATURE(kIsolateSandboxedIframes); -enum class IsolateSandboxedIframesGrouping { - // In this grouping, all isolated sandboxed iframes whose URLs share the same - // site in a given BrowsingInstance will share a process. - kPerSite, - // In this grouping, all isolated sandboxed iframes from a given - // BrowsingInstance whose URLs share the same origin will be isolated in an - // origin-keyed process. - kPerOrigin, - // Unlike the other two modes, which group sandboxed frames per-site or - // per-origin, this one doesn't do any grouping at all and uses one process - // per document. - kPerDocument, -}; -CONTENT_EXPORT extern const base::FeatureParam<IsolateSandboxedIframesGrouping> - kIsolateSandboxedIframesGroupingParam; CONTENT_EXPORT BASE_DECLARE_FEATURE(kJavaScriptArrayGrouping); CONTENT_EXPORT BASE_DECLARE_FEATURE(kJavaScriptExperimentalSharedMemory); CONTENT_EXPORT BASE_DECLARE_FEATURE(kLazyFrameLoading);
diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc index c106f9c..5becf078 100644 --- a/content/renderer/pepper/ppb_var_deprecated_impl.cc +++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -94,17 +94,14 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_name = try_catch.ToV8(name); if (try_catch.HasException()) return false; - v8::Local<v8::Context> context = try_catch.GetContext(); - if (try_catch.HasException()) - return false; - bool result = false; if (!accessor.GetObject()->Has(context, v8_name).To(&result)) { try_catch.HasException(); @@ -121,17 +118,14 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_name = try_catch.ToV8(name); if (try_catch.HasException()) return false; - v8::Local<v8::Context> context = try_catch.GetContext(); - if (try_catch.HasException()) - return false; - bool has_name = false; if (!accessor.GetObject()->Has(context, v8_name).To(&has_name)) { try_catch.HasException(); @@ -153,16 +147,17 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_name = try_catch.ToV8(name); if (try_catch.HasException()) return PP_MakeUndefined(); v8::Local<v8::Value> result; - ScopedPPVar result_var = try_catch.FromV8Maybe( - accessor.GetObject()->Get(try_catch.GetContext(), v8_name)); + ScopedPPVar result_var = + try_catch.FromV8Maybe(accessor.GetObject()->Get(context, v8_name)); if (try_catch.HasException()) return PP_MakeUndefined(); @@ -179,14 +174,14 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); *properties = nullptr; *property_count = 0; - v8::Local<v8::Context> context = try_catch.GetContext(); v8::Local<v8::Array> identifiers; if (!accessor.GetObject()->GetPropertyNames(context).ToLocal(&identifiers)) return; @@ -215,8 +210,9 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_name = try_catch.ToV8(name); v8::Local<v8::Value> v8_value = try_catch.ToV8(value); @@ -238,18 +234,15 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_name = try_catch.ToV8(name); if (try_catch.HasException()) return; - v8::Local<v8::Context> context = try_catch.GetContext(); - if (try_catch.HasException()) - return; - if (accessor.GetObject()->Delete(context, v8_name).IsNothing()) { // Ensure exception object is created if V8 has thrown. try_catch.HasException(); @@ -277,8 +270,9 @@ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(), exception); + v8::Local<v8::Context> context = try_catch.GetContext(); v8::MicrotasksScope microtasks_scope( - accessor.GetObject()->GetIsolate(), + accessor.GetObject()->GetIsolate(), context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> v8_method_name = try_catch.ToV8(scoped_name.get()); if (try_catch.HasException()) @@ -290,7 +284,6 @@ } v8::Local<v8::Object> function = accessor.GetObject(); - v8::Local<v8::Context> context = accessor.instance()->GetMainWorldContext(); v8::Local<v8::Object> recv = context->Global(); if (v8_method_name.As<v8::String>()->Length() != 0) { v8::Local<v8::Value> value;
diff --git a/content/renderer/pepper/v8_var_converter.cc b/content/renderer/pepper/v8_var_converter.cc index e02ccd3..cac746dc 100644 --- a/content/renderer/pepper/v8_var_converter.cc +++ b/content/renderer/pepper/v8_var_converter.cc
@@ -330,7 +330,8 @@ v8::Isolate* isolate = context->GetIsolate(); v8::EscapableHandleScope handle_scope(isolate); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); VarHandleMap visited_ids; ParentVarSet parent_ids; @@ -486,7 +487,8 @@ v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope handle_scope(isolate); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); HandleVarMap visited_handles; ParentHandleSet parent_handles;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index d7f19a4e..2e135b98 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4,7 +4,6 @@ #include "content/renderer/render_frame_impl.h" -#include <algorithm> #include <map> #include <memory> #include <string> @@ -34,6 +33,7 @@ #include "base/metrics/histogram_macros.h" #include "base/observer_list.h" #include "base/process/process.h" +#include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/strings/string_piece.h" @@ -726,8 +726,7 @@ DCHECK(std::is_sorted(params_.digests_of_uris_to_skip.begin(), params_.digests_of_uris_to_skip.end())); // URLs are not duplicated. - DCHECK(std::adjacent_find(params_.digests_of_uris_to_skip.begin(), - params_.digests_of_uris_to_skip.end()) == + DCHECK(base::ranges::adjacent_find(params_.digests_of_uris_to_skip) == params_.digests_of_uris_to_skip.end()); } @@ -3819,9 +3818,6 @@ } void RenderFrameImpl::DidClearWindowObject() { - v8::MicrotasksScope microtasks(blink::MainThreadIsolate(), - v8::MicrotasksScope::kDoNotRunMicrotasks); - if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) WebUIExtension::Install(frame_); @@ -4339,6 +4335,7 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) { v8::MicrotasksScope microtasks(blink::MainThreadIsolate(), + context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); if (((enabled_bindings_ & BINDINGS_POLICY_MOJO_WEB_UI) || enable_mojo_js_bindings_) &&
diff --git a/content/test/data/attribution_reporting/interop/aggregatable_dedup_key.json b/content/test/data/attribution_reporting/interop/aggregatable_dedup_key.json new file mode 100644 index 0000000..df7579f --- /dev/null +++ b/content/test/data/attribution_reporting/interop/aggregatable_dedup_key.json
@@ -0,0 +1,171 @@ +{ + "description": "2nd trigger with the same deduplication key is not attributed", + "input": { + "sources": [ + { + "timestamp": "1643235573000", + "registration_request": { + "source_origin": "https://source.test", + "attribution_src_url": "https://reporter.test/register-source", + "source_type": "navigation" + }, + "responses": [{ + "url": "https://reporter.test/register-source", + "response": { + "Attribution-Reporting-Register-Source": { + "destination": "https://destination.test", + "source_event_id": "123", + "aggregation_keys": { + "a": "0x159" + } + } + } + }] + } + ], + "triggers": [ + // Should result in an event-level report and an aggregatable report. + { + "timestamp": "1643235574000", + "registration_request": { + "attribution_src_url": "https://reporter.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "1", + "deduplication_key": "1" + } + ], + "aggregatable_trigger_data": [ + { + "source_keys": ["a"], + "key_piece": "0x400" + } + ], + "aggregatable_values": { + "a": 123 + }, + "aggregatable_deduplication_key": "1" + } + } + }] + }, + // Should result in an event-level report and the aggregatable report + // will be deduplicated. + { + "timestamp": "1643235575000", + "registration_request": { + "attribution_src_url": "https://reporter.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "2" + } + ], + "aggregatable_trigger_data": [ + { + "source_keys": ["a"], + "key_piece": "0x400" + } + ], + "aggregatable_values": { + "a": 456 + }, + "aggregatable_deduplication_key": "1" + } + } + }] + }, + // Should result in an aggregatable report as the deduplication key is + // different. + { + "timestamp": "1643235576000", + "registration_request": { + "attribution_src_url": "https://reporter.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "aggregatable_trigger_data": [ + { + "source_keys": ["a"], + "key_piece": "0x400" + } + ], + "aggregatable_values": { + "a": 456 + }, + "aggregatable_deduplication_key": "2" + } + } + }] + } + ] + }, + "output": { + "event_level_results": [ + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "source_event_id": "123", + "source_type": "navigation", + "trigger_data": "1" + }, + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643408373000" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "source_event_id": "123", + "source_type": "navigation", + "trigger_data": "2" + }, + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643408373000" + } + ], + "aggregatable_results": [ + { + "payload": { + "attribution_destination": "https://destination.test", + "histograms": [ + { + "key": "0x559", + "value": 123 + } + ] + }, + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-aggregate-attribution", + "report_time": "1643239174000" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "histograms": [ + { + "key": "0x559", + "value": 456 + } + ] + }, + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-aggregate-attribution", + "report_time": "1643239176000" + } + ] + } +}
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 0b96724..0d1d2cd 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -907,9 +907,21 @@ crbug.com/1284804 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ] crbug.com/1285109 [ chromeos chromeos-board-kevin passthrough ] conformance/canvas/render-after-resize-test.html [ Failure ] crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/context/context-hidden-alpha.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/textures/misc/copy-tex-image-2d-formats.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/array/array_001_to_006.html [ Failure ] crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/functions/functions_033_to_040.html [ Failure ] crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/ogles/GL/refract/refract_001_to_006.html [ Failure ] crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/renderbuffers/renderbuffer-initialization.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/rendering/rasterizer-discard-and-implicit-clear.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/image_bitmap_from_blob/tex-3d-rgb16f-rgb-float.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] conformance2/textures/video/tex-3d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_03.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/fbocolorbuffer/tex3d_00.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/framebufferblit/conversion_26.html [ Failure ] +crbug.com/1374285 [ chromeos chromeos-board-kevin passthrough ] deqp/functional/gles3/textureshadow/2d_array_nearest_always.html [ Failure ] crbug.com/1285111 [ chromeos chromeos-board-kevin passthrough ] conformance/textures/misc/copy-tex-image-and-sub-image-2d.html [ Failure ] crbug.com/1285112 [ chromeos chromeos-board-kevin passthrough ] conformance2/rendering/blitframebuffer-multisampled-readbuffer.html [ Failure ] crbug.com/1285114 [ chromeos chromeos-board-kevin passthrough ] conformance2/transform_feedback/transform_feedback.html [ Failure ]
diff --git a/content/web_test/renderer/gc_controller.cc b/content/web_test/renderer/gc_controller.cc index c9b46e2..5743ad7 100644 --- a/content/web_test/renderer/gc_controller.cc +++ b/content/web_test/renderer/gc_controller.cc
@@ -101,7 +101,8 @@ v8::Context::Scope context_scope(context); v8::TryCatch try_catch(isolate); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); auto result = func->Call(context, context->Global(), 0, nullptr); // Swallow potential exception. std::ignore = result;
diff --git a/content/web_test/renderer/web_frame_test_proxy.cc b/content/web_test/renderer/web_frame_test_proxy.cc index c95fcc33a..0dd00b8 100644 --- a/content/web_test/renderer/web_frame_test_proxy.cc +++ b/content/web_test/renderer/web_frame_test_proxy.cc
@@ -744,8 +744,6 @@ // Avoid installing bindings on the about:blank in between tests. This is // especially problematic for web platform tests that would inject javascript // into the page when installing bindings. - v8::MicrotasksScope microtask_scope(blink::MainThreadIsolate(), - v8::MicrotasksScope::kDoNotRunMicrotasks); if (test_runner()->TestIsRunning()) { blink::WebLocalFrame* frame = GetWebFrame(); // These calls will install the various JS bindings for web tests into the
diff --git a/extensions/browser/api/storage/settings_test_util.cc b/extensions/browser/api/storage/settings_test_util.cc index 61e18d57..15a16b9 100644 --- a/extensions/browser/api/storage/settings_test_util.cc +++ b/extensions/browser/api/storage/settings_test_util.cc
@@ -72,15 +72,14 @@ const std::string& id, Manifest::Type type, const std::set<std::string>& permissions_set) { - base::DictionaryValue manifest; - manifest.SetStringKey("name", std::string("Test extension ") + id); - manifest.SetStringKey("version", "1.0"); - manifest.SetIntKey("manifest_version", 2); + base::Value::Dict manifest; + manifest.Set("name", std::string("Test extension ") + id); + manifest.Set("version", "1.0"); + manifest.Set("manifest_version", 2); - std::unique_ptr<base::ListValue> permissions(new base::ListValue()); - for (auto it = permissions_set.cbegin(); it != permissions_set.cend(); ++it) { - permissions->Append(*it); - } + base::Value::List permissions; + for (const auto& perm : permissions_set) + permissions.Append(perm); manifest.Set("permissions", std::move(permissions)); switch (type) { @@ -88,10 +87,10 @@ break; case Manifest::TYPE_LEGACY_PACKAGED_APP: { - auto app = std::make_unique<base::DictionaryValue>(); - auto app_launch = std::make_unique<base::DictionaryValue>(); - app_launch->SetStringKey("local_path", "fake.html"); - app->Set("launch", std::move(app_launch)); + base::Value::Dict app; + base::Value::Dict app_launch; + app_launch.Set("local_path", "fake.html"); + app.Set("launch", std::move(app_launch)); manifest.Set("app", std::move(app)); break; }
diff --git a/extensions/browser/requirements_checker_unittest.cc b/extensions/browser/requirements_checker_unittest.cc index ddcf5ea..a454de32 100644 --- a/extensions/browser/requirements_checker_unittest.cc +++ b/extensions/browser/requirements_checker_unittest.cc
@@ -47,21 +47,18 @@ class RequirementsCheckerTest : public ExtensionsTest { public: - RequirementsCheckerTest() { - manifest_dict_ = std::make_unique<base::DictionaryValue>(); - } - - ~RequirementsCheckerTest() override {} + RequirementsCheckerTest() = default; + ~RequirementsCheckerTest() override = default; void CreateExtension() { - manifest_dict_->SetStringKey("name", "dummy name"); - manifest_dict_->SetStringKey("version", "1"); - manifest_dict_->SetIntKey("manifest_version", 2); + manifest_dict_.Set("name", "dummy name"); + manifest_dict_.Set("version", "1"); + manifest_dict_.Set("manifest_version", 2); std::string error; extension_ = Extension::Create(base::FilePath(), mojom::ManifestLocation::kUnpacked, - *manifest_dict_, Extension::NO_FLAGS, &error); + manifest_dict_, Extension::NO_FLAGS, &error); ASSERT_TRUE(extension_.get()) << error; } @@ -74,15 +71,14 @@ } void RequireWindowShape() { - manifest_dict_->SetBoolPath("requirements.window.shape", true); + manifest_dict_.SetByDottedPath("requirements.window.shape", true); } void RequireFeature(const char feature[]) { - if (!manifest_dict_->FindKey(kFeaturesKey)) - manifest_dict_->Set(kFeaturesKey, std::make_unique<base::ListValue>()); - base::ListValue* features_list = nullptr; - ASSERT_TRUE(manifest_dict_->GetList(kFeaturesKey, &features_list)); - features_list->Append(feature); + base::Value* features_list = manifest_dict_.Find(kFeaturesKey); + if (!features_list) + features_list = manifest_dict_.Set(kFeaturesKey, base::Value::List()); + features_list->GetList().Append(feature); } std::unique_ptr<RequirementsChecker> checker_; @@ -90,7 +86,7 @@ private: scoped_refptr<Extension> extension_; - std::unique_ptr<base::DictionaryValue> manifest_dict_; + base::Value::Dict manifest_dict_; }; // Tests no requirements.
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index 33cd6309..13c985e8 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -141,12 +141,12 @@ // Computes the |extension_id| from the given parameters. On success, returns // true. On failure, populates |error| and returns false. -bool ComputeExtensionID(const base::DictionaryValue& manifest, +bool ComputeExtensionID(const base::DictAdapterForMigration& manifest, const base::FilePath& path, int creation_flags, std::u16string* error, ExtensionId* extension_id) { - if (const base::Value* public_key = manifest.FindKey(keys::kPublicKey)) { + if (const base::Value* public_key = manifest.Find(keys::kPublicKey)) { std::string public_key_bytes; if (!public_key->is_string() || !Extension::ParsePEMKeyBytes(public_key->GetString(), @@ -222,11 +222,12 @@ } // static -scoped_refptr<Extension> Extension::Create(const base::FilePath& path, - ManifestLocation location, - const base::DictionaryValue& value, - int flags, - std::string* utf8_error) { +scoped_refptr<Extension> Extension::Create( + const base::FilePath& path, + ManifestLocation location, + const base::DictAdapterForMigration& value, + int flags, + std::string* utf8_error) { return Extension::Create(path, location, value, @@ -237,12 +238,13 @@ // TODO(sungguk): Continue removing std::string errors and replacing // with std::u16string. See http://crbug.com/71980. -scoped_refptr<Extension> Extension::Create(const base::FilePath& path, - ManifestLocation location, - const base::DictionaryValue& value, - int flags, - const std::string& explicit_id, - std::string* utf8_error) { +scoped_refptr<Extension> Extension::Create( + const base::FilePath& path, + ManifestLocation location, + const base::DictAdapterForMigration& value, + int flags, + const std::string& explicit_id, + std::string* utf8_error) { base::ElapsedTimer timer; DCHECK(utf8_error); std::u16string error; @@ -262,18 +264,14 @@ } std::unique_ptr<extensions::Manifest> manifest; + auto value_clone = base::DictionaryValue::From( + base::Value::ToUniquePtrValue(base::Value(value.Clone()))); if (flags & FOR_LOGIN_SCREEN) { manifest = Manifest::CreateManifestForLoginScreen( - location, - base::DictionaryValue::From( - base::Value::ToUniquePtrValue(value.Clone())), - std::move(extension_id)); + location, std::move(value_clone), std::move(extension_id)); } else { - manifest = std::make_unique<Manifest>( - location, - base::DictionaryValue::From( - base::Value::ToUniquePtrValue(value.Clone())), - std::move(extension_id)); + manifest = std::make_unique<Manifest>(location, std::move(value_clone), + std::move(extension_id)); } std::vector<InstallWarning> install_warnings;
diff --git a/extensions/common/extension.h b/extensions/common/extension.h index a184292..dde6bf6 100644 --- a/extensions/common/extension.h +++ b/extensions/common/extension.h
@@ -32,6 +32,7 @@ #endif namespace base { +class DictAdapterForMigration; class DictionaryValue; } @@ -155,20 +156,22 @@ Extension(const Extension&) = delete; Extension& operator=(const Extension&) = delete; - static scoped_refptr<Extension> Create(const base::FilePath& path, - mojom::ManifestLocation location, - const base::DictionaryValue& value, - int flags, - std::string* error); + static scoped_refptr<Extension> Create( + const base::FilePath& path, + mojom::ManifestLocation location, + const base::DictAdapterForMigration& value, + int flags, + std::string* error); // In a few special circumstances, we want to create an Extension and give it // an explicit id. Most consumers should just use the other Create() method. - static scoped_refptr<Extension> Create(const base::FilePath& path, - mojom::ManifestLocation location, - const base::DictionaryValue& value, - int flags, - const ExtensionId& explicit_id, - std::string* error); + static scoped_refptr<Extension> Create( + const base::FilePath& path, + mojom::ManifestLocation location, + const base::DictAdapterForMigration& value, + int flags, + const ExtensionId& explicit_id, + std::string* error); // Valid schemes for web extent URLPatterns. static const int kValidWebExtentSchemes;
diff --git a/extensions/renderer/binding_generating_native_handler.cc b/extensions/renderer/binding_generating_native_handler.cc index ce599f4..c9d27a040 100644 --- a/extensions/renderer/binding_generating_native_handler.cc +++ b/extensions/renderer/binding_generating_native_handler.cc
@@ -83,7 +83,8 @@ v8::Local<v8::Value> argv[] = {v8_api_name}; v8::Local<v8::Value> binding_instance_value; v8::MicrotasksScope microtasks_scope( - v8_context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); + v8_context->GetIsolate(), v8_context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); // TODO(devlin): We should not be using v8::Function::Call() directly here. // Instead, we should use JSRunner once it's used outside native bindings. if (!create_binding->Call(v8_context, binding, std::size(argv), argv) @@ -108,7 +109,8 @@ v8::Local<v8::Value> compiled_schema; { v8::MicrotasksScope microtasks_scope( - v8_context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); + v8_context->GetIsolate(), v8_context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); // TODO(devlin): We should not be using v8::Function::Call() directly here. // Instead, we should use JSRunner once it's used outside native bindings. if (!generate->Call(v8_context, binding_instance, 0, nullptr)
diff --git a/extensions/renderer/bindings/api_request_handler.cc b/extensions/renderer/bindings/api_request_handler.cc index 142a44f..a7afe4d 100644 --- a/extensions/renderer/bindings/api_request_handler.cc +++ b/extensions/renderer/bindings/api_request_handler.cc
@@ -275,7 +275,8 @@ v8::Isolate* isolate = context->GetIsolate(); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); if (error.empty()) { v8::Local<v8::Value> result;
diff --git a/extensions/renderer/extension_js_runner.cc b/extensions/renderer/extension_js_runner.cc index d15b259..5e3c4ab 100644 --- a/extensions/renderer/extension_js_runner.cc +++ b/extensions/renderer/extension_js_runner.cc
@@ -46,7 +46,7 @@ v8::Isolate* isolate = context->GetIsolate(); DCHECK(context == isolate->GetCurrentContext()); - v8::MicrotasksScope microtasks(isolate, + v8::MicrotasksScope microtasks(isolate, context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Object> global = context->Global();
diff --git a/extensions/renderer/safe_builtins.cc b/extensions/renderer/safe_builtins.cc index 22e89a5..fae59d8 100644 --- a/extensions/renderer/safe_builtins.cc +++ b/extensions/renderer/safe_builtins.cc
@@ -186,7 +186,9 @@ info[2]->IsObject() && // args info[3]->IsInt32() && // first_arg_index info[4]->IsInt32()); // args_length + v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext(); v8::MicrotasksScope microtasks(info.GetIsolate(), + context->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Function> function = info[0].As<v8::Function>(); v8::Local<v8::Object> recv; @@ -207,7 +209,6 @@ int first_arg_index = info[3].As<v8::Int32>()->Value(); int args_length = info[4].As<v8::Int32>()->Value(); - v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext(); int argc = args_length - first_arg_index; std::unique_ptr<v8::Local<v8::Value>[]> argv( new v8::Local<v8::Value>[argc]);
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index d856f08..dcdd44a 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc
@@ -291,7 +291,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); v8::HandleScope handle_scope(isolate()); v8::Context::Scope scope(v8_context()); - v8::MicrotasksScope microtasks(isolate(), + v8::MicrotasksScope microtasks(isolate(), v8_context()->GetMicrotaskQueue(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Object> global = v8_context()->Global(); if (web_frame_) { @@ -550,8 +550,8 @@ return v8::Undefined(isolate()); } - v8::MicrotasksScope microtasks( - isolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::MicrotasksScope microtasks(isolate(), v8_context()->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::TryCatch try_catch(isolate()); try_catch.SetCaptureMessage(true); v8::ScriptOrigin origin(isolate(), v8_helpers::ToV8StringUnsafe(
diff --git a/google_apis/BUILD.gn b/google_apis/BUILD.gn index c3ab9da9..6327be5 100644 --- a/google_apis/BUILD.gn +++ b/google_apis/BUILD.gn
@@ -55,11 +55,6 @@ #`use_official_google_api_keys` was explicitly set to true and will fail to # build if the file is missing. use_official_google_api_keys = true - - # TODO(crbug.com/1294931): Remove this override when fixing the issue. - if (is_fuchsia) { - use_official_google_api_keys = false - } } else { # Check if the key file exists. check_internal_result =
diff --git a/ios/chrome/browser/sync/sync_service_factory_unittest.cc b/ios/chrome/browser/sync/sync_service_factory_unittest.cc index 2d3e9184..9fad64c 100644 --- a/ios/chrome/browser/sync/sync_service_factory_unittest.cc +++ b/ios/chrome/browser/sync/sync_service_factory_unittest.cc
@@ -53,7 +53,7 @@ protected: // Returns the collection of default datatypes. syncer::ModelTypeSet DefaultDatatypes() { - static_assert(42 == syncer::GetNumModelTypes(), + static_assert(43 == syncer::GetNumModelTypes(), "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled)."); @@ -78,6 +78,9 @@ datatypes.Put(syncer::PREFERENCES); datatypes.Put(syncer::PRIORITY_PREFERENCES); datatypes.Put(syncer::READING_LIST); + if (base::FeatureList::IsEnabled(syncer::kSyncSegmentationDataType)) { + datatypes.Put(syncer::SEGMENTATION); + } // TODO(crbug.com/919489) Add SECURITY_EVENTS data type once it is enabled. datatypes.Put(syncer::SESSIONS); datatypes.Put(syncer::PROXY_TABS);
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index d898aa1..625b83ae 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -508,7 +508,8 @@ // Tests that the position of the collection view is restored when navigating // back to the NTP. -- (void)testPositionRestored { +// TODO(crbug.com/1364725): Re-enable test after fixing the test failure. +- (void)DISABLED_testPositionRestored { [self addMostVisitedTile]; // Add suggestions to be able to scroll on iPad.
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index d6d7a37..1594946 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -f38a8f003eaa0529f41c39ef89992f8a874b0a5a \ No newline at end of file +41b99b27bfd6780db9527dba15b96d747097604c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index e3118dc2..4f16d8c 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -846fcf651d96e06dd692197a51338f437522041f \ No newline at end of file +7ee130db21651b87124ac6dbee579f815d1fcd10 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 34595f3..184c2824 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -5dc796d6d88214d693783958cfd90457d2c33537 \ No newline at end of file +85861226e1845e497d36d4ee7b7c9ad7dbcad8a5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 7961104..5ac8e01e 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -1e256610365ffceafca6385c42989ecba29fedf9 \ No newline at end of file +58a43c1c957d5801942af8544a3431466e51ef83 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 916d0790..f07765b3 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -30f9c067d2c5dd7f11772ad87fa1b30ded294d06 \ No newline at end of file +37c7961be73058cfc484135a53c090819d34f464 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 649cb4a..8683eef 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -b7384d271dd061cc697f0d55d3cea95b80fec4c0 \ No newline at end of file +a95ce3b67de477578cc665a551158c801ed981a2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index 21dc00d..e63a7717 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -14d12c8e80190e266070271f6b067925f5ee1896 \ No newline at end of file +4d10d859fda92c6aebf3e93978471f3c56c3206b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index d74c544d..76a9761 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -69426fb5336094108a04cc3714fae485a452ec61 \ No newline at end of file +465e3f571785d6ca6d5fc02034a118bbb26e822c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index 87a5f445..70ec021 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -9fb7c1cb99135f5f817ea19eed8b37491748a4dd \ No newline at end of file +f487ba26fd9339143451a268d7819dc3be64cf26 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index bdfb0c5..f2365e88 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -0ae74e40ec78feca8dba9f62f5b177369e3d10b2 \ No newline at end of file +62ec1a3533e642f50e057cd43ad448429f278f75 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index f743f2a5..718635e 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -2aad958e79bef7e091169afdd3a837fc4115a645 \ No newline at end of file +cd9a9b9980e3eb7c5fed7d4bf0cb0987de95d7cd \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 86782d2c..5b9679c2 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -61b225b35ea1ce3772e2fd82936bc093e60d5f3d \ No newline at end of file +3fe631affa823b5470a33f923e963b547020b5f5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 27e0857..4521cc51 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -2931b4faf0b5afc67e39230ccfb314b15d1bcd49 \ No newline at end of file +68a35c8454595a83d879e67c9d602f61b3cffe30 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 0bb59d5..261b0b0 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -6fe36274fb2afce6699109377148f8d3c628ef98 \ No newline at end of file +4ae6527f1998c39c7cb9448a6eb43f77ff220ff8 \ No newline at end of file
diff --git a/media/media_options.gni b/media/media_options.gni index b75ffaf..4650e50 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -205,8 +205,8 @@ # Enables the use of library CDMs that implements the interface defined at # media/cdm/api/content_decryption_module.h. If true, the actually library CDM # will be hosted in the mojo CDM service running in the CDM (utility) process. - # Used for all desktop platforms except Fuchsia (crbug.com/1265618). - enable_library_cdms = toolkit_views && !is_fuchsia && !is_castos + # Used for all desktop platforms. + enable_library_cdms = toolkit_views && !is_castos } declare_args() {
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index a9ff250..07e4288 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -3011,6 +3011,40 @@ return StartProbing(network, peer_address); } +std::unique_ptr<quic::QuicPathValidationContext> +QuicChromiumClientSession::CreateContextForMultiPortPath() { + if (!connection()->connection_migration_use_new_cid()) { + return nullptr; + } + + // Create and configure socket on default network + std::unique_ptr<DatagramClientSocket> probing_socket = + stream_factory_->CreateSocket(net_log_.net_log(), net_log_.source()); + if (stream_factory_->ConfigureSocket( + probing_socket.get(), ToIPEndPoint(peer_address()), default_network_, + session_key_.socket_tag()) != OK) { + return nullptr; + } + + // Create new packet writer and reader on the probing socket. + auto probing_writer = std::make_unique<QuicChromiumPacketWriter>( + probing_socket.get(), task_runner_); + auto probing_reader = std::make_unique<QuicChromiumPacketReader>( + probing_socket.get(), clock_, this, yield_after_packets_, + yield_after_duration_, net_log_); + + probing_reader->StartReading(); + path_validation_writer_delegate_.set_network(default_network_); + path_validation_writer_delegate_.set_peer_address(peer_address()); + probing_writer->set_delegate(&path_validation_writer_delegate_); + IPEndPoint local_address; + probing_socket->GetLocalAddress(&local_address); + return std::make_unique<QuicChromiumPathValidationContext>( + ToQuicSocketAddress(local_address), peer_address(), default_network_, + std::move(probing_socket), std::move(probing_writer), + std::move(probing_reader)); +} + ProbingResult QuicChromiumClientSession::StartProbing( handles::NetworkHandle network, const quic::QuicSocketAddress& peer_address) {
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index 54edb82..c594635 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -695,6 +695,8 @@ void OnPathDegrading() override; void OnForwardProgressMadeAfterPathDegrading() override; void OnKeyUpdate(quic::KeyUpdateReason reason) override; + std::unique_ptr<quic::QuicPathValidationContext> + CreateContextForMultiPortPath() override; // QuicChromiumPacketReader::Visitor methods: bool OnReadError(int result, const DatagramClientSocket* socket) override;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 70c1595..65eaa56 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -4653,6 +4653,134 @@ EXPECT_TRUE(quic_data2.AllWriteDataConsumed()); } +TEST_P(QuicStreamFactoryTest, MultiPortSession) { + if (!version_.HasIetfQuicFrames()) { + // Path validator is only supported in IETF QUIC. + return; + } + SetIetfConnectionMigrationFlagsAndConnectionOptions(); + // Turning on MPQC will implicitly turn on port migration. + quic_params_->connection_options.push_back(quic::kMPQC); + socket_factory_ = std::make_unique<TestPortMigrationSocketFactory>(); + Initialize(); + + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner so that we can control time. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + + MockQuicData quic_data1(version_); + quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1)); + quic_data1.AddWrite( + SYNCHRONOUS, + ConstructGetRequestPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true)); + quic_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause + quic_data1.AddRead( + ASYNC, + ConstructOkResponsePacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false)); + quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + quic_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckAndDataPacket( + 4, /*include_version=*/false, GetQpackDecoderStreamId(), + /*largest_received=*/2, /*smallest_received=*/1, /*fin=*/false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 5, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + quic_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Set up the second socket data provider that is used for multi-port + MockQuicData quic_data2(version_); + quic::QuicConnectionId cid_on_new_path = + quic::test::TestConnectionId(12345678); + + client_maker_.set_connection_id(cid_on_new_path); + // Connectivity probe to be sent on the new path. + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeConnectivityProbingPacket(2, true)); + quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause + // Connectivity probe to receive from the server. + quic_data2.AddRead(ASYNC, + server_maker_.MakeConnectivityProbingPacket(1, false)); + + quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + quic_data2.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = url_; + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + stream->RegisterRequest(&request_info); + EXPECT_EQ(OK, stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_, + CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + // Manually initialize the connection's self address. In real life, the + // initialization will be done during crypto handshake. + IPEndPoint ip; + session->GetDefaultSocket()->GetLocalAddress(&ip); + quic::test::QuicConnectionPeer::SetSelfAddress(session->connection(), + ToQuicSocketAddress(ip)); + + // This will trigger multi-port path creation. + MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + + // Resume quic data and a connectivity probe response will be read on the new + // socket. + quic_data2.Resume(); + + // The response is received on the default path. + quic_data1.Resume(); + // Response headers are received over the new port. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // The periodic probing is handled and tested in quiche. + EXPECT_TRUE(quic::test::QuicConnectionPeer::GetMultiPortProbingAlarm( + session->connection()) + ->IsSet()); + + stream.reset(); + EXPECT_TRUE(quic_data1.AllReadDataConsumed()); + EXPECT_TRUE(quic_data1.AllWriteDataConsumed()); + EXPECT_TRUE(quic_data2.AllReadDataConsumed()); + EXPECT_TRUE(quic_data2.AllWriteDataConsumed()); +} + TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithoutNetworkHandle_PathValidator) { if (!version_.HasIetfQuicFrames()) {
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 5d754a7e..2446869d 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -12,6 +12,7 @@ #include "base/compiler_specific.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" +#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" @@ -499,9 +500,9 @@ initiator_ = initiator; } -void URLRequest::set_method(const std::string& method) { +void URLRequest::set_method(base::StringPiece method) { DCHECK(!is_pending_); - method_ = method; + method_ = std::string(method); } #if BUILDFLAG(ENABLE_REPORTING)
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 18db4ce..778a965 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -14,6 +14,7 @@ #include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/strings/string_piece_forward.h" #include "base/supports_user_data.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" @@ -346,11 +347,12 @@ // This method may only be called before Start(). void set_initiator(const absl::optional<url::Origin>& initiator); - // The request method, as an uppercase string. "GET" is the default value. - // The request method may only be changed before Start() is called and - // should only be assigned an uppercase value. + // The request method. "GET" is the default value. The request method may + // only be changed before Start() is called. Request methods are + // case-sensitive, so standard HTTP methods like GET or POST should be + // specified in uppercase. const std::string& method() const { return method_; } - void set_method(const std::string& method); + void set_method(base::StringPiece method); #if BUILDFLAG(ENABLE_REPORTING) // Reporting upload nesting depth of this request. @@ -953,7 +955,7 @@ bool force_main_frame_for_same_site_cookies_ = false; absl::optional<url::Origin> initiator_; GURL delegate_redirect_url_; - std::string method_; // "GET", "POST", etc. Should be all uppercase. + std::string method_; // "GET", "POST", etc. Case-sensitive. std::string referrer_; ReferrerPolicy referrer_policy_ = ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 0a622f7f..e2a68e8 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -572,6 +572,12 @@ } } + if (rv == OK && request_info_.method == "CONNECT") { + // CONNECT has different kinds of targets than other methods (RFC 9110, + // section 9.3.6), which are incompatible with URLRequest. + rv = ERR_METHOD_NOT_SUPPORTED; + } + if (rv == OK) { transaction_->SetConnectedCallback(base::BindRepeating( &URLRequestHttpJob::NotifyConnectedCallback, base::Unretained(this)));
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 4892eb28..43aa79a 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -3988,7 +3988,7 @@ std::unique_ptr<URLRequest> r(default_context().CreateRequest( test_server_.GetURL("/echo"), DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->set_method(method.c_str()); + r->set_method(method); r->set_upload(CreateSimpleUploadData(uploadBytes.get())); @@ -8451,9 +8451,6 @@ HTTPRedirectMethodTest(url, "PUT", "GET", true); HTTPRedirectMethodTest(url, "HEAD", "HEAD", false); - HTTPRedirectOriginHeaderTest(url, "CONNECT", "GET", std::string()); - HTTPRedirectOriginHeaderTest(https_redirect_url, "CONNECT", "GET", - std::string()); HTTPRedirectOriginHeaderTest(url, "DELETE", "GET", std::string()); HTTPRedirectOriginHeaderTest(https_redirect_url, "DELETE", "GET", std::string()); @@ -13009,6 +13006,18 @@ EXPECT_EQ("/auth-basic", r->auth_challenge_info()->path); } +TEST_F(URLRequestTestHTTP, ConnectNoSupported) { + ASSERT_TRUE(http_test_server()->Start()); + TestDelegate delegate; + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + http_test_server()->GetURL("/"), DEFAULT_PRIORITY, &delegate, + TRAFFIC_ANNOTATION_FOR_TESTS)); + r->set_method("CONNECT"); + r->Start(); + delegate.RunUntilComplete(); + EXPECT_EQ(ERR_METHOD_NOT_SUPPORTED, delegate.request_status()); +} + class URLRequestDnsAliasTest : public TestWithTaskEnvironment { protected: URLRequestDnsAliasTest() {
diff --git a/services/device/generic_sensor/platform_sensor_fusion.cc b/services/device/generic_sensor/platform_sensor_fusion.cc index c8f2560a..d08aa3b 100644 --- a/services/device/generic_sensor/platform_sensor_fusion.cc +++ b/services/device/generic_sensor/platform_sensor_fusion.cc
@@ -4,8 +4,6 @@ #include "services/device/generic_sensor/platform_sensor_fusion.h" -#include <algorithm> - #include "base/bind.h" #include "base/check.h" #include "base/memory/raw_ptr.h" @@ -47,7 +45,7 @@ const auto& types = fusion_algorithm_->source_types(); DCHECK(!types.empty()); // Make sure there are no dups. - DCHECK(std::adjacent_find(types.begin(), types.end()) == types.end()); + DCHECK(base::ranges::adjacent_find(types) == types.end()); DCHECK(result_callback_); DCHECK(reading_buffer_); DCHECK(provider_);
diff --git a/testing/buildbot/chromium.rust.json b/testing/buildbot/chromium.rust.json index d3f3ce15..1795656 100644 --- a/testing/buildbot/chromium.rust.json +++ b/testing/buildbot/chromium.rust.json
@@ -209,6 +209,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", @@ -221,6 +226,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gnrt_unittests", @@ -233,6 +243,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "rust_gtest_interop_unittests", @@ -246,6 +261,11 @@ "name": "test_cpp_including_rust_unittests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_cpp_including_rust_unittests", @@ -259,6 +279,11 @@ "name": "test_serde_json_lenient", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_serde_json_lenient", @@ -275,6 +300,11 @@ "name": "autocxx_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "autocxx_tests", @@ -289,6 +319,11 @@ "name": "build_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "build_rust_tests", @@ -303,6 +338,11 @@ "name": "mojo_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_rust_tests", @@ -326,6 +366,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", @@ -338,6 +383,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gnrt_unittests", @@ -350,6 +400,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "rust_gtest_interop_unittests", @@ -363,6 +418,11 @@ "name": "test_cpp_including_rust_unittests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_cpp_including_rust_unittests", @@ -376,6 +436,11 @@ "name": "test_serde_json_lenient", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_serde_json_lenient", @@ -392,6 +457,11 @@ "name": "autocxx_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "autocxx_tests", @@ -406,6 +476,11 @@ "name": "build_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "build_rust_tests", @@ -420,6 +495,11 @@ "name": "mojo_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_rust_tests", @@ -443,6 +523,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", @@ -455,6 +540,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gnrt_unittests", @@ -467,6 +557,11 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "rust_gtest_interop_unittests", @@ -480,6 +575,11 @@ "name": "test_cpp_including_rust_unittests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_cpp_including_rust_unittests", @@ -493,6 +593,11 @@ "name": "test_serde_json_lenient", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "test_serde_json_lenient", @@ -509,6 +614,11 @@ "name": "autocxx_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "autocxx_tests", @@ -523,6 +633,11 @@ "name": "build_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "build_rust_tests", @@ -537,6 +652,11 @@ "name": "mojo_rust_tests", "swarming": { "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_rust_tests",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 4ce3966..a2e4fc2 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -5572,6 +5572,9 @@ 'rust_build_tests', 'rust_autocxx_tests', ], + 'mixins': [ + 'linux-bionic' + ], 'test_suites': { 'gtest_tests': 'rust_gtests', 'isolated_scripts': 'rust_native_tests', @@ -5585,6 +5588,9 @@ 'rust_build_tests', 'rust_autocxx_tests', ], + 'mixins': [ + 'linux-bionic' + ], 'test_suites': { 'gtest_tests': 'rust_gtests', 'isolated_scripts': 'rust_native_tests', @@ -5598,6 +5604,9 @@ 'rust_build_tests', 'rust_autocxx_tests', ], + 'mixins': [ + 'linux-bionic' + ], 'test_suites': { 'gtest_tests': 'rust_gtests', 'isolated_scripts': 'rust_native_tests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8a906c7..f7c1742 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -6650,7 +6650,7 @@ { "name": "Enabled", "params": { - "nesting": "10" + "nesting": "15" }, "enable_features": [ "MaxUnthrottledTimeoutNestingLevel" @@ -10861,11 +10861,16 @@ { "name": "Enabled", "params": { - "min_gms_core_version_no_dots": "222612000", - "stage": "0" + "api_error_list_version": "1", + "fallback_on_user_affecting_read_operations": "true", + "ignored_api_errors": "11005,11006", + "min_gms_core_version_no_dots": "223012000", + "retriable_api_errors": "7,17,20,22" }, "enable_features": [ - "UnifiedPasswordManagerAndroid" + "UnifiedPasswordManagerAndroid", + "UnifiedPasswordManagerErrorMessages", + "UnifiedPasswordManagerReenrollment" ] } ]
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 96e7f3f..1dcfe45 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1220,7 +1220,7 @@ "MaxUnthrottledTimeoutNestingLevel", base::FEATURE_DISABLED_BY_DEFAULT); const base::FeatureParam<int> kMaxUnthrottledTimeoutNestingLevelParam{ - &kMaxUnthrottledTimeoutNestingLevel, "nesting", 10}; + &kMaxUnthrottledTimeoutNestingLevel, "nesting", 15}; bool IsMaxUnthrottledTimeoutNestingLevelEnabled() { auto policy = GetUnthrottledNestedTimeoutPolicyOverride(); if (policy != UnthrottledNestedTimeoutPolicyOverride::kNoOverride) @@ -1609,10 +1609,6 @@ "FastPathPaintPropertyUpdates", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kWildcardSubdomainsInPermissionsPolicy, - "WildcardSubdomainsInPermissionsPolicy", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kThreadedBodyLoader, "ThreadedBodyLoader", base::FEATURE_DISABLED_BY_DEFAULT); @@ -1632,5 +1628,23 @@ "WebRtcCombinedNetworkAndWorkerThread", base::FEATURE_DISABLED_BY_DEFAULT); +// Allow process isolation of iframes with the 'sandbox' attribute set. Whether +// or not such an iframe will be isolated may depend on options specified with +// the attribute. Note: At present, only iframes with origin-restricted +// sandboxes are isolated. +BASE_FEATURE(kIsolateSandboxedIframes, + "IsolateSandboxedIframes", + base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<IsolateSandboxedIframesGrouping>::Option + isolated_sandboxed_iframes_grouping_types[] = { + {IsolateSandboxedIframesGrouping::kPerSite, "per-site"}, + {IsolateSandboxedIframesGrouping::kPerOrigin, "per-origin"}, + {IsolateSandboxedIframesGrouping::kPerDocument, "per-document"}}; +const base::FeatureParam<IsolateSandboxedIframesGrouping> + kIsolateSandboxedIframesGroupingParam{ + &kIsolateSandboxedIframes, "grouping", + IsolateSandboxedIframesGrouping::kPerSite, + &isolated_sandboxed_iframes_grouping_types}; + } // namespace features } // namespace blink
diff --git a/third_party/blink/common/permissions/permission_utils.cc b/third_party/blink/common/permissions/permission_utils.cc index c8b01c2..c5de113 100644 --- a/third_party/blink/common/permissions/permission_utils.cc +++ b/third_party/blink/common/permissions/permission_utils.cc
@@ -190,7 +190,7 @@ return PermissionType::NFC; case PermissionName::STORAGE_ACCESS: return PermissionType::STORAGE_ACCESS_GRANT; - case PermissionName::WINDOW_PLACEMENT: + case PermissionName::WINDOW_MANAGEMENT: return PermissionType::WINDOW_PLACEMENT; case PermissionName::LOCAL_FONTS: return PermissionType::LOCAL_FONTS;
diff --git a/third_party/blink/common/permissions_policy/origin_with_possible_wildcards.cc b/third_party/blink/common/permissions_policy/origin_with_possible_wildcards.cc index 4244136..7ad2f84e 100644 --- a/third_party/blink/common/permissions_policy/origin_with_possible_wildcards.cc +++ b/third_party/blink/common/permissions_policy/origin_with_possible_wildcards.cc
@@ -4,10 +4,8 @@ #include "third_party/blink/public/common/permissions_policy/origin_with_possible_wildcards.h" -#include "base/feature_list.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "services/network/public/cpp/cors/origin_access_entry.h" -#include "third_party/blink/public/common/features.h" #include "url/gurl.h" #include "url/origin.h" @@ -41,9 +39,7 @@ // subdomain wildcard if there is a exactly one `*` and it's after the scheme // and before the rest of the host. Invalid origins return an instance of // OriginWithPossibleWildcards with an opaque origin member. - if (base::FeatureList::IsEnabled( - features::kWildcardSubdomainsInPermissionsPolicy) && - type == NodeType::kHeader && + if (type == NodeType::kHeader && (wildcard_pos = allowlist_entry.find("://*.")) != std::string::npos && allowlist_entry.find('*') == allowlist_entry.rfind('*')) { // We need a copy as erase modifies the original. @@ -90,13 +86,7 @@ bool OriginWithPossibleWildcards::DoesMatchOrigin( const url::Origin& match_origin) const { - // TODO(crbug.com/1345994): Merge logic with IsSubdomainOfHost where possible. if (has_subdomain_wildcard) { - // Only try to match at all if wildcard matching is enabled. - if (!base::FeatureList::IsEnabled( - features::kWildcardSubdomainsInPermissionsPolicy)) { - return false; - } // This function won't match https://*.foo.com with https://foo.com. if (origin == match_origin) { return false;
diff --git a/third_party/blink/common/permissions_policy/origin_with_possible_wildcards_unittest.cc b/third_party/blink/common/permissions_policy/origin_with_possible_wildcards_unittest.cc index 621b2d2..404f0b6 100644 --- a/third_party/blink/common/permissions_policy/origin_with_possible_wildcards_unittest.cc +++ b/third_party/blink/common/permissions_policy/origin_with_possible_wildcards_unittest.cc
@@ -5,34 +5,16 @@ #include "third_party/blink/public/common/permissions_policy/origin_with_possible_wildcards.h" #include "base/test/gtest_util.h" -#include "base/test/scoped_feature_list.h" #include "mojo/public/cpp/test_support/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/common/permissions_policy/permissions_policy_mojom_traits.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h" #include "url/gurl.h" #include "url/origin.h" namespace blink { -class OriginWithPossibleWildcardsTest : public testing::TestWithParam<bool> { - public: - void SetUp() override { - scoped_feature_list_.InitWithFeatureState( - features::kWildcardSubdomainsInPermissionsPolicy, - HasWildcardSubdomainsInPermissionsPolicy()); - } - - bool HasWildcardSubdomainsInPermissionsPolicy() { return GetParam(); } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -INSTANTIATE_TEST_SUITE_P(All, OriginWithPossibleWildcardsTest, testing::Bool()); - -TEST_P(OriginWithPossibleWildcardsTest, DoesMatchOrigin) { +TEST(OriginWithPossibleWildcardsTest, DoesMatchOrigin) { // Tuple of {origin to test, origin in policy, w/ wildcard, result, // description}. const auto& values = { @@ -78,23 +60,20 @@ url::Origin::Create(GURL("https://foo.com")), true, false, "Same origin, w/ wildcard"), std::make_tuple(url::Origin::Create(GURL("https://bar.foo.com")), - url::Origin::Create(GURL("https://foo.com")), true, - HasWildcardSubdomainsInPermissionsPolicy(), + url::Origin::Create(GURL("https://foo.com")), true, true, "Subdomain matches, w/ wildcard"), std::make_tuple(url::Origin::Create(GURL("http://bar.foo.com")), url::Origin::Create(GURL("https://foo.com")), true, false, "Different scheme, w/ wildcard"), std::make_tuple(url::Origin::Create(GURL("https://baz.bar.foo.com")), - url::Origin::Create(GURL("https://foo.com")), true, - HasWildcardSubdomainsInPermissionsPolicy(), + url::Origin::Create(GURL("https://foo.com")), true, true, "Sub-subdomain matches, w/ wildcard"), std::make_tuple(url::Origin::Create(GURL("https://foo.com")), url::Origin::Create(GURL("https://bar.foo.com")), true, false, "Subdomain doesn't match, w/ wildcard"), std::make_tuple(url::Origin::Create(GURL("https://bar.foo.com")), url::Origin::Create(GURL("https://foo.com:443")), true, - HasWildcardSubdomainsInPermissionsPolicy(), - "Ignore default port, w/ wildcard"), + true, "Ignore default port, w/ wildcard"), std::make_tuple(url::Origin(), url::Origin::Create(GURL("https://foo.com")), true, false, "Opaque to origin, w/ wildcard"), @@ -121,7 +100,7 @@ } } -TEST_P(OriginWithPossibleWildcardsTest, Parse) { +TEST(OriginWithPossibleWildcardsTest, Parse) { // Tuple of {serialized value, type, origin, wildcard, description}. const auto& values = { std::make_tuple("https://foo.com", @@ -134,10 +113,7 @@ "Origin without subdomain wildcard in attribute"), std::make_tuple( "https://*.foo.com", OriginWithPossibleWildcards::NodeType::kHeader, - HasWildcardSubdomainsInPermissionsPolicy() ? "https://foo.com" - : "https://%2A.foo.com", - HasWildcardSubdomainsInPermissionsPolicy(), - "Origin with subdomain wildcard in header"), + "https://foo.com", true, "Origin with subdomain wildcard in header"), std::make_tuple("https://*.foo.com", OriginWithPossibleWildcards::NodeType::kAttribute, "https://%2A.foo.com", false, @@ -173,10 +149,7 @@ "Origin with only private tld host wildcard in attribute"), std::make_tuple("https://*.foo.appspot.com", OriginWithPossibleWildcards::NodeType::kHeader, - HasWildcardSubdomainsInPermissionsPolicy() - ? "https://foo.appspot.com" - : "https://%2A.foo.appspot.com", - HasWildcardSubdomainsInPermissionsPolicy(), + "https://foo.appspot.com", true, "Origin with private tld host wildcard in header"), std::make_tuple("https://*.foo.appspot.com", OriginWithPossibleWildcards::NodeType::kAttribute, @@ -184,10 +157,7 @@ "Origin with private tld host wildcard in attribute"), std::make_tuple("https://*.example.test", OriginWithPossibleWildcards::NodeType::kHeader, - HasWildcardSubdomainsInPermissionsPolicy() - ? "https://example.test" - : "https://%2A.example.test", - HasWildcardSubdomainsInPermissionsPolicy(), + "https://example.test", true, "Origin with unknown tld host wildcard in header"), std::make_tuple("https://*.example.test", OriginWithPossibleWildcards::NodeType::kAttribute, @@ -228,7 +198,7 @@ } } -TEST_P(OriginWithPossibleWildcardsTest, Serialize) { +TEST(OriginWithPossibleWildcardsTest, Serialize) { // Tuple of {origin, wildcard, serialized value, description}. const auto& values = { std::make_tuple("https://foo.com", false, "https://foo.com", @@ -249,7 +219,7 @@ } } -TEST_P(OriginWithPossibleWildcardsTest, Constructors) { +TEST(OriginWithPossibleWildcardsTest, Constructors) { OriginWithPossibleWildcards a; OriginWithPossibleWildcards b(url::Origin(), false); OriginWithPossibleWildcards c(b); @@ -261,7 +231,7 @@ EXPECT_EQ(a, b); } -TEST_P(OriginWithPossibleWildcardsTest, Opaque) { +TEST(OriginWithPossibleWildcardsTest, Opaque) { EXPECT_DCHECK_DEATH(OriginWithPossibleWildcards(url::Origin(), true)); OriginWithPossibleWildcards original(url::Origin(), false); original.has_subdomain_wildcard = true;
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 11d35671..e739ed13 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -850,10 +850,6 @@ // applied directly instead of using the property tree builder. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kFastPathPaintPropertyUpdates); -// If enabled, wildcard subdomains are supported in permissions policies. -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( - kWildcardSubdomainsInPermissionsPolicy); - // If enabled, reads and decodes navigation body data off the main thread. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kThreadedBodyLoader); @@ -872,6 +868,24 @@ // Combine WebRTC Network and Worker threads. More info at crbug.com/1373439. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcCombinedNetworkAndWorkerThread); +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kIsolateSandboxedIframes); +enum class IsolateSandboxedIframesGrouping { + // In this grouping, all isolated sandboxed iframes whose URLs share the same + // site in a given BrowsingInstance will share a process. + kPerSite, + // In this grouping, all isolated sandboxed iframes from a given + // BrowsingInstance whose URLs share the same origin will be isolated in an + // origin-keyed process. + kPerOrigin, + // Unlike the other two modes, which group sandboxed frames per-site or + // per-origin, this one doesn't do any grouping at all and uses one process + // per document. + kPerDocument, +}; +BLINK_COMMON_EXPORT extern const base::FeatureParam< + IsolateSandboxedIframesGrouping> + kIsolateSandboxedIframesGroupingParam; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/mojom/permissions/permission.mojom b/third_party/blink/public/mojom/permissions/permission.mojom index cf00630..8721ae5 100644 --- a/third_party/blink/public/mojom/permissions/permission.mojom +++ b/third_party/blink/public/mojom/permissions/permission.mojom
@@ -28,7 +28,7 @@ SYSTEM_WAKE_LOCK, NFC, STORAGE_ACCESS, - WINDOW_PLACEMENT, + WINDOW_MANAGEMENT, LOCAL_FONTS, DISPLAY_CAPTURE, };
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index 74072583..f9a3a06 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1428,28 +1428,58 @@ wtf_size_t auto_repeat_insertion_point = computed_grid_track_list.auto_repeat_insertion_point; - // If the element is a grid container, the resolved value is the used value, - // specifying track sizes in pixels and expanding the repeat() notation. if (is_layout_grid) { const auto* grid = ToInterface<LayoutNGGridInterface>(layout_object); - OrderedNamedLinesCollectorInGridLayout collector( - computed_grid_track_list.ordered_named_grid_lines, - computed_grid_track_list.auto_repeat_ordered_named_grid_lines, - auto_repeat_insertion_point, - grid->AutoRepeatCountForDirection(direction), - auto_repeat_track_sizes.size()); - auto getTrackSize = [&](const LayoutUnit& v) { - return ZoomAdjustedPixelValue(v, style); - }; - // Named grid line indices are relative to the explicit grid, but we are - // including all tracks. So we need to subtract the number of leading - // implicit tracks in order to get the proper line index. - int offset = -base::checked_cast<int>( - grid->ExplicitGridStartForDirection(direction)); - PopulateGridTrackList(list, collector, - grid->TrackSizesForComputedStyle(direction), - getTrackSize, offset); - return list; + if (computed_grid_track_list.IsSubgriddedAxis()) { + // If the track list is subgridded, return the word 'subgrid', followed by + // the specified named grid lines in brackets. Empty brackets are also + // valid. + list->Append( + *MakeGarbageCollected<CSSIdentifierValue>(CSSValueID::kSubgrid)); + + wtf_size_t subgrid_line_names_start = + grid->ExplicitGridStartForDirection(direction); + wtf_size_t subgrid_line_names_end = + grid->ExplicitGridEndForDirection(direction); + for (wtf_size_t i = subgrid_line_names_start; i <= subgrid_line_names_end; + ++i) { + auto iter = computed_grid_track_list.ordered_named_grid_lines.find(i); + + cssvalue::CSSBracketedValueList* value_list = + MakeGarbageCollected<cssvalue::CSSBracketedValueList>(); + + if (iter != computed_grid_track_list.ordered_named_grid_lines.end()) { + for (auto named_grid_line : iter->value) { + value_list->Append(*MakeGarbageCollected<CSSCustomIdentValue>( + named_grid_line.line_name)); + } + } + list->Append(*value_list); + } + return list; + } else { + // If the element is a grid container, the resolved value is the used + // value, specifying track sizes in pixels and expanding the repeat() + // notation. + OrderedNamedLinesCollectorInGridLayout collector( + computed_grid_track_list.ordered_named_grid_lines, + computed_grid_track_list.auto_repeat_ordered_named_grid_lines, + auto_repeat_insertion_point, + grid->AutoRepeatCountForDirection(direction), + auto_repeat_track_sizes.size()); + auto getTrackSize = [&](const LayoutUnit& v) { + return ZoomAdjustedPixelValue(v, style); + }; + // Named grid line indices are relative to the explicit grid, but we are + // including all tracks. So we need to subtract the number of leading + // implicit tracks in order to get the proper line index. + int offset = -base::checked_cast<int>( + grid->ExplicitGridStartForDirection(direction)); + PopulateGridTrackList(list, collector, + grid->TrackSizesForComputedStyle(direction), + getTrackSize, offset); + return list; + } } // Otherwise, the resolved value is the computed value, preserving repeat().
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index c28f7f9..e2cd4b4 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1015,9 +1015,8 @@ bool is_first_repeat = false) { DCHECK(value.IsGridLineNamesValue()); - // TODO(ansollan): Serialize subgrid's empty lines. for (auto& named_grid_line_value : To<CSSValueList>(value)) { - String named_grid_line = + AtomicString named_grid_line = To<CSSCustomIdentValue>(*named_grid_line_value).Value(); NamedGridLinesMap::AddResult result = named_grid_lines.insert(named_grid_line, Vector<wtf_size_t>());
diff --git a/third_party/blink/renderer/core/css/transition.css b/third_party/blink/renderer/core/css/transition.css index 2a33056..404abc0e 100644 --- a/third_party/blink/renderer/core/css/transition.css +++ b/third_party/blink/renderer/core/css/transition.css
@@ -11,7 +11,12 @@ html::page-transition { position: fixed; - inset: 0; + top: 0; + left: 0; + + /* Size will be set dynamically to correctly account for UI such as + virtual-keyboards */ + pointer-events: none; }
diff --git a/third_party/blink/renderer/core/document_transition/document_transition.h b/third_party/blink/renderer/core/document_transition/document_transition.h index 5e61b0b..f13e7d6 100644 --- a/third_party/blink/renderer/core/document_transition/document_transition.h +++ b/third_party/blink/renderer/core/document_transition/document_transition.h
@@ -135,6 +135,10 @@ bool IsIdle() const { return state_ == State::kIdle; } + bool IsRootTransitioning() const { + return style_tracker_ && style_tracker_->IsRootTransitioning(); + } + // In physical pixels. See comments on equivalent methods in // DocumentTransitionStyleTracker for info. gfx::Rect GetSnapshotViewportRect() const;
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_builder.cc b/third_party/blink/renderer/core/document_transition/document_transition_style_builder.cc index 72b8880c..c696f80 100644 --- a/third_party/blink/renderer/core/document_transition/document_transition_style_builder.cc +++ b/third_party/blink/renderer/core/document_transition/document_transition_style_builder.cc
@@ -156,10 +156,23 @@ AddContainerStyles(tag, rule_builder.ReleaseString()); } -void DocumentTransitionStyleBuilder::AddRootStyles(const String& rules) { +void DocumentTransitionStyleBuilder::AddRootStyles( + const gfx::RectF& snapshot_viewport_rect_css) { builder_.Append(kTransitionRootName); builder_.Append("{ "); - builder_.Append(rules); + builder_.AppendFormat( + R"CSS( + width: %.3fpx; + height: %.3fpx; + )CSS", + snapshot_viewport_rect_css.width(), snapshot_viewport_rect_css.height()); + if (!snapshot_viewport_rect_css.OffsetFromOrigin().IsZero()) { + builder_.AppendFormat( + R"CSS( + transform: translate(%.3fpx, %.3fpx); + )CSS", + snapshot_viewport_rect_css.x(), snapshot_viewport_rect_css.y()); + } builder_.Append(" }"); }
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_builder.h b/third_party/blink/renderer/core/document_transition/document_transition_style_builder.h index e0367613..6b05019 100644 --- a/third_party/blink/renderer/core/document_transition/document_transition_style_builder.h +++ b/third_party/blink/renderer/core/document_transition/document_transition_style_builder.h
@@ -37,7 +37,7 @@ const ContainerProperties& properties, WritingMode writing_mode); - void AddRootStyles(const String& rules); + void AddRootStyles(const gfx::RectF& snapshot_viewport_rect_css); String Build();
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc index 6cc1e8e..44e73d2 100644 --- a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc +++ b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc
@@ -65,27 +65,6 @@ return kAnimationUAStyles; } -absl::optional<String> GetSnapshotViewportOffsetTransform( - const gfx::Vector2d& offset, - float device_pixel_ratio) { - if (!offset.x() && !offset.y()) - return absl::nullopt; - - // Since we're using the offset in style, convert from physical pixels to CSS - // pixels. - gfx::Vector2dF css_offset = - gfx::ScaleVector2d(offset, 1.f / device_pixel_ratio); - - // The root is translated up and left so that the coordinate space for all - // children has its origin at the point that is the top-left when all UI is - // hidden. This requires non-root shared elements to be shifted back down and - // right. - DCHECK_LE(css_offset.x(), 0.f); - DCHECK_LE(css_offset.y(), 0.f); - return String::Format("transform: translate(%.3fpx, %.3fpx);", css_offset.x(), - css_offset.y()); -} - absl::optional<String> ComputeInsetDifference(PhysicalRect reference_rect, const LayoutRect& target_rect, float device_pixel_ratio) { @@ -987,29 +966,31 @@ DCHECK(document.View()); DCHECK(document.GetPage()); DCHECK(document.GetFrame()); - - if (!document.GetFrame()->IsOutermostMainFrame()) - return gfx::Outsets(); - - Page& page = *document.GetPage(); + DCHECK(document.GetLayoutView()); int top = 0; int right = 0; int bottom = 0; int left = 0; - // TODO(bokan): This assumes any shown ratio implies controls are shown. We - // many need to do some synchronization to make this work seamlessly with URL - // bar animations. - BrowserControls& controls = page.GetBrowserControls(); - if (page.GetBrowserControls().TopShownRatio()) { - top += controls.TopHeight() - controls.TopMinHeight(); - bottom += controls.BottomHeight() - controls.BottomMinHeight(); + if (document.GetFrame()->IsOutermostMainFrame()) { + // TODO(bokan): This assumes any shown ratio implies controls are shown. We + // many need to do some synchronization to make this work seamlessly with + // URL bar animations. + BrowserControls& controls = document.GetPage()->GetBrowserControls(); + if (controls.TopShownRatio()) + top += controls.TopHeight() - controls.TopMinHeight(); + if (controls.BottomShownRatio()) + bottom += controls.BottomHeight() - controls.BottomMinHeight(); } // TODO(bokan): Account for virtual-keyboard - // TODO(bokan): Account for scrollbars. + // TODO(bokan): Handle left-hand side vertical scrollbars. + + LocalFrameView& view = *document.View(); + right += view.LayoutViewport()->VerticalScrollbarWidth(); + bottom += view.LayoutViewport()->HorizontalScrollbarHeight(); gfx::Outsets outsets; outsets.set_top(top); @@ -1027,11 +1008,11 @@ LocalFrameView& view = *document_->View(); - // Start with the full FrameView size, i.e. the position: fixed viewport and + // Start with the FrameView size, i.e. the position: fixed viewport, and // expand the viewport by any insetting UI such as the mobile URL bar, - // virtual-keyboard, etc. Note: the FrameView size already includes - // scrollbars. - gfx::Rect snapshot_viewport_rect(view.Size()); + // virtual-keyboard, scrollbars, etc. + gfx::Rect snapshot_viewport_rect( + view.LayoutViewport()->ExcludeScrollbars(view.Size())); snapshot_viewport_rect.Outset(GetFixedToSnapshotViewportOutsets(*document_)); return snapshot_viewport_rect; @@ -1039,8 +1020,14 @@ gfx::Vector2d DocumentTransitionStyleTracker::GetRootSnapshotPaintOffset() const { + DCHECK(document_->GetLayoutView()); + DCHECK(document_->View()); + gfx::Outsets outsets = GetFixedToSnapshotViewportOutsets(*document_); - return gfx::Vector2d(outsets.left(), outsets.top()); + int left = outsets.left(); + int top = outsets.top(); + + return gfx::Vector2d(left, top); } void DocumentTransitionStyleTracker::InvalidateStyle() { @@ -1144,14 +1131,19 @@ ->StyleRef() .EffectiveZoom(); - // Position the root container behind any viewport insetting widgets (such - // as the URL bar) so that it's stable across a transition. - absl::optional<String> snapshot_viewport_offset = - GetSnapshotViewportOffsetTransform( - GetSnapshotViewportRect().OffsetFromOrigin(), device_pixel_ratio); - if (snapshot_viewport_offset) { - builder.AddRootStyles(*snapshot_viewport_offset); - } + // Size and position the root container behind any viewport insetting widgets + // (such as the URL bar) so that it's stable across a transition. This rect + // is called the "snapshot viewport". Since this is applied in style, + // convert from physical pixels to CSS pixels. + gfx::RectF snapshot_viewport_css_pixels = gfx::ScaleRect( + gfx::RectF(GetSnapshotViewportRect()), 1.f / device_pixel_ratio); + + // If adjusted, the root is always translated up and left underneath any UI + // so the direction must always be negative. + DCHECK_LE(snapshot_viewport_css_pixels.x(), 0.f); + DCHECK_LE(snapshot_viewport_css_pixels.y(), 0.f); + + builder.AddRootStyles(snapshot_viewport_css_pixels); for (auto& root_tag : AllRootTags()) { // This is case 3 above.
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 83a62e2..4c1364e1 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -293,7 +293,9 @@ HTMLMediaElement&) = 0; virtual void DidCommitDocumentReplacementNavigation(DocumentLoader*) = 0; - virtual void DispatchDidClearWindowObjectInMainWorld() = 0; + virtual void DispatchDidClearWindowObjectInMainWorld( + v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue) = 0; virtual void DocumentElementAvailable() = 0; virtual void RunScriptsAtDocumentElementAvailable() = 0; virtual void RunScriptsAtDocumentReady(bool document_is_empty) = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc index 7b726508..ff373fdfa 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -191,9 +191,17 @@ } } -void LocalFrameClientImpl::DispatchDidClearWindowObjectInMainWorld() { +void LocalFrameClientImpl::DispatchDidClearWindowObjectInMainWorld( + v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue) { if (web_frame_->Client()) { - web_frame_->Client()->DidClearWindowObject(); + // Do not run microtasks while invoking the callback. + { + v8::MicrotasksScope microtasks(isolate, microtask_queue, + + v8::MicrotasksScope::kDoNotRunMicrotasks); + web_frame_->Client()->DidClearWindowObject(); + } Document* document = web_frame_->GetFrame()->GetDocument(); if (document) { const Settings* const settings = web_frame_->GetFrame()->GetSettings();
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h index c974fa2..2fe4b1c 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -72,7 +72,9 @@ // Notifies the WebView delegate that the JS window object has been cleared, // giving it a chance to bind native objects to the window before script // parsing begins. - void DispatchDidClearWindowObjectInMainWorld() override; + void DispatchDidClearWindowObjectInMainWorld( + v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue) override; void DocumentElementAvailable() override; void RunScriptsAtDocumentElementAvailable() override; void RunScriptsAtDocumentReady(bool document_is_empty) override;
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc index 58d28da..9afebbe 100644 --- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -1699,7 +1699,7 @@ // commit. Processing the data now can lead to unexpected states. // TODO(https://crbug.com/1364695): see if this limitation can be removed. if (auto* sink = probe::ToCoreProbeSink(GetDocument())) { - if (sink->HasAgentsGlobal(CoreProbeSink::kInspectorDOMDebuggerAgent)) + if (sink->HasAgentsGlobal(CoreProbeSink::kDevToolsSession)) return false; }
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc index dc08ce1..7ddf9a9 100644 --- a/third_party/blink/renderer/core/layout/layout_view.cc +++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -587,10 +587,12 @@ if (!frame_view_) return PhysicalRect(); + // TODO(bokan): This shouldn't be just for the outermost main frame, we + // should do it for all frames. crbug.com/1311518. if (frame_view_->GetFrame().IsOutermostMainFrame()) { auto* supplement = DocumentTransitionSupplement::FromIfExists(GetDocument()); - if (supplement && !supplement->GetTransition()->IsIdle()) { + if (supplement && supplement->GetTransition()->IsRootTransitioning()) { // If we're capturing a transition snapshot, the root transition needs to // produce the snapshot at a known stable size, excluding all insetting // UI like mobile URL bars and virtual keyboards. @@ -622,7 +624,14 @@ } rect.offset += location; - if (IsScrollContainer()) + + // When capturing the root snapshot for a transition, we paint the background + // color where the scrollbar would be so keep the clip rect the full ViewRect + // size. + auto* supplement = DocumentTransitionSupplement::FromIfExists(GetDocument()); + bool is_in_transition = + supplement && supplement->GetTransition()->IsRootTransitioning(); + if (IsScrollContainer() && !is_in_transition) ExcludeScrollbars(rect, overlay_scrollbar_clip_behavior); return rect;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h index 87cec8f2..7ffc3ed 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
@@ -22,8 +22,15 @@ // Subgrids need to map named lines from every parent grid. This constructor // should be used exclusively by subgrids to differentiate such scenario. NGGridPlacementData(const ComputedStyle& grid_style, - const NGGridLineResolver& parent_line_resolver) - : line_resolver(grid_style, parent_line_resolver) {} + const NGGridLineResolver& parent_line_resolver, + GridArea subgrid_area) + : line_resolver(grid_style, parent_line_resolver, subgrid_area), + subgridded_column_span_size(subgrid_area.columns.IsTranslatedDefinite() + ? subgrid_area.SpanSize(kForColumns) + : kNotFound), + subgridded_row_span_size(subgrid_area.rows.IsTranslatedDefinite() + ? subgrid_area.SpanSize(kForRows) + : kNotFound) {} // This constructor only copies inputs to the auto-placement algorithm. NGGridPlacementData(const NGGridPlacementData& other)
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index cf6580f..3515bab 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -507,29 +507,30 @@ const auto& style = node.Style(); bool has_nested_subgrid; + auto& sizing_data = sizing_tree->CreateSizingData(node, parent_sizing_data, subgrid_data_in_parent); { + GridArea subgridded_area_in_parent; + if (subgrid_data_in_parent) { + subgridded_area_in_parent = subgrid_data_in_parent->resolved_position; + if (!subgrid_data_in_parent->is_parallel_with_root_grid) { + std::swap(subgridded_area_in_parent.columns, + subgridded_area_in_parent.rows); + } + + if (!subgrid_data_in_parent->has_subgridded_columns) + subgridded_area_in_parent.columns = GridSpan::IndefiniteGridSpan(); + if (!subgrid_data_in_parent->has_subgridded_rows) + subgridded_area_in_parent.rows = GridSpan::IndefiniteGridSpan(); + } + // Initialize this grid's placement data. auto placement_data = - parent_line_resolver ? NGGridPlacementData(style, *parent_line_resolver) + parent_line_resolver ? NGGridPlacementData(style, *parent_line_resolver, + subgridded_area_in_parent) : NGGridPlacementData(style); - if (subgrid_data_in_parent) { - wtf_size_t column_span_size_in_parent = - subgrid_data_in_parent->SpanSize(kForColumns); - wtf_size_t row_span_size_in_parent = - subgrid_data_in_parent->SpanSize(kForRows); - - if (!subgrid_data_in_parent->is_parallel_with_root_grid) - std::swap(column_span_size_in_parent, row_span_size_in_parent); - - if (subgrid_data_in_parent->has_subgridded_columns) - placement_data.subgridded_column_span_size = column_span_size_in_parent; - if (subgrid_data_in_parent->has_subgridded_rows) - placement_data.subgridded_row_span_size = row_span_size_in_parent; - } - // TODO(ethavar): Compute automatic repetitions for subgridded axes as // described in https://drafts.csswg.org/css-grid-2/#auto-repeat. if (!parent_sizing_data) {
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc index fa8a29a..50c0481 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc
@@ -28,23 +28,73 @@ NGGridLineResolver::NGGridLineResolver( const ComputedStyle& grid_style, - const NGGridLineResolver& parent_line_resolver) - : style_(&grid_style), is_subgrid_line_resolver_(true) { - column_subgrid_merged_grid_line_names_ = - grid_style.GridTemplateColumns().named_grid_lines; - row_subgrid_merged_grid_line_names_ = - grid_style.GridTemplateRows().named_grid_lines; + const NGGridLineResolver& parent_line_resolver, + GridArea subgrid_area) + : style_(&grid_style), + subgrid_column_start_line_(subgrid_area.columns.IsTranslatedDefinite() + ? subgrid_area.StartLine(kForColumns) + : 0), + subgrid_row_start_line_(subgrid_area.rows.IsTranslatedDefinite() + ? subgrid_area.StartLine(kForRows) + : 0), + column_subgrid_merged_grid_line_names_( + grid_style.GridTemplateColumns().named_grid_lines), + row_subgrid_merged_grid_line_names_( + grid_style.GridTemplateRows().named_grid_lines) { + auto MergeNamedGridLinesWithAncestor = [](NamedGridLinesMap& subgrid_map, + const NamedGridLinesMap& parent_map, + GridSpan subgrid_span) -> void { + // Update `subgrid_map` to a merged map from a parent grid or subgrid map + // (`parent_map`). The map is a key-value store with keys as the line name + // and the value as an array of ascending indices. + for (auto& pair : parent_map) { + Vector<wtf_size_t, 16> merged_list; + for (const auto& position : pair.value) { + // Filter out parent named lines are are out of the subgrid range. Also + // offset entries by `subgrid_start_line` before inserting them into the + // merged map so they are all relative to offset 0. These are already in + // ascending order so there's no need to sort. + if ((position >= subgrid_span.StartLine()) && + (position <= + (subgrid_span.StartLine() + subgrid_span.IntegerSpan()))) { + merged_list.push_back(position - subgrid_span.StartLine()); + } + } - // Add the parent grid/subgrid's line numbers to the shared line name set. - // TODO(kschmi): Merge/filter these lists. - for (const auto& pair : - parent_line_resolver.ExplicitNamedLinesMap(kForColumns)) { - column_subgrid_merged_grid_line_names_.insert(pair.key, pair.value); + // If there's a name collision, merge the values and sort. These are from + // the subgrid and not the parent container, so they are already relative + // to index 0 and don't need to be offset. + const auto& existing_entry = subgrid_map.find(pair.key); + if (existing_entry != subgrid_map.end()) { + for (auto& value : existing_entry->value) + merged_list.push_back(value); + std::sort(merged_list.begin(), merged_list.end()); + } + + // Override the existing subgrid's line names map with the new merged list + // for this particular line name entry. If `merged_list` list is empty, + // (this can happen when all entries for a particular line name are out + // of the subgrid range), erase the entry entirely, as + // `NGGridNamedLineCollection` doesn't support named line entries without + // values. + if (merged_list.empty()) + subgrid_map.erase(pair.key); + else + subgrid_map.Set(pair.key, merged_list); + } + }; + + if (subgrid_area.columns.IsTranslatedDefinite()) { + MergeNamedGridLinesWithAncestor( + *column_subgrid_merged_grid_line_names_, + parent_line_resolver.ExplicitNamedLinesMap(kForColumns), + subgrid_area.columns); } - - for (const auto& pair : - parent_line_resolver.ExplicitNamedLinesMap(kForRows)) { - row_subgrid_merged_grid_line_names_.insert(pair.key, pair.value); + if (subgrid_area.rows.IsTranslatedDefinite()) { + MergeNamedGridLinesWithAncestor( + *row_subgrid_merged_grid_line_names_, + parent_line_resolver.ExplicitNamedLinesMap(kForRows), + subgrid_area.rows); } } @@ -134,14 +184,15 @@ int last_line, NGGridNamedLineCollection& lines_collection) const { int start, end; + const int span_position = position.SpanPosition(); if (side == kRowStartSide || side == kColumnStartSide) { - start = LookBackForNamedGridLine(opposite_line - 1, position.SpanPosition(), + start = LookBackForNamedGridLine(opposite_line - 1, span_position, last_line, lines_collection); end = opposite_line; } else { start = opposite_line; - end = LookAheadForNamedGridLine(opposite_line + 1, position.SpanPosition(), - last_line, lines_collection); + end = LookAheadForNamedGridLine(opposite_line + 1, span_position, last_line, + lines_collection); } return GridSpan::UntranslatedDefiniteGridSpan(start, end); @@ -153,7 +204,7 @@ if (subgrid_span_size != kNotFound) return subgrid_span_size; - // TODO(kschmi): Refactor with `is_subgrid_line_resolver_` factored in. + // TODO(kschmi): Refactor so that `subgrid_span_size` isn't necessary. return std::min<wtf_size_t>(std::max(style_->GridTemplateColumns() .track_sizes.NGTrackList() .TrackCountWithoutAutoRepeat() + @@ -168,7 +219,7 @@ if (subgrid_span_size != kNotFound) return subgrid_span_size; - // TODO(kschmi): Refactor with `is_subgrid_line_resolver_` factored in. + // TODO(kschmi): Refactor so that `subgrid_span_size` isn't necessary. return std::min<wtf_size_t>(std::max(style_->GridTemplateRows() .track_sizes.NGTrackList() .TrackCountWithoutAutoRepeat() + @@ -194,7 +245,8 @@ const GridPosition& position, wtf_size_t auto_repeat_tracks_count, GridPositionSide side, - wtf_size_t subgrid_span_size) const { + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const { DCHECK(position.IsSpan()); DCHECK(!position.NamedGridLine().IsNull()); // Negative positions are not allowed per the specification and should have @@ -204,7 +256,6 @@ GridTrackSizingDirection track_direction = DirectionFromSide(side); const auto& implicit_grid_line_names = ImplicitNamedLinesMap(track_direction); const auto& explicit_grid_line_names = ExplicitNamedLinesMap(track_direction); - const auto& computed_grid_track_list = ComputedGridTrackList(track_direction); wtf_size_t last_line = ExplicitGridSizeForSide(side, auto_repeat_tracks_count, @@ -213,7 +264,7 @@ NGGridNamedLineCollection lines_collection( position.NamedGridLine(), track_direction, implicit_grid_line_names, explicit_grid_line_names, computed_grid_track_list, last_line, - auto_repeat_tracks_count); + auto_repeat_tracks_count, is_subgridded_to_parent); return DefiniteGridSpanWithNamedSpanAgainstOpposite( opposite_line, position, side, last_line, lines_collection); } @@ -234,7 +285,7 @@ const NamedGridLinesMap& NGGridLineResolver::ImplicitNamedLinesMap( GridTrackSizingDirection track_direction) const { - // TODO(kschmi): Merge implicit list if `is_subgrid_line_resolver_`. + // TODO(kschmi): Merge implicit list if it's subgridded. return (track_direction == kForColumns) ? style_->ImplicitNamedGridColumnLines() : style_->ImplicitNamedGridRowLines(); @@ -242,20 +293,19 @@ const NamedGridLinesMap& NGGridLineResolver::ExplicitNamedLinesMap( GridTrackSizingDirection track_direction) const { - // Subgrids look at the merged map of the parent's grid line names, while - // standalone grids should look directly at the style object. - if (is_subgrid_line_resolver_) { - return (track_direction == kForColumns) - ? column_subgrid_merged_grid_line_names_ - : row_subgrid_merged_grid_line_names_; - } - return ComputedGridTrackList(track_direction).named_grid_lines; + const auto& subgrid_merged_grid_line_names = + (track_direction == kForColumns) ? column_subgrid_merged_grid_line_names_ + : row_subgrid_merged_grid_line_names_; + + return subgrid_merged_grid_line_names + ? *subgrid_merged_grid_line_names + : ComputedGridTrackList(track_direction).named_grid_lines; } const blink::ComputedGridTrackList& NGGridLineResolver::ComputedGridTrackList( GridTrackSizingDirection track_direction) const { - // TODO(kschmi): Refactor so this isn't necessary when - // `is_subgrid_line_resolver_`. + // TODO(kschmi): Refactor so this isn't necessary and handle auto-repeats + // for subgrids. return (track_direction == kForColumns) ? style_->GridTemplateColumns() : style_->GridTemplateRows(); } @@ -265,7 +315,8 @@ const GridPosition& position, GridPositionSide side, wtf_size_t auto_repeat_tracks_count, - wtf_size_t subgrid_span_size) const { + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const { if (position.IsAuto()) { if (side == kColumnStartSide || side == kRowStartSide) { return GridSpan::UntranslatedDefiniteGridSpan(opposite_line - 1, @@ -283,7 +334,7 @@ // our opposite position. return ResolveNamedGridLinePositionAgainstOppositePosition( opposite_line, position, auto_repeat_tracks_count, side, - subgrid_span_size); + subgrid_span_size, is_subgridded_to_parent); } return DefiniteGridSpanWithSpanAgainstOpposite(opposite_line, position, side); @@ -315,11 +366,12 @@ return SpanSizeFromPositions(initial_position, final_position); } -int NGGridLineResolver::ResolveNamedGridLinePositionFromStyle( +int NGGridLineResolver::ResolveNamedGridLinePosition( const GridPosition& position, GridPositionSide side, wtf_size_t auto_repeat_tracks_count, - wtf_size_t subgrid_span_size) const { + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const { DCHECK(!position.NamedGridLine().IsNull()); wtf_size_t last_line = ExplicitGridSizeForSide(side, auto_repeat_tracks_count, @@ -330,8 +382,8 @@ const auto& track_list = ComputedGridTrackList(track_direction); NGGridNamedLineCollection lines_collection( position.NamedGridLine(), track_direction, implicit_grid_line_names, - explicit_grid_line_names, track_list, last_line, - auto_repeat_tracks_count); + explicit_grid_line_names, track_list, last_line, auto_repeat_tracks_count, + is_subgridded_to_parent); if (position.IsPositive()) { return LookAheadForNamedGridLine(0, abs(position.IntegerPosition()), @@ -342,19 +394,29 @@ last_line, lines_collection); } -int NGGridLineResolver::ResolveGridPositionFromStyle( +int NGGridLineResolver::ResolveGridPosition( const GridPosition& position, GridPositionSide side, wtf_size_t auto_repeat_tracks_count, bool is_subgridded_to_parent, wtf_size_t subgrid_span_size) const { + auto track_direction = DirectionFromSide(side); + + // TODO(kschmi): Remove `subgrid_offset` once `auto_repeat_tracks_count` is + // correct. + const int subgrid_offset = (track_direction == kForColumns) + ? subgrid_column_start_line_.value_or(0) + : subgrid_row_start_line_.value_or(0); switch (position.GetType()) { case kExplicitPosition: { DCHECK(position.IntegerPosition()); + // `ResolveNamedGridLinePosition` already factors in + // `subgrid_offset` via `ExplicitGridSizeForSide`. if (!position.NamedGridLine().IsNull()) { - return ResolveNamedGridLinePositionFromStyle( - position, side, auto_repeat_tracks_count, subgrid_span_size); + return ResolveNamedGridLinePosition( + position, side, auto_repeat_tracks_count, subgrid_span_size, + is_subgridded_to_parent); } // Handle <integer> explicit position. @@ -378,7 +440,6 @@ wtf_size_t last_line = ExplicitGridSizeForSide( side, auto_repeat_tracks_count, subgrid_span_size); - GridTrackSizingDirection track_direction = DirectionFromSide(side); const auto& implicit_grid_line_names = ImplicitNamedLinesMap(track_direction); const auto& explicit_grid_line_names = @@ -390,7 +451,7 @@ implicit_grid_line_names, explicit_grid_line_names, track_list, last_line, auto_repeat_tracks_count); if (implicit_lines.HasNamedLines()) - return implicit_lines.FirstPosition(); + return implicit_lines.FirstPosition() + subgrid_offset; // Otherwise, if there is a named line with the specified name, // contributes the first such line to the grid item's placement. @@ -399,11 +460,11 @@ explicit_grid_line_names, track_list, last_line, auto_repeat_tracks_count, is_subgridded_to_parent); if (explicit_lines.HasNamedLines()) - return explicit_lines.FirstPosition(); + return explicit_lines.FirstPosition() + subgrid_offset; // If none of the above works specs mandate to assume that all the lines // in the implicit grid have this name. - return last_line + 1; + return last_line + subgrid_offset + 1; } case kAutoPosition: case kSpanPosition: @@ -447,31 +508,31 @@ if (initial_should_be_resolved_against_opposite_position) { // Infer the position from the final_position position ('auto / 1' or 'span // 2 / 3' case). - int end_line = ResolveGridPositionFromStyle( + int end_line = ResolveGridPosition( final_position, final_side, auto_repeat_tracks_count, is_subgridded_to_parent, subgrid_span_size); return ResolveGridPositionAgainstOppositePosition( end_line, initial_position, initial_side, auto_repeat_tracks_count, - subgrid_span_size); + subgrid_span_size, is_subgridded_to_parent); } if (final_should_be_resolved_against_opposite_position) { // Infer our position from the initial_position position ('1 / auto' or '3 / // span 2' case). - int start_line = ResolveGridPositionFromStyle( + int start_line = ResolveGridPosition( initial_position, initial_side, auto_repeat_tracks_count, is_subgridded_to_parent, subgrid_span_size); return ResolveGridPositionAgainstOppositePosition( start_line, final_position, final_side, auto_repeat_tracks_count, - subgrid_span_size); + subgrid_span_size, is_subgridded_to_parent); } - int start_line = ResolveGridPositionFromStyle( + int start_line = ResolveGridPosition( initial_position, initial_side, auto_repeat_tracks_count, is_subgridded_to_parent, subgrid_span_size); - int end_line = ResolveGridPositionFromStyle( - final_position, final_side, auto_repeat_tracks_count, - is_subgridded_to_parent, subgrid_span_size); + int end_line = + ResolveGridPosition(final_position, final_side, auto_repeat_tracks_count, + is_subgridded_to_parent, subgrid_span_size); if (end_line < start_line) std::swap(end_line, start_line);
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h index ac8a4f47..07eb2890 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h
@@ -5,7 +5,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_LINE_RESOLVER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_LINE_RESOLVER_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/core/style/computed_grid_track_list.h" +#include "third_party/blink/renderer/core/style/grid_area.h" #include "third_party/blink/renderer/core/style/grid_enums.h" #include "third_party/blink/renderer/core/style/named_grid_lines_map.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -27,12 +29,13 @@ NGGridLineResolver() = default; explicit NGGridLineResolver(const ComputedStyle& grid_style) - : style_(&grid_style), is_subgrid_line_resolver_(false) {} + : style_(&grid_style) {} // Subgrids need to map named lines from every parent grid. This constructor // should be used exclusively by subgrids to differentiate such scenario. explicit NGGridLineResolver(const ComputedStyle& grid_style, - const NGGridLineResolver& parent_line_resolver); + const NGGridLineResolver& parent_line_resolver, + GridArea subgrid_area); wtf_size_t ExplicitGridColumnCount( wtf_size_t auto_repeat_columns_count, @@ -67,20 +70,22 @@ const GridPosition& position, GridPositionSide side, wtf_size_t auto_repeat_tracks_count, - wtf_size_t subgrid_span_size) const; + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const; GridSpan ResolveNamedGridLinePositionAgainstOppositePosition( int opposite_line, const GridPosition& position, wtf_size_t auto_repeat_tracks_count, GridPositionSide side, - wtf_size_t subgrid_span_size) const; + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const; - int ResolveGridPositionFromStyle(const GridPosition& position, - GridPositionSide side, - wtf_size_t auto_repeat_tracks_count, - bool is_subgridded_to_parent, - wtf_size_t subgrid_span_size) const; + int ResolveGridPosition(const GridPosition& position, + GridPositionSide side, + wtf_size_t auto_repeat_tracks_count, + bool is_subgridded_to_parent, + wtf_size_t subgrid_span_size) const; wtf_size_t ExplicitGridSizeForSide(GridPositionSide side, wtf_size_t auto_repeat_tracks_count, @@ -101,10 +106,11 @@ wtf_size_t SpanSizeFromPositions(const GridPosition& initial_position, const GridPosition& final_position) const; - int ResolveNamedGridLinePositionFromStyle(const GridPosition& position, - GridPositionSide side, - wtf_size_t auto_repeat_tracks_count, - wtf_size_t subgrid_span_size) const; + int ResolveNamedGridLinePosition(const GridPosition& position, + GridPositionSide side, + wtf_size_t auto_repeat_tracks_count, + wtf_size_t subgrid_span_size, + bool is_subgridded_to_parent) const; void InitialAndFinalPositionsFromStyle( const ComputedStyle& grid_item_style, @@ -121,10 +127,13 @@ scoped_refptr<const ComputedStyle> style_; - bool is_subgrid_line_resolver_ : 1; + // TODO(kschmi) remove these, as they will be unnecessary when the rest of + // the line resolution work is completed. + absl::optional<wtf_size_t> subgrid_column_start_line_; + absl::optional<wtf_size_t> subgrid_row_start_line_; - NamedGridLinesMap column_subgrid_merged_grid_line_names_; - NamedGridLinesMap row_subgrid_merged_grid_line_names_; + absl::optional<NamedGridLinesMap> column_subgrid_merged_grid_line_names_; + absl::optional<NamedGridLinesMap> row_subgrid_merged_grid_line_names_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index ba841a4..f876e56 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -358,7 +358,9 @@ HTMLMediaElement&) override; void DidCommitDocumentReplacementNavigation(DocumentLoader*) override {} - void DispatchDidClearWindowObjectInMainWorld() override {} + void DispatchDidClearWindowObjectInMainWorld( + v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue) override {} void DocumentElementAvailable() override {} void RunScriptsAtDocumentElementAvailable() override {} void RunScriptsAtDocumentReady(bool) override {}
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index b0c3dfe..bf017fd 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -1729,18 +1729,21 @@ &dispatching_did_clear_window_object_in_main_world_, true); // We just cleared the document, not the entire window object, but for the // embedder that's close enough. - Client()->DispatchDidClearWindowObjectInMainWorld(); + Client()->DispatchDidClearWindowObjectInMainWorld( + window->GetIsolate(), window->GetMicrotaskQueue()); } void FrameLoader::DispatchDidClearWindowObjectInMainWorld() { - if (!frame_->DomWindow()->CanExecuteScripts(kNotAboutToExecuteScript)) + LocalDOMWindow* window = frame_->DomWindow(); + if (!window->CanExecuteScripts(kNotAboutToExecuteScript)) return; if (dispatching_did_clear_window_object_in_main_world_) return; base::AutoReset<bool> in_did_clear_window_object( &dispatching_did_clear_window_object_in_main_world_, true); - Client()->DispatchDidClearWindowObjectInMainWorld(); + Client()->DispatchDidClearWindowObjectInMainWorld( + window->GetIsolate(), window->GetMicrotaskQueue()); } network::mojom::blink::WebSandboxFlags
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 305a123..8f62d7a 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -61,6 +61,8 @@ #include "third_party/blink/renderer/core/animation/scroll_timeline.h" #include "third_party/blink/renderer/core/content_capture/content_capture_manager.h" #include "third_party/blink/renderer/core/css/style_request.h" +#include "third_party/blink/renderer/core/document_transition/document_transition.h" +#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" @@ -702,8 +704,23 @@ gfx::Size PaintLayerScrollableArea::PixelSnappedContentsSize( const PhysicalOffset& paint_offset) const { - return ToPixelSnappedRect(PhysicalRect(paint_offset, overflow_rect_.size)) - .size(); + PhysicalSize size = overflow_rect_.size; + + // If we're capturing a transition snapshot, ensure the content size is + // considered at least as large as the container. Otherwise, the snapshot + // will be clipped by PendingLayer to the content size. + if (IsA<LayoutView>(GetLayoutBox())) { + auto* supplement = DocumentTransitionSupplement::FromIfExists( + GetLayoutBox()->GetDocument()); + if (supplement && supplement->GetTransition()->IsRootTransitioning()) { + PhysicalSize container_size( + supplement->GetTransition()->GetSnapshotViewportRect().size()); + size.width = std::max(container_size.width, size.width); + size.height = std::max(container_size.height, size.height); + } + } + + return ToPixelSnappedRect(PhysicalRect(paint_offset, size)).size(); } void PaintLayerScrollableArea::ContentsResized() {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 466479f..1fae5b6 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -2910,7 +2910,8 @@ // origin rather than behind the UI. if (auto* supplement = DocumentTransitionSupplement::FromIfExists(object_.GetDocument())) { - if (object_.IsDocumentElement() && !supplement->GetTransition()->IsIdle()) { + if (object_.IsDocumentElement() && + supplement->GetTransition()->IsRootTransitioning()) { PhysicalOffset offset = PhysicalOffset( supplement->GetTransition()->GetRootSnapshotPaintOffset()); context_.current.paint_offset += offset;
diff --git a/third_party/blink/renderer/core/paint/video_painter_test.cc b/third_party/blink/renderer/core/paint/video_painter_test.cc index ddc26ba..f1c265d 100644 --- a/third_party/blink/renderer/core/paint/video_painter_test.cc +++ b/third_party/blink/renderer/core/paint/video_painter_test.cc
@@ -140,8 +140,10 @@ EXPECT_EQ(gfx::Size(300, 150), layer->bounds()); } -class MockWebMediaPlayer : public EmptyWebMediaPlayer { +class MockWebMediaPlayer : public StubWebMediaPlayer { public: + explicit MockWebMediaPlayer(WebMediaPlayerClient* client) + : StubWebMediaPlayer(client) {} MOCK_CONST_METHOD0(HasAvailableVideoFrame, bool()); MOCK_METHOD3(Paint, void(cc::PaintCanvas*, const gfx::Rect&, cc::PaintFlags&)); @@ -151,14 +153,17 @@ public: WebMediaPlayer* CreateMediaPlayer( const WebMediaPlayerSource&, - WebMediaPlayerClient*, + WebMediaPlayerClient* client, blink::MediaInspectorContext*, WebMediaPlayerEncryptedMediaClient*, WebContentDecryptionModule*, const WebString& sink_id, const cc::LayerTreeSettings& settings, scoped_refptr<base::TaskRunner> compositor_worker_task_runner) override { - return new MockWebMediaPlayer(); + MockWebMediaPlayer* player = new MockWebMediaPlayer(client); + EXPECT_CALL(*player, HasAvailableVideoFrame) + .WillRepeatedly(testing::Return(false)); + return player; } }; @@ -282,6 +287,10 @@ ASSERT_TRUE(PlayVideo()); // Capture using poster. + auto* element = To<HTMLMediaElement>(GetDocument().body()->firstChild()); + MockWebMediaPlayer* player = + static_cast<MockWebMediaPlayer*>(element->GetWebMediaPlayer()); + EXPECT_CALL(*player, Paint(testing::_, testing::_, testing::_)).Times(0); auto record = CapturePaintPreview(/*skip_accelerated_content=*/true); std::vector<std::pair<GURL, SkRect>> links; @@ -294,6 +303,7 @@ EXPECT_EQ(1U, CountImagesOfType(record.get(), cc::ImageType::kGIF)); // Capture using video frame. + EXPECT_CALL(*player, Paint(testing::_, testing::_, testing::_)); record = CapturePaintPreview(/*skip_accelerated_content=*/false); links.clear();
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc index b0091d25..c1617dd 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
@@ -8,9 +8,7 @@ #include <string> #include "base/ranges/algorithm.h" -#include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/permissions_policy/origin_with_possible_wildcards.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" @@ -140,7 +138,6 @@ const char* permissions_policy_string; const char* self_origin; const char* src_origin; - const bool subdomain_wildcards; // Test expectation. ParsedPolicyForTest expected_parse_result; @@ -222,8 +219,6 @@ } } - base::test::ScopedFeatureList scoped_feature_list_; - public: static const PermissionsPolicyParserTestCase kCases[]; }; @@ -236,7 +231,6 @@ /* permissions_policy_string */ "", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ {}, }, { @@ -245,7 +239,6 @@ /* permissions_policy_string */ "geolocation=self", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -262,7 +255,6 @@ /* permissions_policy_string */ "geolocation=(self)", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -279,7 +271,6 @@ /* permissions_policy_string */ "geolocation=*", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -302,7 +293,6 @@ "payment=self", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -338,7 +328,6 @@ "payment=(self \"badorigin\")", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -372,7 +361,6 @@ "geolocation=self,fullscreen=self,payment=self", /* self_origin */ ORIGIN_A, /* src_origin */ nullptr, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -401,7 +389,6 @@ /* permissions_policy_string */ "", /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ {}, }, { @@ -410,7 +397,6 @@ /* permissions_policy_string */ NOT_APPLICABLE, /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -427,7 +413,6 @@ /* permissions_policy_string */ NOT_APPLICABLE, /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -444,7 +429,6 @@ /* permissions_policy_string */ "geolocation=*", /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -462,7 +446,6 @@ "geolocation=(\"" ORIGIN_B "\" \"" ORIGIN_C "\")", /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -481,7 +464,6 @@ /* permissions_policy_string */ NOT_APPLICABLE, /* self_origin */ ORIGIN_A, /* src_origin */ OPAQUE_ORIGIN, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -499,7 +481,6 @@ /* permissions_policy_string */ "geolocation=9", /* self_origin */ ORIGIN_A, /* src_origin */ nullptr, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -517,7 +498,6 @@ /* permissions_policy_string */ "geolocation=1.1", /* self_origin */ ORIGIN_A, /* src_origin */ nullptr, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -535,7 +515,6 @@ /* permissions_policy_string */ "geolocation=?0", /* self_origin */ ORIGIN_A, /* src_origin */ nullptr, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -552,7 +531,6 @@ /* permissions_policy_string */ "geolocation=\"\"", /* self_origin */ ORIGIN_A, /* src_origin */ nullptr, - /* subdomain_wildcards */ false, /* expected_parse_result */ { { @@ -564,34 +542,12 @@ }, }, { - /* test_name */ "ProperWildcardIncludedWhileFeatureDisabled", - /* feature_policy_string */ - "fullscreen " ORIGIN_A_SUBDOMAIN_WILDCARD, - /* permissions_policy_string */ - "fullscreen=(\"" ORIGIN_A_SUBDOMAIN_WILDCARD "\")", - /* self_origin */ ORIGIN_A, - /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, - /* expected_parse_result */ - { - { - mojom::blink::PermissionsPolicyFeature::kFullscreen, - /* matches_all_origins */ false, - /* matches_opaque_src */ false, - {{ORIGIN_A_SUBDOMAIN_ESCAPED, - /*has_subdomain_wildcard=*/false}}, - }, - }, - }, - { - /* test_name */ "ProperWildcardIncludedWhileFeatureEnabledForFeatur" - "ePolicy", + /* test_name */ "ProperWildcardIncludedForFeaturePolicy", /* feature_policy_string */ "fullscreen " ORIGIN_A_SUBDOMAIN_WILDCARD, /* permissions_policy_string */ NOT_APPLICABLE, /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ true, /* expected_parse_result */ { { @@ -604,14 +560,12 @@ }, }, { - /* test_name */ "ProperWildcardIncludedWhileFeatureEnabledForPermis" - "sionsPolicy", + /* test_name */ "ProperWildcardIncludedForPermissionsPolicy", /* feature_policy_string */ NOT_APPLICABLE, /* permissions_policy_string */ "fullscreen=(\"" ORIGIN_A_SUBDOMAIN_WILDCARD "\")", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ true, /* expected_parse_result */ { { @@ -624,7 +578,7 @@ }, }, { - /* test_name */ "ImproperWildcardsIncludedWhileFeatureDisabled", + /* test_name */ "ImproperWildcardsIncluded", /* feature_policy_string */ "fullscreen *://example.com https://foo.*.example.com " "https://*.*.example.com https://example.com:*", @@ -633,31 +587,6 @@ "\"https://*.*.example.com\" \"https://example.com:*\")", /* self_origin */ ORIGIN_A, /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ false, - /* expected_parse_result */ - { - { - mojom::blink::PermissionsPolicyFeature::kFullscreen, - /* matches_all_origins */ false, - /* matches_opaque_src */ false, - {{"https://%2A.%2A.example.com", - /*has_subdomain_wildcard=*/false}, - {"https://foo.%2A.example.com", - /*has_subdomain_wildcard=*/false}}, - }, - }, - }, - { - /* test_name */ "ImproperWildcardsIncludedWhileFeatureEnabled", - /* feature_policy_string */ - "fullscreen *://example.com https://foo.*.example.com " - "https://*.*.example.com https://example.com:*", - /* permissions_policy_string */ - "fullscreen=(\"*://example.com\" \"https://foo.*.example.com\" " - "\"https://*.*.example.com\" \"https://example.com:*\")", - /* self_origin */ ORIGIN_A, - /* src_origin */ ORIGIN_B, - /* subdomain_wildcards */ true, /* expected_parse_result */ { { @@ -687,9 +616,6 @@ return; ASSERT_NE(test_case.self_origin, nullptr); - scoped_feature_list_.InitWithFeatureState( - features::kWildcardSubdomainsInPermissionsPolicy, - test_case.subdomain_wildcards); CheckParsedPolicy( ParseFeaturePolicy(test_case.feature_policy_string, test_case.self_origin, test_case.src_origin, logger, test_feature_name_map), @@ -703,9 +629,6 @@ return; ASSERT_NE(test_case.self_origin, nullptr); - scoped_feature_list_.InitWithFeatureState( - features::kWildcardSubdomainsInPermissionsPolicy, - test_case.subdomain_wildcards); CheckParsedPolicy( ParsePermissionsPolicy(test_case.permissions_policy_string, test_case.self_origin, test_case.src_origin,
diff --git a/third_party/blink/renderer/core/permissions_policy/policy_test.cc b/third_party/blink/renderer/core/permissions_policy/policy_test.cc index f9a14993..055de97 100644 --- a/third_party/blink/renderer/core/permissions_policy/policy_test.cc +++ b/third_party/blink/renderer/core/permissions_policy/policy_test.cc
@@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/test/scoped_feature_list.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/permissions_policy/dom_feature_policy.h" @@ -26,12 +24,9 @@ using testing::UnorderedElementsAre; -class PolicyTest : public testing::TestWithParam<bool> { +class PolicyTest : public testing::Test { public: void SetUp() override { - scoped_feature_list_.InitWithFeatureState( - features::kWildcardSubdomainsInPermissionsPolicy, - HasWildcardSubdomainsInPermissionsPolicy()); page_holder_ = std::make_unique<DummyPageHolder>(); auto origin = SecurityOrigin::CreateFromString(kSelfOrigin); @@ -53,15 +48,12 @@ DOMFeaturePolicy* GetPolicy() const { return policy_; } - bool HasWildcardSubdomainsInPermissionsPolicy() { return GetParam(); } - PolicyParserMessageBuffer dummy_logger_ = PolicyParserMessageBuffer("", true /* discard_message */); protected: std::unique_ptr<DummyPageHolder> page_holder_; Persistent<DOMFeaturePolicy> policy_; - base::test::ScopedFeatureList scoped_feature_list_; }; class DOMFeaturePolicyTest : public PolicyTest { @@ -73,8 +65,6 @@ } }; -INSTANTIATE_TEST_SUITE_P(All, DOMFeaturePolicyTest, testing::Bool()); - class IFramePolicyTest : public PolicyTest { public: void SetUp() override { @@ -85,9 +75,7 @@ } }; -INSTANTIATE_TEST_SUITE_P(All, IFramePolicyTest, testing::Bool()); - -TEST_P(DOMFeaturePolicyTest, TestAllowsFeature) { +TEST_F(DOMFeaturePolicyTest, TestAllowsFeature) { EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "badfeature")); EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "midi")); EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "midi", kSelfOrigin)); @@ -106,15 +94,14 @@ EXPECT_TRUE(GetPolicy()->allowsFeature(nullptr, "sync-xhr", kOriginA)); EXPECT_TRUE(GetPolicy()->allowsFeature(nullptr, "gyroscope")); EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "gyroscope", kOriginA)); - EXPECT_EQ( - HasWildcardSubdomainsInPermissionsPolicy(), + EXPECT_TRUE( GetPolicy()->allowsFeature(nullptr, "gyroscope", kOriginASubdomain)); EXPECT_TRUE(GetPolicy()->allowsFeature(nullptr, "gyroscope", kOriginB)); EXPECT_FALSE( GetPolicy()->allowsFeature(nullptr, "gyroscope", kOriginBSubdomain)); } -TEST_P(DOMFeaturePolicyTest, TestGetAllowList) { +TEST_F(DOMFeaturePolicyTest, TestGetAllowList) { EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "camera"), UnorderedElementsAre(kSelfOrigin, kOriginA, kOriginB)); EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "payment"), @@ -128,14 +115,12 @@ EXPECT_TRUE(GetPolicy()->getAllowlistForFeature(nullptr, "midi").empty()); EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "sync-xhr"), UnorderedElementsAre("*")); - EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "gyroscope"), - UnorderedElementsAre(kSelfOrigin, kOriginB, - HasWildcardSubdomainsInPermissionsPolicy() - ? "https://*.example.com" - : "https://%2A.example.com")); + EXPECT_THAT( + GetPolicy()->getAllowlistForFeature(nullptr, "gyroscope"), + UnorderedElementsAre(kSelfOrigin, kOriginB, "https://*.example.com")); } -TEST_P(DOMFeaturePolicyTest, TestAllowedFeatures) { +TEST_F(DOMFeaturePolicyTest, TestAllowedFeatures) { Vector<String> allowed_features = GetPolicy()->allowedFeatures(nullptr); EXPECT_TRUE(allowed_features.Contains("fullscreen")); EXPECT_TRUE(allowed_features.Contains("payment")); @@ -149,7 +134,7 @@ EXPECT_TRUE(allowed_features.Contains("sync-xhr")); } -TEST_P(IFramePolicyTest, TestAllowsFeature) { +TEST_F(IFramePolicyTest, TestAllowsFeature) { EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "badfeature")); EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "midi")); EXPECT_FALSE(GetPolicy()->allowsFeature(nullptr, "midi", kSelfOrigin)); @@ -176,7 +161,7 @@ GetPolicy()->allowsFeature(nullptr, "gyroscope", kOriginBSubdomain)); } -TEST_P(IFramePolicyTest, TestGetAllowList) { +TEST_F(IFramePolicyTest, TestGetAllowList) { EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "camera"), UnorderedElementsAre(kSelfOrigin)); EXPECT_THAT(GetPolicy()->getAllowlistForFeature(nullptr, "payment"), @@ -194,7 +179,7 @@ UnorderedElementsAre(kSelfOrigin)); } -TEST_P(IFramePolicyTest, TestSameOriginAllowedFeatures) { +TEST_F(IFramePolicyTest, TestSameOriginAllowedFeatures) { Vector<String> allowed_features = GetPolicy()->allowedFeatures(nullptr); // These features are allowed in a same origin context, and not restricted by // the parent document's policy. @@ -211,7 +196,7 @@ EXPECT_FALSE(allowed_features.Contains("badfeature")); } -TEST_P(IFramePolicyTest, TestCrossOriginAllowedFeatures) { +TEST_F(IFramePolicyTest, TestCrossOriginAllowedFeatures) { // Update the iframe's policy, given a new origin. GetPolicy()->UpdateContainerPolicy( ParsedPermissionsPolicy(), SecurityOrigin::CreateFromString(kOriginA)); @@ -229,7 +214,7 @@ EXPECT_FALSE(allowed_features.Contains("badfeature")); } -TEST_P(IFramePolicyTest, TestCombinedPolicyOnOriginA) { +TEST_F(IFramePolicyTest, TestCombinedPolicyOnOriginA) { ParsedPermissionsPolicy container_policy = PermissionsPolicyParser::ParseAttribute( "geolocation 'src'; payment 'none'; midi; camera 'src'; gyroscope " @@ -255,7 +240,7 @@ EXPECT_FALSE(allowed_features.Contains("badfeature")); } -TEST_P(IFramePolicyTest, TestCombinedPolicyOnOriginASubdomain) { +TEST_F(IFramePolicyTest, TestCombinedPolicyOnOriginASubdomain) { ParsedPermissionsPolicy container_policy = PermissionsPolicyParser::ParseAttribute( "geolocation 'src'; payment 'none'; midi; camera 'src'; gyroscope " @@ -273,16 +258,15 @@ // These are allowed by the attribute, but still blocked by the parent policy. EXPECT_FALSE(allowed_features.Contains("midi")); EXPECT_FALSE(allowed_features.Contains("camera")); - // These features are allowed if subdomain wildcard matching is on. - EXPECT_EQ(HasWildcardSubdomainsInPermissionsPolicy(), - allowed_features.Contains("gyroscope")); + // These features are allowed via wildcard matching. + EXPECT_TRUE(allowed_features.Contains("gyroscope")); // "sync-xhr" is still implicitly allowed on all origins. EXPECT_TRUE(allowed_features.Contains("sync-xhr")); // This feature does not exist, so should not be advertised as allowed. EXPECT_FALSE(allowed_features.Contains("badfeature")); } -TEST_P(IFramePolicyTest, TestCombinedPolicyOnOriginB) { +TEST_F(IFramePolicyTest, TestCombinedPolicyOnOriginB) { ParsedPermissionsPolicy container_policy = PermissionsPolicyParser::ParseAttribute( "geolocation 'src'; payment 'none'; midi; camera 'src'; gyroscope " @@ -307,7 +291,7 @@ EXPECT_FALSE(allowed_features.Contains("badfeature")); } -TEST_P(IFramePolicyTest, TestCombinedPolicyOnOriginBSubdomain) { +TEST_F(IFramePolicyTest, TestCombinedPolicyOnOriginBSubdomain) { ParsedPermissionsPolicy container_policy = PermissionsPolicyParser::ParseAttribute( "geolocation 'src'; payment 'none'; midi; camera 'src'; gyroscope "
diff --git a/third_party/blink/renderer/core/style/ordered_named_grid_lines.h b/third_party/blink/renderer/core/style/ordered_named_grid_lines.h index 9040ca79..5f169db 100644 --- a/third_party/blink/renderer/core/style/ordered_named_grid_lines.h +++ b/third_party/blink/renderer/core/style/ordered_named_grid_lines.h
@@ -7,13 +7,12 @@ #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { struct NamedGridLine { - explicit NamedGridLine(const String line_name, + explicit NamedGridLine(const AtomicString& line_name, bool is_in_repeat = false, bool is_first_repeat = false) : line_name(line_name), @@ -25,9 +24,9 @@ is_first_repeat == other.is_first_repeat; } - String line_name; - bool is_in_repeat; - bool is_first_repeat; + AtomicString line_name; + bool is_in_repeat : 1; + bool is_first_repeat : 1; }; using OrderedNamedGridLines =
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc index 00eb640c..b51c212 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -235,6 +235,7 @@ private: friend class ThreadedWorkletTest; + FRIEND_TEST_ALL_PREFIXES(ThreadedWorkletTest, NestedRunLoopTermination); std::unique_ptr<WorkerThread> CreateWorkerThread() final { return std::make_unique<ThreadedWorkletThreadForTest>(WorkletObjectProxy()); @@ -281,6 +282,16 @@ } Document& GetDocument() { return page_->GetDocument(); } + void WaitForReady(WorkerThread* worker_thread) { + base::WaitableEvent child_waitable; + PostCrossThreadTask( + *worker_thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBindOnce(&base::WaitableEvent::Signal, + CrossThreadUnretained(&child_waitable))); + + child_waitable.Wait(); + } + private: std::unique_ptr<DummyPageHolder> page_; Persistent<ThreadedWorkletMessagingProxyForTest> messaging_proxy_; @@ -404,4 +415,40 @@ test::EnterRunLoop(); } +TEST_F(ThreadedWorkletTest, NestedRunLoopTermination) { + MessagingProxy()->Start(); + + ThreadedWorkletMessagingProxyForTest* second_messaging_proxy = + MakeGarbageCollected<ThreadedWorkletMessagingProxyForTest>( + GetExecutionContext()); + + // Get a nested event loop where the first one is on the stack + // and the second is still alive. + second_messaging_proxy->Start(); + + // Wait until the workers are setup and ready to accept work before we + // pause them. + WaitForReady(GetWorkerThread()); + WaitForReady(second_messaging_proxy->GetWorkerThread()); + + // Pause the second worker, then the first. + second_messaging_proxy->GetWorkerThread()->Pause(); + GetWorkerThread()->Pause(); + + // Resume then terminate the second worker. + second_messaging_proxy->GetWorkerThread()->Resume(); + second_messaging_proxy->GetWorkerThread()->Terminate(); + second_messaging_proxy = nullptr; + + // Now resume the first worker. + GetWorkerThread()->Resume(); + + // Make sure execution still works without crashing. + PostCrossThreadTask( + *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBindOnce(&ThreadedWorkletThreadForTest::TestTaskRunner, + CrossThreadUnretained(GetWorkerThread()))); + test::EnterRunLoop(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index b20c2286..8bf05b2 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -30,7 +30,6 @@ #include <memory> #include <utility> -#include "base/auto_reset.h" #include "base/metrics/histogram_functions.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" @@ -598,6 +597,7 @@ const absl::optional<WorkerBackingThreadStartupData>& thread_startup_data, std::unique_ptr<WorkerDevToolsParams> devtools_params) { DCHECK(IsCurrentThread()); + backing_thread_weak_factory_.emplace(this); worker_reporting_proxy_.WillInitializeWorkerContext(); { TRACE_EVENT0("blink.worker", "WorkerThread::InitializeWorkerContext"); @@ -739,11 +739,13 @@ SetThreadState(ThreadState::kReadyToShutdown); } + backing_thread_weak_factory_ = absl::nullopt; if (pause_or_freeze_count_ > 0) { DCHECK(nested_runner_); pause_or_freeze_count_ = 0; nested_runner_->QuitNow(); } + pause_handle_.reset(); if (WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(GetIsolate())) debugger->WorkerThreadDestroyed(this); @@ -888,8 +890,7 @@ if (pause_or_freeze_count_ > 1) return; - std::unique_ptr<scheduler::WorkerScheduler::PauseHandle> pause_handle = - GetScheduler()->Pause(); + pause_handle_ = GetScheduler()->Pause(); { // Since the nested message loop runner needs to be created and destroyed on // the same thread we allocate and destroy a new message loop runner each @@ -897,13 +898,20 @@ // the worker thread such that the resume/terminate can quit this runner. std::unique_ptr<Platform::NestedMessageLoopRunner> nested_runner = Platform::Current()->CreateNestedMessageLoopRunner(); - base::AutoReset<Platform::NestedMessageLoopRunner*> nested_runner_autoreset( - &nested_runner_, nested_runner.get()); + auto weak_this = backing_thread_weak_factory_->GetWeakPtr(); + nested_runner_ = nested_runner.get(); nested_runner->Run(); + + // Careful `this` may be destroyed. + if (!weak_this) { + return; + } + nested_runner_ = nullptr; } GlobalScope()->SetDefersLoadingForResourceFetchers(LoaderFreezeMode::kNone); GlobalScope()->SetIsInBackForwardCache(false); GlobalScope()->SetLifecycleState(mojom::blink::FrameLifecycleState::kRunning); + pause_handle_.reset(); } void WorkerThread::ResumeOnWorkerThread() {
diff --git a/third_party/blink/renderer/core/workers/worker_thread.h b/third_party/blink/renderer/core/workers/worker_thread.h index 7254460e..298c36e 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.h +++ b/third_party/blink/renderer/core/workers/worker_thread.h
@@ -31,6 +31,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/task/single_thread_task_runner.h" @@ -82,7 +83,7 @@ // abstract class. Multiple WorkerThreads may share one WorkerBackingThread for // worklets. // -// WorkerThread start and termination must be initiated on the main thread and +// WorkerThread start and termination must be initiated on the parent thread and // an actual task is executed on the worker thread. // // When termination starts, (debugger) tasks on WorkerThread are handled as @@ -105,7 +106,7 @@ ~WorkerThread() override; // Starts the underlying thread and creates the global scope. Called on the - // main thread. + // parent thread. // Startup data for WorkerBackingThread is absl::nullopt if |this| doesn't own // the underlying WorkerBackingThread. // TODO(nhiroki): We could separate WorkerBackingThread initialization from @@ -117,14 +118,14 @@ std::unique_ptr<WorkerDevToolsParams>); // Posts a task to evaluate a top-level classic script on the worker thread. - // Called on the main thread after Start(). + // Called on the parent thread after Start(). void EvaluateClassicScript(const KURL& script_url, const String& source_code, std::unique_ptr<Vector<uint8_t>> cached_meta_data, const v8_inspector::V8StackTraceId& stack_id); // Posts a task to fetch and run a top-level classic script on the worker - // thread. Called on the main thread after Start(). + // thread. Called on the parent thread after Start(). void FetchAndRunClassicScript( const KURL& script_url, std::unique_ptr<WorkerMainScriptLoadParameters> @@ -136,7 +137,7 @@ const v8_inspector::V8StackTraceId& stack_id); // Posts a task to fetch and run a top-level module script on the worker - // thread. Called on the main thread after Start(). + // thread. Called on the parent thread after Start(). void FetchAndRunModuleScript( const KURL& script_url, std::unique_ptr<WorkerMainScriptLoadParameters> @@ -158,7 +159,7 @@ // Terminates the worker thread. Subclasses of WorkerThread can override this // to do cleanup. The default behavior is to call Terminate() and // synchronously call EnsureScriptExecutionTerminates() to ensure the thread - // is quickly terminated. Called on the main thread. + // is quickly terminated. Called on the parent thread. virtual void TerminateForTesting(); // Thread::TaskObserver. @@ -185,7 +186,7 @@ void DebuggerTaskStarted(); void DebuggerTaskFinished(); - // Callable on both the main thread and the worker thread. + // Callable on both the parent thread and the worker thread. const base::UnguessableToken& GetDevToolsWorkerToken() const { return devtools_worker_token_; } @@ -330,7 +331,7 @@ // already shutting down. Does not terminate if a debugger task is running, // because the debugger task is guaranteed to finish and it heavily uses V8 // API calls which would crash after forcible script termination. Called on - // the main thread. + // the parent thread. void EnsureScriptExecutionTerminates(ExitCode) LOCKS_EXCLUDED(lock_); // These are called in this order during worker thread startup. @@ -417,7 +418,7 @@ // A unique identifier among all WorkerThreads. const int worker_thread_id_; - // Set on the main thread. + // Set on the parent thread. bool requested_to_terminate_ GUARDED_BY(lock_) = false; ThreadState thread_state_ GUARDED_BY(lock_) = ThreadState::kNotStarted; @@ -451,7 +452,7 @@ TaskTypeTraits>; TaskRunnerHashMap worker_task_runners_; - // This lock protects shared states between the main thread and the worker + // This lock protects shared states between the parent thread and the worker // thread. See thread-safety annotations (e.g., GUARDED_BY) in this header // file. base::Lock lock_; @@ -460,6 +461,10 @@ // only on the worker thread. int pause_or_freeze_count_ = 0; + // The `PauseHandle` needs to be destroyed before the scheduler is destroyed + // otherwise we will hit a DCHECK. + std::unique_ptr<scheduler::WorkerScheduler::PauseHandle> pause_handle_; + // A nested message loop for handling pausing. Pointer is not owned. Used only // on the worker thread. Platform::NestedMessageLoopRunner* nested_runner_ = nullptr; @@ -485,6 +490,12 @@ // a pointer to a member in this list. HashSet<std::unique_ptr<InterruptData>> pending_interrupts_ GUARDED_BY(lock_); + // Since the WorkerThread is allocated and deallocated on the parent thread, + // we need a WeakPtrFactory that is allocated and cleared on the backing + // thread. + absl::optional<base::WeakPtrFactory<WorkerThread>> + backing_thread_weak_factory_; + THREAD_CHECKER(parent_thread_checker_); };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl index 6a415ec..9468801 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
@@ -86,7 +86,7 @@ readonly attribute boolean? canTrickleIceCandidates; void restartIce(); [CallWith=ScriptState] RTCConfiguration getConfiguration(); - [CallWith=ScriptState, RaisesException] void setConfiguration(RTCConfiguration configuration); + [CallWith=ScriptState, RaisesException] void setConfiguration(optional RTCConfiguration configuration = {}); void close(); attribute EventHandler onnegotiationneeded; attribute EventHandler onicecandidate;
diff --git a/third_party/blink/renderer/modules/peerconnection/testing/mock_peer_connection_interface.h b/third_party/blink/renderer/modules/peerconnection/testing/mock_peer_connection_interface.h index 39140cc..e7b01c1 100644 --- a/third_party/blink/renderer/modules/peerconnection/testing/mock_peer_connection_interface.h +++ b/third_party/blink/renderer/modules/peerconnection/testing/mock_peer_connection_interface.h
@@ -15,194 +15,13 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/webrtc/api/peer_connection_interface.h" #include "third_party/webrtc/api/scoped_refptr.h" +#include "third_party/webrtc/api/test/mock_peerconnectioninterface.h" #include "third_party/webrtc/rtc_base/ref_count.h" namespace blink { class MockPeerConnectionInterface - : public rtc::RefCountedObject<webrtc::PeerConnectionInterface> { - public: - // PeerConnectionInterface - MOCK_METHOD(rtc::scoped_refptr<webrtc::StreamCollectionInterface>, - local_streams, - (), - (override)); - MOCK_METHOD(rtc::scoped_refptr<webrtc::StreamCollectionInterface>, - remote_streams, - (), - (override)); - MOCK_METHOD(bool, AddStream, (webrtc::MediaStreamInterface*), (override)); - MOCK_METHOD(void, RemoveStream, (webrtc::MediaStreamInterface*), (override)); - MOCK_METHOD( - webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>, - AddTrack, - (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>, - const std::vector<std::string>&), - (override)); - MOCK_METHOD(webrtc::RTCError, - RemoveTrackOrError, - (rtc::scoped_refptr<webrtc::RtpSenderInterface>), - (override)); - MOCK_METHOD( - webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>, - AddTransceiver, - (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>), - (override)); - MOCK_METHOD( - webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>, - AddTransceiver, - (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>, - const webrtc::RtpTransceiverInit&), - (override)); - MOCK_METHOD( - webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>, - AddTransceiver, - (cricket::MediaType), - (override)); - MOCK_METHOD( - webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>, - AddTransceiver, - (cricket::MediaType, const webrtc::RtpTransceiverInit&), - (override)); - MOCK_METHOD(rtc::scoped_refptr<webrtc::RtpSenderInterface>, - CreateSender, - (const std::string&, const std::string&), - (override)); - MOCK_METHOD(std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>>, - GetSenders, - (), - (const override)); - MOCK_METHOD(std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>>, - GetReceivers, - (), - (const override)); - MOCK_METHOD(std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>, - GetTransceivers, - (), - (const override)); - MOCK_METHOD(bool, - GetStats, - (webrtc::StatsObserver*, - webrtc::MediaStreamTrackInterface*, - StatsOutputLevel), - (override)); - MOCK_METHOD(void, GetStats, (webrtc::RTCStatsCollectorCallback*), (override)); - MOCK_METHOD(void, - GetStats, - (rtc::scoped_refptr<webrtc::RtpSenderInterface>, - rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback>), - (override)); - MOCK_METHOD(void, - GetStats, - (rtc::scoped_refptr<webrtc::RtpReceiverInterface>, - rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback>), - (override)); - MOCK_METHOD(void, ClearStatsCache, (), (override)); - MOCK_METHOD(rtc::scoped_refptr<webrtc::SctpTransportInterface>, - GetSctpTransport, - (), - (const override)); - MOCK_METHOD(rtc::scoped_refptr<webrtc::DataChannelInterface>, - CreateDataChannel, - (const std::string&, const webrtc::DataChannelInit*), - (override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - local_description, - (), - (const override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - remote_description, - (), - (const override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - current_local_description, - (), - (const override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - current_remote_description, - (), - (const override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - pending_local_description, - (), - (const override)); - MOCK_METHOD(const webrtc::SessionDescriptionInterface*, - pending_remote_description, - (), - (const override)); - MOCK_METHOD(void, RestartIce, (), (override)); - MOCK_METHOD(void, - CreateOffer, - (webrtc::CreateSessionDescriptionObserver*, - const RTCOfferAnswerOptions&), - (override)); - MOCK_METHOD(void, - CreateAnswer, - (webrtc::CreateSessionDescriptionObserver*, - const RTCOfferAnswerOptions&), - (override)); - MOCK_METHOD(void, - SetLocalDescription, - (webrtc::SetSessionDescriptionObserver*, - webrtc::SessionDescriptionInterface*), - (override)); - MOCK_METHOD(void, - SetRemoteDescription, - (webrtc::SetSessionDescriptionObserver*, - webrtc::SessionDescriptionInterface*), - (override)); - MOCK_METHOD( - void, - SetRemoteDescription, - (std::unique_ptr<webrtc::SessionDescriptionInterface>, - rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>), - (override)); - MOCK_METHOD(PeerConnectionInterface::RTCConfiguration, - GetConfiguration, - (), - (override)); - MOCK_METHOD(webrtc::RTCError, - SetConfiguration, - (const PeerConnectionInterface::RTCConfiguration&), - (override)); - MOCK_METHOD(bool, - AddIceCandidate, - (const webrtc::IceCandidateInterface*), - (override)); - MOCK_METHOD(bool, - RemoveIceCandidates, - (const std::vector<cricket::Candidate>&), - (override)); - MOCK_METHOD(webrtc::RTCError, - SetBitrate, - (const webrtc::BitrateSettings&), - (override)); - MOCK_METHOD(void, SetAudioPlayout, (bool), (override)); - MOCK_METHOD(void, SetAudioRecording, (bool), (override)); - MOCK_METHOD(rtc::scoped_refptr<webrtc::DtlsTransportInterface>, - LookupDtlsTransportByMid, - (const std::string&), - (override)); - MOCK_METHOD(SignalingState, signaling_state, (), (override)); - MOCK_METHOD(IceConnectionState, ice_connection_state, (), (override)); - MOCK_METHOD(IceConnectionState, - standardized_ice_connection_state, - (), - (override)); - MOCK_METHOD(PeerConnectionState, peer_connection_state, (), (override)); - MOCK_METHOD(IceGatheringState, ice_gathering_state, (), (override)); - MOCK_METHOD(absl::optional<bool>, can_trickle_ice_candidates, (), (override)); - MOCK_METHOD(bool, - StartRtcEventLog, - (std::unique_ptr<webrtc::RtcEventLogOutput>, int64_t), - (override)); - MOCK_METHOD(bool, - StartRtcEventLog, - (std::unique_ptr<webrtc::RtcEventLogOutput>), - (override)); - MOCK_METHOD(void, StopRtcEventLog, (), (override)); - MOCK_METHOD(void, Close, (), (override)); -}; + : public rtc::RefCountedObject<webrtc::MockPeerConnectionInterface> {}; static_assert(!std::is_abstract<MockPeerConnectionInterface>::value, "");
diff --git a/third_party/blink/renderer/modules/permissions/permission_utils.cc b/third_party/blink/renderer/modules/permissions/permission_utils.cc index 6e060bc9..81a9cb4 100644 --- a/third_party/blink/renderer/modules/permissions/permission_utils.cc +++ b/third_party/blink/renderer/modules/permissions/permission_utils.cc
@@ -95,7 +95,7 @@ return "nfc"; case PermissionName::STORAGE_ACCESS: return "storage_access"; - case PermissionName::WINDOW_PLACEMENT: + case PermissionName::WINDOW_MANAGEMENT: return "window_placement"; case PermissionName::LOCAL_FONTS: return "local_fonts"; @@ -280,7 +280,7 @@ exception_state.ThrowTypeError("Window Placement is not enabled."); return nullptr; } - return CreatePermissionDescriptor(PermissionName::WINDOW_PLACEMENT); + return CreatePermissionDescriptor(PermissionName::WINDOW_MANAGEMENT); } if (name == "local-fonts") { if (!RuntimeEnabledFeatures::FontAccessEnabled(
diff --git a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc index 03a69bc..dbd476bb 100644 --- a/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc +++ b/third_party/blink/renderer/modules/screen_enumeration/window_screens.cc
@@ -71,7 +71,7 @@ } auto permission_descriptor = CreatePermissionDescriptor( - mojom::blink::PermissionName::WINDOW_PLACEMENT); + mojom::blink::PermissionName::WINDOW_MANAGEMENT); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto callback = WTF::BindOnce(&WindowScreens::OnPermissionRequestComplete, WrapPersistent(this), WrapPersistent(resolver));
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc index 672a82f..ecf1b5a 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -41,72 +41,52 @@ #include "third_party/blink/renderer/platform/scheduler/public/main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { namespace { -void CreateContextProvider( - const KURL& url, - base::WaitableEvent* waitable_event, - std::unique_ptr<WebGraphicsContext3DProvider>* created_context_provider) { +void CreateContextProviderOnMainThread( + ExecutionContext* execution_context, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + CrossThreadOnceFunction<void(std::unique_ptr<WebGraphicsContext3DProvider>)> + callback) { DCHECK(IsMainThread()); - *created_context_provider = - Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url); - waitable_event->Signal(); -} - -std::unique_ptr<WebGraphicsContext3DProvider> CreateContextProviderOnMainThread( - const KURL& url) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - Thread::MainThread()->GetDeprecatedTaskRunner(); - - base::WaitableEvent waitable_event; - std::unique_ptr<WebGraphicsContext3DProvider> created_context_provider; + const KURL& url = execution_context->Url(); PostCrossThreadTask( *task_runner, FROM_HERE, - CrossThreadBindOnce(&CreateContextProvider, url, - CrossThreadUnretained(&waitable_event), - CrossThreadUnretained(&created_context_provider))); - - waitable_event.Wait(); - return created_context_provider; + CrossThreadBindOnce( + std::move(callback), + Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url))); } -std::unique_ptr<WebGraphicsContext3DProvider> CreateContextProvider( - ExecutionContext& execution_context) { - const KURL& url = execution_context.Url(); - std::unique_ptr<WebGraphicsContext3DProvider> context_provider; +void EnsureDawnControlClientInitialized( + ExecutionContext* execution_context, + base::OnceCallback<void(std::unique_ptr<WebGraphicsContext3DProvider>)> + callback) { if (IsMainThread()) { - context_provider = - Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url); + const KURL& url = execution_context->Url(); + std::move(callback).Run( + Platform::Current()->CreateWebGPUGraphicsContext3DProvider(url)); } else { - context_provider = CreateContextProviderOnMainThread(url); + // Posts a task to the main thread to create context provider + // because the current RendererBlinkPlatformImpl and viz::Gpu + // APIs allow to create it only on the main thread. + // When it is created, posts it back to the current thread + // and call the callback with it. + // TODO(takahiro): Directly create context provider on Workers threads + // if RendererBlinkPlatformImpl and viz::Gpu will start to + // allow the context provider creation on Workers. + PostCrossThreadTask( + *Thread::MainThread()->GetDeprecatedTaskRunner(), FROM_HERE, + CrossThreadBindOnce(&CreateContextProviderOnMainThread, + WrapCrossThreadPersistent(execution_context), + execution_context->GetTaskRunner(TaskType::kWebGPU), + CrossThreadBindOnce(std::move(callback)))); } - - // Note that we check for API blocking *after* creating the context. This is - // because context creation synchronizes against GpuProcessHost lifetime in - // the browser process, and GpuProcessHost destruction is what updates API - // blocking state on a GPU process crash. See https://crbug.com/1215907#c10 - // for more details. - bool blocked = true; - mojo::Remote<mojom::blink::GpuDataManager> gpu_data_manager; - Platform::Current()->GetBrowserInterfaceBroker()->GetInterface( - gpu_data_manager.BindNewPipeAndPassReceiver()); - gpu_data_manager->Are3DAPIsBlockedForUrl(url, &blocked); - if (blocked) { - return nullptr; - } - - // TODO(kainino): we will need a better way of accessing the GPU interface - // from multiple threads than BindToCurrentSequence et al. - if (context_provider && !context_provider->BindToCurrentSequence()) { - // TODO(crbug.com/973017): Collect GPU info and surface context creation - // error. - return nullptr; - } - return context_provider; } [[maybe_unused]] void AddConsoleWarning(ExecutionContext* execution_context, @@ -287,34 +267,95 @@ .Record(context->UkmRecorder()); } -ScriptPromise GPU::requestAdapter(ScriptState* script_state, - const GPURequestAdapterOptions* options) { - auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); - ScriptPromise promise = resolver->Promise(); - ExecutionContext* execution_context = ExecutionContext::From(script_state); +std::unique_ptr<WebGraphicsContext3DProvider> CheckContextProvider( + const KURL& url, + std::unique_ptr<WebGraphicsContext3DProvider> context_provider) { + // Note that we check for API blocking *after* creating the context. This is + // because context creation synchronizes against GpuProcessHost lifetime in + // the browser process, and GpuProcessHost destruction is what updates API + // blocking state on a GPU process crash. See https://crbug.com/1215907#c10 + // for more details. + bool blocked = true; + mojo::Remote<mojom::blink::GpuDataManager> gpu_data_manager; + Platform::Current()->GetBrowserInterfaceBroker()->GetInterface( + gpu_data_manager.BindNewPipeAndPassReceiver()); + gpu_data_manager->Are3DAPIsBlockedForUrl(url, &blocked); + if (blocked) { + return nullptr; + } + // TODO(kainino): we will need a better way of accessing the GPU interface + // from multiple threads than BindToCurrentSequence et al. + if (context_provider && !context_provider->BindToCurrentSequence()) { + // TODO(crbug.com/973017): Collect GPU info and surface context creation + // error. + return nullptr; + } + + return context_provider; +} + +void GPU::RequestAdapterImpl(ScriptState* script_state, + const GPURequestAdapterOptions* options, + ScriptPromiseResolver* resolver) { + ExecutionContext* execution_context = ExecutionContext::From(script_state); if (!dawn_control_client_ || dawn_control_client_->IsContextLost()) { + dawn_control_client_initialized_callbacks_.push_back(WTF::BindOnce( + [](GPU* gpu, ScriptState* script_state, + const GPURequestAdapterOptions* options, + ScriptPromiseResolver* resolver) { + if (gpu->dawn_control_client_ && + !gpu->dawn_control_client_->IsContextLost()) { + gpu->RequestAdapterImpl(script_state, options, resolver); + } else { + // Failed to create context provider, won't be able to request + // adapter + // TODO(crbug.com/973017): Collect GPU info and surface context + // creation error. + resolver->Resolve(v8::Null(script_state->GetIsolate())); + } + }, + WrapPersistent(this), WrapPersistent(script_state), + WrapPersistent(options), WrapPersistent(resolver))); + + // Returning since the task to create the control client from a previous + // call to EnsureDawnControlClientInitialized should be already running + if (dawn_control_client_initialized_callbacks_.size() > 1) { + return; + } + // TODO(natlee@microsoft.com): if GPU process is lost, wait for the GPU // process to come back instead of rejecting right away - std::unique_ptr<WebGraphicsContext3DProvider> context_provider = - CreateContextProvider(*execution_context); - if (!context_provider) { - // Failed to create context provider, won't be able to request adapter - // TODO(crbug.com/973017): Collect GPU info and surface context creation - // error. - resolver->Resolve(v8::Null(script_state->GetIsolate())); - return promise; - } else { - context_provider->WebGPUInterface()->SetWebGPUExecutionContextToken( - GetExecutionContextToken(execution_context)); + EnsureDawnControlClientInitialized( + execution_context, + WTF::BindOnce( + [](GPU* gpu, ExecutionContext* execution_context, + std::unique_ptr<WebGraphicsContext3DProvider> context_provider) { + const KURL& url = execution_context->Url(); + context_provider = + CheckContextProvider(url, std::move(context_provider)); + if (context_provider) { + context_provider->WebGPUInterface() + ->SetWebGPUExecutionContextToken( + GetExecutionContextToken(execution_context)); - // Make a new DawnControlClientHolder with the context provider we just - // made and set the lost context callback - dawn_control_client_ = DawnControlClientHolder::Create( - std::move(context_provider), - execution_context->GetTaskRunner(TaskType::kWebGPU)); - } + // Make a new DawnControlClientHolder with the context provider + // we just made and set the lost context callback + gpu->dawn_control_client_ = DawnControlClientHolder::Create( + std::move(context_provider), + execution_context->GetTaskRunner(TaskType::kWebGPU)); + } + + WTF::Vector<base::OnceCallback<void()>> callbacks = + std::move(gpu->dawn_control_client_initialized_callbacks_); + for (auto& callback : callbacks) { + std::move(callback).Run(); + } + }, + WrapPersistent(this), WrapPersistent(execution_context))); + + return; } DCHECK_NE(dawn_control_client_, nullptr); @@ -332,7 +373,13 @@ *execution_context->GetAgent()->event_loop()); UseCounter::Count(execution_context, WebFeature::kWebGPU); +} +ScriptPromise GPU::requestAdapter(ScriptState* script_state, + const GPURequestAdapterOptions* options) { + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + ScriptPromise promise = resolver->Promise(); + RequestAdapterImpl(script_state, options, resolver); return promise; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.h b/third_party/blink/renderer/modules/webgpu/gpu.h index 827d8dc..c699aa0 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.h +++ b/third_party/blink/renderer/modules/webgpu/gpu.h
@@ -8,6 +8,7 @@ #include <dawn/webgpu.h> #include "base/memory/scoped_refptr.h" +#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -105,7 +106,21 @@ const GPURequestAdapterOptions* options, GPUAdapter* adapter) const; + void OnContextProviderCreated( + const KURL& url, + ScriptState* script_state, + const GPURequestAdapterOptions* options, + ScriptPromiseResolver* resolver, + ExecutionContext* execution_context, + std::unique_ptr<WebGraphicsContext3DProvider> context_provider); + + void RequestAdapterImpl(ScriptState* script_state, + const GPURequestAdapterOptions* options, + ScriptPromiseResolver* resolver); + scoped_refptr<DawnControlClientHolder> dawn_control_client_; + WTF::Vector<base::OnceCallback<void()>> + dawn_control_client_initialized_callbacks_; HeapHashSet<WeakMember<GPUBuffer>> mappable_buffers_; // Mappable buffers remove themselves from this set on destruction. // It is boxed in a scoped_refptr so GPUBuffer can access it in its
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc index 32df292..69a153a9 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -7,6 +7,7 @@ #include <hb.h> #include "base/logging.h" +#include "base/ranges/algorithm.h" #include "third_party/blink/renderer/platform/fonts/font.h" #include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" @@ -411,9 +412,8 @@ void Finish(unsigned from, unsigned to) { std::sort(cluster_starts_.begin(), cluster_starts_.end()); - DCHECK_EQ( - std::adjacent_find(cluster_starts_.begin(), cluster_starts_.end()), - cluster_starts_.end()); + DCHECK_EQ(base::ranges::adjacent_find(cluster_starts_), + cluster_starts_.end()); DVLOG(4) << " Cluster starts: " << base::make_span(cluster_starts_); if (!cluster_starts_.empty()) { // 'from' may point inside a cluster; the least seen index may be larger.
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc index 5ebd1f1..b6da23bd 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -347,7 +347,7 @@ continue; auto& feedback = timing_details.find(frame_token)->value.presentation_feedback; -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_LINUX) // TODO: On Linux failure flag is unreliable, and perfectly rendered frames // are reported as failures all the time. bool presentation_failure = false;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index de5e6e97..ee01a0c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -4025,10 +4025,6 @@ crbug.com/618969 external/wpt/css/css-grid/subgrid/grid-template-computed-nogrid.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/independent-formatting-context.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/item-percentage-height-001.html [ Failure ] -crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-001.html [ Failure ] -crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-002.html [ Failure ] -crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-003.html [ Failure ] -crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-004.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-005.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-006.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/line-names-007.html [ Failure ] @@ -4037,6 +4033,8 @@ crbug.com/618969 external/wpt/css/css-grid/subgrid/orthogonal-writing-mode-002.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/orthogonal-writing-mode-003.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/orthogonal-writing-mode-004.html [ Failure ] +crbug.com/618969 external/wpt/css/css-grid/subgrid/parent-repeat-auto-fit-001.html [ Failure ] +crbug.com/618969 external/wpt/css/css-grid/subgrid/parent-repeat-auto-fit-002.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/repeat-auto-fill-001.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/repeat-auto-fill-002.html [ Failure ] crbug.com/618969 external/wpt/css/css-grid/subgrid/repeat-auto-fill-003.html [ Failure ] @@ -6665,6 +6663,7 @@ crbug.com/1304956 storage/indexeddb/dont-wedge.html [ Failure Pass ] # Sheriff 2022-03-15 +crbug.com/626703 external/wpt/scroll-to-text-fragment/force-load-at-top.html [ Pass Timeout ] crbug.com/1269534 fast/spatial-navigation/snav-zero-margin-content.html [ Failure Pass ] crbug.com/1295980 virtual/fenced-frame-mparch/wpt_internal/fenced_frame/user-activation.https.html [ Failure Pass Timeout ] crbug.com/1295980 virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/user-activation.https.html [ Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index f120845..267642c 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -698,12 +698,6 @@ "args": ["--disable-features=PrefersReducedMotionClientHintHeader"] }, { - "prefix": "disable-wildcard-subdomains-in-permissions-policy", - "platforms": ["Linux", "Mac", "Win"], - "bases": ["external/wpt/permissions-policy/"], - "args": ["--disable-features=WildcardSubdomainsInPermissionsPolicy"] - }, - { "prefix": "storage-access-api", "platforms": ["Linux", "Mac", "Win"], "bases": [ "external/wpt/storage-access-api" ],
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html new file mode 100644 index 0000000..22727e39 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_all_cookies method w/ default SameSite</title> +<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> +<script> +promise_test(async t => { + document.cookie = "test0=0"; + const cookies = await test_driver.get_all_cookies(); + assert_equals(cookies.length, 1); + let cookieMap = new Map(); + for (const cookie of cookies) { + cookieMap.set(cookie["name"], cookie); + } + assert_equals(cookieMap.get("test0")["name"], "test0"); + assert_equals(cookieMap.get("test0")["value"], "0"); + assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); +}, "Get all cookies w/ default SameSite"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html new file mode 100644 index 0000000..405473c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_named_cookie method w/ default SameSite</title> +<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> +<script> +promise_test(async t => { + document.cookie = "test0=0"; + const cookie = await test_driver.get_named_cookie("test0"); + assert_equals(cookie["name"], "test0"); + assert_equals(cookie["value"], "0"); + assert_equals(cookie["sameSite"], "Lax"); +}, "Get Named cookie w/ default SameSite"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009-ref.html new file mode 100644 index 0000000..103a359 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009-ref.html
@@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: subgrid line names are not inherited to a non-subgridded axis</title> + <link rel="author" title="Kurt Catti-Schmidt" href="mailto:kschmi@microsoft.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2"> + <style> + html,body { + color:black; background-color:white; font:12px/1 monospace; padding:0; margin:0; + } + + div > div { background: grey; grid-column:2 / span 2; } + + i { + grid-row: 1; + counter-increment: i; + } + i::before { content: counter(i, decimal); } + + x { background: silver; } + </style> +</head> +<body> + +<div style="display:grid;"> + <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][d][e]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:1 / 4;"> + <x style="grid-column:c">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][d][e]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c / 4;"> + <x style="grid-column:span 1">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c 2 / 4;"> + <x style="grid-column:4">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c 2 / 4;"> + <x style="grid-column:span 1">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c-1 / c 3;"> + <x style="grid-column:span 1">x</x> + </div> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009.html new file mode 100644 index 0000000..bd8a776 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/line-names-009.html
@@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: subgrid line names are not inherited to a non-subgridded axis</title> + <link rel="author" title="Kurt Catti-Schmidt" href="mailto:kschmi@microsoft.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2"> + <link rel="match" href="line-names-009-ref.html"> + <style> + html,body { + color:black; background-color:white; font:12px/1 monospace; padding:0; margin:0; + } + + div > div { background: grey; grid-column:2 / span 2; } + + i { + grid-row: 1; + counter-increment: i; + } + i::before { content: counter(i, decimal); } + + x { background: silver; } + </style> +</head> +<body> + +<div style="display:grid;"> + <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][d][e]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:1 / 4;"> + <x style="grid-column:c">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][d][e]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c / 4;"> + <x style="grid-column:span c">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c 2 / 4;"> + <x style="grid-column:c 2">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c 2 / 4;"> + <x style="grid-column:span c 2">x</x> + </div> + </div> +</div> + +<div style="display:grid;"> +<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i> + <div style="display:grid; grid:auto/subgrid [a][b][c][c][c]; grid-column:2 / 9;"> + <div style="display:grid; grid:subgrid/auto; grid-column:c-1 / c 3;"> + <x style="grid-column:span c">x</x> + </div> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/duration-with-target-low.html b/third_party/blink/web_tests/external/wpt/event-timing/duration-with-target-low.html new file mode 100644 index 0000000..11a8c3a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/event-timing/duration-with-target-low.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<meta charset=utf-8 /> +<title>Event Timing: PerformanceObserver with a durationThreshold way smaller than processingDelay</title> +<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> +<script src=resources/event-timing-test-utils.js></script> +<div id='myDiv'>Click me</div> +<script> +promise_test(async t => { + return testDurationWithDurationThreshold(t, 'myDiv', numEntries=5, durThreshold=300, processingDelay=0); +}, "PerformanceObserver with durationThreshold of 300 and processingDelay of 0 doesn't see any entries in the observer"); +</script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/large-duration-threshold.html b/third_party/blink/web_tests/external/wpt/event-timing/large-duration-threshold.html index 5665d42..4eed8d97 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/large-duration-threshold.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/large-duration-threshold.html
@@ -10,7 +10,7 @@ <div id='myDiv'>Click me</div> <script> promise_test(async t => { - return testDuration(t, 'myDiv', numEntries=2, dur=125, fastDur=70, slowDur=140); + return testDuration(t, 'myDiv', numEntries=2, dur=125, slowDur=140); }, "PerformanceObserver observes events according to its durationThreshold"); </script> </html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/medium-duration-threshold.html b/third_party/blink/web_tests/external/wpt/event-timing/medium-duration-threshold.html index a827f22..a2f79cf6 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/medium-duration-threshold.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/medium-duration-threshold.html
@@ -10,7 +10,7 @@ <div id='myDiv'>Click me</div> <script> promise_test(async t => { - return testDuration(t, 'myDiv', numEntries=3, dur=50, fastDur=20, slowDur=70); + return testDuration(t, 'myDiv', numEntries=3, dur=50, slowDur=70); }, "PerformanceObserver observes events according to its durationThreshold"); </script> </html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/min-duration-threshold.html b/third_party/blink/web_tests/external/wpt/event-timing/min-duration-threshold.html index 443b38a2..b7382f9 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/min-duration-threshold.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/min-duration-threshold.html
@@ -10,7 +10,7 @@ <div id='myDiv'>Click me</div> <script> promise_test(async t => { - return testDuration(t, 'myDiv', numEntries=5, dur=0, fastDur=0, slowDur=20); + return testDuration(t, 'myDiv', numEntries=5, dur=0, slowDur=20); }, "PerformanceObserver with durationThreshold of 0 sees events of duration >= 16"); </script> </html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js b/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js index ab3f110c..fc4d1ae 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js +++ b/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js
@@ -5,10 +5,12 @@ const element = document.getElementById(id); const clickHandler = () => { mainThreadBusy(delay); - if (callback) + if (callback) { callback(); + } element.removeEventListener("pointerdown", clickHandler); }; + element.addEventListener("pointerdown", clickHandler); await test_driver.click(element); } @@ -81,17 +83,15 @@ // attempt to check that the duration is appropriately checked by: // * Asserting that entries received have a duration which is the smallest multiple of 8 // that is greater than or equal to |dur|. - // * Issuing |numEntries| entries that are fast, of duration |slowDur|. - // * Issuing |numEntries| entries that are slow, of duration |fastDur|. - // * Asserting that at least |numEntries| entries are received (at least the slow ones). + // * Issuing |numEntries| entries that has duration greater than |slowDur|. + // * Asserting that exactly |numEntries| entries are received. // Parameters: // |t| - the test harness. // |dur| - the durationThreshold for the PerformanceObserver. // |id| - the ID of the element to be clicked. - // |numEntries| - the number of slow and number of fast entries. + // |numEntries| - the number of entries. // |slowDur| - the min duration of a slow entry. - // |fastDur| - the min duration of a fast entry. -async function testDuration(t, id, numEntries, dur, fastDur, slowDur) { +async function testDuration(t, id, numEntries, dur, slowDur) { assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.'); const observerPromise = new Promise(async resolve => { let minDuration = Math.ceil(dur / 8) * 8; @@ -106,29 +106,62 @@ }); }); numEntriesReceived += pointerDowns.length; - // Note that we may receive more entries if the 'fast' click events turn out slower - // than expected. - if (numEntriesReceived >= numEntries) + // All the entries should be received since the slowDur is higher + // than the duration threshold. + if (numEntriesReceived === numEntries) resolve(); }).observe({type: "event", durationThreshold: dur}); }); const clicksPromise = new Promise(async resolve => { for (let index = 0; index < numEntries; index++) { - // Add some fast click events. + // Add some click events that has at least slowDur for duration. await clickOnElementAndDelay(id, slowDur); - // Add some slow click events. - if (fastDur > 0) { - await clickOnElementAndDelay(id, fastDur); - } else { - // We can just directly call test_driver when |fastDur| is 0. - await test_driver.click(document.getElementById(id)); - } } resolve(); }); return Promise.all([observerPromise, clicksPromise]); } + // Add a PerformanceObserver and observe with a durationThreshold of |durThreshold|. This test will + // attempt to check that the duration is appropriately checked by: + // * Asserting that entries received have a duration which is the smallest multiple of 8 + // that is greater than or equal to |durThreshold|. + // * Issuing |numEntries| entries that have at least |processingDelay| as duration. + // * Asserting that the entries we receive has duration greater than or equals to the + // duration threshold we setup + // Parameters: + // |t| - the test harness. + // |id| - the ID of the element to be clicked. + // |durThreshold| - the durationThreshold for the PerformanceObserver. + // |numEntries| - the number of slow and number of fast entries. + // |processingDelay| - the event duration we add on each event. + async function testDurationWithDurationThreshold(t, id, numEntries, durThreshold, processingDelay) { + assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.'); + const observerPromise = new Promise(async resolve => { + let minDuration = Math.ceil(durThreshold / 8) * 8; + // Exposed events must always have a minimum duration of 16. + minDuration = Math.max(minDuration, 16); + new PerformanceObserver(t.step_func(list => { + const pointerDowns = list.getEntriesByName('pointerdown'); + pointerDowns.forEach(p => { + assert_greater_than_equal(p.duration, minDuration, + "The entry's duration should be greater than or equal to " + minDuration + " ms."); + }); + resolve(); + })).observe({type: "event", durationThreshold: durThreshold}); + }); + for (let index = 0; index < numEntries; index++) { + // These clicks are expected to be ignored, unless the test has some extra delays. + // In that case, the test will verify the event duration to ensure the event duration is + // greater than the duration threshold + await clickOnElementAndDelay(id, processingDelay); + } + // Send click with event duration equals to or greater than |durThreshold|, so the + // observer promise can be resolved + await clickOnElementAndDelay(id, durThreshold); + return observerPromise; + } + // Apply events that trigger an event of the given |eventType| to be dispatched to the // |target|. Some of these assume that the target is not on the top left corner of the // screen, which means that (0, 0) of the viewport is outside of the |target|.
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html index 8545d06..a145e52 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html
@@ -31,7 +31,8 @@ assert_equals(cookieMap.get("test0")["secure"], false); assert_equals(cookieMap.get("test0")["httpOnly"], false); assert_equals(cookieMap.get("test0")["expiry"], undefined); - assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test1 [Expires in 10 days] assert_equals(cookieMap.get("test1")["name"], "test1"); @@ -41,7 +42,8 @@ assert_equals(cookieMap.get("test1")["secure"], false); assert_equals(cookieMap.get("test1")["httpOnly"], false); assert_equals(cookieMap.get("test1")["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); - assert_equals(cookieMap.get("test1")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test2 [Path /] assert_equals(cookieMap.get("test2")["name"], "test2"); @@ -51,7 +53,8 @@ assert_equals(cookieMap.get("test2")["secure"], false); assert_equals(cookieMap.get("test2")["httpOnly"], false); assert_equals(cookieMap.get("test2")["expiry"], undefined); - assert_equals(cookieMap.get("test2")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test3 [HttpOnly] assert_equals(cookieMap.get("test3")["name"], "test3"); @@ -61,7 +64,8 @@ assert_equals(cookieMap.get("test3")["secure"], false); assert_equals(cookieMap.get("test3")["httpOnly"], true); assert_equals(cookieMap.get("test3")["expiry"], undefined); - assert_equals(cookieMap.get("test3")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test4 [Secure] Omitted
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html index 08ab8cc3..e3402780 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html
@@ -31,7 +31,8 @@ assert_equals(cookieMap.get("test0")["secure"], false); assert_equals(cookieMap.get("test0")["httpOnly"], false); assert_equals(cookieMap.get("test0")["expiry"], undefined); - assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test1 [Expires in 10 days] assert_equals(cookieMap.get("test1")["name"], "test1"); @@ -41,7 +42,8 @@ assert_equals(cookieMap.get("test1")["secure"], false); assert_equals(cookieMap.get("test1")["httpOnly"], false); assert_equals(cookieMap.get("test1")["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); - assert_equals(cookieMap.get("test1")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test2 [Path /] assert_equals(cookieMap.get("test2")["name"], "test2"); @@ -51,7 +53,8 @@ assert_equals(cookieMap.get("test2")["secure"], false); assert_equals(cookieMap.get("test2")["httpOnly"], false); assert_equals(cookieMap.get("test2")["expiry"], undefined); - assert_equals(cookieMap.get("test2")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test3 [HttpOnly] assert_equals(cookieMap.get("test3")["name"], "test3"); @@ -61,7 +64,8 @@ assert_equals(cookieMap.get("test3")["secure"], false); assert_equals(cookieMap.get("test3")["httpOnly"], true); assert_equals(cookieMap.get("test3")["expiry"], undefined); - assert_equals(cookieMap.get("test3")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test4 [Secure] assert_equals(cookieMap.get("test4")["name"], "test4"); @@ -71,7 +75,8 @@ assert_equals(cookieMap.get("test4")["secure"], true); assert_equals(cookieMap.get("test4")["httpOnly"], false); assert_equals(cookieMap.get("test4")["expiry"], undefined); - assert_equals(cookieMap.get("test4")["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); // test5 [SameSite Strict] assert_equals(cookieMap.get("test5")["name"], "test5");
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html index c3a8eed..3cbc784 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html
@@ -26,7 +26,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test1 [Expires in 10 days] cookie = await test_driver.get_named_cookie("test1"); @@ -37,7 +38,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test2 [Path /] cookie = await test_driver.get_named_cookie("test2"); @@ -48,7 +50,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test3 [HttpOnly] cookie = await test_driver.get_named_cookie("test3"); @@ -59,7 +62,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], true); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test4 [Secure] Omitted try {
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html index d316d4e..d0d8612a 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html
@@ -26,7 +26,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test1 [Expires in 10 days] cookie = await test_driver.get_named_cookie("test1"); @@ -37,7 +38,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test2 [Path /] cookie = await test_driver.get_named_cookie("test2"); @@ -48,7 +50,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test3 [HttpOnly] cookie = await test_driver.get_named_cookie("test3"); @@ -59,7 +62,8 @@ assert_equals(cookie["secure"], false); assert_equals(cookie["httpOnly"], true); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test4 [Secure] cookie = await test_driver.get_named_cookie("test4"); @@ -70,7 +74,8 @@ assert_equals(cookie["secure"], true); assert_equals(cookie["httpOnly"], false); assert_equals(cookie["expiry"], undefined); - assert_equals(cookie["sameSite"], "Lax"); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); // test5 [SameSite Strict] cookie = await test_driver.get_named_cookie("test5");
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt index c9ca12c2..19ec66a 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 499 tests; 483 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 499 tests; 484 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -41,7 +41,7 @@ PASS RTCPeerConnection interface: attribute canTrickleIceCandidates PASS RTCPeerConnection interface: operation restartIce() PASS RTCPeerConnection interface: operation getConfiguration() -FAIL RTCPeerConnection interface: operation setConfiguration(optional RTCConfiguration) assert_equals: property has wrong .length expected 0 but got 1 +PASS RTCPeerConnection interface: operation setConfiguration(optional RTCConfiguration) PASS RTCPeerConnection interface: operation close() PASS RTCPeerConnection interface: attribute onnegotiationneeded PASS RTCPeerConnection interface: attribute onicecandidate
diff --git a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/README.md b/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/README.md deleted file mode 100644 index 31860a83..0000000 --- a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/README.md +++ /dev/null
@@ -1 +0,0 @@ -Tests with WildcardSubdomainsInPermissionsPolicy enabled.
diff --git a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/README.txt b/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/README.txt deleted file mode 100644 index 31860a83..0000000 --- a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/README.txt +++ /dev/null
@@ -1 +0,0 @@ -Tests with WildcardSubdomainsInPermissionsPolicy enabled.
diff --git a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/permissions-policy-header-policy-allowed-for-wildcard.https.sub-expected.txt b/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/permissions-policy-header-policy-allowed-for-wildcard.https.sub-expected.txt deleted file mode 100644 index 23dbddc..0000000 --- a/third_party/blink/web_tests/virtual/disable-wildcard-subdomains-in-permissions-policy/external/wpt/permissions-policy/permissions-policy-header-policy-allowed-for-wildcard.https.sub-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -This is a testharness.js-based test. -FAIL Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test allowlist is [self wildcard_origin]. assert_array_equals: expected property 0 to be "https://*.web-platform.test:8444" but got "https://%2A.web-platform.test:8444" (expected array ["https://*.web-platform.test:8444", "https://web-platform.test:8444"] got ["https://%2A.web-platform.test:8444", "https://web-platform.test:8444"]) -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is allowed on same-origin subframe -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is allowed on same-origin subframe even with allow attribute -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is disallowed on cross-origin subframe -FAIL Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is allowed on cross-origin subframe allow attribute assert_true: fullscreen expected true got false -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is disallowed on another cross-origin subframe -FAIL Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is allowed on another cross-origin subframe allow attribute assert_true: fullscreen expected true got false -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is disallowed on cross-origin subframe with wildcard allow attribute -PASS Permissions-Policy: fullscreen=("https://*.web-platform.test:8444") -- test fullscreen is disallowed on another cross-origin subframe with wildcard allow attribute -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/document-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt b/third_party/blink/web_tests/virtual/document-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt index 95e3f8f..06613e3 100644 --- a/third_party/blink/web_tests/virtual/document-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt +++ b/third_party/blink/web_tests/virtual/document-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt
@@ -101,28 +101,56 @@ value : 0px } [2] : { - name : right - value : 0px - } - [3] : { - name : bottom - value : 0px - } - [4] : { name : left value : 0px } - [5] : { + [3] : { name : pointer-events value : none } ] shorthandEntries : [ + ] + } + supports : [ + ] + } + } + [1] : { + matchingSelectors : [ + [0] : 0 + ] + rule : { + containerQueries : [ + ] + layers : [ + ] + media : [ + ] + origin : user-agent + scopes : [ + ] + selectorList : { + selectors : [ [0] : { - name : inset - value : 0px + text : html::page-transition } ] + text : html::page-transition + } + style : { + cssProperties : [ + [0] : { + name : width + value : 800px + } + [1] : { + name : height + value : 600px + } + ] + shorthandEntries : [ + ] } supports : [ ] @@ -1672,28 +1700,56 @@ value : 0px } [2] : { - name : right - value : 0px - } - [3] : { - name : bottom - value : 0px - } - [4] : { name : left value : 0px } - [5] : { + [3] : { name : pointer-events value : none } ] shorthandEntries : [ + ] + } + supports : [ + ] + } + } + [1] : { + matchingSelectors : [ + [0] : 0 + ] + rule : { + containerQueries : [ + ] + layers : [ + ] + media : [ + ] + origin : user-agent + scopes : [ + ] + selectorList : { + selectors : [ [0] : { - name : inset - value : 0px + text : html::page-transition } ] + text : html::page-transition + } + style : { + cssProperties : [ + [0] : { + name : width + value : 800px + } + [1] : { + name : height + value : 600px + } + ] + shorthandEntries : [ + ] } supports : [ ]
diff --git a/third_party/blink/web_tests/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt b/third_party/blink/web_tests/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt index 95e3f8f..06613e3 100644 --- a/third_party/blink/web_tests/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt +++ b/third_party/blink/web_tests/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt
@@ -101,28 +101,56 @@ value : 0px } [2] : { - name : right - value : 0px - } - [3] : { - name : bottom - value : 0px - } - [4] : { name : left value : 0px } - [5] : { + [3] : { name : pointer-events value : none } ] shorthandEntries : [ + ] + } + supports : [ + ] + } + } + [1] : { + matchingSelectors : [ + [0] : 0 + ] + rule : { + containerQueries : [ + ] + layers : [ + ] + media : [ + ] + origin : user-agent + scopes : [ + ] + selectorList : { + selectors : [ [0] : { - name : inset - value : 0px + text : html::page-transition } ] + text : html::page-transition + } + style : { + cssProperties : [ + [0] : { + name : width + value : 800px + } + [1] : { + name : height + value : 600px + } + ] + shorthandEntries : [ + ] } supports : [ ] @@ -1672,28 +1700,56 @@ value : 0px } [2] : { - name : right - value : 0px - } - [3] : { - name : bottom - value : 0px - } - [4] : { name : left value : 0px } - [5] : { + [3] : { name : pointer-events value : none } ] shorthandEntries : [ + ] + } + supports : [ + ] + } + } + [1] : { + matchingSelectors : [ + [0] : 0 + ] + rule : { + containerQueries : [ + ] + layers : [ + ] + media : [ + ] + origin : user-agent + scopes : [ + ] + selectorList : { + selectors : [ [0] : { - name : inset - value : 0px + text : html::page-transition } ] + text : html::page-transition + } + style : { + cssProperties : [ + [0] : { + name : width + value : 800px + } + [1] : { + name : height + value : 600px + } + ] + shorthandEntries : [ + ] } supports : [ ]
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/content-with-clip-root.html b/third_party/blink/web_tests/wpt_internal/document-transition/content-with-clip-root.html index fa57a3b..1aa2d060 100644 --- a/third_party/blink/web_tests/wpt_internal/document-transition/content-with-clip-root.html +++ b/third_party/blink/web_tests/wpt_internal/document-transition/content-with-clip-root.html
@@ -41,7 +41,6 @@ } html::page-transition-container(root) { - position: fixed; top: -50vh; bottom: 50vh; }
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars-ref.html b/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars-ref.html new file mode 100644 index 0000000..b84efaa --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars-ref.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Shared transitions: incoming viewport has scrollbars (ref)</title> +<link rel="help" href="https://github.com/WICG/shared-element-transitions"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859"> +<link rel="author" href="mailto:bokan@chromium.org"> +<style> + html, body { + width: 100%; + height: 100%; + background-color: lightpink; + } + body { + margin: 50px; + } + div { + background-image: + linear-gradient(45deg, #000 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, #000 25%, lightgreen 25%); + background-size: 200px 200px; + background-position: 0 0, 0 0, -100px -100px, 100px 100px; + width: 200%; + height: 200%; + } +</style> +<div></div>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars.html b/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars.html new file mode 100644 index 0000000..eb112b2d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/document-transition/new-content-has-scrollbars.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta name="timeout" content="long"> +<html class=reftest-wait> +<title>Shared transitions: incoming viewport has scrollbars</title> +<link rel="help" href="https://github.com/WICG/shared-element-transitions"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859"> +<link rel="author" href="mailto:bokan@chromium.org"> +<link rel="match" href="new-content-has-scrollbars-ref.html"> +<meta name=fuzzy content="new-content-has-scrollbars-ref.html:0-40;0-30000"> +<script src="/common/reftest-wait.js"></script> +<style> + html, body { + width: 100%; + height: 100%; + background-color: lightpink; + } + html { + overflow: hidden; + } + body { + /* Margin to make sure background color is correctly drawn into the snapshot. */ + margin: 50px; + } + div { + /* Draw a checkerboard pattern to make sure the snapshot is captured at the + * full size, rather than scaled. */ + background-image: + linear-gradient(45deg, #000 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, #000 25%, lightgreen 25%); + background-size: 200px 200px; + background-position: 0 0, 0 0, -100px -100px, 100px 100px; + width: 200%; + height: 200%; + } + + /* We're verifying what we capture, so just display the old contents for 5 minutes. */ + html::page-transition-incoming-image(root) { animation: unset; opacity: 0; } + html::page-transition-outgoing-image(root) { + animation-duration: 3s; + animation-timing-function: steps(1, end); + opacity: 1; + } +</style> + +<div></div> +<script> +// Ensure a root snapshot captured in the absence of scrollbars is displayed at +// full size when rendered in the incoming viewport which is inset by +// scrollbars. The content must not be scaled-to-fit. +async function runTest() { + let t = document.createDocumentTransition(); + t.start(() => { + document.documentElement.style.overflow = "unset"; + requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)); + }); +} +onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest)); +</script> +
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars-ref.html b/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars-ref.html new file mode 100644 index 0000000..4c7d9760 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars-ref.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<title>Shared transitions: outgoing viewport has scrollbars (ref)</title> +<link rel="help" href="https://github.com/WICG/shared-element-transitions"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859"> +<link rel="author" href="mailto:bokan@chromium.org"> +<style> + html, body { + width: 100%; + height: 100%; + background-color: lightpink; + } + html { + overflow: hidden; + } + body { + margin: 50px; + } + div { + background-image: + linear-gradient(45deg, #000 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, #000 25%, lightgreen 25%); + background-size: 200px 200px; + background-position: 0 0, 0 0, -100px -100px, 100px 100px; + width: 200%; + height: 200%; + } +</style> +<div></div>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars.html b/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars.html new file mode 100644 index 0000000..b5314f8d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/document-transition/old-content-has-scrollbars.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta name="timeout" content="long"> +<html class=reftest-wait> +<title>Shared transitions: outgoing viewport has scrollbars</title> +<link rel="help" href="https://github.com/WICG/shared-element-transitions"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859"> +<link rel="author" href="mailto:bokan@chromium.org"> +<link rel="match" href="old-content-has-scrollbars-ref.html"> +<meta name=fuzzy content="old-content-has-scrollbars-ref.html:0-40;0-30000"> +<script src="/common/reftest-wait.js"></script> +<style> + html, body { + width: 100%; + height: 100%; + background-color: lightpink; + } + body { + /* Margin to make sure background color is correctly drawn into the snapshot. */ + margin: 50px; + } + div { + /* Draw a checkerboard pattern to make sure the snapshot is captured at the + * full size, rather than scaled. */ + background-image: + linear-gradient(45deg, #000 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, transparent 75%, #000 75%), + linear-gradient(45deg, #000 25%, lightgreen 25%); + background-size: 200px 200px; + background-position: 0 0, 0 0, -100px -100px, 100px 100px; + width: 200%; + height: 200%; + } + + /* We're verifying what we capture, so just display the old contents for 5 minutes. */ + html::page-transition-incoming-image(root) { animation: unset; opacity: 0; } + html::page-transition-outgoing-image(root) { + animation-duration: 300s; + animation-timing-function: steps(1, end); + opacity: 1; + } +</style> + +<div></div> +<script> +// Ensure a root snapshot captured on a page with scrollbars uses the full +// viewport size (including scrollbars). Areas obscured by scrollbars should be +// filled with background and content; the snapshot should not be scaled-to-fit. +async function runTest() { + let t = document.createDocumentTransition(); + t.start(() => { + document.querySelector('div').remove(); + document.documentElement.style.overflow = "hidden"; + requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)); + }); +} +onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest)); +</script> +
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js index 5237e93..c8731eb 100644 --- a/third_party/closure_compiler/externs/accessibility_private.js +++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -265,6 +265,7 @@ ENHANCED_NETWORK_VOICES: 'enhancedNetworkVoices', GOOGLE_TTS_LANGUAGE_PACKS: 'googleTtsLanguagePacks', DICTATION_PUMPKIN_PARSING: 'dictationPumpkinParsing', + DICTATION_MORE_COMMANDS: 'dictationMoreCommands', SELECT_TO_SPEAK_VOICE_SWITCHING: 'selectToSpeakVoiceSwitching', };
diff --git a/third_party/d3/OWNERS b/third_party/d3/OWNERS index 81967977..1bef084 100644 --- a/third_party/d3/OWNERS +++ b/third_party/d3/OWNERS
@@ -1,2 +1 @@ -chrisha@chromium.org zentaro@chromium.org
diff --git a/third_party/dom_distiller_js/BUILD.gn b/third_party/dom_distiller_js/BUILD.gn index 7096af7..81b46bc 100644 --- a/third_party/dom_distiller_js/BUILD.gn +++ b/third_party/dom_distiller_js/BUILD.gn
@@ -1,4 +1,4 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. +# Copyright 2014 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/LICENSE b/third_party/dom_distiller_js/LICENSE index 085efa7..3a8aeb9 100644 --- a/third_party/dom_distiller_js/LICENSE +++ b/third_party/dom_distiller_js/LICENSE
@@ -1,4 +1,4 @@ -Copyright 2014 The Chromium Authors. All rights reserved. +Copyright 2014 The Chromium Authors Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are
diff --git a/third_party/dom_distiller_js/protoc_plugins/json_values_converter.py b/third_party/dom_distiller_js/protoc_plugins/json_values_converter.py index a65f08f..6c044001 100755 --- a/third_party/dom_distiller_js/protoc_plugins/json_values_converter.py +++ b/third_party/dom_distiller_js/protoc_plugins/json_values_converter.py
@@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright 2016 The Chromium Authors. All rights reserved. +# Copyright 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/protoc_plugins/json_values_converter_tests.py b/third_party/dom_distiller_js/protoc_plugins/json_values_converter_tests.py index 0318983..54ae94fe 100755 --- a/third_party/dom_distiller_js/protoc_plugins/json_values_converter_tests.py +++ b/third_party/dom_distiller_js/protoc_plugins/json_values_converter_tests.py
@@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Chromium Authors. All rights reserved. +# Copyright (c) 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/protoc_plugins/util/plugin_protos.py b/third_party/dom_distiller_js/protoc_plugins/util/plugin_protos.py index 352591c..2c03e6835 100644 --- a/third_party/dom_distiller_js/protoc_plugins/util/plugin_protos.py +++ b/third_party/dom_distiller_js/protoc_plugins/util/plugin_protos.py
@@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. +# Copyright 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/protoc_plugins/util/types.py b/third_party/dom_distiller_js/protoc_plugins/util/types.py index b82b8500..f33e01b 100644 --- a/third_party/dom_distiller_js/protoc_plugins/util/types.py +++ b/third_party/dom_distiller_js/protoc_plugins/util/types.py
@@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. +# Copyright 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/protoc_plugins/util/writer.py b/third_party/dom_distiller_js/protoc_plugins/util/writer.py index a56e9cb..9ee673a 100644 --- a/third_party/dom_distiller_js/protoc_plugins/util/writer.py +++ b/third_party/dom_distiller_js/protoc_plugins/util/writer.py
@@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. +# Copyright 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/test_sample.proto b/third_party/dom_distiller_js/test_sample.proto index bceb5c7..30167fe 100644 --- a/third_party/dom_distiller_js/test_sample.proto +++ b/third_party/dom_distiller_js/test_sample.proto
@@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2016 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
diff --git a/third_party/dom_distiller_js/update_domdistiller_js.sh b/third_party/dom_distiller_js/update_domdistiller_js.sh index 4cd40433..50417d1 100755 --- a/third_party/dom_distiller_js/update_domdistiller_js.sh +++ b/third_party/dom_distiller_js/update_domdistiller_js.sh
@@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright 2014 The Chromium Authors. All rights reserved. +# Copyright 2014 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. #
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn index 1fd7a2e..986d256 100644 --- a/third_party/grpc/BUILD.gn +++ b/third_party/grpc/BUILD.gn
@@ -54,6 +54,10 @@ "-Wno-shadow", "-Wno-unreachable-code-return", "-Wno-unreachable-code-break", + + # TODO(crbug.com/1372394): Remove after integrating + # https://github.com/grpc/grpc/pull/31306 + "-Wno-thread-safety-analysis", ] if (is_android) {
diff --git a/third_party/grpc/template/BUILD.chromium.gn.template b/third_party/grpc/template/BUILD.chromium.gn.template index 991c94c..b30a7db 100644 --- a/third_party/grpc/template/BUILD.chromium.gn.template +++ b/third_party/grpc/template/BUILD.chromium.gn.template
@@ -15,11 +15,12 @@ # TODO(169395837): Somehow gRPC symbols cannot be found on Android. # Keep using static linking for now. - # In windows and mac use static linking. + # In windows, mac and iOS use static linking. # Use static linking on Chrome OS as a workaround for the symbol lookup # error(crbug/1241330) due to a gRPC version mismatch between what Chrome # uses and what CrOS provides. - grpc_use_static_linking = is_android || is_win || is_chromeos || is_mac + grpc_use_static_linking = + is_android || is_win || is_chromeos || is_mac || is_ios } if (is_android) { @@ -58,6 +59,10 @@ "-Wno-shadow", "-Wno-unreachable-code-return", "-Wno-unreachable-code-break", + + # TODO(crbug.com/1372394): Remove after integrating + # https://github.com/grpc/grpc/pull/31306 + "-Wno-thread-safety-analysis", ] if (is_android) {
diff --git a/tools/android/test_health/README.md b/tools/android/test_health/README.md index b10e50d9..9267322 100644 --- a/tools/android/test_health/README.md +++ b/tools/android/test_health/README.md
@@ -11,7 +11,7 @@ The `get_test_health.py` script extracts Java test health from a Git repository. The script defaults to the Chromium repository containing this script itself. The test health data includes a listing of tests that are disabled (annotated as -`@DisabledTest`), conditionally-disabled (`@DisableIf`) or flaky (`@FlakyTest`). +`@DisabledTest`) or conditionally-disabled (`@DisableIf`). The script exports the data in newline-delimited JSON ([JSON Lines](http://jsonlines.org)) format so that it can be easily [ingested into BigQuery][bq-load-gcs-json]. @@ -43,8 +43,8 @@ ### Java Test Utilities The `java_test_utils` module contains utility functions to extract counts of -test cases annotated with `@DisabledTest`, `@DisableIf` and `@FlakyTest`, as -well as the Java package name, from the source code of Java test files. +test cases annotated with `@DisabledTest` and `@DisableIf`, as well as the +Java package name, from the source code of Java test files. ### Other Modules
diff --git a/tools/android/test_health/java_test_utils.py b/tools/android/test_health/java_test_utils.py index 1082bd7..a1cd9f138 100644 --- a/tools/android/test_health/java_test_utils.py +++ b/tools/android/test_health/java_test_utils.py
@@ -32,7 +32,6 @@ _DISABLED_TEST_ANNOTATION = 'DisabledTest' _DISABLE_IF_TEST_ANNOTATION = 'DisableIf' -_FLAKY_TEST_ANNOTATION = 'FlakyTest' _DISABLE_IF_TEST_PATTERN = re.compile(_DISABLE_IF_TEST_ANNOTATION + r'\.\w+') @@ -47,7 +46,7 @@ disable_if_tests_count: int """The number of test cases annotated with @DisableIf.""" flaky_tests_count: int - """The number of test cases annotated with @FlakyTest.""" + """The number of test cases annotated with the removed @FlakyTest, now always 0.""" def get_java_test_health(test_path: pathlib.Path) -> JavaTestHealth: @@ -108,7 +107,7 @@ java_package=_get_java_package_name(java_ast), disabled_tests_count=annotation_counter[_DISABLED_TEST_ANNOTATION], disable_if_tests_count=annotation_counter[_DISABLE_IF_TEST_ANNOTATION], - flaky_tests_count=annotation_counter[_FLAKY_TEST_ANNOTATION]) + flaky_tests_count=0) def _get_java_package_name(java_ast: CompilationUnit) -> Optional[str]: @@ -137,8 +136,6 @@ counter[_DISABLED_TEST_ANNOTATION] += 1 elif re.fullmatch(_DISABLE_IF_TEST_PATTERN, annotation.name): counter[_DISABLE_IF_TEST_ANNOTATION] += 1 - elif annotation.name == _FLAKY_TEST_ANNOTATION: - counter[_FLAKY_TEST_ANNOTATION] += 1 return counter
diff --git a/tools/android/test_health/java_test_utils_unittest.py b/tools/android/test_health/java_test_utils_unittest.py index b290b62..1cdce9e 100755 --- a/tools/android/test_health/java_test_utils_unittest.py +++ b/tools/android/test_health/java_test_utils_unittest.py
@@ -33,13 +33,11 @@ 'SampleDisabledTest.java') _DISABLE_IF_TEST_PATH = (_TEST_FILES_PATH / 'disabled_tests' / 'SampleDisableIfTest.java') -_FLAKY_TEST_PATH = _TEST_FILES_PATH / 'flaky_tests' / 'SampleFlakyTest.java' _BASE_JAVA_PACKAGE = 'org.chromium.chrome.browser.test_health' _JAVA_PACKAGE_HEALTHY_TESTS = _BASE_JAVA_PACKAGE + '.healthy_tests' _JAVA_PACKAGE_UNHEALTHY_TESTS = _BASE_JAVA_PACKAGE + '.unhealthy_tests' _JAVA_PACKAGE_DISABLED_TESTS = _BASE_JAVA_PACKAGE + '.disabled_tests' -_JAVA_PACKAGE_FLAKY_TESTS = _BASE_JAVA_PACKAGE + '.flaky_tests' class TestJavaTestHealthStats(unittest.TestCase): @@ -70,7 +68,7 @@ test_health.java_package) self.assertEqual(1, test_health.disabled_tests_count) self.assertEqual(1, test_health.disable_if_tests_count) - self.assertEqual(1, test_health.flaky_tests_count) + self.assertEqual(0, test_health.flaky_tests_count) def test_get_java_test_health_stats_disabled_tests(self): test_health = java_test_utils.get_java_test_health(_DISABLED_TEST_PATH) @@ -91,14 +89,6 @@ self.assertEqual(2, test_health.disable_if_tests_count) self.assertEqual(0, test_health.flaky_tests_count) - def test_get_java_test_health_stats_flaky_tests(self): - test_health = java_test_utils.get_java_test_health(_FLAKY_TEST_PATH) - - self.assertEqual(_JAVA_PACKAGE_FLAKY_TESTS, test_health.java_package) - self.assertEqual(0, test_health.disabled_tests_count) - self.assertEqual(0, test_health.disable_if_tests_count) - self.assertEqual(2, test_health.flaky_tests_count) - def test_get_java_test_health_invalid_test_syntax(self): expected_filename = str( _INVALID_SYNTAX_TEST_PATH.relative_to(_CHROMIUM_SRC_PATH))
diff --git a/tools/android/test_health/test_health_extractor.py b/tools/android/test_health/test_health_extractor.py index c1f5251..aac763e 100644 --- a/tools/android/test_health/test_health_extractor.py +++ b/tools/android/test_health/test_health_extractor.py
@@ -65,7 +65,7 @@ ) -> List[TestHealthInfo]: """Gets test health information and stats for a Git repository. - This function checks for Java tests annotated as disabled or flaky but could + This function checks for Java tests annotated as disabled but could be extended to check other metrics or languages in the future. Args:
diff --git a/tools/android/test_health/test_health_extractor_unittest.py b/tools/android/test_health/test_health_extractor_unittest.py index ab05ae3d2..5318ddb 100755 --- a/tools/android/test_health/test_health_extractor_unittest.py +++ b/tools/android/test_health/test_health_extractor_unittest.py
@@ -31,7 +31,7 @@ _UNHEALTHY_TESTS_PATH / 'InvalidSyntaxTest.java').relative_to(_TEST_FILES_PATH) -_IGNORED_DIRS = ('disabled_tests', 'flaky_tests', 'unhealthy_tests') +_IGNORED_DIRS = ('disabled_tests', 'unhealthy_tests') _BASE_JAVA_PACKAGE = 'org.chromium.chrome.browser.test_health' _JAVA_PACKAGE_HEALTHY_TESTS = _BASE_JAVA_PACKAGE + '.healthy_tests' @@ -74,12 +74,12 @@ java_package=_JAVA_PACKAGE_UNHEALTHY_TESTS, disabled_tests_count=1, disable_if_tests_count=1, - flaky_tests_count=1), + flaky_tests_count=0), git_repo_info=_CHROMIUM_REPO_INFO) test_health_infos = test_health_extractor.get_repo_test_health( test_dir=_TEST_FILES_PATH, - ignored_dirs=('disabled_tests', 'flaky_tests', 'healthy_tests'), + ignored_dirs=('disabled_tests', 'healthy_tests'), ignored_files={str(_INVALID_SYNTAX_TEST_PATH)}) self.assertEqual(expected_test_health_info, test_health_infos[0]) @@ -101,8 +101,7 @@ with self.assertLogs(level=logging.WARNING) as logging_cm: test_health_infos = test_health_extractor.get_repo_test_health( test_dir=_TEST_FILES_PATH, - ignored_dirs=('disabled_tests', 'flaky_tests', - 'healthy_tests'), + ignored_dirs=('disabled_tests', 'healthy_tests'), ignored_files={ str((_UNHEALTHY_TESTS_PATH / 'SampleTest.java').relative_to(_TEST_FILES_PATH))
diff --git a/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/flaky_tests/SampleFlakyTest.java b/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/flaky_tests/SampleFlakyTest.java deleted file mode 100644 index 327844b..0000000 --- a/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/flaky_tests/SampleFlakyTest.java +++ /dev/null
@@ -1,41 +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. - -package org.chromium.chrome.browser.test_health.flaky_tests; - -import androidx.test.filters.SmallTest; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.test.BaseJUnit4ClassRunner; - -import java.util.Random; - -/** A sample Java test with flaky test cases. */ -@SmallTest -@RunWith(BaseJUnit4ClassRunner.class) -public class SampleFlakyTest { - @FlakyTest(message = "Flaky since value is sometimes false.") - @Test - public void testFalseIsTrue() { - Random random = new Random(); - - boolean value = random.nextBoolean(); - - Assert.assertTrue(value); - } - - @FlakyTest - @Test - public void testTrueIsFalse() { - // Flaky since value is sometimes true. - Random random = new Random(); - - boolean value = random.nextBoolean(); - - Assert.assertFalse(value); - } -}
diff --git a/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/unhealthy_tests/SampleTest.java b/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/unhealthy_tests/SampleTest.java index 3d60625..cc7f969 100644 --- a/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/unhealthy_tests/SampleTest.java +++ b/tools/android/test_health/testdata/javatests/org/chromium/chrome/browser/test_health/unhealthy_tests/SampleTest.java
@@ -13,9 +13,6 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.FlakyTest; - -import java.util.Random; /** A sample Java test. */ @SmallTest @@ -42,14 +39,4 @@ public void testDisableIfTest() { Assert.assertTrue(false); } - - @FlakyTest - @Test - public void testFlakyTest() { - Random random = new Random(); - - boolean value = random.nextBoolean(); - - Assert.assertFalse(value); - } }
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py index 4b44cd26..764d487 100755 --- a/tools/clang/scripts/build.py +++ b/tools/clang/scripts/build.py
@@ -1019,15 +1019,20 @@ # results on # https://chromium-review.googlesource.com/c/chromium/src/+/3702739/4 # Maybe it should work for builtins too? - ('armv7-unknown-linux-gnueabihf', - compiler_rt_cmake_flags(sanitizers=True, profile=True) + [ - 'CMAKE_SYSROOT=%s' % sysroot_arm, - ])) - runtimes_triples_args.append( - ('aarch64-unknown-linux-gnu', - compiler_rt_cmake_flags(sanitizers=True, profile=True) + [ - 'CMAKE_SYSROOT=%s' % sysroot_arm64, - ])) + ( + 'armv7-unknown-linux-gnueabihf', + compiler_rt_cmake_flags(sanitizers=True, profile=True) + [ + 'CMAKE_SYSROOT=%s' % sysroot_arm, + # Can't run tests on x86 host. + 'LLVM_INCLUDE_TESTS=OFF', + ])) + runtimes_triples_args.append(( + 'aarch64-unknown-linux-gnu', + compiler_rt_cmake_flags(sanitizers=True, profile=True) + [ + 'CMAKE_SYSROOT=%s' % sysroot_arm64, + # Can't run tests on x86 host. + 'LLVM_INCLUDE_TESTS=OFF', + ])) elif sys.platform == 'win32': runtimes_triples_args.append( ('i386-pc-windows-msvc',
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 01f27f9..8b0842c 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -474,6 +474,10 @@ "META": {"sizes": {"includes": [10]}}, "includes": [2665], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/lens/resources.grd": { + "META": {"sizes": {"includes": [10]}}, + "includes": [2675], + }, # END chrome/ WebUI resources section # START chrome/ miscellaneous section.
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 12903c68..d093ce1 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -3619,6 +3619,9 @@ </action> <action name="AppList_ShowPlayStoreQueryResults"> + <obsolete> + Deprecated in M108. App List search no longer shows tile results. + </obsolete> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <description> @@ -3660,6 +3663,7 @@ </action> <action name="AppList_ZeroStateOpenInstalledApp"> + <obsolete>Deprecated in M108. Launcher zero state has been removed.</obsolete> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <description>User opens a suggested installed app in zero state.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index ebc6183e..f8f36a345 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -21688,6 +21688,7 @@ <int value="24" label="SMART_SELECT_BTWN_INCL"/> <int value="25" label="NAV_NEXT_SENT"/> <int value="26" label="NAV_PREV_SENT"/> + <int value="27" label="DELETE_ALL_TEXT"/> </enum> <enum name="CrosDictationToggleDictationMethod"> @@ -56726,6 +56727,7 @@ <int value="-2112547309" label="ClickToCallReceiver:enabled"/> <int value="-2111273398" label="SendTabToSelfManageDevicesLink:enabled"/> <int value="-2111196530" label="EnableAssistantLauncherUI:disabled"/> + <int value="-2108866112" label="FeedHeaderStickToTop:enabled"/> <int value="-2108564200" label="AutofillUpstream:disabled"/> <int value="-2106960993" label="HarfBuzzPDFSubsetter:disabled"/> <int value="-2106763275" label="ArcRtVcpuQuadCore:enabled"/> @@ -56820,6 +56822,7 @@ <int value="-2054612904" label="BuiltInModuleInfra:enabled"/> <int value="-2053860791" label="XGEOVisibleNetworks:enabled"/> <int value="-2053062676" label="EnableNeuralPalmAdaptiveHold:enabled"/> + <int value="-2050829390" label="LensRegionSearchStaticPage:enabled"/> <int value="-2050039250" label="JourneysOnDeviceClusteringContentClustering:enabled"/> <int value="-2048927838" label="AutoplayWhitelistSettings:enabled"/> @@ -56943,6 +56946,7 @@ <int value="-1991935790" label="ShareCrowLaunchTab:enabled"/> <int value="-1990678808" label="SafetyCheckUnusedSitePermissions:disabled"/> <int value="-1990614981" label="StoragePressureUI:disabled"/> + <int value="-1990583427" label="FeedHeaderStickToTop:disabled"/> <int value="-1990238241" label="ChromeOSHWVBREncoding:enabled"/> <int value="-1989747818" label="TabStripKeyboardFocus:disabled"/> <int value="-1989624484" label="StartSurfaceRefactor:disabled"/> @@ -61223,6 +61227,7 @@ <int value="564355877" label="OopRasterizationDDL:disabled"/> <int value="564452531" label="SystemEmojiPickerExtension:enabled"/> <int value="564522013" label="Av1Decoder:disabled"/> + <int value="565254510" label="LensRegionSearchStaticPage:disabled"/> <int value="565406673" label="EnableVirtualKeyboardMdUi:enabled"/> <int value="567368307" label="enable-experimental-canvas-features"/> <int value="570469494" label="LoginDetection:disabled"/> @@ -95575,6 +95580,7 @@ <int value="52" label="Printers Authorization Servers"/> <int value="53" label="Contact info"/> <int value="54" label="Autofill Wallet Usage"/> + <int value="55" label="Segmentation"/> </enum> <enum name="SyncModelTypeStoreInitResult"> @@ -103357,6 +103363,27 @@ <int value="3" label="Transferred WebContents"/> </enum> +<enum name="WebFeedChangeReason"> + <int value="0" label="Unspecified">Unknown change reason</int> + <int value="1" label="Web page menu"> + The user tapped the Follow/Unfollow option from the three dot menu while on + a web page. + </int> + <int value="2" label="Web page accelerator"> + The user tapped the Follow accelerator while visiting a site. + </int> + <int value="3" label="Management page"> + The user tapped to Follow/Unfollow on the Follow Management page. + </int> + <int value="4" label="In feed recommendation"> + The user tapped to Follow/Unfollow a recommendation embedded in feed + content. + </int> + <int value="5" label="Back of card unfollow"> + The user tapped 'Unfollow' on the back of card menu. + </int> +</enum> + <enum name="WebFeedPageInformationRequestReason"> <int value="0" label="User Requested Follow"> The user requested to Follow the current web page.
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index beb5ac0..95f1efc3 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -1499,6 +1499,9 @@ <histogram name="Apps.AppListPlayStoreAppLaunchedIndex" units="indices" expires_after="2021-12-31"> + <obsolete> + Deprecated in M108. Tiled app results are no longer shown. + </obsolete> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -1515,10 +1518,14 @@ <histogram name="Apps.AppListPlayStoreSearchAppsDisplayed" units="apss" expires_after="2021-12-31"> + <obsolete> + Deprecated in M108. Tiled app results are no longer shown. + </obsolete> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> - The number of the play store apps displayed to user for a query. + Deprecated in Oct 2022. The number of the play store apps displayed to user + as tile items for a query. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index 1a0ba11..eb68c155 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1658,6 +1658,9 @@ <histogram name="Arc.PlayStoreSearch.DefaultResultClickLatency" units="ms" expires_after="2021-12-31"> + <obsolete> + Deprecated in M108. Tiled app results are no longer shown. + </obsolete> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml index 427bda19..596259c 100644 --- a/tools/metrics/histograms/metadata/content/histograms.xml +++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -1473,6 +1473,19 @@ </token> </histogram> +<histogram name="ContentSuggestions.Feed.WebFeed.NewFollow.ChangeReason" + enum="WebFeedChangeReason" expires_after="2023-04-01"> + <owner>harringtond@chromium.org</owner> + <owner>feed@chromium.org</owner> + <summary> + Change reason for the follow. + + Reported upon successfully following a web feed. Reported as 'true' if the + web feed was recommended, even if the user did not see or interact with + recommendation UI. + </summary> +</histogram> + <histogram name="ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended" enum="Boolean" expires_after="2023-03-01"> <owner>harringtond@chromium.org</owner> @@ -1480,9 +1493,7 @@ <summary> Whether the followed web feed was recommended by the server. - Reported upon successfully following a web feed. Reported as 'true' if the - web feed was recommended, even if the user did not see or interact with - recommendation UI. + Reported upon successfully following a web feed. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index 073c8c66..dea969ba 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -54,6 +54,7 @@ <variant name=".READING_LIST" summary="READING_LIST"/> <variant name=".SEARCH_ENGINE" summary="SEARCH_ENGINE"/> <variant name=".SECURITY_EVENT" summary="SECURITY_EVENT"/> + <variant name=".SEGMENTATION" summary="SEGMENTATION"/> <variant name=".SEND_TAB_TO_SELF" summary="SEND_TAB_TO_SELF"/> <variant name=".SESSION" summary="SESSION"/> <variant name=".SHARING_MESSAGE" summary="SHARING_MESSAGE"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 7c97b6eb..2950587 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -16542,6 +16542,11 @@ PageTimelineState UKM events. One PageTimelineState is recorded for each browser tab when a slice is collected. </summary> + <metric name="BatterySaverMode" enum="Boolean"> + <summary> + True if Batter Saver Mode is enabled at the time this event is recorded. + </summary> + </metric> <metric name="ChangedFaviconOrTitleInBackground" enum="Boolean"> <summary> True if this page has been observed to change its favicon or title when in @@ -16553,6 +16558,43 @@ The state the tab was in when the slice was recorded. </summary> </metric> + <metric name="HasNotificationPermission" enum="Boolean"> + <summary> + True if this page has been granted the notification permission. + </summary> + </metric> + <metric name="HighEfficiencyMode" enum="Boolean"> + <summary> + True if High Efficiency Mode is enabled at the time this event is + recorded. + </summary> + </metric> + <metric name="IsActiveTab" enum="Boolean"> + <summary> + True if this page is the active tab in its tab strip. + </summary> + </metric> + <metric name="IsCapturingMedia" enum="Boolean"> + <summary> + True if this page is capturing media (audio/video/screen). + </summary> + </metric> + <metric name="IsConnectedToDevice" enum="Boolean"> + <summary> + True if this page is connected to a BT or USB device. + </summary> + </metric> + <metric name="IsPlayingAudio" enum="Boolean"> + <summary> + True if this page is playing audio. + </summary> + </metric> + <metric name="ResidentSetSize"> + <summary> + The total resident set size footprint of this page at the moment the + sample was recorded, in bytes. + </summary> + </metric> <metric name="SliceId"> <summary> A strictly increasing ID used to order slices in relation to each other.
diff --git a/tools/perf/benchmarks/loading_metrics_category.py b/tools/perf/benchmarks/loading_metrics_category.py index b507ecf..25d9db7e 100644 --- a/tools/perf/benchmarks/loading_metrics_category.py +++ b/tools/perf/benchmarks/loading_metrics_category.py
@@ -26,5 +26,6 @@ # properly compute time-to-interactive. cat_filter.AddDisabledByDefault('disabled-by-default-network') - tbm_options.AddTimelineBasedMetric('loadingMetric') + tbm_options.ExtendTimelineBasedMetric( + ['loadingMetric', 'coreWebVitalsMetric']) return tbm_options
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 3ef368e..dc3fa53 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,15 +6,15 @@ }, "win": { "hash": "cd36010f4aaa8261c0ead7927e3b5b0c51b23680", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/08c1f851b8a083fbf2e052f42f190db9b8915e0b/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7bd83a8f9af8604e932cd717fdd56e586c54d3a4/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "3c5d52cc52064a87d37f0e22efbb8d0ea38856ff", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/fabd415c7415ae91f871fc08683cd3bdcc47830e/trace_processor_shell" + "hash": "b3d9c24d59f3e90d4cc0351d61bd90f45f8ac025", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/7bd83a8f9af8604e932cd717fdd56e586c54d3a4/trace_processor_shell" }, "mac_arm64": { "hash": "92318bea34f5c9beec69d2d826a9a92ec9d3cdcd", @@ -22,7 +22,7 @@ }, "linux": { "hash": "9ec936285839034b556c7e91136aeda7c8a59150", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/08c1f851b8a083fbf2e052f42f190db9b8915e0b/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7bd83a8f9af8604e932cd717fdd56e586c54d3a4/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/compositor/total_animation_throughput_reporter.cc b/ui/compositor/total_animation_throughput_reporter.cc index ffd295b..53f0608 100644 --- a/ui/compositor/total_animation_throughput_reporter.cc +++ b/ui/compositor/total_animation_throughput_reporter.cc
@@ -10,19 +10,6 @@ namespace ui { -TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker:: - ScopedThroughputReporterBlocker( - base::WeakPtr<TotalAnimationThroughputReporter> reporter) - : reporter_(std::move(reporter)) { - reporter_->scoped_blocker_count_++; -} - -TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker:: - ~ScopedThroughputReporterBlocker() { - if (reporter_) - reporter_->scoped_blocker_count_--; -} - TotalAnimationThroughputReporter::TotalAnimationThroughputReporter( ui::Compositor* compositor, ReportOnceCallback once_callback, @@ -58,9 +45,6 @@ void TotalAnimationThroughputReporter::OnFirstNonAnimatedFrameStarted( ui::Compositor* compositor) { - if (IsBlocked()) - return; - throughput_tracker_->Stop(); throughput_tracker_.reset(); // Stop observing if no need to report multiple times. @@ -80,19 +64,6 @@ delete this; } -base::WeakPtr<ui::TotalAnimationThroughputReporter> -TotalAnimationThroughputReporter::GetWeakPtr() { - return ptr_factory_.GetWeakPtr(); -} - -std::unique_ptr< - TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker> -TotalAnimationThroughputReporter::NewScopedBlocker() { - return std::make_unique< - ui::TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker>( - ptr_factory_.GetWeakPtr()); -} - TotalAnimationThroughputReporter::TotalAnimationThroughputReporter( ui::Compositor* compositor, ReportRepeatingCallback repeating_callback, @@ -123,8 +94,4 @@ report_repeating_callback_.Run(data); } -bool TotalAnimationThroughputReporter::IsBlocked() const { - return scoped_blocker_count_; -} - } // namespace ui
diff --git a/ui/compositor/total_animation_throughput_reporter.h b/ui/compositor/total_animation_throughput_reporter.h index 866676e..bddc5e4 100644 --- a/ui/compositor/total_animation_throughput_reporter.h +++ b/ui/compositor/total_animation_throughput_reporter.h
@@ -14,10 +14,6 @@ #include "ui/compositor/compositor_observer.h" #include "ui/compositor/throughput_tracker.h" -namespace ash { -class LoginUnlockThroughputRecorderTestBase; -} - namespace ui { // Reports cc::FrameSequenceMetrics::ThroughputData between the first animation @@ -36,31 +32,9 @@ // report callback is invoked on the next begin frame if there is enough data. // Since this observes multiple animations, aborting one of animations will // not cancel the tracking, and the data will be reported as normal. -// -// The reporter will not fire if ScopedThroughputReporterBlocker is active. -// This allows to measure throughput from the very first animation (when -// reporter was created) till the specific expected animation ends even if -// there were delays between the animations. class COMPOSITOR_EXPORT TotalAnimationThroughputReporter : public CompositorObserver { public: - // This allows to temporarily ignore OnFirstNonAnimatedFrameStarted event - // until an interesting event happens. - class COMPOSITOR_EXPORT ScopedThroughputReporterBlocker { - public: - explicit ScopedThroughputReporterBlocker( - base::WeakPtr<TotalAnimationThroughputReporter> reporter); - ScopedThroughputReporterBlocker(const ScopedThroughputReporterBlocker&) = - delete; - ~ScopedThroughputReporterBlocker(); - - ScopedThroughputReporterBlocker& operator=( - const ScopedThroughputReporterBlocker&) = delete; - - private: - base::WeakPtr<TotalAnimationThroughputReporter> reporter_; - }; - using ReportOnceCallback = base::OnceCallback<void( const cc::FrameSequenceMetrics::CustomReportData& data)>; using ReportRepeatingCallback = base::RepeatingCallback<void( @@ -90,18 +64,9 @@ void OnFirstNonAnimatedFrameStarted(Compositor* compositor) override; void OnCompositingShuttingDown(Compositor* compositor) override; - base::WeakPtr<ui::TotalAnimationThroughputReporter> GetWeakPtr(); - bool IsMeasuringForTesting() const { return bool{throughput_tracker_}; } - // The returned scope will delay the animation report until the next - // |OnFirstNonAnimatedFrameStarted| received after it is destructed. See - // |ScopedThroughputReporterBlocker| above. - std::unique_ptr<ScopedThroughputReporterBlocker> NewScopedBlocker(); - private: - friend class ash::LoginUnlockThroughputRecorderTestBase; - TotalAnimationThroughputReporter(Compositor* compositor, ReportRepeatingCallback repeating_callback, ReportOnceCallback once_callback, @@ -109,18 +74,12 @@ void Report(const cc::FrameSequenceMetrics::CustomReportData& data); - // Returns true if there is an active ScopedThroughputReporterBlocker. - bool IsBlocked() const; - raw_ptr<Compositor> compositor_; ReportRepeatingCallback report_repeating_callback_; ReportOnceCallback report_once_callback_; bool should_delete_ = false; absl::optional<ThroughputTracker> throughput_tracker_; - // Number of active ScopedThroughputReporterBlocker objects. - int scoped_blocker_count_ = 0; - base::WeakPtrFactory<TotalAnimationThroughputReporter> ptr_factory_{this}; };
diff --git a/ui/compositor/total_animation_throughput_reporter_unittest.cc b/ui/compositor/total_animation_throughput_reporter_unittest.cc index b4c02dc..7f8d369 100644 --- a/ui/compositor/total_animation_throughput_reporter_unittest.cc +++ b/ui/compositor/total_animation_throughput_reporter_unittest.cc
@@ -48,58 +48,6 @@ layer.SetOpacity(opacity); } -class TestCompositorMonitor : public ui::CompositorObserver { - public: - explicit TestCompositorMonitor(ui::Compositor* compositor) - : compositor_(compositor) { - compositor->AddObserver(this); - } - - ~TestCompositorMonitor() override { compositor_->RemoveObserver(this); } - - // ui::CompositorObserver - void OnFirstAnimationStarted(Compositor* compositor) override { - animatins_running_ = true; - } - - void OnFirstNonAnimatedFrameStarted(Compositor* compositor) override { - DCHECK_EQ(compositor_, compositor); - if (animatins_running_) { - waiting_for_did_present_compositor_frame_ = true; - } - animatins_running_ = false; - } - - void OnDidPresentCompositorFrame( - uint32_t frame_token, - const gfx::PresentationFeedback& feedback) override { - if (waiting_for_did_present_compositor_frame_) { - waiting_for_did_present_compositor_frame_ = false; - if (animatins_running_) - return; - - if (run_loop_) - run_loop_->Quit(); - } - } - - void WaitForAllAnimationsEnd() { - if (!animatins_running_ && !waiting_for_did_present_compositor_frame_) - return; - - run_loop_ = std::make_unique<base::RunLoop>( - base::RunLoop::Type::kNestableTasksAllowed); - run_loop_->Run(); - run_loop_.reset(); - } - - private: - const base::raw_ptr<ui::Compositor> compositor_; - bool animatins_running_ = false; - bool waiting_for_did_present_compositor_frame_ = false; - std::unique_ptr<base::RunLoop> run_loop_; -}; - } // namespace using TotalAnimationThroughputReporterTest = @@ -113,21 +61,7 @@ ThroughputReportChecker checker(this); TotalAnimationThroughputReporter reporter(compositor(), checker.repeating_callback()); - auto scoped_blocker = reporter.NewScopedBlocker(); SetLayerOpacity(layer, 1.0f, base::Milliseconds(48)); - Advance(base::Milliseconds(200)); - - // No report should happen while scoped_blocker exists. - EXPECT_FALSE(checker.reported()); - - scoped_blocker.reset(); - // No animation should be running yet, nothing to report. - EXPECT_FALSE(checker.reported()); - Advance(base::Milliseconds(200)); - EXPECT_FALSE(checker.reported()); - - // Animation of opacity goes to 0.5. - SetLayerOpacity(layer, 0.5f, base::Milliseconds(48)); Advance(base::Milliseconds(32)); EXPECT_FALSE(checker.reported()); EXPECT_TRUE(checker.WaitUntilReported()); @@ -192,6 +126,7 @@ ThroughputReportChecker checker(this); TotalAnimationThroughputReporter reporter(compositor(), checker.repeating_callback()); + SetLayerOpacity(layer, 1.0f, base::Milliseconds(48)); { LayerAnimator* animator = layer.GetAnimator(); @@ -354,7 +289,6 @@ // Make sure the once reporter is called only once. TEST_F(TotalAnimationThroughputReporterTest, OnceReporter) { - TestCompositorMonitor compositor_monitor(compositor()); Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -366,7 +300,6 @@ ThroughputReportChecker checker(this); TotalAnimationThroughputReporter reporter( compositor(), checker.once_callback(), /*should_delete=*/false); - auto scoped_blocker = reporter.NewScopedBlocker(); // Make sure the TotalAnimationThroughputReporter removes itself // from compositor as observer. @@ -374,22 +307,6 @@ // Report data for animation of opacity goes to 1. SetLayerOpacity(layer, 1.0f, base::Milliseconds(48)); - Advance(base::Milliseconds(100)); - - // No report should happen while scoped_blocker exists. - EXPECT_FALSE(checker.reported()); - - // Make sure there are no animations running. - compositor_monitor.WaitForAllAnimationsEnd(); - - scoped_blocker.reset(); - // No animation should be running yet, nothing to report. - EXPECT_FALSE(checker.reported()); - Advance(base::Milliseconds(100)); - EXPECT_FALSE(checker.reported()); - - // Animation of opacity goes to 0.5. - SetLayerOpacity(layer, 0.7f, base::Milliseconds(48)); EXPECT_TRUE(checker.WaitUntilReported()); // Report data for animation of opacity goes to 0.5. @@ -417,7 +334,6 @@ raw_ptr<bool> deleted_; }; - TestCompositorMonitor compositor_monitor(compositor()); Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -430,40 +346,21 @@ base::RunLoop run_loop; bool deleted = false; - TotalAnimationThroughputReporter* reporter = new DeleteTestReporter( + new DeleteTestReporter( compositor(), base::BindLambdaForTesting( [&](const cc::FrameSequenceMetrics::CustomReportData&) { run_loop.Quit(); }), &deleted); - auto scoped_blocker = reporter->NewScopedBlocker(); // Report data for animation of opacity goes to 1. SetLayerOpacity(layer, 1.0f, base::Milliseconds(48)); - Advance(base::Milliseconds(100)); - - // No report should happen while scoped_blocker exists. - EXPECT_FALSE(deleted); - - // Make sure there are no animations running. - compositor_monitor.WaitForAllAnimationsEnd(); - - scoped_blocker.reset(); - // No animation should be running yet, nothing to report. - EXPECT_FALSE(deleted); - Advance(base::Milliseconds(100)); - EXPECT_FALSE(deleted); - - // Animation of opacity goes to 0.5. - layer.SetOpacity(0.7f); - EXPECT_FALSE(deleted); - Advance(base::Milliseconds(100)); + run_loop.Run(); EXPECT_TRUE(deleted); } TEST_F(TotalAnimationThroughputReporterTest, ThreadCheck) { - TestCompositorMonitor compositor_monitor(compositor()); Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -486,26 +383,9 @@ TotalAnimationThroughputReporter reporter(c, std::move(callback), /*should_delete=*/false); - auto scoped_blocker = reporter.NewScopedBlocker(); // Report data for animation of opacity goes to 1. layer.SetOpacity(1.0f); - Advance(base::Milliseconds(100)); - - // No report should happen while scoped_blocker exists. - EXPECT_FALSE(checker.reported()); - - // Make sure there are no animations running. - compositor_monitor.WaitForAllAnimationsEnd(); - - scoped_blocker.reset(); - // No animation should be running yet, nothing to report. - EXPECT_FALSE(checker.reported()); - Advance(base::Milliseconds(100)); - EXPECT_FALSE(checker.reported()); - - // Animation of opacity goes to 0.5. - layer.SetOpacity(0.7f); EXPECT_TRUE(checker.WaitUntilReported()); }
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc index 907ad7640..8766c097 100644 --- a/ui/views/bubble/bubble_dialog_model_host.cc +++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -17,7 +17,6 @@ #include "ui/base/models/dialog_model_field.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/geometry/insets.h" -#include "ui/views/accessibility/accessibility_paint_checks.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/border.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" @@ -797,12 +796,6 @@ // TODO(pbos): Support updates to the existing model. auto textfield = std::make_unique<Textfield>(); - // TODO(crbug.com/1218186): Remove this, this is in place temporarily to be - // able to submit accessibility checks, but this focusable View needs to - // add a name so that the screen reader knows what to announce. The - // placeholder name may need to be pushed into DialogModel, unless we can tie - // this to the label. Maybe SetAssociatedField on Textfield is sufficient? - textfield->SetProperty(kSkipAccessibilityPaintChecks, true); textfield->SetAccessibleName( model_field->accessible_name(GetPassKey()).empty() ? model_field->label(GetPassKey())
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 1be7478..8ece700 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -432,9 +432,6 @@ } if (new_index.has_value()) { - if (menu_selection_at_callback_) - menu_selection_at_callback_.Run(new_index.value()); - SetSelectedIndex(new_index); OnPerformAction(); }
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index eeb848b..e287da1 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -160,7 +160,6 @@ "js/cr.m.js", "js/cr/ui.js", "js/load_time_data.m.js", - "js/icon.js", "js/util.js", ] @@ -185,6 +184,7 @@ "js/focus_grid.ts", "js/focus_row.ts", "js/focus_outline_manager.ts", + "js/icon.ts", "js/keyboard_shortcut_list.ts", "js/plural_string_proxy.ts", "js/static_types.ts",
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index acbc5ae..ccb1561 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -48,6 +48,7 @@ "focus_grid.ts", "focus_outline_manager.ts", "focus_row.ts", + "icon.ts", "keyboard_shortcut_list.ts", "plural_string_proxy.ts", "search_highlight_utils.ts", @@ -78,7 +79,6 @@ "cr.m.js", "cr/event_target.js", "cr/ui.js", - "icon.js", "load_time_data.m.js", "load_time_data_deprecated.js", "parse_html_subset.js", @@ -138,7 +138,6 @@ deps = [ ":assert", ":cr.m", - ":icon", ":load_time_data.m", ":parse_html_subset", ":promise_resolver", @@ -157,10 +156,6 @@ externs_list = [ "$externs_path/chrome_send.js" ] } -js_library("icon") { - deps = [ ":cr.m" ] -} - js_library("load_time_data.m") { }
diff --git a/ui/webui/resources/js/icon.js b/ui/webui/resources/js/icon.ts similarity index 76% rename from ui/webui/resources/js/icon.js rename to ui/webui/resources/js/icon.ts index 5cd55f0..a19ce7b 100644 --- a/ui/webui/resources/js/icon.js +++ b/ui/webui/resources/js/icon.ts
@@ -5,10 +5,9 @@ import {isAndroid, isIOS} from './cr.m.js'; /** - * @return {!Array<number>} The scale factors supported by this platform for - * webui resources. + * @return The scale factors supported by this platform for webui resources. */ -function getSupportedScaleFactors() { +function getSupportedScaleFactors(): number[] { const supportedScaleFactors = []; if (!isIOS) { // This matches the code in ResourceBundle::InitSharedInstance() that @@ -33,10 +32,10 @@ /** * Generates a CSS url string. - * @param {string} s The URL to generate the CSS url for. - * @return {string} The CSS url string. + * @param s The URL to generate the CSS url for. + * @return The CSS url string. */ -export function getUrlForCss(s) { +export function getUrlForCss(s: string): string { // http://www.w3.org/TR/css3-values/#uris // Parentheses, commas, whitespace characters, single quotes (') and double // quotes (") appearing in a URI must be escaped with a backslash @@ -46,10 +45,8 @@ /** * A URL for the filetype icon for |filePath|. OS and theme dependent. - * @param {string} filePath - * @return {string} */ -export function getFileIconUrl(filePath) { +export function getFileIconUrl(filePath: string): string { const url = new URL('chrome://fileicon/'); url.searchParams.set('path', filePath); url.searchParams.set('scale', window.devicePixelRatio + 'x'); @@ -62,11 +59,11 @@ * The scale-factor-specific url is generated by replacing the first instance * of 'scalefactor' in |path| with the numeric scale factor. * - * @param {string} path The URL to generate an image set for. + * @param path The URL to generate an image set for. * 'scalefactor' should be a substring of |path|. - * @return {string} The CSS -webkit-image-set. + * @return The CSS -webkit-image-set. */ -function getImageSet(path) { +function getImageSet(path: string): string { const supportedScaleFactors = getSupportedScaleFactors(); const replaceStartIndex = path.indexOf('SCALEFACTOR'); @@ -93,10 +90,10 @@ * Returns the URL of the image, or an image set of URLs for the provided * path. Resources in chrome://theme have multiple supported scale factors. * - * @param {string} path The path of the image. - * @return {string} The url, or an image set of URLs. + * @param path The path of the image. + * @return The url, or an image set of URLs. */ -export function getImage(path) { +export function getImage(path: string): string { const chromeThemePath = 'chrome://theme'; const isChromeThemeUrl = (path.slice(0, chromeThemePath.length) === chromeThemePath); @@ -104,7 +101,7 @@ getUrlForCss(path); } -function getBaseFaviconUrl() { +function getBaseFaviconUrl(): URL { const faviconUrl = new URL('chrome://favicon2/'); faviconUrl.searchParams.set('size', '16'); faviconUrl.searchParams.set('scaleFactor', 'SCALEFACTORx'); @@ -114,10 +111,10 @@ /** * Creates a CSS -webkit-image-set for a favicon. * - * @param {string} url URL of the favicon - * @return {string} -webkit-image-set for the favicon + * @param url URL of the favicon + * @return -webkit-image-set for the favicon */ -export function getFavicon(url) { +export function getFavicon(url: string): string { const faviconUrl = getBaseFaviconUrl(); faviconUrl.searchParams.set('iconUrl', url); return getImageSet(faviconUrl.toString()); @@ -126,25 +123,26 @@ /** * Creates a CSS -webkit-image-set for a favicon request based on a page URL. * - * @param {string} url URL of the original page - * @param {boolean} isSyncedUrlForHistoryUi Should be set to true only if the + * @param url URL of the original page + * @param isSyncedUrlForHistoryUi Should be set to true only if the * caller is an UI aimed at displaying user history, and the requested url * is known to be present in Chrome sync data. - * @param {string=} remoteIconUrlForUma In case the entry is contained in sync + * @param remoteIconUrlForUma In case the entry is contained in sync * data, we can pass the associated icon url. - * @param {number=} size The favicon size. - * @param {boolean=} forceLightMode Flag to force the service to show the light + * @param size The favicon size. + * @param forceLightMode Flag to force the service to show the light * mode version of the default favicon. * - * @return {string} -webkit-image-set for the favicon. + * @return -webkit-image-set for the favicon. */ export function getFaviconForPageURL( - url, isSyncedUrlForHistoryUi, remoteIconUrlForUma = '', size = 16, - forceLightMode = false) { + url: string, isSyncedUrlForHistoryUi: boolean, + remoteIconUrlForUma: string = '', size: number = 16, + forceLightMode: boolean = false): string { // Note: URL param keys used below must match those in the description of // chrome://favicon2 format in components/favicon_base/favicon_url_parser.h. const faviconUrl = getBaseFaviconUrl(); - faviconUrl.searchParams.set('size', size); + faviconUrl.searchParams.set('size', size.toString()); faviconUrl.searchParams.set('pageUrl', url); // TODO(dbeam): use the presence of 'allowGoogleServerFallback' to // indicate true, otherwise false. @@ -154,7 +152,7 @@ faviconUrl.searchParams.set('iconUrl', remoteIconUrlForUma); } if (forceLightMode) { - faviconUrl.searchParams.set('forceLightMode', true); + faviconUrl.searchParams.set('forceLightMode', 'true'); } return getImageSet(faviconUrl.toString());