diff --git a/DEPS b/DEPS index 89a624bd..6d4b0fc 100644 --- a/DEPS +++ b/DEPS
@@ -297,11 +297,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '0450b8d5a2a40aea9b31e1b467ee6c39f0c6f06d', + 'skia_revision': 'd121e0a831fa17e062a7923fdedf11a4cd5988b7', # 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': '562b2178254da2933bbe84c932ddbe861179b722', + 'v8_revision': 'fe3bd2821cd7a082e05d04fec07ed628f684155a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -313,7 +313,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'edf817eed90f91e5966bff6863643fb785b7d875', + 'pdfium_revision': 'ee44620f2b58999b0d272d58fa0b994d5935f688', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -324,7 +324,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:9.20220812.1.1', + 'fuchsia_version': 'version:9.20220816.1.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. @@ -412,7 +412,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'dadb934e19784bdc64c00e545b1da00654e6cac7', + 'dawn_revision': 'f83652f01935236cc5635e52756245cff1c78581', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -440,7 +440,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': 'e5c24b8b8ac4b093ccf741d1af8e3ecd896a1eda', + 'nearby_revision': '0849bc7598e56dc68a6ee67976ad8250f5e87e40', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -1174,7 +1174,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '1771b7788497cf8573347ee90abd7346fd428d15', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '564038ed79022b8a0a651b41b4e02c2caf95c7a1', 'condition': 'checkout_linux', }, @@ -1184,7 +1184,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '268d645853ee8e1b884260049e5464a5ca2d8a30', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '940cd8e20f5451a03737f1fbcc505f7b84dff2b3', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1465,7 +1465,7 @@ Var('chromium_git') + '/webm/libwebp.git' + '@' + '7366f7f394af26de814296152c50e673ed0a832f', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '1c5a8bb17ac4092da557e55cf519bf4df105d8f1', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '65e7c9d5706a77d1949da59bfcb0817c252ef8d6', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -1573,7 +1573,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd7a3c46d86229bfcb6064bcf2b10be528bbcdf07', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '2fbf8d8bf878dac5ee4670f0dc3327393e9e7e72', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1693,7 +1693,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@863822794aa708b003edf3d547c10895768e3f54', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@31a5e38f3e48d6706f5ccb2d2b74eeda1de6a21a', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1729,7 +1729,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '44e4c8770158c505b03ee7feafa4859d083b0912', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'dd01507ff53bf61b357623209d52a65831ed7d4d', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '30e9e048a1ff56f0bb235b9462dd1547daa017c7', 'src/third_party/webrtc': Var('webrtc_git') + '/src.git' + '@' + '0cf140d720e15f5b9064190511ef51746a6efe84', @@ -1805,7 +1805,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6882dd54f1b6bd7da135a2d8912871ef51b56676', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@12e5578d6729a79f1416a126ae22b6bb98a02f3f', 'condition': 'checkout_src_internal', }, @@ -1824,7 +1824,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'UWjW5UUyYh7eJT-i7CeuIruu8MlSh4yYurvj5X2vS7gC', + 'version': 'Qa1IWoOECUYzahsB4j2P_hfFOSZ2Q978_xvr5rFv1QMC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index c758099..6d0635e 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -973,6 +973,8 @@ "style/default_color_constants.h", "style/default_colors.cc", "style/default_colors.h", + "style/dot_indicator.cc", + "style/dot_indicator.h", "style/icon_button.cc", "style/icon_button.h", "style/pill_button.cc", @@ -1562,6 +1564,8 @@ "system/power/video_activity_notifier.h", "system/privacy/privacy_indicators_controller.cc", "system/privacy/privacy_indicators_controller.h", + "system/privacy/privacy_indicators_tray_item_view.cc", + "system/privacy/privacy_indicators_tray_item_view.h", "system/privacy_hub/camera_privacy_switch_controller.cc", "system/privacy_hub/camera_privacy_switch_controller.h", "system/privacy_hub/microphone_privacy_switch_controller.cc", @@ -2548,7 +2552,6 @@ "ambient/ui/media_string_view_unittest.cc", "ambient/ui/photo_view_unittest.cc", "ambient/util/ambient_util_unittest.cc", - "app_menu/app_menu_model_adapter_unittest.cc", "app_menu/notification_menu_controller_unittest.cc", "app_menu/notification_menu_view_unittest.cc", "app_menu/notification_overflow_view_unittest.cc", @@ -3099,6 +3102,7 @@ "//cc:test_support", "//chromeos:test_support", "//chromeos/ash/components/assistant:buildflags", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", "//chromeos/ash/components/dbus/hammerd", "//chromeos/ash/components/dbus/hermes", @@ -3119,7 +3123,6 @@ "//chromeos/components/sensors/mojom", "//chromeos/constants", "//chromeos/crosapi/cpp", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", "//chromeos/services/bluetooth_config:test_support", @@ -3549,13 +3552,13 @@ "//base/test:test_support", "//cc:test_support", "//chromeos/ash/components/attestation:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", "//chromeos/ash/components/dbus/rgbkbd", "//chromeos/ash/components/dbus/system_clock", "//chromeos/ash/components/network:test_support", "//chromeos/ash/services/assistant:test_support", "//chromeos/ash/services/assistant/public/cpp", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", "//chromeos/login/login_state",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 3a884ba..ffc2628 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -254,7 +254,10 @@ // TestNewWindowDelegate: MOCK_METHOD(void, OpenCalculator, (), (override)); MOCK_METHOD(void, ShowKeyboardShortcutViewer, (), (override)); - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; class MockAcceleratorObserver
diff --git a/ash/app_list/views/app_list_bubble_apps_page.cc b/ash/app_list/views/app_list_bubble_apps_page.cc index 078d854..0452064d 100644 --- a/ash/app_list/views/app_list_bubble_apps_page.cc +++ b/ash/app_list/views/app_list_bubble_apps_page.cc
@@ -392,9 +392,25 @@ gfx::Transform translate_down; translate_down.Translate(0, kShowPageAnimationVerticalOffset); + // Update view visibility when the animation is done. Needed to ensure + // the view has the correct opacity and transform when the animation is + // aborted. + auto set_visible_true = base::BindRepeating( + [](base::WeakPtr<AppListBubbleAppsPage> self) { + if (!self) + return; + self->SetVisible(true); + ui::Layer* layer = self->scroll_view()->contents()->layer(); + layer->SetOpacity(1.f); + layer->SetTransform(gfx::Transform()); + }, + weak_factory_.GetWeakPtr()); + views::AnimationBuilder() .SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET) + .OnEnded(set_visible_true) + .OnAborted(set_visible_true) .Once() .SetOpacity(scroll_contents, 0.f) .SetTransform(scroll_contents, translate_down)
diff --git a/ash/app_list/views/app_list_bubble_apps_page_unittest.cc b/ash/app_list/views/app_list_bubble_apps_page_unittest.cc index ed2bf8ac..fba25ef 100644 --- a/ash/app_list/views/app_list_bubble_apps_page_unittest.cc +++ b/ash/app_list/views/app_list_bubble_apps_page_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/app_list/test/test_focus_change_listener.h" #include "ash/app_list/views/app_list_a11y_announcer.h" #include "ash/app_list/views/app_list_bubble_search_page.h" +#include "ash/app_list/views/app_list_bubble_view.h" #include "ash/app_list/views/app_list_toast_container_view.h" #include "ash/app_list/views/app_list_toast_view.h" #include "ash/app_list/views/apps_grid_view_test_api.h" @@ -153,6 +154,40 @@ EXPECT_EQ(1.0f, apps_page->scroll_view()->contents()->layer()->opacity()); } +// Regression test for https://crbug.com/1349833 +TEST_F(AppListBubbleAppsPageTest, + AppsPageVisibleAfterQuicklyHidingAndShowingLauncherFromSearchPage) { + // Open the app list without animation. + ASSERT_EQ(ui::ScopedAnimationDurationScaleMode::duration_multiplier(), + ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); + auto* helper = GetAppListTestHelper(); + helper->AddAppItems(5); + helper->ShowAppList(); + + auto* apps_page = helper->GetBubbleAppsPage(); + ASSERT_TRUE(apps_page->GetVisible()); + + // Type a key to trigger the animation to transition to the search page. + PressAndReleaseKey(ui::VKEY_A); + EXPECT_FALSE(apps_page->GetVisible()); + + // Enable animations. + ui::ScopedAnimationDurationScaleMode duration( + ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); + + helper->GetBubbleView()->StartHideAnimation(/*is_side_shelf=*/false, + base::DoNothing()); + helper->GetBubbleView()->StartShowAnimation(/*is_side_shelf=*/false); + apps_page->AbortAllAnimations(); + + LayerAnimationStoppedWaiter().Wait(apps_page->GetPageAnimationLayerForTest()); + + EXPECT_TRUE(apps_page->GetVisible()); + EXPECT_EQ(1.0f, apps_page->scroll_view()->contents()->layer()->opacity()); + EXPECT_EQ(gfx::Transform(), + apps_page->scroll_view()->contents()->layer()->transform()); +} + TEST_F(AppListBubbleAppsPageTest, AnimateHidePage) { // Open the app list without animation. ASSERT_EQ(ui::ScopedAnimationDurationScaleMode::duration_multiplier(),
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index 60660dd..c8324fc6 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -23,6 +23,7 @@ #include "ash/public/cpp/style/color_provider.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" +#include "ash/style/dot_indicator.h" #include "base/auto_reset.h" #include "base/bind.h" #include "base/check.h" @@ -42,15 +43,14 @@ #include "ui/gfx/geometry/transform_util.h" #include "ui/gfx/image/canvas_image_source.h" #include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/scoped_canvas.h" #include "ui/gfx/shadow_value.h" -#include "ui/gfx/skia_paint_util.h" #include "ui/views/accessibility/accessibility_paint_checks.h" #include "ui/views/accessibility/view_accessibility.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/widget/widget.h" namespace ash { @@ -165,54 +165,6 @@ } // namespace -// The badge which is activated when the app corresponding with this -// AppListItemView receives a notification. -class AppListItemView::AppNotificationIndicatorView : public views::View { - public: - explicit AppNotificationIndicatorView(SkColor indicator_color) - : shadow_values_(gfx::ShadowValue::MakeMdShadowValues(2)), - indicator_color_(indicator_color) {} - AppNotificationIndicatorView(const AppNotificationIndicatorView& other) = - delete; - AppNotificationIndicatorView& operator=( - const AppNotificationIndicatorView& other) = delete; - ~AppNotificationIndicatorView() override = default; - - void OnPaint(gfx::Canvas* canvas) override { - gfx::ScopedCanvas scoped(canvas); - - canvas->SaveLayerAlpha(SK_AlphaOPAQUE); - - DCHECK_EQ(width(), height()); - const float dsf = canvas->UndoDeviceScaleFactor(); - - float radius = width() * kNotificationIndicatorWidthRatio / 2.0f; - float padding = width() * kNotificationIndicatorPaddingRatio; - - float center_x = - base::i18n::IsRTL() ? padding + radius : width() - radius - padding; - float center_y = padding + radius; - gfx::PointF center = gfx::PointF(center_x, center_y); - center.Scale(dsf); - - // Fill the center. - cc::PaintFlags flags; - flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); - flags.setColor(indicator_color_); - flags.setAntiAlias(true); - canvas->DrawCircle(center, dsf * radius, flags); - } - - void SetColor(SkColor new_color) { - indicator_color_ = new_color; - SchedulePaint(); - } - - private: - const gfx::ShadowValues shadow_values_; - SkColor indicator_color_; -}; - // ImageView for the item icon. class AppListItemView::IconImageView : public views::ImageView { public: @@ -354,11 +306,8 @@ false /*animate*/); } - notification_indicator_ = - AddChildView(std::make_unique<AppNotificationIndicatorView>( - item->GetNotificationBadgeColor())); - notification_indicator_->SetPaintToLayer(); - notification_indicator_->layer()->SetFillsBoundsOpaquely(false); + notification_indicator_ = AddChildView( + std::make_unique<DotIndicator>(item->GetNotificationBadgeColor())); notification_indicator_->SetVisible(item->has_notification_badge()); title_ = AddChildView(std::move(title)); @@ -466,13 +415,17 @@ switch (ui_state) { case UI_STATE_NORMAL: title_->SetVisible(true); - if (ui_state_ == UI_STATE_DRAGGING) + if (ui_state_ == UI_STATE_DRAGGING) { + GetWidget()->SetCursor(ui::mojom::CursorType::kNull); ScaleAppIcon(false); + } break; case UI_STATE_DRAGGING: title_->SetVisible(false); - if (ui_state_ == UI_STATE_NORMAL && !in_cardified_grid_) + if (ui_state_ == UI_STATE_NORMAL && !in_cardified_grid_) { + GetWidget()->SetCursor(ui::mojom::CursorType::kGrabbing); ScaleAppIcon(true); + } break; case UI_STATE_DROPPING_IN_FOLDER: break; @@ -896,7 +849,18 @@ kNewInstallDotSize, kNewInstallDotSize); } - notification_indicator_->SetBoundsRect(icon_bounds); + const float indicator_size = + icon_bounds.width() * kNotificationIndicatorWidthRatio; + const float indicator_padding = + icon_bounds.width() * kNotificationIndicatorPaddingRatio; + + const float indicator_x = + icon_bounds.right() - indicator_size - indicator_padding; + const float indicator_y = icon_bounds.y() + indicator_padding; + + const gfx::Rect indicator_bounds = gfx::ToRoundedRect( + gfx::RectF(indicator_x, indicator_y, indicator_size, indicator_size)); + notification_indicator_->SetIndicatorBounds(indicator_bounds); } gfx::Size AppListItemView::CalculatePreferredSize() const {
diff --git a/ash/app_list/views/app_list_item_view.h b/ash/app_list/views/app_list_item_view.h index 67679cb..4a5abd2 100644 --- a/ash/app_list/views/app_list_item_view.h +++ b/ash/app_list/views/app_list_item_view.h
@@ -41,6 +41,7 @@ class AppListItem; class AppListMenuModelAdapter; class AppListViewDelegate; +class DotIndicator; namespace test { class AppsGridViewTest; @@ -258,7 +259,6 @@ friend class test::AppsGridViewTest; class IconImageView; - class AppNotificationIndicatorView; enum UIState { UI_STATE_NORMAL, // Normal UI (icon + label) @@ -461,7 +461,7 @@ // Draws an indicator in the top right corner of the image to represent an // active notification. - AppNotificationIndicatorView* notification_indicator_ = nullptr; + DotIndicator* notification_indicator_ = nullptr; // Indicates the context in which this view is shown. const Context context_;
diff --git a/ash/app_list/views/app_list_main_view_unittest.cc b/ash/app_list/views/app_list_main_view_unittest.cc index 4ef0c1c5..ba4a8de 100644 --- a/ash/app_list/views/app_list_main_view_unittest.cc +++ b/ash/app_list/views/app_list_main_view_unittest.cc
@@ -256,6 +256,11 @@ // Tests dragging an item out of a single item folder and dropping it onto the // page switcher. Regression test for http://crbug.com/415530/. TEST_P(AppListMainViewTest, DragReparentItemOntoPageSwitcher) { + // This test is flaky when ProductivityLauncher is false. Skip the test in + // that case. http://crbug.com/1351834 + if (!features::IsProductivityLauncherEnabled()) + return; + AppListItemView* folder_item_view = CreateAndOpenSingleItemFolder(); ASSERT_TRUE(folder_item_view);
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc index 56275062..cc5eafc6 100644 --- a/ash/app_list/views/apps_grid_view_unittest.cc +++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -4612,6 +4612,87 @@ EXPECT_TRUE(ShelfModel::Get()->items().empty()); } +TEST_P(AppsGridViewDragTest, MousePointerIsGrabbingDuringDrag) { + auto* cursor_manager = Shell::Get()->cursor_manager(); + auto previous_cursor_type = cursor_manager->GetCursor().type(); + + // Populate the apps grid and start dragging one of the items. + model_->PopulateApps(3); + UpdateLayout(); + AppListItemView* const item_view = GetItemViewInTopLevelGrid(1); + auto* generator = GetEventGenerator(); + generator->MoveMouseTo(item_view->GetBoundsInScreen().CenterPoint()); + generator->PressLeftButton(); + item_view->FireMouseDragTimerForTest(); + + // Ensure the cursor type is set to grabbing during the drag. + EXPECT_EQ(ui::mojom::CursorType::kGrabbing, + cursor_manager->GetCursor().type()); + + // Release the left mouse button to cancel the drag and verify that the cursor + // type is reset. + generator->ReleaseLeftButton(); + EXPECT_EQ(previous_cursor_type, cursor_manager->GetCursor().type()); +} + +TEST_P(AppsGridViewDragTest, MousePointerIsResetOnCanceledDrag) { + auto* cursor_manager = Shell::Get()->cursor_manager(); + auto previous_cursor_type = cursor_manager->GetCursor().type(); + + // Populate the apps grid and start dragging one of the items. + model_->PopulateApps(3); + UpdateLayout(); + AppListItemView* const item_view = GetItemViewInTopLevelGrid(1); + auto* generator = GetEventGenerator(); + generator->MoveMouseTo(item_view->GetBoundsInScreen().CenterPoint()); + generator->PressLeftButton(); + item_view->FireMouseDragTimerForTest(); + + // The cursor type should be set to grabbing during the drag. + ASSERT_EQ(ui::mojom::CursorType::kGrabbing, + cursor_manager->GetCursor().type()); + + // Cancel the drag without releasing the left mouse button and verify that the + // cursor is still reset in this case. + generator->PressAndReleaseKey(ui::VKEY_ESCAPE); + EXPECT_EQ(previous_cursor_type, cursor_manager->GetCursor().type()); +} + +// Verify the cursor type when dragging one item over another item and back. +TEST_P(AppsGridViewDragTest, MouseDragItemToOtherItemAndBack) { + auto* cursor_manager = Shell::Get()->cursor_manager(); + model_->PopulateApps(3); + UpdateLayout(); + + // Start dragging the first item. + AppListItemView* const item0 = GetItemViewInTopLevelGrid(0); + gfx::Point starting_point = item0->GetBoundsInScreen().CenterPoint(); + AppListItemView* const item1 = GetItemViewInTopLevelGrid(1); + auto* generator = GetEventGenerator(); + generator->MoveMouseTo(starting_point); + generator->PressLeftButton(); + item0->FireMouseDragTimerForTest(); + + // Verify the cursor is grabbing now that the drag has started. + ASSERT_EQ(ui::mojom::CursorType::kGrabbing, + cursor_manager->GetCursor().type()); + + // Move the first item on top of the second item as if to create a folder, but + // don't actually create a folder. + generator->MoveMouseTo(item1->GetBoundsInScreen().CenterPoint()); + + // Verify the cursor is still grabbing in this state. + ASSERT_EQ(ui::mojom::CursorType::kGrabbing, + cursor_manager->GetCursor().type()); + + // Move the first item back to its original position. + generator->MoveMouseTo(starting_point); + + // The cursor should still be grabbing. + EXPECT_EQ(ui::mojom::CursorType::kGrabbing, + cursor_manager->GetCursor().type()); +} + TEST_P(AppsGridViewTabletTest, Basic) { base::HistogramTester histogram_tester;
diff --git a/ash/app_list/views/remove_query_confirmation_dialog.cc b/ash/app_list/views/remove_query_confirmation_dialog.cc index 84b5a7ed..9fef83f 100644 --- a/ash/app_list/views/remove_query_confirmation_dialog.cc +++ b/ash/app_list/views/remove_query_confirmation_dialog.cc
@@ -65,7 +65,7 @@ title_ = AddChildView(std::make_unique<views::Label>( l10n_util::GetStringUTF16(IDS_REMOVE_ZERO_STATE_SUGGESTION_TITLE))); title_->SetTextContext(views::style::CONTEXT_DIALOG_TITLE); - title_->SetTextStyle(ash::STYLE_EMPHASIZED); + title_->SetTextStyle(views::style::STYLE_EMPHASIZED); title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_->SetAutoColorReadabilityEnabled(false); // Needs to paint to layer so it's stacked above `this` view.
diff --git a/ash/app_list/views/search_result_inline_icon_view.cc b/ash/app_list/views/search_result_inline_icon_view.cc index d1596a8..b69c4aa 100644 --- a/ash/app_list/views/search_result_inline_icon_view.cc +++ b/ash/app_list/views/search_result_inline_icon_view.cc
@@ -20,6 +20,7 @@ #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/flex_layout.h" #include "ui/views/layout/flex_layout_view.h" +#include "ui/views/style/typography.h" namespace ash { @@ -69,7 +70,7 @@ label_->SetVisible(true); label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); label_->SetTextContext(CONTEXT_SEARCH_RESULT_VIEW_INLINE_ANSWER_DETAILS); - label_->SetTextStyle(STYLE_EMPHASIZED); + label_->SetTextStyle(views::style::STYLE_EMPHASIZED); } label_->SetText(text);
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index 7aa6f46..a48bcfb6 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -42,6 +42,7 @@ #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 { @@ -424,7 +425,7 @@ void SearchResultTileItemView::SetTitleTags(const SearchResultTags& tags) { for (const auto& tag : tags) { if (tag.styles & SearchResult::Tag::MATCH) { - title_->SetTextStyleRange(AshTextStyle::STYLE_EMPHASIZED, tag.range); + title_->SetTextStyleRange(views::style::STYLE_EMPHASIZED, tag.range); } } }
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc index f96377a..33ad64e6 100644 --- a/ash/app_list/views/search_result_view.cc +++ b/ash/app_list/views/search_result_view.cc
@@ -899,7 +899,7 @@ if (has_match_tag) { switch (view_type_) { case SearchResultViewType::kClassic: - label->SetTextStyleRange(AshTextStyle::STYLE_EMPHASIZED, tag.range); + label->SetTextStyleRange(views::style::STYLE_EMPHASIZED, tag.range); break; case SearchResultViewType::kDefault: ABSL_FALLTHROUGH_INTENDED;
diff --git a/ash/app_list/views/suggested_content_info_view.cc b/ash/app_list/views/suggested_content_info_view.cc index b9f4c9f..632a08e 100644 --- a/ash/app_list/views/suggested_content_info_view.cc +++ b/ash/app_list/views/suggested_content_info_view.cc
@@ -31,7 +31,8 @@ view_delegate_->MarkSuggestedContentInfoDismissed(); constexpr char url[] = "chrome://os-settings/osPrivacy"; NewWindowDelegate::GetInstance()->OpenUrl( - GURL(url), NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(url), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } } // namespace ash
diff --git a/ash/app_menu/app_menu_model_adapter.cc b/ash/app_menu/app_menu_model_adapter.cc index a60f815..2757c4f 100644 --- a/ash/app_menu/app_menu_model_adapter.cc +++ b/ash/app_menu/app_menu_model_adapter.cc
@@ -6,7 +6,6 @@ #include "ash/app_menu/notification_menu_controller.h" #include "ash/constants/ash_features.h" -#include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/shelf_model.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -106,19 +105,8 @@ // example, for search result menus, the command could open an app window // causing the app list search to get cleared, destroying non-zero state // search results. - auto weak_self = weak_ptr_factory_.GetWeakPtr(); RecordExecuteCommandHistogram(GetCommandIdForHistograms(id)); views::MenuModelAdapter::ExecuteCommand(id, mouse_event_flags); - - if (!weak_self) - return; - - if (id >= USE_LAUNCH_TYPE_COMMAND_START && - id <= USE_LAUNCH_TYPE_COMMAND_END) { - // Rebuild the menu to ensure that the `LAUNCH_NEW` menu item is refreshed - // after changing the app launch type. - BuildMenu(root_); - } } void AppMenuModelAdapter::OnMenuClosed(views::MenuItemView* menu) { @@ -136,13 +124,6 @@ std::move(on_menu_closed_callback_).Run(); } -bool AppMenuModelAdapter::ShouldExecuteCommandWithoutClosingMenu( - int id, - const ui::Event& event) { - return id >= USE_LAUNCH_TYPE_COMMAND_START && - id <= USE_LAUNCH_TYPE_COMMAND_END; -} - void AppMenuModelAdapter::RecordExecuteCommandHistogram(int command_id) { const bool is_not_from_app = app_id().empty(); base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommand
diff --git a/ash/app_menu/app_menu_model_adapter.h b/ash/app_menu/app_menu_model_adapter.h index e8e6166..7a73afd 100644 --- a/ash/app_menu/app_menu_model_adapter.h +++ b/ash/app_menu/app_menu_model_adapter.h
@@ -65,8 +65,6 @@ // views::MenuModelAdapter: void ExecuteCommand(int id, int mouse_event_flags) override; void OnMenuClosed(views::MenuItemView* menu) override; - bool ShouldExecuteCommandWithoutClosingMenu(int id, - const ui::Event& event) override; ui::SimpleMenuModel* model() { return model_.get(); } views::MenuItemView* root_for_testing() { return root_; } @@ -116,8 +114,6 @@ // Whether tablet mode is active. bool is_tablet_mode_; - - base::WeakPtrFactory<AppMenuModelAdapter> weak_ptr_factory_{this}; }; } // namespace ash
diff --git a/ash/app_menu/app_menu_model_adapter_unittest.cc b/ash/app_menu/app_menu_model_adapter_unittest.cc deleted file mode 100644 index 5db6572..0000000 --- a/ash/app_menu/app_menu_model_adapter_unittest.cc +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/app_menu/app_menu_model_adapter.h" - -#include <memory> - -#include "ash/public/cpp/app_menu_constants.h" -#include "ash/test/ash_test_base.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/models/simple_menu_model.h" -#include "ui/events/base_event_utils.h" -#include "ui/events/types/event_type.h" -#include "ui/views/controls/menu/menu_item_view.h" -#include "ui/views/controls/menu/submenu_view.h" -#include "ui/views/test/menu_test_utils.h" - -namespace ash { -namespace { - -class TestAppMenuModelAdapter : public AppMenuModelAdapter { - public: - explicit TestAppMenuModelAdapter(std::unique_ptr<ui::SimpleMenuModel> model) - : AppMenuModelAdapter("test-app-id", - std::move(model), - nullptr, - ui::MENU_SOURCE_TYPE_LAST, - base::OnceClosure(), - false) {} - TestAppMenuModelAdapter(const TestAppMenuModelAdapter&) = delete; - TestAppMenuModelAdapter& operator=(const TestAppMenuModelAdapter&) = delete; - ~TestAppMenuModelAdapter() override = default; - - private: - void RecordHistogramOnMenuClosed() override {} -}; - -} // namespace - -class AppMenuModelAdapterTest : public AshTestBase { - public: - AppMenuModelAdapterTest() = default; - AppMenuModelAdapterTest(const AppMenuModelAdapterTest&) = delete; - AppMenuModelAdapterTest& operator=(const AppMenuModelAdapterTest&) = delete; - ~AppMenuModelAdapterTest() override = default; - - // AshTestBase: - void SetUp() override { - AshTestBase::SetUp(); - - views::test::DisableMenuClosureAnimations(); - - auto menu_model = std::make_unique<ui::SimpleMenuModel>(nullptr); - submenu_model_ = std::make_unique<ui::SimpleMenuModel>(nullptr); - menu_model->AddItem(MENU_CLOSE, u"item 0"); - submenu_model_->AddItem(USE_LAUNCH_TYPE_REGULAR, u"item 2"); - menu_model->AddActionableSubMenu(LAUNCH_NEW, u"item 1", - submenu_model_.get()); - app_menu_model_adapter_ = - std::make_unique<TestAppMenuModelAdapter>(std::move(menu_model)); - } - - void ClickOnMenuItemForCommandId(int command_id) { - auto* menu_item_view = app_menu_model_adapter_->root_for_testing(); - auto* target_menu_item = menu_item_view->GetMenuItemByID(command_id); - auto location = target_menu_item->bounds().CenterPoint(); - ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, location, location, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - 0); - ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, location, location, - ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, 0); - auto* source = target_menu_item->GetParentMenuItem()->GetSubmenu(); - menu_item_view->GetMenuController()->OnMousePressed(source, press_event); - menu_item_view->GetMenuController()->OnMouseReleased(source, release_event); - } - - bool IsShowingSubmenuForCommandId(int command_id) { - return app_menu_model_adapter() - ->root_for_testing() - ->GetMenuItemByID(command_id) - ->SubmenuIsShowing(); - } - - void OpenMenu() { - app_menu_model_adapter_->Run(gfx::Rect(), - views::MenuAnchorPosition::kBottomCenter, - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::USE_ASH_SYS_UI_LAYOUT | - views::MenuRunner::FIXED_ANCHOR); - } - - void ShowSubmenuForCommandId(int command_id) { - auto* menu_item_view = app_menu_model_adapter_->root_for_testing(); - menu_item_view->GetMenuController()->SelectItemAndOpenSubmenu( - menu_item_view->GetMenuItemByID(command_id)); - } - - TestAppMenuModelAdapter* app_menu_model_adapter() { - return app_menu_model_adapter_.get(); - } - - private: - std::unique_ptr<TestAppMenuModelAdapter> app_menu_model_adapter_; - std::unique_ptr<ui::SimpleMenuModel> submenu_model_; -}; - -TEST_F(AppMenuModelAdapterTest, ShouldCloseMenuOnNonUseLaunchTypeCommand) { - EXPECT_FALSE(app_menu_model_adapter()->IsShowingMenu()); - OpenMenu(); - EXPECT_TRUE(app_menu_model_adapter()->IsShowingMenu()); - - ClickOnMenuItemForCommandId(MENU_CLOSE); - EXPECT_FALSE(app_menu_model_adapter()->IsShowingMenu()); -} - -TEST_F(AppMenuModelAdapterTest, ShouldCloseMenuOnLaunchNewCommand) { - EXPECT_FALSE(app_menu_model_adapter()->IsShowingMenu()); - OpenMenu(); - EXPECT_TRUE(app_menu_model_adapter()->IsShowingMenu()); - - ClickOnMenuItemForCommandId(LAUNCH_NEW); - EXPECT_FALSE(app_menu_model_adapter()->IsShowingMenu()); -} - -TEST_F(AppMenuModelAdapterTest, ShouldKeepMenuOpenOnUseLaunchTypeCommand) { - EXPECT_FALSE(app_menu_model_adapter()->IsShowingMenu()); - OpenMenu(); - EXPECT_TRUE(app_menu_model_adapter()->IsShowingMenu()); - - EXPECT_FALSE(IsShowingSubmenuForCommandId(LAUNCH_NEW)); - ShowSubmenuForCommandId(LAUNCH_NEW); - EXPECT_TRUE(IsShowingSubmenuForCommandId(LAUNCH_NEW)); - - ClickOnMenuItemForCommandId(USE_LAUNCH_TYPE_REGULAR); - EXPECT_FALSE(IsShowingSubmenuForCommandId(LAUNCH_NEW)); - EXPECT_TRUE(app_menu_model_adapter()->IsShowingMenu()); -} - -} // namespace ash
diff --git a/ash/assistant/assistant_controller_impl_unittest.cc b/ash/assistant/assistant_controller_impl_unittest.cc index 0a8fd32..dff96727 100644 --- a/ash/assistant/assistant_controller_impl_unittest.cc +++ b/ash/assistant/assistant_controller_impl_unittest.cc
@@ -78,7 +78,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); MOCK_METHOD(void, OpenFeedbackPage, @@ -164,7 +167,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("https://g.co/"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); EXPECT_CALL(controller_observer_mock, OnUrlOpened) .WillOnce(testing::Invoke([](const GURL& url, bool from_server) {
diff --git a/ash/assistant/ui/main_stage/assistant_card_element_view.cc b/ash/assistant/ui/main_stage/assistant_card_element_view.cc index d1f8fef..60368bff 100644 --- a/ash/assistant/ui/main_stage/assistant_card_element_view.cc +++ b/ash/assistant/ui/main_stage/assistant_card_element_view.cc
@@ -203,9 +203,6 @@ // Contents view. contents_view_ = AddChildView( const_cast<AssistantCardElement*>(card_element_)->MoveContentsView()); - - // OverrideDescription() doesn't work. Only names are read automatically. - GetViewAccessibility().OverrideName(card_element_->fallback()); } std::unique_ptr<ElementAnimator> AssistantCardElementView::CreateAnimator() {
diff --git a/ash/components/cryptohome/BUILD.gn b/ash/components/cryptohome/BUILD.gn index 5b14178b..5116621 100644 --- a/ash/components/cryptohome/BUILD.gn +++ b/ash/components/cryptohome/BUILD.gn
@@ -47,10 +47,10 @@ "//ash/components/login/auth/public:challenge_response_key", "//base", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/cryptohome:cryptohome_proto", "//chromeos/ash/components/dbus/userdataauth:userdataauth", "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", - "//chromeos/dbus:test_support", "//testing/gtest:gtest", ] sources = [
diff --git a/ash/components/disks/BUILD.gn b/ash/components/disks/BUILD.gn index cb1baeb..5ca260d 100644 --- a/ash/components/disks/BUILD.gn +++ b/ash/components/disks/BUILD.gn
@@ -35,8 +35,8 @@ deps = [ "//base", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/cros_disks", - "//chromeos/dbus:test_support", "//chromeos/dbus/power:power_manager_proto", "//testing/gmock", "//testing/gtest", @@ -53,8 +53,8 @@ ":disks", ":test_support", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/cros_disks", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", "//testing/gmock",
diff --git a/ash/components/disks/disk_mount_manager.cc b/ash/components/disks/disk_mount_manager.cc index 94646f74..0c24b13b2 100644 --- a/ash/components/disks/disk_mount_manager.cc +++ b/ash/components/disks/disk_mount_manager.cc
@@ -1029,7 +1029,7 @@ // Mount event change observers. base::ObserverList<DiskMountManager::Observer> observers_; - CrosDisksClient* const cros_disks_client_ = chromeos::CrosDisksClient::Get(); + CrosDisksClient* const cros_disks_client_ = CrosDisksClient::Get(); // The list of disks found. DiskMountManager::Disks disks_;
diff --git a/ash/components/disks/disk_mount_manager_unittest.cc b/ash/components/disks/disk_mount_manager_unittest.cc index 40517e264..299f684 100644 --- a/ash/components/disks/disk_mount_manager_unittest.cc +++ b/ash/components/disks/disk_mount_manager_unittest.cc
@@ -576,7 +576,7 @@ } protected: - chromeos::FakeCrosDisksClient* fake_cros_disks_client_; + FakeCrosDisksClient* fake_cros_disks_client_; std::unique_ptr<MockDiskMountManagerObserver> observer_; private:
diff --git a/ash/components/drivefs/BUILD.gn b/ash/components/drivefs/BUILD.gn index a6a736293..f09b5000 100644 --- a/ash/components/drivefs/BUILD.gn +++ b/ash/components/drivefs/BUILD.gn
@@ -61,8 +61,8 @@ ":drivefs", "//ash/components/drivefs/mojom", "//base", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/cros_disks", - "//chromeos/dbus:test_support", "//net", "//testing/gmock", ]
diff --git a/ash/components/drivefs/drivefs_host_unittest.cc b/ash/components/drivefs/drivefs_host_unittest.cc index 5f44145a..28d532b 100644 --- a/ash/components/drivefs/drivefs_host_unittest.cc +++ b/ash/components/drivefs/drivefs_host_unittest.cc
@@ -465,7 +465,6 @@ const AccountId unsupported_accounts[] = { AccountId::FromGaiaId("ID"), AccountId::FromUserEmail("test2@example.com"), - AccountId::AdFromObjGuid("ID"), }; for (auto& account : unsupported_accounts) { host_delegate_ = std::make_unique<TestingDriveFsHostDelegate>(
diff --git a/ash/components/drivefs/fake_drivefs.cc b/ash/components/drivefs/fake_drivefs.cc index 526b16ecc..5d64082 100644 --- a/ash/components/drivefs/fake_drivefs.cc +++ b/ash/components/drivefs/fake_drivefs.cc
@@ -267,7 +267,7 @@ void FakeDriveFs::RegisterMountingForAccountId( base::RepeatingCallback<std::string()> account_id_getter) { - static_cast<chromeos::FakeCrosDisksClient*>(chromeos::CrosDisksClient::Get()) + static_cast<ash::FakeCrosDisksClient*>(ash::CrosDisksClient::Get()) ->AddCustomMountPointCallback(base::BindRepeating(&MaybeMountDriveFs)); GetRegisteredFakeDriveFsIntances().emplace_back(std::move(account_id_getter),
diff --git a/ash/components/drivefs/fake_drivefs_launcher_client.cc b/ash/components/drivefs/fake_drivefs_launcher_client.cc index 3d44b1e..9eb6c4a 100644 --- a/ash/components/drivefs/fake_drivefs_launcher_client.cc +++ b/ash/components/drivefs/fake_drivefs_launcher_client.cc
@@ -64,7 +64,7 @@ base::BindOnce(&ConnectAsync, launcher_.BindNewPipeAndPassReceiver(), socket_path_.value())); - static_cast<chromeos::FakeCrosDisksClient*>(chromeos::CrosDisksClient::Get()) + static_cast<ash::FakeCrosDisksClient*>(ash::CrosDisksClient::Get()) ->AddCustomMountPointCallback( base::BindRepeating(&FakeDriveFsLauncherClient::MaybeMountDriveFs, base::Unretained(this)));
diff --git a/ash/components/tpm/BUILD.gn b/ash/components/tpm/BUILD.gn index 30baff9..abd3769a 100644 --- a/ash/components/tpm/BUILD.gn +++ b/ash/components/tpm/BUILD.gn
@@ -47,11 +47,11 @@ ":tpm", "//ash/components/cryptohome", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/cryptohome", "//chromeos/ash/components/dbus/cryptohome:cryptohome_proto", "//chromeos/ash/components/dbus/userdataauth:userdataauth", "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", - "//chromeos/dbus:test_support", "//chromeos/dbus/constants", "//chromeos/dbus/tpm_manager", "//chromeos/dbus/tpm_manager:tpm_manager_proto",
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 95e4d21..ec9e63f8 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -824,6 +824,10 @@ const base::Feature kHandwritingLegacyRecognitionAllLang{ "HandwritingLegacyRecognitionAllLang", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables downloading the handwriting libraries via DLC. +const base::Feature kHandwritingLibraryDlc{"HandwritingLibraryDlc", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables the Background Page in the help app. const base::Feature kHelpAppBackgroundPage{"HelpAppBackgroundPage", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 2604739..5d3f4b8 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -347,6 +347,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kHandwritingLegacyRecognitionAllLang; COMPONENT_EXPORT(ASH_CONSTANTS) +extern const base::Feature kHandwritingLibraryDlc; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kHelpAppBackgroundPage; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kHelpAppDiscoverTab; COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/dbus/url_handler_service_provider.cc b/ash/dbus/url_handler_service_provider.cc index 71bd034..c333a17 100644 --- a/ash/dbus/url_handler_service_provider.cc +++ b/ash/dbus/url_handler_service_provider.cc
@@ -81,7 +81,8 @@ VLOG(1) << "Opening url now"; NewWindowDelegate::GetPrimary()->OpenUrl( - gurl, NewWindowDelegate::OpenUrlFrom::kUnspecified); + gurl, NewWindowDelegate::OpenUrlFrom::kUnspecified, + NewWindowDelegate::Disposition::kNewForegroundTab); std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call)); }
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 161166a3..038c2522 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc
@@ -134,7 +134,7 @@ if (!enabled_ || IsDragDropInProgress()) return DragOperation::kNone; - drop_weak_factory_.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); const ui::OSExchangeDataProvider* provider = &data->provider(); // We do not support touch drag/drop without a drag image, unless it is a tab @@ -171,10 +171,15 @@ } } + // |drag_source_window_| and |pending_long_tap_| could be non-null if a new + // drag starts while cancel animation or forwarding long tap event is ongoing. + // In this case, forwarding long tap event is aborted and related state should + // be cleaned up. + CleanupPendingLongTap(); + drag_source_window_ = source_window; if (drag_source_window_) drag_source_window_->AddObserver(this); - pending_long_tap_.reset(); drag_data_ = std::move(data); allowed_operations_ = allowed_operations; @@ -183,14 +188,17 @@ start_location_ = screen_location; current_location_ = screen_location; + // Ends cancel animation if it's in progress. + // This should happen before setting drag image because it refers to the drag + // image. + if (cancel_animation_) + cancel_animation_->End(); + cancel_animation_.reset(); + SetDragImage(provider->GetDragImage(), provider->GetDragImageOffset()); drag_window_ = nullptr; - // Ends cancel animation if it's in progress. - if (cancel_animation_) - cancel_animation_->End(); - for (aura::client::DragDropClientObserver& observer : observers_) observer.OnDragStarted(); @@ -204,8 +212,10 @@ DCHECK(!tab_drag_drop_delegate_); tab_drag_drop_delegate_ = std::make_unique<TabDragDropDelegate>( root_window, drag_source_window_, start_location_); - static_cast<DragImageView*>(drag_image_widget_->GetContentsView()) - ->SetTouchDragOperationHintOff(); + if (drag_image_widget_) { + static_cast<DragImageView*>(drag_image_widget_->GetContentsView()) + ->SetTouchDragOperationHintOff(); + } // Avoid taking capture twice. if (is_touch_source && !touch_capture_attempted) { touch_capture_attempted = true; @@ -246,16 +256,15 @@ } } - if (!cancel_animation_.get() || !cancel_animation_->is_animating() || - !pending_long_tap_.get()) { - // If drag cancel animation is running, this cleanup is done when the - // animation completes. - if (drag_source_window_) { - // A check to catch an UAF issue like crbug.com/1282480 on non asan build. - DCHECK(!drag_source_window_->is_destroying()); - drag_source_window_->RemoveObserver(this); - } - drag_source_window_ = nullptr; + if (!will_forward_long_tap_) { + // If drag cancel animation or long tap event forwarding is running, this + // cleanup is done when the long tap event forwarding is done, or when a new + // drag is started. + + // A check to catch an UAF issue like crbug.com/1282480 on non asan build. + DCHECK(!drag_source_window_ || !drag_source_window_->is_destroying()); + + CleanupPendingLongTap(); } return operation_; @@ -263,6 +272,13 @@ void DragDropController::SetDragImage(const gfx::ImageSkia& image, const gfx::Vector2d& image_offset) { + if (image.size().IsEmpty()) { + drag_image_widget_.reset(); + drag_image_final_bounds_for_cancel_animation_ = gfx::Rect(); + drag_image_offset_ = gfx::Vector2d(); + return; + } + auto source = current_drag_event_source_; auto* source_window = drag_source_window_; @@ -275,10 +291,8 @@ drag_image_final_bounds_for_cancel_animation_ = gfx::Rect(start_location_ - image_offset, image.size()); - if (!drag_image_widget_) { - drag_image_widget_ = - DragImageView::Create(source_window->GetRootWindow(), source); - } + drag_image_widget_ = + DragImageView::Create(source_window->GetRootWindow(), source); DragImageView* drag_image = static_cast<DragImageView*>(drag_image_widget_->GetContentsView()); @@ -566,12 +580,11 @@ gfx::Point root_location_in_screen = event.root_location(); ::wm::ConvertPointToScreen(target->GetRootWindow(), &root_location_in_screen); + current_location_ = root_location_in_screen; - DCHECK(drag_image_widget_); - DragImageView* drag_image = - static_cast<DragImageView*>(drag_image_widget_->GetContentsView()); - if (drag_image->GetVisible()) { - current_location_ = root_location_in_screen; + if (drag_image_widget_) { + DragImageView* drag_image = + static_cast<DragImageView*>(drag_image_widget_->GetContentsView()); drag_image->SetScreenPosition(root_location_in_screen - drag_image_offset_); drag_image->SetTouchDragOperation(drag_info.drag_operation); } @@ -625,8 +638,8 @@ DropIfAllowed( drag_data_.get(), current_drag_info_, base::BindOnce(&DragDropController::PerformDrop, - drop_weak_factory_.GetWeakPtr(), drop_location_in_screen, - e, std::move(drag_data_), std::move(delegate_drop_cb), + weak_factory_.GetWeakPtr(), drop_location_in_screen, e, + std::move(drag_data_), std::move(delegate_drop_cb), std::move(tab_drag_drop_delegate_), std::move(drag_cancel))); @@ -664,21 +677,8 @@ cancel_animation_.reset(); cancel_animation_notifier_.reset(); - // By the time we finish animation, another drag/drop session may have - // started. We do not want to destroy the drag image in that case. - if (!IsDragDropInProgress()) - drag_image_widget_.reset(); - if (pending_long_tap_) { - // If not in a nested run loop, we can forward the long tap right now. - if (nested_loop_disabled_for_testing_) { - ForwardPendingLongTap(); - } else { - // See comment about this in OnGestureEvent(). - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&DragDropController::ForwardPendingLongTap, - weak_factory_.GetWeakPtr())); - } - } + drag_image_widget_.reset(); + ScheduleForwardPendingLongTap(); } void DragDropController::DoDragCancel( @@ -700,14 +700,15 @@ observer.OnDragCancelled(); Cleanup(); - // If the drop is async, then |drag_image_widget_| is already reset. - if (drag_image_widget_) - StartCanceledAnimation(drag_cancel_animation_duration); + StartCanceledAnimation(drag_cancel_animation_duration); + if (quit_closure_) std::move(quit_closure_).Run(); } void DragDropController::AnimationProgressed(const gfx::Animation* animation) { + DCHECK(drag_image_widget_); + gfx::Rect current_bounds = animation->CurrentValueBetween( drag_image_initial_bounds_for_cancel_animation_, drag_image_final_bounds_for_cancel_animation_); @@ -728,7 +729,17 @@ void DragDropController::StartCanceledAnimation( base::TimeDelta animation_duration) { - DCHECK(drag_image_widget_); + DCHECK(!cancel_animation_); + DCHECK(!will_forward_long_tap_); + + if (pending_long_tap_) + will_forward_long_tap_ = true; + + if (!drag_image_widget_) { + ScheduleForwardPendingLongTap(); + return; + } + DragImageView* drag_image = static_cast<DragImageView*>(drag_image_widget_->GetContentsView()); drag_image->SetTouchDragOperationHintOff(); @@ -743,16 +754,30 @@ cancel_animation_->Start(); } +void DragDropController::ScheduleForwardPendingLongTap() { + if (!pending_long_tap_) + return; + + // If not in a nested run loop, we can forward the long tap right now. + if (nested_loop_disabled_for_testing_) { + ForwardPendingLongTap(); + return; + } + + // See comment about this in OnGestureEvent(). + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&DragDropController::ForwardPendingLongTap, + weak_factory_.GetWeakPtr())); +} + void DragDropController::ForwardPendingLongTap() { if (drag_source_window_ && drag_source_window_->delegate()) { drag_source_window_->delegate()->OnGestureEvent( pending_long_tap_->AsGestureEvent()); DispatchGestureEndToWindow(drag_source_window_); } - pending_long_tap_.reset(); - if (drag_source_window_) - drag_source_window_->RemoveObserver(this); - drag_source_window_ = nullptr; + + CleanupPendingLongTap(); } void DragDropController::Cleanup() { @@ -761,7 +786,8 @@ drag_source_window_->ReleaseCapture(); } - // Do not remove observer `the drag_window_1 is same as `drag_source_window_`. + // Do not remove observer if `drag_window_` is the same as + // `drag_source_window_`. // `drag_source_window_` is still necessary to process long tab and the // observer will be reset when `drag_source_window_` is destroyed. if (drag_window_ && drag_window_ != drag_source_window_) @@ -775,6 +801,14 @@ capture_delegate_ = nullptr; } +void DragDropController::CleanupPendingLongTap() { + pending_long_tap_.reset(); + will_forward_long_tap_ = false; + if (drag_source_window_) + drag_source_window_->RemoveObserver(this); + drag_source_window_ = nullptr; +} + void DragDropController::PerformDrop( const gfx::Point drop_location_in_screen, ui::DropTargetEvent event, @@ -793,7 +827,6 @@ } if (operation_ == DragOperation::kNone && tab_drag_drop_delegate) { - DCHECK(drag_image_widget_); // Release the ownership of object so that it can delete itself. tab_drag_drop_delegate.release()->DropAndDeleteSelf(drop_location_in_screen, copied_data);
diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h index 8b7a551..74f935e 100644 --- a/ash/drag_drop/drag_drop_controller.h +++ b/ash/drag_drop/drag_drop_controller.h
@@ -140,12 +140,18 @@ // Helper method to start drag widget flying back animation. void StartCanceledAnimation(base::TimeDelta animation_duration); - // Helper method to forward |pending_log_tap_| event to |drag_source_window_|. + // Helper methods to forward |pending_log_tap_| event to + // |drag_source_window_|. + void ScheduleForwardPendingLongTap(); void ForwardPendingLongTap(); - // Helper method to reset everything. + // Helper method to reset most of the state, except state that could be used + // during async operations of cancellation (including cancel animation and + // posting task to dispatch long tap event). void Cleanup(); + void CleanupPendingLongTap(); + // Helper method to perform the drop if allowed by // DataTransferPolicyController. If it's run, `drag_cancel` will be replaced. // Otherwise `drag_cancel` will run to cancel the drag. @@ -204,6 +210,10 @@ // Holds a synthetic long tap event to be sent to the |drag_source_window_|. // See comment in OnGestureEvent() on why we need this. std::unique_ptr<ui::Event> pending_long_tap_; + // Set to true during async operations of cancellation (including cancel + // animation and posting task to dispatch long tap event), indicating that a + // long tap event will be dispatched. + bool will_forward_long_tap_ = false; gfx::Point start_location_; gfx::Point current_location_; @@ -213,9 +223,7 @@ ToplevelWindowDragDelegate* toplevel_window_drag_delegate_ = nullptr; - // Weak ptr for async drop callbacks to be invalidated if a new drag starts. - base::WeakPtrFactory<DragDropController> drop_weak_factory_{this}; - + // Weak ptr for async callbacks to be invalidated if a new drag starts. base::WeakPtrFactory<DragDropController> weak_factory_{this}; };
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc index 43e91b8..03573c5 100644 --- a/ash/drag_drop/drag_drop_controller_unittest.cc +++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -65,6 +65,22 @@ using ::testing::Return; using ::ui::mojom::DragOperation; +// Sets string and drag image for testing. +void SetDragData(OSExchangeData* data, bool with_image) { + data->SetString(u"I am being dragged"); + if (with_image) { + gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f); + gfx::ImageSkia image_skia(image_rep); + data->provider().SetDragImage(image_skia, gfx::Vector2d()); + } +} + +std::unique_ptr<ui::OSExchangeData> CreateDragData(bool with_image) { + auto data = std::make_unique<ui::OSExchangeData>(); + SetDragData(data.get(), with_image); + return data; +} + // A simple view that makes sure RunShellDrag is invoked on mouse drag. class DragTestView : public views::View { public: @@ -90,6 +106,8 @@ return views::View::GetHorizontalDragThreshold(); } + void OmitDragImage() { omit_drag_image_ = true; } + int num_drag_enters_; int num_drag_exits_; int num_drag_updates_; @@ -104,10 +122,7 @@ } void WriteDragData(const gfx::Point& p, OSExchangeData* data) override { - data->SetString(u"I am being dragged"); - gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f); - gfx::ImageSkia image_skia(image_rep); - data->provider().SetDragImage(image_skia, gfx::Vector2d()); + SetDragData(data, /*with_image=*/!omit_drag_image_); } bool OnMousePressed(const ui::MouseEvent& event) override { return true; } @@ -144,12 +159,13 @@ void OnDragDone() override { drag_done_received_ = true; } - private: void PerformDrop(const ui::DropTargetEvent& event, ui::mojom::DragOperation& output_drag_op) { num_drops_++; output_drag_op = DragOperation::kCopy; } + + bool omit_drag_image_ = false; }; class CompletableLinearAnimation : public gfx::LinearAnimation { @@ -584,9 +600,10 @@ ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), window); generator.PressLeftButton(); - window->SetCapture(); // aura::Window do not explicitly take capture, so call - // this - // manually to simulate dragging a view which does take capture. + + // aura::Window does not explicitly take capture, so call this manually to + // simulate dragging a view which does take capture. + window->SetCapture(); EXPECT_TRUE(window->HasCapture()); int n = 0; @@ -993,50 +1010,6 @@ EXPECT_FALSE(drag_view2->drag_done_received_); } -TEST_F(DragDropControllerTest, TouchDragDropCancelsOnLongTap) { - std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); - DragTestView* drag_view = new DragTestView; - AddViewToWidgetAndResize(widget.get(), drag_view); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - widget->GetNativeView()); - - generator.PressTouch(); - gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint(); - DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point); - DispatchGesture(ui::ET_GESTURE_LONG_TAP, point); - - EXPECT_TRUE(drag_drop_controller_->drag_start_received_); - EXPECT_TRUE(drag_drop_controller_->drag_canceled_); - EXPECT_EQ(0, drag_drop_controller_->num_drag_updates_); - EXPECT_FALSE(drag_drop_controller_->drop_received_); - EXPECT_EQ(u"I am being dragged", drag_drop_controller_->drag_string_); - EXPECT_EQ(0, drag_view->num_drag_enters_); - EXPECT_EQ(0, drag_view->num_drops_); - EXPECT_EQ(0, drag_view->num_drag_exits_); - EXPECT_TRUE(drag_view->drag_done_received_); -} - -TEST_F(DragDropControllerTest, TouchDragDropLongTapGestureIsForwarded) { - std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); - DragTestView* drag_view = new DragTestView; - AddViewToWidgetAndResize(widget.get(), drag_view); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - widget->GetNativeView()); - - generator.PressTouch(); - gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint(); - DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point); - - // Since we are not running inside a nested loop, the |drag_source_window_| - // will get destroyed immediately. Hence we reassign it. - EXPECT_EQ(NULL, GetDragSourceWindow()); - SetDragSourceWindow(widget->GetNativeView()); - EXPECT_FALSE(drag_view->long_tap_received_); - DispatchGesture(ui::ET_GESTURE_LONG_TAP, point); - CompleteCancelAnimation(); - EXPECT_TRUE(drag_view->long_tap_received_); -} - TEST_F(DragDropControllerTest, DragDropWithChangingIcon) { std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); DragTestView* drag_view1 = new DragTestView; @@ -1124,8 +1097,7 @@ } { - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/true); std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); aura::Window* window = widget->GetNativeWindow(); drag_drop_controller_->StartDragAndDrop( @@ -1158,8 +1130,7 @@ } { - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/true); std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); aura::Window* window = widget->GetNativeWindow(); drag_drop_controller_->StartDragAndDrop( @@ -1202,8 +1173,7 @@ aura::client::SetDragDropClient(root, drag_drop_controller_.get()); } - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/false); std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); aura::Window* window = widget->GetNativeWindow(); drag_drop_controller_->StartDragAndDrop( @@ -1283,8 +1253,7 @@ drag_drop_controller_->AddObserver(&observer); { - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/false); ui::OSExchangeData* data_ptr = data.get(); std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); @@ -1326,8 +1295,7 @@ drag_drop_controller_->AddObserver(&observer); // Data for the drag. - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/false); std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); aura::Window* window = widget->GetNativeWindow(); @@ -1365,8 +1333,7 @@ base::Unretained(&generator))); drag_drop_controller_->set_should_block_during_drag_drop(true); - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/false); drag_drop_controller_->StartDragAndDrop( std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse); @@ -1673,11 +1640,7 @@ aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), -1, gfx::Rect(0, 0, 100, 100))); - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); - gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f); - gfx::ImageSkia image_skia(image_rep); - data->provider().SetDragImage(image_skia, gfx::Vector2d()); + auto data = CreateDragData(/*with_image=*/true); drag_drop_controller_->StartDragAndDrop( std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5), @@ -1722,11 +1685,7 @@ EXPECT_CALL(*mock_shell_delegate(), IsTabDrag(_)).WillOnce(Return(true)); // Drag and drop needs a drag image to work. - auto data = std::make_unique<ui::OSExchangeData>(); - data->SetString(u"I am being dragged"); - gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f); - gfx::ImageSkia image_skia(image_rep); - data->provider().SetDragImage(image_skia, gfx::Vector2d()); + auto data = CreateDragData(/*with_image=*/true); // Start drag and drop on the left tab window. auto drag_operation = drag_drop_controller_->StartDragAndDrop( @@ -1775,8 +1734,7 @@ ui::test::EventGenerator generator(window->GetRootWindow(), window.get()); generator.PressLeftButton(); - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/false); // Drop. EXPECT_CALL(dlp_contoller, DropIfAllowed(_, _, _)) @@ -1812,8 +1770,7 @@ ui::test::EventGenerator generator(window->GetRootWindow(), window.get()); generator.PressLeftButton(); - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/true); EXPECT_CALL(dlp_contoller, DropIfAllowed(_, _, _)); @@ -1828,6 +1785,8 @@ // For perform drop generator.ReleaseLeftButton(); + // There is a non-empty drag image, an animation is expected to be run for + // cancellation. EXPECT_TRUE(cancel_animation()); EXPECT_TRUE(GetDragImageWindow()); EXPECT_EQ(EventTargetTestDelegate::State::kDragExitInvoked, delegate.state()); @@ -1846,8 +1805,7 @@ ui::test::EventGenerator generator(window->GetRootWindow(), window.get()); generator.PressLeftButton(); - auto data(std::make_unique<ui::OSExchangeData>()); - data->SetString(u"I am being dragged"); + auto data = CreateDragData(/*with_image=*/true); base::OnceClosure drop_callback; @@ -1885,6 +1843,24 @@ delegate.state()); } +TEST_F(DragDropControllerTest, DragImageWidgetNotCreatedIfNoImage) { + std::unique_ptr<views::Widget> widget = CreateFramelessWidget(); + aura::Window* window = widget->GetNativeWindow(); + + auto data = CreateDragData(/*with_image=*/false); + drag_drop_controller_->StartDragAndDrop( + std::move(data), window->GetRootWindow(), window, gfx::Point(5, 5), + ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse); + EXPECT_FALSE(GetDragImageWindow()); + drag_drop_controller_->DragCancel(); + + data = CreateDragData(/*with_image=*/true); + drag_drop_controller_->StartDragAndDrop( + std::move(data), window->GetRootWindow(), window, gfx::Point(5, 5), + ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse); + EXPECT_TRUE(GetDragImageWindow()); +} + class MouseOrTouchDragDropControllerTest : public DragDropControllerTest, public testing::WithParamInterface<bool> { @@ -1975,4 +1951,88 @@ MouseOrTouchDragDropControllerTest, testing::Bool()); +namespace { + +class DragDropControllerLongTapCancelTest : public DragDropControllerTest { + public: + DragDropControllerLongTapCancelTest( + const DragDropControllerLongTapCancelTest& other) = delete; + DragDropControllerLongTapCancelTest& operator=( + const DragDropControllerLongTapCancelTest& other) = delete; + + protected: + DragDropControllerLongTapCancelTest() = default; + ~DragDropControllerLongTapCancelTest() override = default; + + void SetUp() override { + DragDropControllerTest::SetUp(); + + widget_ = CreateFramelessWidget(); + drag_view_ = new DragTestView; + AddViewToWidgetAndResize(widget_.get(), drag_view_); + generator_ = std::make_unique<ui::test::EventGenerator>( + Shell::GetPrimaryRootWindow(), widget_->GetNativeView()); + } + + void IssueLongTap() { + auto loop_task = [this](bool inside) { + gfx::Point point = gfx::Rect(drag_view_->bounds()).CenterPoint(); + if (!inside) { + generator_->PressTouch(); + DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point); + } else { + ASSERT_FALSE(inside_loop_task_executed_); + inside_loop_task_executed_ = true; + + EXPECT_FALSE(drag_view_->long_tap_received_); + DispatchGesture(ui::ET_GESTURE_LONG_TAP, point); + } + }; + RunWithClosure(base::BindLambdaForTesting(loop_task)); + } + + std::unique_ptr<views::Widget> widget_; + DragTestView* drag_view_ = nullptr; + std::unique_ptr<ui::test::EventGenerator> generator_; + bool inside_loop_task_executed_ = false; +}; + +} // namespace + +TEST_F(DragDropControllerLongTapCancelTest, TouchDragDropCancelsOnLongTap) { + IssueLongTap(); + + EXPECT_TRUE(drag_drop_controller_->drag_start_received_); + EXPECT_TRUE(drag_drop_controller_->drag_canceled_); + EXPECT_EQ(0, drag_drop_controller_->num_drag_updates_); + EXPECT_FALSE(drag_drop_controller_->drop_received_); + EXPECT_EQ(u"I am being dragged", drag_drop_controller_->drag_string_); + EXPECT_EQ(0, drag_view_->num_drag_enters_); + EXPECT_EQ(0, drag_view_->num_drops_); + EXPECT_EQ(0, drag_view_->num_drag_exits_); + EXPECT_TRUE(drag_view_->drag_done_received_); + + // The long tap gesture is expected to be forwarded after the cancel + // animation. + ASSERT_TRUE(cancel_animation()); + EXPECT_FALSE(drag_view_->long_tap_received_); + CompleteCancelAnimation(); + EXPECT_TRUE(drag_view_->long_tap_received_); +} + +TEST_F(DragDropControllerLongTapCancelTest, + LongTapForwardedWithoutCancelAnimation) { + drag_view_->OmitDragImage(); + + // DragDropController does not support touch drag/drop without a drag image, + // unless it has a non-null |toplevel_window_drag_delegate_|. + TestToplevelWindowDragDelegate delegate; + drag_drop_controller_->set_toplevel_window_drag_delegate(&delegate); + + IssueLongTap(); + + ASSERT_FALSE(cancel_animation()); + EXPECT_TRUE(drag_view_->long_tap_received_); +} + } // namespace ash
diff --git a/ash/public/cpp/ash_typography.cc b/ash/public/cpp/ash_typography.cc index 74e2ecd3..bc95f94 100644 --- a/ash/public/cpp/ash_typography.cc +++ b/ash/public/cpp/ash_typography.cc
@@ -51,9 +51,6 @@ } switch (style) { - case STYLE_EMPHASIZED: - details.weight = gfx::Font::Weight::MEDIUM; - break; case STYLE_HIGHLIGHT: details.weight = gfx::Font::Weight::BOLD; break;
diff --git a/ash/public/cpp/ash_typography.h b/ash/public/cpp/ash_typography.h index e9200754..df14423 100644 --- a/ash/public/cpp/ash_typography.h +++ b/ash/public/cpp/ash_typography.h
@@ -70,12 +70,9 @@ enum AshTextStyle { ASH_TEXT_STYLE_START = views::style::VIEWS_TEXT_STYLE_END, - // Used to draw attention to a section of body text such as the date. - STYLE_EMPHASIZED = ASH_TEXT_STYLE_START, - // Used to strongly draw attention to a section or body of text such as a // matched search string. - STYLE_HIGHLIGHT, + STYLE_HIGHLIGHT = ASH_TEXT_STYLE_START, // Text styling specifically for the Chrome OS sharesheet. STYLE_SHARESHEET,
diff --git a/ash/public/cpp/new_window_delegate.h b/ash/public/cpp/new_window_delegate.h index 5b4c0ffe..c8ab9625 100644 --- a/ash/public/cpp/new_window_delegate.h +++ b/ash/public/cpp/new_window_delegate.h
@@ -71,12 +71,21 @@ // If the |from| is kArc, then the new window is annotated a special tag, // so that on requesting to opening ARC app from the page, confirmation // dialog will be skipped. + // |Disposition| corresponds to the subset of |WindowOpenDisposition| that is + // supported by crosapi. enum class OpenUrlFrom { kUnspecified, kUserInteraction, kArc, }; - virtual void OpenUrl(const GURL& url, OpenUrlFrom from) = 0; + enum class Disposition { + kNewForegroundTab, + kNewWindow, + kSwitchToTab, + }; + virtual void OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) = 0; // Invoked when an accelerator (calculator key) is used to open calculator. virtual void OpenCalculator() = 0;
diff --git a/ash/public/cpp/test/test_new_window_delegate.cc b/ash/public/cpp/test/test_new_window_delegate.cc index 26bd0fe..46f8bce 100644 --- a/ash/public/cpp/test/test_new_window_delegate.cc +++ b/ash/public/cpp/test/test_new_window_delegate.cc
@@ -22,7 +22,9 @@ NewWindowForDetachingTabCallback closure) { std::move(closure).Run(/*new_window=*/nullptr); } -void TestNewWindowDelegate::OpenUrl(const GURL& url, OpenUrlFrom from) {} +void TestNewWindowDelegate::OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) {} void TestNewWindowDelegate::OpenCalculator() {} void TestNewWindowDelegate::OpenFileManager() {} void TestNewWindowDelegate::OpenDownloadsFolder() {}
diff --git a/ash/public/cpp/test/test_new_window_delegate.h b/ash/public/cpp/test/test_new_window_delegate.h index 77d0aae4..b0a6e5e 100644 --- a/ash/public/cpp/test/test_new_window_delegate.h +++ b/ash/public/cpp/test/test_new_window_delegate.h
@@ -27,7 +27,9 @@ aura::Window* source_window, const ui::OSExchangeData& drop_data, NewWindowForDetachingTabCallback closure) override; - void OpenUrl(const GURL& url, OpenUrlFrom from) override; + void OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) override; void OpenCalculator() override; void OpenFileManager() override; void OpenDownloadsFolder() override;
diff --git a/ash/quick_pair/ui/fast_pair/fast_pair_presenter_impl.cc b/ash/quick_pair/ui/fast_pair/fast_pair_presenter_impl.cc index f46ced7..6b63f1d 100644 --- a/ash/quick_pair/ui/fast_pair/fast_pair_presenter_impl.cc +++ b/ash/quick_pair/ui/fast_pair/fast_pair_presenter_impl.cc
@@ -253,7 +253,8 @@ DiscoveryCallback callback) { NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kDiscoveryLearnMoreLink), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); callback.Run(DiscoveryAction::kLearnMore); } @@ -382,7 +383,8 @@ AssociateAccountCallback callback) { NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kAssociateAccountLearnMoreLink), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); callback.Run(AssociateAccountAction::kLearnMore); }
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index a2f53eb..24b5307b 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -242,6 +242,8 @@ "phone_hub_silence_phone.icon", "pin_request_lock.icon", "pinned.icon", + "privacy_indicators_camera.icon", + "privacy_indicators_microphone.icon", "privacy_screen.icon", "remove_outline.icon", "reorder.icon",
diff --git a/ash/resources/vector_icons/privacy_indicators_camera.icon b/ash/resources/vector_icons/privacy_indicators_camera.icon new file mode 100644 index 0000000..8d2667ae --- /dev/null +++ b/ash/resources/vector_icons/privacy_indicators_camera.icon
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 2, 6, +CUBIC_TO, 2, 5.45f, 2.45f, 5, 3, 5, +R_H_LINE_TO, 10, +CUBIC_TO, 13.55f, 5, 14, 5.45f, 14, 6, +R_V_LINE_TO, 8.01f, +R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -1, 1, +H_LINE_TO, 3, +CUBIC_TO, 2.45f, 15, 2, 14.55f, 2, 14, +V_LINE_TO, 6, +CLOSE, +MOVE_TO, 14, 8.5f, +R_LINE_TO, 4, -3, +R_V_LINE_TO, 9, +LINE_TO, 14, 12, +V_LINE_TO, 8.5f, +CLOSE \ No newline at end of file
diff --git a/ash/resources/vector_icons/privacy_indicators_microphone.icon b/ash/resources/vector_icons/privacy_indicators_microphone.icon new file mode 100644 index 0000000..f0573ea5 --- /dev/null +++ b/ash/resources/vector_icons/privacy_indicators_microphone.icon
@@ -0,0 +1,24 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 10, 12.11f, +R_CUBIC_TO, 1.42f, 0, 2.56f, -1.13f, 2.56f, -2.53f, +R_LINE_TO, 0.01f, -5.05f, +CUBIC_TO, 12.57f, 3.13f, 11.42f, 2, 10, 2, +CUBIC_TO, 8.58f, 2, 7.43f, 3.13f, 7.43f, 4.53f, +R_V_LINE_TO, 5.05f, +R_CUBIC_TO, 0, 1.4f, 1.15f, 2.53f, 2.57f, 2.53f, +CLOSE, +R_MOVE_TO, 4.54f, -2.53f, +R_CUBIC_TO, 0, 2.53f, -2.18f, 4.29f, -4.54f, 4.29f, +R_CUBIC_TO, -2.37f, 0, -4.54f, -1.77f, -4.54f, -4.29f, +H_LINE_TO, 4, +CUBIC_TO, 4, 12.46f, 6.33f, 14.83f, 9.14f, 15.24f, +V_LINE_TO, 18, +R_H_LINE_TO, 1.71f, +R_V_LINE_TO, -2.76f, +CUBIC_TO, 13.67f, 14.83f, 16, 12.46f, 16, 9.58f, +R_H_LINE_TO, -1.46f, +CLOSE \ No newline at end of file
diff --git a/ash/services/device_sync/BUILD.gn b/ash/services/device_sync/BUILD.gn index b67ee22..840fa9b5 100644 --- a/ash/services/device_sync/BUILD.gn +++ b/ash/services/device_sync/BUILD.gn
@@ -324,9 +324,9 @@ "//ash/services/device_sync/public/mojom:unit_tests", "//base", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/network", "//chromeos/ash/components/network:test_support", - "//chromeos/dbus:test_support", "//components/gcm_driver:test_support", "//components/prefs:test_support", "//components/signin/public/identity_manager:test_support",
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc index fa60b95..04982ed 100644 --- a/ash/shelf/home_button.cc +++ b/ash/shelf/home_button.cc
@@ -36,6 +36,7 @@ #include "ui/views/controls/button/button_controller.h" #include "ui/views/controls/label.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" namespace ash { @@ -409,7 +410,7 @@ nudge_label_->SetPaintToLayer(); nudge_label_->layer()->SetFillsBoundsOpaquely(false); nudge_label_->SetTextContext(CONTEXT_LAUNCHER_NUDGE_LABEL); - nudge_label_->SetTextStyle(STYLE_EMPHASIZED); + nudge_label_->SetTextStyle(views::style::STYLE_EMPHASIZED); nudge_label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( AshColorProvider::ContentLayerType::kTextColorPrimary));
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc index 58ba72d..dbdb32d4 100644 --- a/ash/shelf/shelf_app_button.cc +++ b/ash/shelf/shelf_app_button.cc
@@ -15,6 +15,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/default_color_constants.h" #include "ash/style/default_colors.h" +#include "ash/style/dot_indicator.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/bind.h" #include "base/i18n/rtl.h" @@ -42,7 +43,6 @@ #include "ui/views/animation/ink_drop.h" #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/animation/square_ink_drop_ripple.h" -#include "ui/views/controls/dot_indicator.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/image_view.h" @@ -61,7 +61,7 @@ // The size of the notification indicator circle padding over the size of the // icon. -constexpr float kNotificationIndicatorPaddingRatio = 4.0f / 64.0f; +constexpr float kNotificationIndicatorPaddingRatio = 5.0f / 64.0f; constexpr SkColor kDefaultIndicatorColor = SK_ColorWHITE; constexpr SkAlpha kInactiveIndicatorOpacity = 0x80; @@ -373,8 +373,8 @@ AddChildView(indicator_); AddChildView(icon_view_); - notification_indicator_ = views::DotIndicator::Install(this); - SetNotificationBadgeColor(kDefaultIndicatorColor); + notification_indicator_ = + AddChildView(std::make_unique<DotIndicator>(kDefaultIndicatorColor)); views::InkDrop::Get(this)->GetInkDrop()->AddObserver(this); @@ -442,7 +442,7 @@ indicator_->ShowActiveStatus(true); if (state & STATE_NOTIFICATION) - notification_indicator_->Show(); + notification_indicator_->SetVisible(true); if (state & STATE_DRAGGING) ScaleAppIcon(true); @@ -459,7 +459,7 @@ indicator_->ShowActiveStatus(false); if (state & STATE_NOTIFICATION) - notification_indicator_->Hide(); + notification_indicator_->SetVisible(false); if (state & STATE_DRAGGING) ScaleAppIcon(false); @@ -736,10 +736,10 @@ gfx::Rect ShelfAppButton::GetNotificationIndicatorBounds(float icon_scale) { gfx::Rect scaled_icon_view_bounds = GetIconViewBounds(GetContentsBounds(), icon_scale); - float diameter = std::ceil(kNotificationIndicatorWidthRatio * - scaled_icon_view_bounds.width()); - float padding = std::ceil(kNotificationIndicatorPaddingRatio * - scaled_icon_view_bounds.width()); + float diameter = + kNotificationIndicatorWidthRatio * scaled_icon_view_bounds.width(); + float padding = + kNotificationIndicatorPaddingRatio * scaled_icon_view_bounds.width(); return gfx::ToRoundedRect( gfx::RectF(scaled_icon_view_bounds.right() - diameter - padding, scaled_icon_view_bounds.y() + padding, diameter, diameter)); @@ -755,7 +755,7 @@ icon_view_->SetBoundsRect(icon_view_bounds); - notification_indicator_->SetBoundsRect( + notification_indicator_->SetIndicatorBounds( GetNotificationIndicatorBounds(icon_scale_)); // The indicators should be aligned with the icon, not the icon + shadow. @@ -1022,8 +1022,7 @@ void ShelfAppButton::SetNotificationBadgeColor(SkColor color) { if (notification_indicator_) - notification_indicator_->SetColor( - /*dot_color=*/color, /*border_color=*/SkColorSetA(SK_ColorBLACK, 0x4D)); + notification_indicator_->SetColor(color); } void ShelfAppButton::MaybeHideInkDropWhenGestureEnds() {
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h index 862ad52..e4d4600 100644 --- a/ash/shelf/shelf_app_button.h +++ b/ash/shelf/shelf_app_button.h
@@ -17,12 +17,12 @@ #include "ui/views/animation/ink_drop_state.h" namespace views { -class DotIndicator; class ImageView; } // namespace views namespace ash { struct ShelfItem; +class DotIndicator; class ShelfView; // Button used for app shortcuts on the shelf.. @@ -201,7 +201,7 @@ // Draws an indicator in the top right corner of the image to represent an // active notification. - views::DotIndicator* notification_indicator_ = nullptr; + DotIndicator* notification_indicator_ = nullptr; // The current application state, a bitfield of State enum values. int state_ = STATE_NORMAL;
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc index 6aa7cd91..020b1cdb 100644 --- a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc +++ b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -59,6 +59,7 @@ #include "ui/views/controls/textfield/textfield.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/widget/widget.h" namespace keyboard_shortcut_viewer { @@ -596,7 +597,7 @@ item_view->description_label_view(); // Clear previous styles. description_label_view->ClearStyleRanges(); - style.text_style = ash::AshTextStyle::STYLE_EMPHASIZED; + style.text_style = views::style::STYLE_EMPHASIZED; description_label_view->AddStyleRange( gfx::Range(match_index, match_index + match_length), style); // Apply new styles to highlight matched search query.
diff --git a/ash/style/dot_indicator.cc b/ash/style/dot_indicator.cc new file mode 100644 index 0000000..917be5d --- /dev/null +++ b/ash/style/dot_indicator.cc
@@ -0,0 +1,71 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/dot_indicator.h" + +#include "ui/compositor/layer.h" +#include "ui/gfx/geometry/insets.h" +#include "ui/gfx/scoped_canvas.h" +#include "ui/gfx/skia_paint_util.h" + +namespace ash { + +namespace { + +// The shadow value installed on the dot indicator. +const gfx::ShadowValues kIndicatorShadow = + gfx::ShadowValue::MakeChromeOSSystemUIShadowValues(2); + +} // namespace + +DotIndicator::DotIndicator(SkColor indicator_color) + : shadow_values_(kIndicatorShadow), indicator_color_(indicator_color) { + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + SetVisible(false); +} + +DotIndicator::~DotIndicator() = default; + +void DotIndicator::SetColor(SkColor new_color) { + indicator_color_ = new_color; + SchedulePaint(); +} + +void DotIndicator::SetIndicatorBounds(gfx::Rect indicator_bounds) { + // Include the shadow margin to the bounds. + indicator_bounds.Inset(gfx::ShadowValue::GetMargin(shadow_values_)); + SetBoundsRect(indicator_bounds); +} + +void DotIndicator::OnPaint(gfx::Canvas* canvas) { + // Return early if the indicator bounds are not set yet. + if (bounds().IsEmpty()) + return; + + gfx::ScopedCanvas scoped(canvas); + canvas->SaveLayerAlpha(SK_AlphaOPAQUE); + + const float dsf = canvas->UndoDeviceScaleFactor(); + + // Remove the shadow margin to get the indicator bounds without shadow. + gfx::Rect bounds_without_shadow = bounds(); + gfx::Insets shadow_insets = -gfx::ShadowValue::GetMargin(shadow_values_); + bounds_without_shadow.Inset(shadow_insets); + float radius = bounds_without_shadow.width() / 2.0f; + + // Set the center of the dot with the shadow offset. + gfx::PointF center = + gfx::PointF(radius + shadow_insets.left(), radius + shadow_insets.top()); + center.Scale(dsf); + + // Fill the center. + cc::PaintFlags flags; + flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); + flags.setColor(indicator_color_); + flags.setAntiAlias(true); + canvas->DrawCircle(center, dsf * radius, flags); +} + +} // namespace ash
diff --git a/ash/style/dot_indicator.h b/ash/style/dot_indicator.h new file mode 100644 index 0000000..95628718 --- /dev/null +++ b/ash/style/dot_indicator.h
@@ -0,0 +1,39 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_STYLE_DOT_INDICATOR_H_ +#define ASH_STYLE_DOT_INDICATOR_H_ + +#include "ash/ash_export.h" +#include "ui/views/view.h" + +namespace ash { + +// The indicator which is activated when its corresponding app receives a +// notification. This is thus set invisible as default and should be explicitly +// set to visible by the owner view. The owner of this component is also +// responsible for setting the correct bounds on the app icon. +class ASH_EXPORT DotIndicator : public views::View { + public: + explicit DotIndicator(SkColor indicator_color); + DotIndicator(const DotIndicator& other) = delete; + DotIndicator& operator=(const DotIndicator& other) = delete; + ~DotIndicator() override; + + void SetColor(SkColor new_color); + + // Sets the bounds of the indicator without shadow. + void SetIndicatorBounds(gfx::Rect indicator_bounds); + + private: + // views::View: + void OnPaint(gfx::Canvas* canvas) override; + + const gfx::ShadowValues shadow_values_; + SkColor indicator_color_; +}; + +} // namespace ash + +#endif // ASH_STYLE_DOT_INDICATOR_H_ \ No newline at end of file
diff --git a/ash/system/keyboard_brightness/unified_keyboard_brightness_slider_controller.cc b/ash/system/keyboard_brightness/unified_keyboard_brightness_slider_controller.cc index 080dba9..50920dd 100644 --- a/ash/system/keyboard_brightness/unified_keyboard_brightness_slider_controller.cc +++ b/ash/system/keyboard_brightness/unified_keyboard_brightness_slider_controller.cc
@@ -90,6 +90,7 @@ auto* image = rb.GetImageSkiaNamed(IDR_SETTINGS_RGB_KEYBOARD_RAINBOW_COLOR_48_PNG); button->SetBackgroundImage(*image); + button->SetIconColor(gfx::kGoogleGrey900); } else { SkColor color = ConvertBacklightColorToIconBackgroundColor(backlight_color);
diff --git a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.cc b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.cc index 9099229f..cc9200a 100644 --- a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.cc +++ b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller.cc
@@ -104,7 +104,8 @@ case ButtonIndex::kLearnMore: NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); break; } RemoveNotification(kPciePeripheralLimitedPerformanceNotificationId); @@ -112,8 +113,8 @@ void OnGuestNotificationClicked(bool is_thunderbolt_only) { NewWindowDelegate::GetPrimary()->OpenUrl( - GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); if (is_thunderbolt_only) { RemoveNotification(kPciePeripheralGuestModeNotSupportedNotificationId); @@ -125,15 +126,15 @@ void OnPeripheralBlockedNotificationClicked() { NewWindowDelegate::GetPrimary()->OpenUrl( - GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); RemoveNotification(kPciePeripheralDeviceBlockedNotificationId); } void OnBillboardNotificationClicked() { NewWindowDelegate::GetPrimary()->OpenUrl( - GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); RemoveNotification(kPciePeripheralBillboardDeviceNotificationId); }
diff --git a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller_unittest.cc b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller_unittest.cc index 14b5118..60bd926 100644 --- a/ash/system/pcie_peripheral/pcie_peripheral_notification_controller_unittest.cc +++ b/ash/system/pcie_peripheral/pcie_peripheral_notification_controller_unittest.cc
@@ -43,7 +43,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; } // namespace @@ -163,7 +166,8 @@ // Click on the notification and expect the Learn More page to appear. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); ClickGuestNotification(/*is_thunderbolt_only=*/true); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount()); } @@ -187,7 +191,8 @@ // Click on the notification and expect the Learn More page to appear. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); ClickGuestNotification(/*is_thunderbolt_only=*/false); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount()); } @@ -209,7 +214,8 @@ // Click on the notification and expect the Learn More page to appear. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); MessageCenter::Get()->ClickOnNotification( kPciePeripheralDeviceBlockedNotificationId); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount()); @@ -234,7 +240,8 @@ // Click on the notification and expect the Learn More page to appear. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); MessageCenter::Get()->ClickOnNotification( kPciePeripheralBillboardDeviceNotificationId); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount()); @@ -258,7 +265,8 @@ EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); // Click the learn more link. ClickLimitedNotificationButton(/*button_index=*/1); EXPECT_EQ(2, GetPrefNotificationCount()); @@ -266,7 +274,8 @@ EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); controller()->NotifyLimitedPerformance(); ClickLimitedNotificationButton(/*button_index=*/1); EXPECT_EQ(1, GetPrefNotificationCount()); @@ -274,7 +283,8 @@ EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); controller()->NotifyLimitedPerformance(); ClickLimitedNotificationButton(/*button_index=*/1); EXPECT_EQ(0, GetPrefNotificationCount()); @@ -360,7 +370,8 @@ // decrement. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); ClickGuestNotification(/*is_thunderbolt_only=*/true); EXPECT_EQ(3, GetPrefNotificationCount()); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount()); @@ -388,7 +399,8 @@ // decrement. EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(kLearnMoreHelpUrl), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); ClickGuestNotification(/*is_thunderbolt_only=*/false); EXPECT_EQ(3, GetPrefNotificationCount()); EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
diff --git a/ash/system/phonehub/bluetooth_disabled_view.cc b/ash/system/phonehub/bluetooth_disabled_view.cc index d9c0a964..581f175 100644 --- a/ash/system/phonehub/bluetooth_disabled_view.cc +++ b/ash/system/phonehub/bluetooth_disabled_view.cc
@@ -67,7 +67,8 @@ LogInterstitialScreenEvent(InterstitialScreenEvent::kLearnMore); NewWindowDelegate::GetPrimary()->OpenUrl( GURL(phonehub::kPhoneHubLearnMoreLink), - NewWindowDelegate::OpenUrlFrom::kUserInteraction); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } BEGIN_METADATA(BluetoothDisabledView, views::View)
diff --git a/ash/system/phonehub/continue_browsing_chip.cc b/ash/system/phonehub/continue_browsing_chip.cc index d9b290a..429697a 100644 --- a/ash/system/phonehub/continue_browsing_chip.cc +++ b/ash/system/phonehub/continue_browsing_chip.cc
@@ -142,7 +142,8 @@ user_action_recorder_->RecordBrowserTabOpened(); NewWindowDelegate::GetPrimary()->OpenUrl( - url_, NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url_, NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); // Close Phone Hub bubble in current display. views::Widget* const widget = GetWidget();
diff --git a/ash/system/phonehub/multidevice_feature_opt_in_view.cc b/ash/system/phonehub/multidevice_feature_opt_in_view.cc index e33d8044..7af67bb 100644 --- a/ash/system/phonehub/multidevice_feature_opt_in_view.cc +++ b/ash/system/phonehub/multidevice_feature_opt_in_view.cc
@@ -151,7 +151,8 @@ PA_LOG(INFO) << "MultideviceFeatureOptInView SetUpButtonPressed target url:" << url; NewWindowDelegate::GetInstance()->OpenUrl( - GURL(url), NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(url), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } void MultideviceFeatureOptInView::DismissButtonPressed() {
diff --git a/ash/system/phonehub/phone_disconnected_view.cc b/ash/system/phonehub/phone_disconnected_view.cc index 906527c5..aad1803 100644 --- a/ash/system/phonehub/phone_disconnected_view.cc +++ b/ash/system/phonehub/phone_disconnected_view.cc
@@ -52,7 +52,8 @@ &NewWindowDelegate::OpenUrl, base::Unretained(NewWindowDelegate::GetPrimary()), GURL(phonehub::kPhoneHubLearnMoreLink), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)), + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)), l10n_util::GetStringUTF16( IDS_ASH_PHONE_HUB_PHONE_DISCONNECTED_DIALOG_LEARN_MORE_BUTTON), PillButton::Type::kIconlessFloating, /*icon=*/nullptr);
diff --git a/ash/system/phonehub/phone_hub_tray_unittest.cc b/ash/system/phonehub/phone_hub_tray_unittest.cc index 1f30c6df..ad06283 100644 --- a/ash/system/phonehub/phone_hub_tray_unittest.cc +++ b/ash/system/phonehub/phone_hub_tray_unittest.cc
@@ -41,7 +41,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; } // namespace @@ -316,7 +319,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=5"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); @@ -365,7 +369,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=7"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); } @@ -394,7 +399,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=4"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); } @@ -421,7 +427,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=1"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); } @@ -450,7 +457,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=2"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); } @@ -497,7 +505,8 @@ EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("chrome://os-settings/multidevice/" "features?showPhonePermissionSetupDialog&mode=3"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); LeftClickOn(notification_opt_in_set_up_button()); } @@ -634,7 +643,8 @@ // article in a browser tab. EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("https://support.google.com/chromebook?p=phone_hub"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); // Simulates a click on the "Learn more" button. LeftClickOn(disconnected_learn_more_button()); @@ -652,7 +662,8 @@ // article in a browser tab. EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("https://support.google.com/chromebook?p=phone_hub"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); // Simulate a click on "Learn more" button. LeftClickOn(bluetooth_disabled_learn_more_button()); }
diff --git a/ash/system/phonehub/task_continuation_view_unittest.cc b/ash/system/phonehub/task_continuation_view_unittest.cc index b322480..fb60743 100644 --- a/ash/system/phonehub/task_continuation_view_unittest.cc +++ b/ash/system/phonehub/task_continuation_view_unittest.cc
@@ -25,7 +25,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; } // namespace @@ -116,7 +119,8 @@ // OpenUrl is expected to call after button pressed simulation. EXPECT_CALL(new_window_delegate(), OpenUrl(GURL("https://www.example.com/tab1"), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); // Simulate clicking button using dummy event. views::test::ButtonTestApi(chip).NotifyClick(ui::test::TestEvent()); }
diff --git a/ash/system/privacy/privacy_indicators_tray_item_view.cc b/ash/system/privacy/privacy_indicators_tray_item_view.cc new file mode 100644 index 0000000..3ada849 --- /dev/null +++ b/ash/system/privacy/privacy_indicators_tray_item_view.cc
@@ -0,0 +1,127 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/privacy/privacy_indicators_tray_item_view.h" + +#include <memory> +#include <string> + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/shelf/shelf.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_provider.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/color/color_id.h" +#include "ui/gfx/geometry/insets.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/background.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +namespace { + +constexpr auto kPrivacyIndicatorsViewPadding = gfx::Insets::VH(4, 8); +const int kPrivacyIndicatorsViewSpacing = 2; +const int kPrivacyIndicatorsIconSize = 16; +const int kPrivacyIndicatorsViewHeight = 24; +const int kPrivacyIndicatorsViewWidth = 50; + +} // namespace + +PrivacyIndicatorsTrayItemView::PrivacyIndicatorsTrayItemView(Shelf* shelf) + : TrayItemView(shelf) { + auto container_view = std::make_unique<views::View>(); + auto* layout = + container_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, + kPrivacyIndicatorsViewPadding, kPrivacyIndicatorsViewSpacing)); + layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kCenter); + + auto camera_icon = std::make_unique<views::ImageView>(); + camera_icon_ = container_view->AddChildView(std::move(camera_icon)); + + auto microphone_icon = std::make_unique<views::ImageView>(); + microphone_icon_ = container_view->AddChildView(std::move(microphone_icon)); + + AddChildView(std::move(container_view)); + + UpdateIcons(); +} + +PrivacyIndicatorsTrayItemView::~PrivacyIndicatorsTrayItemView() = default; + +void PrivacyIndicatorsTrayItemView::Update(bool camera_is_used, + bool microphone_is_used) { + if (camera_is_used_ == camera_is_used && + microphone_is_used_ == microphone_is_used) { + return; + } + camera_is_used_ = camera_is_used; + microphone_is_used_ = microphone_is_used; + + TooltipTextChanged(); + + // TODO(crbug/1352595): Handle icon visibility change. +} + +void PrivacyIndicatorsTrayItemView::UpdateAlignmentForShelf(Shelf* shelf) { + // TODO(crbug/1352593): Handle layout change when shelf alignment changes. +} + +void PrivacyIndicatorsTrayItemView::HandleLocaleChange() { + TooltipTextChanged(); +} + +gfx::Size PrivacyIndicatorsTrayItemView::CalculatePreferredSize() const { + return gfx::Size(kPrivacyIndicatorsViewWidth, kPrivacyIndicatorsViewHeight); +} + +void PrivacyIndicatorsTrayItemView::OnThemeChanged() { + views::View::OnThemeChanged(); + SetBackground(views::CreateThemedRoundedRectBackground( + ui::kColorAshPrivacyIndicatorsBackground, height() / 2, + height() - kPrivacyIndicatorsViewHeight)); + UpdateIcons(); +} + +std::u16string PrivacyIndicatorsTrayItemView::GetTooltipText( + const gfx::Point& p) const { + if (camera_is_used_ && microphone_is_used_) { + return l10n_util::GetStringUTF16( + IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA_AND_MIC); + } + + if (camera_is_used_) + return l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA); + + if (microphone_is_used_) + return l10n_util::GetStringUTF16(IDS_PRIVACY_NOTIFICATION_TITLE_MIC); + + return std::u16string(); +} + +views::View* PrivacyIndicatorsTrayItemView::GetTooltipHandlerForPoint( + const gfx::Point& point) { + return GetLocalBounds().Contains(point) ? this : nullptr; +} + +const char* PrivacyIndicatorsTrayItemView::GetClassName() const { + return "PrivacyIndicatorsTrayItemView"; +} + +void PrivacyIndicatorsTrayItemView::UpdateIcons() { + const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kIconColorPrimary); + + camera_icon_->SetImage(gfx::CreateVectorIcon( + kPrivacyIndicatorsCameraIcon, kPrivacyIndicatorsIconSize, icon_color)); + microphone_icon_->SetImage( + gfx::CreateVectorIcon(kPrivacyIndicatorsMicrophoneIcon, + kPrivacyIndicatorsIconSize, icon_color)); +} + +} // namespace ash
diff --git a/ash/system/privacy/privacy_indicators_tray_item_view.h b/ash/system/privacy/privacy_indicators_tray_item_view.h new file mode 100644 index 0000000..87dc242f7 --- /dev/null +++ b/ash/system/privacy/privacy_indicators_tray_item_view.h
@@ -0,0 +1,54 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_PRIVACY_PRIVACY_INDICATORS_TRAY_ITEM_VIEW_H_ +#define ASH_SYSTEM_PRIVACY_PRIVACY_INDICATORS_TRAY_ITEM_VIEW_H_ + +#include "ash/ash_export.h" +#include "ash/system/tray/tray_item_view.h" + +namespace ash { +class Shelf; + +// A tray item which resides in the system tray, indicating to users that an app +// is currently accessing camera/microphone. +class ASH_EXPORT PrivacyIndicatorsTrayItemView : public TrayItemView { + public: + explicit PrivacyIndicatorsTrayItemView(Shelf* shelf); + + PrivacyIndicatorsTrayItemView(const PrivacyIndicatorsTrayItemView&) = delete; + PrivacyIndicatorsTrayItemView& operator=( + const PrivacyIndicatorsTrayItemView&) = delete; + + ~PrivacyIndicatorsTrayItemView() override; + + // Update the view according to the state of camara/microphone access. + void Update(bool camera_is_used, bool microphone_is_used); + + // Update the view according to the shelf alignment. + void UpdateAlignmentForShelf(Shelf* shelf); + + private: + // TrayItemView: + void HandleLocaleChange() override; + gfx::Size CalculatePreferredSize() const override; + void OnThemeChanged() override; + std::u16string GetTooltipText(const gfx::Point& p) const override; + views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override; + const char* GetClassName() const override; + + // Update the icons for the children views. + void UpdateIcons(); + + // Owned by the views hierarchy. + views::ImageView* camera_icon_ = nullptr; + views::ImageView* microphone_icon_ = nullptr; + + bool camera_is_used_ = false; + bool microphone_is_used_ = false; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_PRIVACY_PRIVACY_INDICATORS_TRAY_ITEM_VIEW_H_
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc index f1cbc55..cb95e0d 100644 --- a/ash/system/time/calendar_view.cc +++ b/ash/system/time/calendar_view.cc
@@ -42,6 +42,7 @@ #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/table_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" #include "ui/views/view_class_properties.h" @@ -162,8 +163,8 @@ gfx::Insets::VH(calendar_utils::kDateVerticalPadding, 0)))); label->SetElideBehavior(gfx::NO_ELIDE); label->SetSubpixelRenderingEnabled(false); - label->SetFontList( - views::style::GetFont(CONTEXT_CALENDAR_DATE, STYLE_EMPHASIZED)); + label->SetFontList(views::style::GetFont(CONTEXT_CALENDAR_DATE, + views::style::STYLE_EMPHASIZED)); AddChildView(std::move(label)); }
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index 6cc2b106..be7d2b9 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -25,6 +25,7 @@ #include "ash/system/model/system_tray_model.h" #include "ash/system/network/network_tray_view.h" #include "ash/system/power/tray_power.h" +#include "ash/system/privacy/privacy_indicators_tray_item_view.h" #include "ash/system/privacy_screen/privacy_screen_toast_controller.h" #include "ash/system/status_area_widget.h" #include "ash/system/time/calendar_metrics.h" @@ -192,7 +193,10 @@ CameraMicTrayItemView::Type::kCamera)), mic_view_( new CameraMicTrayItemView(shelf, CameraMicTrayItemView::Type::kMic)), - time_view_(new TimeTrayItemView(shelf, TimeView::Type::kTime)) { + time_view_(new TimeTrayItemView(shelf, TimeView::Type::kTime)), + privacy_indicators_view_(features::IsPrivacyIndicatorsEnabled() + ? new PrivacyIndicatorsTrayItemView(shelf) + : nullptr) { if (media::ShouldEnableAutoFraming()) { autozoom_toast_controller_ = std::make_unique<AutozoomToastController>( this, std::make_unique<AutozoomToastController::Delegate>()); @@ -259,6 +263,9 @@ AddTrayItemToContainer(time_view_); } + if (features::IsPrivacyIndicatorsEnabled()) + AddTrayItemToContainer(privacy_indicators_view_); + set_separator_visibility(false); set_use_bounce_in_animation(false); @@ -314,6 +321,14 @@ vertical_clock_padding_->SetVisible(should_show_padding); } +void UnifiedSystemTray::UpdatePrivacyIndicatorsTrayItem( + bool camera_is_used, + bool microphone_is_used) { + if (!features::IsPrivacyIndicatorsEnabled()) + return; + privacy_indicators_view_->Update(camera_is_used, microphone_is_used); +} + void UnifiedSystemTray::OnViewVisibilityChanged(views::View* observed_view, views::View* starting_view) { MaybeUpdateVerticalClockPadding();
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index 06c056cc..e1f7e28 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -39,6 +39,7 @@ class NetworkTrayView; class NotificationGroupingController; class NotificationIconsController; +class PrivacyIndicatorsTrayItemView; class PrivacyScreenToastController; class SnoopingProtectionView; class TimeTrayItemView; @@ -88,6 +89,10 @@ // icons in the tray, removes it if the clock is the only visible icon. void MaybeUpdateVerticalClockPadding(); + // Update `privacy_indicators_view_` according to camera/microphone access. + void UpdatePrivacyIndicatorsTrayItem(bool camera_is_used, + bool microphone_is_used); + // views::ViewObserver: void OnViewVisibilityChanged(views::View* observed_view, views::View* starting_view) override; @@ -297,6 +302,7 @@ CameraMicTrayItemView* const camera_view_; CameraMicTrayItemView* const mic_view_; TimeTrayItemView* const time_view_; + PrivacyIndicatorsTrayItemView* const privacy_indicators_view_; NetworkTrayView* network_tray_view_ = nullptr; ChannelIndicatorView* channel_indicator_view_ = nullptr;
diff --git a/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc b/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc index a3cb3f0..beced32a 100644 --- a/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc +++ b/ash/system/usb_peripheral/usb_peripheral_notification_controller.cc
@@ -67,7 +67,8 @@ if (button_index) { NewWindowDelegate::GetInstance()->OpenUrl( - GURL(landing_page), NewWindowDelegate::OpenUrlFrom::kUserInteraction); + GURL(landing_page), NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } message_center::MessageCenter::Get()->RemoveNotification(notification_id,
diff --git a/ash/webui/camera_app_ui/camera_app_helper_impl.cc b/ash/webui/camera_app_ui/camera_app_helper_impl.cc index 1f2ce0f..c49f645 100644 --- a/ash/webui/camera_app_ui/camera_app_helper_impl.cc +++ b/ash/webui/camera_app_ui/camera_app_helper_impl.cc
@@ -243,7 +243,8 @@ void CameraAppHelperImpl::OpenUrlInBrowser(const GURL& url) { NewWindowDelegate::GetPrimary()->OpenUrl( - url, NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } void CameraAppHelperImpl::SetCameraUsageMonitor(
diff --git a/ash/webui/diagnostics_ui/backend/BUILD.gn b/ash/webui/diagnostics_ui/backend/BUILD.gn index acf2637f..a1fd10f 100644 --- a/ash/webui/diagnostics_ui/backend/BUILD.gn +++ b/ash/webui/diagnostics_ui/backend/BUILD.gn
@@ -95,10 +95,10 @@ "//ash/webui/diagnostics_ui/mojom", "//base", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/shill", "//chromeos/ash/services/cros_healthd/public/cpp", "//chromeos/ash/services/cros_healthd/public/mojom", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", "//chromeos/login/login_state:login_state",
diff --git a/ash/webui/media_app_ui/media_app_guest_ui.cc b/ash/webui/media_app_ui/media_app_guest_ui.cc index 8786aad..2b880ba 100644 --- a/ash/webui/media_app_ui/media_app_guest_ui.cc +++ b/ash/webui/media_app_ui/media_app_guest_ui.cc
@@ -7,9 +7,12 @@ #include "ash/webui/grit/ash_media_app_resources.h" #include "ash/webui/media_app_ui/url_constants.h" #include "ash/webui/web_applications/webui_test_prod_util.h" +#include "base/bind.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/memory/ref_counted_memory.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/user_metrics.h" #include "base/task/task_runner_util.h" #include "base/task/thread_pool.h" #include "chromeos/grit/chromeos_media_app_bundle_resources.h" @@ -32,6 +35,60 @@ int g_media_app_window_count = 0; +// Helper class to populate MediaApp metrics for UMA and for Happiness Tracking +// surveys. Manages its own lifetime; tracking whether at least one MediaApp +// WebUI instance is still running. +class MediaAppMetricsHelper { + public: + static MediaAppUserActions actions; + + static void OnUiFirstNavigated() { + // Record the number of other media app windows that currently exist when a + // new one is created. Counts windows open with any supported file type, or + // in the "zero state" (with no open file). Pick 50 as a sensible maximum + // (additional windows will be recorded in the 51 bucket). + constexpr int kMaxExpectedWindowCount = 50; + UMA_HISTOGRAM_EXACT_LINEAR("Apps.MediaApp.Load.OtherOpenWindowCount", + g_media_app_window_count, + kMaxExpectedWindowCount); + if (g_media_app_window_count++ == 0) { + DCHECK(!instance); + instance = new MediaAppMetricsHelper(); + } + } + + static void OnUiDestroyedAfterNavigation() { + if (--g_media_app_window_count == 0) { + delete instance; + instance = nullptr; + } + } + + MediaAppMetricsHelper(const MediaAppMetricsHelper&) = delete; + MediaAppMetricsHelper& operator=(const MediaAppMetricsHelper&) = delete; + + private: + MediaAppMetricsHelper() { base::AddActionCallback(callback_); } + ~MediaAppMetricsHelper() { base::RemoveActionCallback(callback_); } + + static void OnAction(const std::string& user_action, + base::TimeTicks action_time) { + actions.clicked_edit_image_in_photos = + actions.clicked_edit_image_in_photos || + user_action == "MediaApp.Image.Tool.EditInPhotos"; + actions.clicked_edit_video_in_photos = + actions.clicked_edit_video_in_photos || + user_action == "MediaApp.Video.Tool.EditInPhotos"; + } + + base::ActionCallback callback_ = + base::BindRepeating(&MediaAppMetricsHelper::OnAction); + + static MediaAppMetricsHelper* instance; +}; +MediaAppUserActions MediaAppMetricsHelper::actions = {false, false}; +MediaAppMetricsHelper* MediaAppMetricsHelper::instance = nullptr; + bool IsFontRequest(const std::string& path) { return base::StartsWith(path, kFontRequestPrefix); } @@ -147,7 +204,7 @@ MediaAppGuestUI::~MediaAppGuestUI() { if (app_navigation_committed_) - --g_media_app_window_count; + MediaAppMetricsHelper::OnUiDestroyedAfterNavigation(); } void MediaAppGuestUI::ReadyToCommitNavigation( @@ -158,16 +215,8 @@ return; if (!app_navigation_committed_) { - // Record the number of other media app windows that currently exist when a - // new one is created. Counts windows open with any supported file type, or - // in the "zero state" (with no open file). Pick 50 as a sensible maximum - // (additional windows will be recorded in the 51 bucket). - constexpr int kMaxExpectedWindowCount = 50; - UMA_HISTOGRAM_EXACT_LINEAR("Apps.MediaApp.Load.OtherOpenWindowCount", - g_media_app_window_count, - kMaxExpectedWindowCount); app_navigation_committed_ = true; - ++g_media_app_window_count; + MediaAppMetricsHelper::OnUiFirstNavigated(); } mojo::AssociatedRemote<blink::mojom::AutoplayConfigurationClient> client; @@ -209,4 +258,8 @@ } } +MediaAppUserActions GetMediaAppUserActionsForHappinessTracking() { + return MediaAppMetricsHelper::actions; +} + } // namespace ash
diff --git a/ash/webui/media_app_ui/media_app_guest_ui.h b/ash/webui/media_app_ui/media_app_guest_ui.h index 057b5b7c..fff556e 100644 --- a/ash/webui/media_app_ui/media_app_guest_ui.h +++ b/ash/webui/media_app_ui/media_app_guest_ui.h
@@ -54,6 +54,14 @@ base::WeakPtrFactory<MediaAppGuestUI> weak_factory_{this}; }; +struct MediaAppUserActions { + bool clicked_edit_image_in_photos; + bool clicked_edit_video_in_photos; +}; +// Returns a snapshot of the user actions that are tracked whilst any MediaApp +// instance is running, in order to populate product-specific survey data. +MediaAppUserActions GetMediaAppUserActionsForHappinessTracking(); + } // namespace ash #endif // ASH_WEBUI_MEDIA_APP_UI_MEDIA_APP_GUEST_UI_H_
diff --git a/ash/webui/projector_app/OWNERS b/ash/webui/projector_app/OWNERS index d5ef8447..174c491 100644 --- a/ash/webui/projector_app/OWNERS +++ b/ash/webui/projector_app/OWNERS
@@ -1,3 +1 @@ -llin@chromium.org -tobyhuang@chromium.org -yilkal@chromium.org +file://ash/projector/OWNERS
diff --git a/ash/webui/shimless_rma/backend/BUILD.gn b/ash/webui/shimless_rma/backend/BUILD.gn index a842741..ee292d99 100644 --- a/ash/webui/shimless_rma/backend/BUILD.gn +++ b/ash/webui/shimless_rma/backend/BUILD.gn
@@ -46,12 +46,12 @@ "//ash/webui/shimless_rma/mojom", "//base", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/rmad", "//chromeos/ash/components/dbus/rmad:rmad_proto", "//chromeos/ash/components/dbus/update_engine:update_engine", "//chromeos/ash/components/network", "//chromeos/ash/components/network:test_support", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/login/login_state:login_state", "//chromeos/services/network_config/public/cpp:test_support",
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.cc b/ash/webui/shimless_rma/backend/shimless_rma_service.cc index ae6b5f4..b883e2e 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
@@ -193,6 +193,19 @@ std::move(callback), /*reboot=*/true)); } +void ShimlessRmaService::ShutDownAfterHardwareError() { + if (state_proto_.state_case() != rmad::RmadState::kProvisionDevice && + state_proto_.state_case() != rmad::RmadState::kFinalize) { + LOG(ERROR) << "ShutDownAfterHardwareError called from incorrect state " + << state_proto_.state_case() << " / " << mojo_state_; + return; + } + + chromeos::PowerManagerClient::Get()->RequestShutdown( + power_manager::REQUEST_SHUTDOWN_FOR_USER, + "Shutting down after encountering a hardware error."); +} + void ShimlessRmaService::BeginFinalization(BeginFinalizationCallback callback) { if (state_proto_.state_case() != rmad::RmadState::kWelcome || mojo_state_ != mojom::State::kWelcomeScreen) { @@ -204,34 +217,36 @@ state_proto_.mutable_welcome()->set_choice( rmad::WelcomeState::RMAD_CHOICE_FINALIZE_REPAIR); - if (!HaveAllowedNetworkConnection()) { - // Enable WiFi on the device. - chromeos::NetworkStateHandler* network_state_handler = - chromeos::NetworkHandler::Get()->network_state_handler(); - if (!network_state_handler->IsTechnologyEnabled( - chromeos::NetworkTypePattern::WiFi())) { - network_state_handler->SetTechnologyEnabled( - chromeos::NetworkTypePattern::WiFi(), /*enabled=*/true, - network_handler::ErrorCallback()); - } + // Only when the `ShimlessRMAOsUpdate` flag is enabled should the network + // connection and OS update status be checked. + if (features::IsShimlessRMAOsUpdateEnabled()) { + if (!HaveAllowedNetworkConnection()) { + // Enable WiFi on the device. + chromeos::NetworkStateHandler* network_state_handler = + chromeos::NetworkHandler::Get()->network_state_handler(); + if (!network_state_handler->IsTechnologyEnabled( + chromeos::NetworkTypePattern::WiFi())) { + network_state_handler->SetTechnologyEnabled( + chromeos::NetworkTypePattern::WiFi(), /*enabled=*/true, + network_handler::ErrorCallback()); + } - user_has_seen_network_page_ = true; - mojo_state_ = mojom::State::kConfigureNetwork; - std::move(callback).Run( - CreateStateResult(mojom::State::kConfigureNetwork, - /*can_exit=*/true, /*can_go_back=*/true, - rmad::RmadErrorCode::RMAD_ERROR_OK)); - } else { - if (features::IsShimlessRMAOsUpdateEnabled()) { + user_has_seen_network_page_ = true; + mojo_state_ = mojom::State::kConfigureNetwork; + std::move(callback).Run( + CreateStateResult(mojom::State::kConfigureNetwork, + /*can_exit=*/true, /*can_go_back=*/true, + rmad::RmadErrorCode::RMAD_ERROR_OK)); + } else { // This callback is invoked once VersionUpdated determines if an OS Update // is available. check_os_callback_ = base::BindOnce(&ShimlessRmaService::OsUpdateOrNextRmadStateCallback, weak_ptr_factory_.GetWeakPtr(), std::move(callback)); version_updater_.CheckOsUpdateAvailable(); - } else { - TransitionNextStateGeneric(std::move(callback)); } + } else { + TransitionNextStateGeneric(std::move(callback)); } }
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.h b/ash/webui/shimless_rma/backend/shimless_rma_service.h index e05f55b..71c978a 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service.h +++ b/ash/webui/shimless_rma/backend/shimless_rma_service.h
@@ -144,6 +144,7 @@ void CriticalErrorExitToLogin( CriticalErrorExitToLoginCallback callback) override; void CriticalErrorReboot(CriticalErrorRebootCallback callback) override; + void ShutDownAfterHardwareError() override; void ObserveError( ::mojo::PendingRemote<mojom::ErrorObserver> observer) override;
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc index 79537823..4d78e51 100644 --- a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc +++ b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
@@ -482,7 +482,9 @@ run_loop.Run(); } -TEST_F(ShimlessRmaServiceTest, ChooseNetworkPageSkipsOsUpdateIfFlagIsOff) { +// Make sure the network and OS update pages are skipped when the +// `ShimlessRMAOsUpdate` feature flag is disabled. +TEST_F(ShimlessRmaServiceTest, NetworkPageOsUpdatePageSkipped) { ResetFeatures(); const std::vector<rmad::GetStateReply> fake_states = { @@ -501,24 +503,13 @@ })); run_loop.RunUntilIdle(); - // No network should prompt select network page + // Even without a network connection, the network page will be skipped. shimless_rma_provider_->BeginFinalization( base::BindLambdaForTesting([&](mojom::StateResultPtr state_result_ptr) { - EXPECT_EQ(state_result_ptr->state, mojom::State::kConfigureNetwork); - EXPECT_EQ(state_result_ptr->error, rmad::RmadErrorCode::RMAD_ERROR_OK); - })); - run_loop.RunUntilIdle(); - SetupWiFiNetwork(kDefaultWifiGuid); - - // With a WiFi network it should redirect to kSelectComponents because the OS - // Update flag is off. - shimless_rma_provider_->NetworkSelectionComplete( - base::BindLambdaForTesting([&](mojom::StateResultPtr state_result_ptr) { EXPECT_EQ(state_result_ptr->state, mojom::State::kSelectComponents); EXPECT_EQ(state_result_ptr->error, rmad::RmadErrorCode::RMAD_ERROR_OK); - run_loop.Quit(); })); - run_loop.Run(); + run_loop.RunUntilIdle(); } TEST_F(ShimlessRmaServiceTest, ChooseNetworkHasNoNetworkConnection) { @@ -1088,6 +1079,48 @@ EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); } +TEST_F(ShimlessRmaServiceTest, + ShutDownAfterHardwareErrorInFinalizationRequestsShutdown) { + const std::vector<rmad::GetStateReply> fake_states = { + CreateStateReply(rmad::RmadState::kFinalize, rmad::RMAD_ERROR_OK)}; + fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states)); + fake_rmad_client_()->SetAbortable(true); + base::RunLoop run_loop; + + shimless_rma_provider_->GetCurrentState( + base::BindLambdaForTesting([&](mojom::StateResultPtr state_result_ptr) { + EXPECT_EQ(state_result_ptr->state, mojom::State::kFinalize); + EXPECT_EQ(state_result_ptr->error, rmad::RmadErrorCode::RMAD_ERROR_OK); + })); + run_loop.RunUntilIdle(); + + shimless_rma_provider_->ShutDownAfterHardwareError(); + run_loop.RunUntilIdle(); + + EXPECT_EQ(1, FakePowerManagerClient::Get()->num_request_shutdown_calls()); +} + +TEST_F(ShimlessRmaServiceTest, + ShutDownAfterHardwareErrorInProvisioningRequestsShutdown) { + const std::vector<rmad::GetStateReply> fake_states = { + CreateStateReply(rmad::RmadState::kProvisionDevice, rmad::RMAD_ERROR_OK)}; + fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states)); + fake_rmad_client_()->SetAbortable(true); + base::RunLoop run_loop; + + shimless_rma_provider_->GetCurrentState( + base::BindLambdaForTesting([&](mojom::StateResultPtr state_result_ptr) { + EXPECT_EQ(state_result_ptr->state, mojom::State::kProvisionDevice); + EXPECT_EQ(state_result_ptr->error, rmad::RmadErrorCode::RMAD_ERROR_OK); + })); + run_loop.RunUntilIdle(); + + shimless_rma_provider_->ShutDownAfterHardwareError(); + run_loop.RunUntilIdle(); + + EXPECT_EQ(1, FakePowerManagerClient::Get()->num_request_shutdown_calls()); +} + TEST_F(ShimlessRmaServiceTest, CriticalErrorRebootRequestsFullReboot) { const std::vector<rmad::GetStateReply> fake_states = {CreateStateReply( rmad::RmadState::kDeviceDestination, rmad::RMAD_ERROR_OK)};
diff --git a/ash/webui/shimless_rma/mojom/shimless_rma.mojom b/ash/webui/shimless_rma/mojom/shimless_rma.mojom index f142160e..09a919d1 100644 --- a/ash/webui/shimless_rma/mojom/shimless_rma.mojom +++ b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
@@ -761,6 +761,12 @@ => (StateResult state_result); /////////////////////////////////////// + // Methods for kHardwareError state. + // + // Shut down after encountering an unrecoverable hardware error. + ShutDownAfterHardwareError(); + + /////////////////////////////////////// // Critical error handling // These methods will fail if backend is not in critical error state. // Currently the only critical error is when error is kRmaNotRequired
diff --git a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js index aaf0fb93..bc23caf7 100644 --- a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js +++ b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
@@ -784,6 +784,9 @@ 'criticalErrorReboot', this.resolveMethodDelayMs_); } + shutDownAfterHardwareError() { + console.log('(Fake) Shutting down...'); + } /** * Implements ShimlessRmaServiceInterface.ObserveError. @@ -1323,6 +1326,8 @@ // Critical error handling this.methods_.register('criticalErrorExitToLogin'); this.methods_.register('criticalErrorReboot'); + + this.methods_.register('shutDownAfterHardwareError'); } /**
diff --git a/ash/webui/shimless_rma/resources/hardware_error_page.js b/ash/webui/shimless_rma/resources/hardware_error_page.js index 9ab45f9..5b6768bc 100644 --- a/ash/webui/shimless_rma/resources/hardware_error_page.js +++ b/ash/webui/shimless_rma/resources/hardware_error_page.js
@@ -11,7 +11,7 @@ import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getShimlessRmaService} from './mojo_interface_provider.js'; -import {ShimlessRmaServiceInterface, ShutdownMethod} from './shimless_rma_types.js'; +import {ShimlessRmaServiceInterface} from './shimless_rma_types.js'; import {disableAllButtons, executeThenTransitionState} from './shimless_rma_util.js'; /** @@ -54,8 +54,7 @@ /** @protected */ onShutDownButtonClicked_() { - executeThenTransitionState( - this, () => this.shimlessRmaService_.endRma(ShutdownMethod.kShutdown)); + this.shimlessRmaService_.shutDownAfterHardwareError(); disableAllButtons(this, /* showBusyStateOverlay= */ true); } }
diff --git a/ash/webui/shimless_rma/resources/onboarding_network_page.js b/ash/webui/shimless_rma/resources/onboarding_network_page.js index 205b823..39fe892 100644 --- a/ash/webui/shimless_rma/resources/onboarding_network_page.js +++ b/ash/webui/shimless_rma/resources/onboarding_network_page.js
@@ -9,13 +9,13 @@ import 'chrome://resources/cr_components/chromeos/network/network_config.m.js'; import 'chrome://resources/cr_components/chromeos/network/network_list.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/icons.m.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import {HTMLEscape} from '//resources/js/util.m.js'; import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/cr_components/chromeos/network/network_listener_behavior.m.js'; import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js index ed24dfe2..48bc912a 100644 --- a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js +++ b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js
@@ -9,6 +9,7 @@ import './base_page.js'; import './icons.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js index 5c108b0..8039385f 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import './base_page.js'; import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index fdb9193..e92d1c2 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -1049,16 +1049,10 @@ base::UTF16ToUTF8(active_desk_->name()), root_window_to_show); } -void DesksController::CreateNewDeskForTemplate( +const Desk* DesksController::CreateNewDeskForTemplate( bool activate_desk, - base::OnceCallback<void(const Desk*)> callback, const std::u16string& customized_desk_name) { - DCHECK(!callback.is_null()); - - if (!CanCreateDesks()) { - std::move(callback).Run(nullptr); - return; - } + DCHECK(CanCreateDesks()); // If there is an ongoing animation, we should stop it before creating and // activating the new desk, which triggers its own animation. @@ -1124,7 +1118,7 @@ DCHECK(!animation_); } - std::move(callback).Run(desk); + return desk; } bool DesksController::OnSingleInstanceAppLaunchingFromTemplate(
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index c155f17..4d2f9d16 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -307,14 +307,12 @@ DeskTemplateType template_type, aura::Window* root_window_to_show) const; - // Creates (and optionally activates) a new desk. If `customized_desk_name` - // is provided, desk name will be `customized_desk_name` or - // `customized_desk_name ({counter})` to resolve naming conflicts. Runs - // `callback` with the newly created desk if creation was successful, nullptr - // otherwise. - void CreateNewDeskForTemplate( + // Creates (and optionally activates) a new desk. If `customized_desk_name` is + // provided, desk name will be `customized_desk_name` or `customized_desk_name + // ({counter})` to resolve naming conflicts. CanCreateDesks() must be checked + // before calling this. + const Desk* CreateNewDeskForTemplate( bool activate_desk, - base::OnceCallback<void(const Desk*)> callback, const std::u16string& customized_desk_name = std::u16string()); // Called when an app with `app_id` is a single instance app which is about to
diff --git a/ash/wm/desks/templates/saved_desk_presenter.cc b/ash/wm/desks/templates/saved_desk_presenter.cc index 9255338..cebb30f 100644 --- a/ash/wm/desks/templates/saved_desk_presenter.cc +++ b/ash/wm/desks/templates/saved_desk_presenter.cc
@@ -359,9 +359,11 @@ std::unique_ptr<DeskTemplate> saved_desk, base::TimeDelta delay, aura::Window* root_window) { + DesksController* desks_controller = DesksController::Get(); + // If we are at the max desk limit (currently is 8), a new desk // cannot be created, and a toast will be displayed to the user. - if (!DesksController::Get()->CanCreateDesks()) { + if (!desks_controller->CanCreateDesks()) { ToastData toast_data = { /*id=*/kMaximumDeskLaunchTemplateToastName, ToastCatalogName::kMaximumDeskLaunchTemplate, @@ -373,19 +375,18 @@ return; } - // Copy fields we need from `desk_template` since we're about to move it. Also - // be very careful about doing anything after `CreateNewDeskForTemplate` since - // it may exit overview (and thus destroy `this`). - // See https://crbug.com/1284138. - const auto saved_desk_name = saved_desk->template_name(); + // Copy fields we need from `desk_template` since we're about to move it. const auto saved_desk_type = saved_desk->type(); const bool activate_desk = saved_desk_type == DeskTemplateType::kTemplate; - DesksController::Get()->CreateNewDeskForTemplate( - activate_desk, - base::BindOnce(&SavedDeskPresenter::OnNewDeskCreatedForTemplate, - weak_ptr_factory_.GetWeakPtr(), std::move(saved_desk), - base::Time::Now(), delay, root_window), - saved_desk_name); + + const Desk* new_desk = desks_controller->CreateNewDeskForTemplate( + activate_desk, saved_desk->template_name()); + LaunchSavedDeskIntoNewDesk(std::move(saved_desk), delay, root_window, + new_desk); + + // Note: `LaunchSavedDeskIntoNewDesk` *may* cause overview mode to exit. This + // means that the saved desk presenter may have been destroyed at this point. + // Do not add any code below this point that depend on `this`. RecordLaunchSavedDeskHistogram(saved_desk_type); } @@ -504,21 +505,20 @@ RemoveUIEntries({uuid}); } -void SavedDeskPresenter::OnNewDeskCreatedForTemplate( - std::unique_ptr<DeskTemplate> desk_template, - base::Time time_launch_started, +void SavedDeskPresenter::LaunchSavedDeskIntoNewDesk( + std::unique_ptr<DeskTemplate> saved_desk, base::TimeDelta delay, aura::Window* root_window, const Desk* new_desk) { - // Desk creation failed. - if (!new_desk) - return; + DCHECK(new_desk); + + base::Time time_launch_started = base::Time::Now(); // For Save & Recall, the underlying desk definition is deleted on launch. We // store the template ID here since we're about to move the desk template. - const auto saved_desk_type = desk_template->type(); - const auto saved_desk_creation_time = desk_template->created_time(); - const std::string uuid = desk_template->uuid().AsLowercaseString(); + const auto saved_desk_type = saved_desk->type(); + const auto saved_desk_creation_time = saved_desk->created_time(); + const std::string uuid = saved_desk->uuid().AsLowercaseString(); auto* overview_controller = Shell::Get()->overview_controller(); if (saved_desk_type == DeskTemplateType::kSaveAndRecall) { @@ -533,17 +533,17 @@ DCHECK(mini_view); SavedDeskLibraryView* library = overview_grid->GetSavedDeskLibraryView(); - library->AnimateDeskLaunch(desk_template->uuid(), mini_view); + library->AnimateDeskLaunch(saved_desk->uuid(), mini_view); } } // Copy the index of the newly created desk to the template. This ensures that // apps appear on the right desk even if the user switches to another. const int desk_index = DesksController::Get()->GetDeskIndex(new_desk); - desk_template->SetDeskIndex(desk_index); + saved_desk->SetDeskIndex(desk_index); Shell::Get()->desks_templates_delegate()->LaunchAppsFromTemplate( - std::move(desk_template), time_launch_started, delay); + std::move(saved_desk), time_launch_started, delay); if (!overview_controller->InOverviewSession()) { // Note: it is the intention that we don't leave overview mode when
diff --git a/ash/wm/desks/templates/saved_desk_presenter.h b/ash/wm/desks/templates/saved_desk_presenter.h index 8de0918..7c7e3f0c 100644 --- a/ash/wm/desks/templates/saved_desk_presenter.h +++ b/ash/wm/desks/templates/saved_desk_presenter.h
@@ -96,19 +96,18 @@ private: friend class SavedDeskPresenterTestApi; + // Launch `saved_desk` into `new_desk`. + void LaunchSavedDeskIntoNewDesk(std::unique_ptr<DeskTemplate> saved_desk, + base::TimeDelta delay, + aura::Window* root_window, + const Desk* new_desk); + // Callback after deleting an entry. Will then call `RemoveUIEntries` to // update the UI by removing the deleted saved desk. void OnDeleteEntry(const std::string& uuid, absl::optional<DeskTemplateType> record_for_type, desks_storage::DeskModel::DeleteEntryStatus status); - // Callback after creating a new desk for launching a template. - void OnNewDeskCreatedForTemplate(std::unique_ptr<DeskTemplate> desk_template, - base::Time time_launch_started, - base::TimeDelta delay, - aura::Window* root_window, - const Desk* new_desk); - // Callback after adding or updating an entry. Will then call // `AddOrUpdateUIEntries` to update the UI by adding or updating the template. void OnAddOrUpdateEntry(
diff --git a/base/BUILD.gn b/base/BUILD.gn index 149e8e99..741cd65 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -217,6 +217,7 @@ "base64.h", "base64url.cc", "base64url.h", + "base_export.h", "base_switches.h", "big_endian.cc", "big_endian.h", @@ -368,6 +369,7 @@ "hash/hash.h", "hash/legacy_hash.cc", "hash/legacy_hash.h", + "immediate_crash.h", "json/json_common.h", "json/json_file_value_serializer.cc", "json/json_file_value_serializer.h", @@ -1520,10 +1522,6 @@ "//third_party/abseil-cpp:absl", ] - if (use_custom_libcxx && !is_debug) { - public_deps += [ ":nodebug_assertion" ] - } - # Needed for <atomic> if using newer C++ library than sysroot, except if # building inside the cros_sdk environment - use host_toolchain as a # more robust check for this. @@ -2663,10 +2661,8 @@ # base_static. static_library("base_static") { sources = [ - "base_export.h", "base_switches.cc", "base_switches.h", - "immediate_crash.h", ] deps = [ "//build:chromeos_buildflags" ] @@ -2692,23 +2688,6 @@ } } -if (use_custom_libcxx && !is_debug) { - # nodebug_assertion.cc has to be in its own source_set instead of being - # included as a source in //base to prevent the linker from removing its - # contents during dead code elimination. - source_set("nodebug_assertion") { - defines = [ "BASE_IMPLEMENTATION" ] - sources = [ "nodebug_assertion.cc" ] - deps = [ ":base_static" ] - if (is_win && is_component_build) { - # For Windows component builds, we need to set __declspec(dllexport) on - # our redeclaration of __libcpp_verbose_abort(...) so it can be picked up. - # Therefore, we disable the corresponding error. - cflags = [ "-Wno-dll-attribute-on-redeclaration" ] - } - } -} - component("i18n") { output_name = "base_i18n" sources = [ @@ -3424,10 +3403,6 @@ "vlog_unittest.cc", ] - if (use_custom_libcxx) { - sources += [ "libcpp_hardening_test.cc" ] - } - # TODO(crbug.com/1304253): iOS test() targets don't support mixing Rust code # yet. if (!is_ios) {
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn index 5b57dfa..ec59501 100644 --- a/base/allocator/partition_allocator/BUILD.gn +++ b/base/allocator/partition_allocator/BUILD.gn
@@ -131,6 +131,7 @@ "partition_alloc_base/time/time.h", "partition_alloc_base/time/time_override.cc", "partition_alloc_base/time/time_override.h", + "partition_alloc_base/types/strong_alias.h", "partition_alloc_base/win/windows_types.h", "partition_alloc_check.h", "partition_alloc_config.h",
diff --git a/base/allocator/partition_allocator/partition_alloc_base/types/strong_alias.h b/base/allocator/partition_allocator/partition_alloc_base/types/strong_alias.h new file mode 100644 index 0000000..95f98934 --- /dev/null +++ b/base/allocator/partition_allocator/partition_alloc_base/types/strong_alias.h
@@ -0,0 +1,141 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_TYPES_STRONG_ALIAS_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_TYPES_STRONG_ALIAS_H_ + +#include <type_traits> +#include <utility> + +namespace partition_alloc::internal::base { + +// A type-safe alternative for a typedef or a 'using' directive. +// +// C++ currently does not support type-safe typedefs, despite multiple proposals +// (ex. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3515.pdf). The +// next best thing is to try and emulate them in library code. +// +// The motivation is to disallow several classes of errors: +// +// using Orange = int; +// using Apple = int; +// Apple apple(2); +// Orange orange = apple; // Orange should not be able to become an Apple. +// Orange x = orange + apple; // Shouldn't add Oranges and Apples. +// if (orange > apple); // Shouldn't compare Apples to Oranges. +// void foo(Orange); +// void foo(Apple); // Redefinition. +// etc. +// +// StrongAlias may instead be used as follows: +// +// using Orange = StrongAlias<class OrangeTag, int>; +// using Apple = StrongAlias<class AppleTag, int>; +// using Banana = StrongAlias<class BananaTag, std::string>; +// Apple apple(2); +// Banana banana("Hello"); +// Orange orange = apple; // Does not compile. +// Orange other_orange = orange; // Compiles, types match. +// Orange x = orange + apple; // Does not compile. +// Orange y = Orange(orange.value() + apple.value()); // Compiles. +// Orange z = Orange(banana->size() + *other_orange); // Compiles. +// if (orange > apple); // Does not compile. +// if (orange > other_orange); // Compiles. +// void foo(Orange); +// void foo(Apple); // Compiles into separate overload. +// +// StrongAlias is a zero-cost abstraction, it's compiled away. +// +// TagType is an empty tag class (also called "phantom type") that only serves +// the type system to differentiate between different instantiations of the +// template. +// UnderlyingType may be almost any value type. Note that some methods of the +// StrongAlias may be unavailable (ie. produce elaborate compilation errors when +// used) if UnderlyingType doesn't support them. +// +// StrongAlias only directly exposes comparison operators (for convenient use in +// ordered containers) and a Hasher struct (for unordered_map/set). It's +// impossible, without reflection, to expose all methods of the UnderlyingType +// in StrongAlias's interface. It's also potentially unwanted (ex. you don't +// want to be able to add two StrongAliases that represent socket handles). +// A getter and dereference operators are provided in case you need to access +// the UnderlyingType. +// +// See also +// - //styleguide/c++/blink-c++.md which provides recommendation and examples of +// using StrongAlias<Tag, bool> instead of a bare bool. +// - IdType<...> which provides helpers for specializing StrongAlias to be +// used as an id. +// - TokenType<...> which provides helpers for specializing StrongAlias to be +// used as a wrapper of base::UnguessableToken. +template <typename TagType, typename UnderlyingType> +class StrongAlias { + public: + constexpr StrongAlias() = default; + constexpr explicit StrongAlias(const UnderlyingType& v) : value_(v) {} + constexpr explicit StrongAlias(UnderlyingType&& v) noexcept + : value_(std::move(v)) {} + + constexpr UnderlyingType* operator->() { return &value_; } + constexpr const UnderlyingType* operator->() const { return &value_; } + + constexpr UnderlyingType& operator*() & { return value_; } + constexpr const UnderlyingType& operator*() const& { return value_; } + constexpr UnderlyingType&& operator*() && { return std::move(value_); } + constexpr const UnderlyingType&& operator*() const&& { + return std::move(value_); + } + + constexpr UnderlyingType& value() & { return value_; } + constexpr const UnderlyingType& value() const& { return value_; } + constexpr UnderlyingType&& value() && { return std::move(value_); } + constexpr const UnderlyingType&& value() const&& { return std::move(value_); } + + constexpr explicit operator const UnderlyingType&() const& { return value_; } + + constexpr bool operator==(const StrongAlias& other) const { + return value_ == other.value_; + } + constexpr bool operator!=(const StrongAlias& other) const { + return value_ != other.value_; + } + constexpr bool operator<(const StrongAlias& other) const { + return value_ < other.value_; + } + constexpr bool operator<=(const StrongAlias& other) const { + return value_ <= other.value_; + } + constexpr bool operator>(const StrongAlias& other) const { + return value_ > other.value_; + } + constexpr bool operator>=(const StrongAlias& other) const { + return value_ >= other.value_; + } + + // Hasher to use in std::unordered_map, std::unordered_set, etc. + // + // Example usage: + // using MyType = base::StrongAlias<...>; + // using MySet = std::unordered_set<MyType, typename MyType::Hasher>; + // + // https://google.github.io/styleguide/cppguide.html#std_hash asks to avoid + // defining specializations of `std::hash` - this is why the hasher needs to + // be explicitly specified and why the following code will *not* work: + // using MyType = base::StrongAlias<...>; + // using MySet = std::unordered_set<MyType>; // This won't work. + struct Hasher { + using argument_type = StrongAlias; + using result_type = std::size_t; + result_type operator()(const argument_type& id) const { + return std::hash<UnderlyingType>()(id.value()); + } + }; + + protected: + UnderlyingType value_; +}; + +} // namespace partition_alloc::internal::base + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_TYPES_STRONG_ALIAS_H_
diff --git a/base/libcpp_hardening_test.cc b/base/libcpp_hardening_test.cc deleted file mode 100644 index 7ff04d14b..0000000 --- a/base/libcpp_hardening_test.cc +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright (c) 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -#if !_LIBCPP_ENABLE_ASSERTIONS -#error \ - "Define _LIBCPP_ENABLE_ASSERTIONS to 1 in \ -buildtools/third_party/libc++/__config_site" - -#endif - -using ::testing::ContainsRegex; -using ::testing::Not; - -TEST(LibcppHardeningTest, Assertions) { - std::vector<int> vec = {0, 1, 2}; -#ifdef NDEBUG -// We have to explicitly check for the GTEST_HAS_DEATH_TEST macro instead of -// using EXPECT_DEATH_IF_SUPPORTED(...) for the following reasons: -// -// 0. EXPECT_DEATH(...) does not support (non-escaped) parentheses in the regex, -// so we can't use negative look arounds (https://stackoverflow.com/a/406408) -// to check that the error message doesn't exist. -// 1. EXPECT_DEATH_IF_SUPPORTED(...) does not support having gmock matchers as -// the second argument if GTEST_HAS_DEATH_TEST is false. -#if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(vec[3], Not(ContainsRegex(".*assertion.*failed:"))); -#else - GTEST_UNSUPPORTED_DEATH_TEST(vec[3], "", ); -#endif // GTEST_HAS_DEATH_TEST -#else - EXPECT_DEATH_IF_SUPPORTED(vec[3], ".*assertion.*failed:"); -#endif // NDEBUG -} - -} // namespace
diff --git a/base/nodebug_assertion.cc b/base/nodebug_assertion.cc deleted file mode 100644 index ebf6c2f..0000000 --- a/base/nodebug_assertion.cc +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <__assert> -#include <__config> -#include <__verbose_abort> - -#include "base/base_export.h" -#include "base/immediate_crash.h" - -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_NORETURN BASE_EXPORT void __libcpp_verbose_abort(char const* format, - ...) { - IMMEDIATE_CRASH(); -} - -_LIBCPP_END_NAMESPACE_STD
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 5455aa07..b5f91fe4 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -142,7 +142,7 @@ class LegacyWebRtcVideoFrameAdapter; class WorkerThread; namespace scheduler { -class WorkerThread; +class NonMainThreadImpl; } } // namespace blink namespace cc { @@ -568,7 +568,7 @@ friend class blink::IdentifiabilityActiveSampler; friend class blink::SourceStream; friend class blink::WorkerThread; - friend class blink::scheduler::WorkerThread; + friend class blink::scheduler::NonMainThreadImpl; friend class chrome_cleaner::ResetShortcutsComponent; friend class chrome_cleaner::SystemReportComponent; friend class content::BrowserMainLoop;
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto index 58007f42..a7e3544 100644 --- a/base/tracing/protos/chrome_track_event.proto +++ b/base/tracing/protos/chrome_track_event.proto
@@ -696,6 +696,7 @@ TASK_TYPE_WEB_GPU = 78; TASK_TYPE_INTERNAL_POST_MESSAGE_FORWARDING = 79; TASK_TYPE_INTERNAL_NAVIGATION_CANCELLATION = 80; + TASK_TYPE_LOW_PRIORITY_SCRIPT_EXECUTION = 81; } enum FrameType {
diff --git a/base/values.cc b/base/values.cc index e0880ae..4803510 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -1071,12 +1071,6 @@ GetList().Append(std::move(value)); } -CheckedContiguousIterator<Value> Value::Insert( - CheckedContiguousConstIterator<Value> pos, - Value&& value) { - return GetList().Insert(pos, std::move(value)); -} - bool Value::EraseListIter(CheckedContiguousConstIterator<Value> iter) { const auto offset = iter - ListView(list()).begin(); auto list_iter = list().begin() + offset;
diff --git a/base/values.h b/base/values.h index 5a7f62416..cb54ede 100644 --- a/base/values.h +++ b/base/values.h
@@ -728,13 +728,6 @@ // DEPRECATED: prefer `Value::List::Append()`. void Append(std::string&& value); - // Inserts `value` before `pos`. - // - // DEPRECATED: prefer `Value::List::Insert()`. - CheckedContiguousIterator<Value> Insert( - CheckedContiguousConstIterator<Value> pos, - Value&& value); - // Erases the Value pointed to by `iter`. Returns false if `iter` is out of // bounds. //
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index 3485b01..6056899 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -520,35 +520,31 @@ EXPECT_TRUE(value.GetListDeprecated().back().is_list()); } -TEST(ValuesTest, Insert) { - ListValue value; - auto GetListDeprecated = [&value]() -> decltype(auto) { - return value.GetListDeprecated(); - }; - auto GetConstList = [&value] { return as_const(value).GetListDeprecated(); }; +TEST(ValuesTest, ListInsert) { + Value::List list; + const Value::List& const_list = list; - auto storage_iter = value.Insert(GetListDeprecated().end(), Value(true)); - EXPECT_TRUE(GetListDeprecated().begin() == storage_iter); - EXPECT_TRUE(storage_iter->is_bool()); + auto iter = list.Insert(list.end(), Value(true)); + EXPECT_TRUE(list.begin() == iter); + EXPECT_EQ(*iter, true); - auto span_iter = value.Insert(GetConstList().begin(), Value(123)); - EXPECT_TRUE(GetConstList().begin() == span_iter); - EXPECT_TRUE(span_iter->is_int()); + iter = list.Insert(const_list.begin(), Value(123)); + EXPECT_TRUE(const_list.begin() == iter); + EXPECT_EQ(*iter, 123); - Value::List& list = value.GetList(); - auto list_iter = list.Insert(list.begin() + 1, Value("Hello world!")); - EXPECT_TRUE(list.begin() + 1 == list_iter); - EXPECT_TRUE(list_iter->is_string()); + iter = list.Insert(list.begin() + 1, Value("Hello world!")); + EXPECT_TRUE(list.begin() + 1 == iter); + EXPECT_EQ(*iter, "Hello world!"); } // Test all three behaviors of EnsureDict() (Create a new dict where no // matchining values exist, return an existing dict, create a dict overwriting // a value of another type). TEST(ValuesTest, DictEnsureDict) { - base::Value::Dict root; + Value::Dict root; // This call should create a new nested dictionary. - base::Value::Dict* foo_dict = root.EnsureDict("foo"); + Value::Dict* foo_dict = root.EnsureDict("foo"); EXPECT_TRUE(foo_dict->empty()); foo_dict->Set("a", "b"); @@ -560,7 +556,7 @@ // Use EnsureDict() to overwrite an existing non-dictionary value. root.Set("bar", 3); - base::Value::Dict* bar_dict = root.EnsureDict("bar"); + Value::Dict* bar_dict = root.EnsureDict("bar"); EXPECT_TRUE(bar_dict->empty()); bar_dict->Set("b", "c"); @@ -576,10 +572,10 @@ // matchining value exists, return an existing list, create a list overwriting // a value of another type). TEST(ValuesTest, DictEnsureList) { - base::Value::Dict root; + Value::Dict root; // This call should create a new list. - base::Value::List* foo_list = root.EnsureList("foo"); + Value::List* foo_list = root.EnsureList("foo"); EXPECT_TRUE(foo_list->empty()); foo_list->Append("a"); @@ -587,11 +583,11 @@ // new one. foo_list = root.EnsureList("foo"); ASSERT_EQ(1u, foo_list->size()); - EXPECT_EQ((*foo_list)[0], base::Value("a")); + EXPECT_EQ((*foo_list)[0], Value("a")); // Use EnsureList() to overwrite an existing non-list value. root.Set("bar", 3); - base::Value::List* bar_list = root.EnsureList("bar"); + Value::List* bar_list = root.EnsureList("bar"); EXPECT_TRUE(bar_list->empty()); bar_list->Append("b"); @@ -599,7 +595,7 @@ bar_list = root.FindList("bar"); ASSERT_NE(nullptr, bar_list); ASSERT_EQ(1u, bar_list->size()); - EXPECT_EQ((*bar_list)[0], base::Value("b")); + EXPECT_EQ((*bar_list)[0], Value("b")); } // TODO(dcheng): Add more tests directly exercising the updated dictionary and
diff --git a/build/add_rts_filters.py b/build/add_rts_filters.py index 4186c39..31df75e7 100755 --- a/build/add_rts_filters.py +++ b/build/add_rts_filters.py
@@ -2,10 +2,11 @@ # Copyright (c) 2021 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Creates a dummy RTS filter file if a real one doesn't exist yes. - Real filter files are generated by the RTS binary for suites with any - skippable tests. The rest of the suites need to have dummy files because gn - will expect the file to be present. +"""Creates a dummy RTS filter file and a dummy inverse filter file if a + real ones do not exist yet. Real filter files (and their inverse) are + generated by the RTS binary for suites with any skippable tests. The + rest of the suites need to have dummy files because gn will expect the + file to be present. Implementation uses try / except because the filter files are written relatively close to when this code creates the dummy files. @@ -22,6 +23,15 @@ def main(): filter_file = sys.argv[1] + # '*' is a dummy that means run everything + write_filter_file(filter_file, '*') + + inverted_filter_file = sys.argv[2] + # '-*' is a dummy that means run nothing + write_filter_file(inverted_filter_file, '-*') + + +def write_filter_file(filter_file, filter_string): directory = os.path.dirname(filter_file) try: os.makedirs(directory) @@ -30,7 +40,6 @@ pass else: raise - try: fp = os.open(filter_file, os.O_CREAT | os.O_EXCL | os.O_WRONLY) except OSError as err: @@ -40,7 +49,7 @@ raise else: with os.fdopen(fp, 'w') as file_obj: - file_obj.write('*') # '*' is a dummy that means run everything + file_obj.write(filter_string) if __name__ == '__main__':
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index c909fba..ef8ac01 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -3885,8 +3885,16 @@ action("${invoker.target_name}__rts_filters") { script = "//build/add_rts_filters.py" rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter" - args = [ rebase_path(rts_file, root_build_dir) ] - outputs = [ rts_file ] + inverted_rts_file = + "${root_build_dir}/gen/rts/${invoker.target_name}_inverted.filter" + args = [ + rebase_path(rts_file, root_build_dir), + rebase_path(inverted_rts_file, root_build_dir), + ] + outputs = [ + rts_file, + inverted_rts_file, + ] } } _incremental_apk = !(defined(invoker.never_incremental) &&
diff --git a/buildtools/third_party/libc++/__config_site b/buildtools/third_party/libc++/__config_site index 691c324..98383cd 100644 --- a/buildtools/third_party/libc++/__config_site +++ b/buildtools/third_party/libc++/__config_site
@@ -28,8 +28,4 @@ /* #undef _LIBCPP_HAS_NO_LOCALIZATION */ #define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES -// Enable libc++ assertions for hardening and safety -// (https://crbug.com/1335422). -#define _LIBCPP_ENABLE_ASSERTIONS 1 - #endif // _LIBCPP_CONFIG_SITE
diff --git a/chrome/VERSION b/chrome/VERSION index a3903fb..9054a54d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=106 MINOR=0 -BUILD=5245 +BUILD=5246 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index e631d5a5b..6dbabae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -1884,7 +1884,11 @@ int direction = towardEnd ? 1 : -1; int destinationTabId = mTabGroupModelFilter.getRootId( getTabById(mStripTabs[curIndex + direction].getId())); - int numTabsToSkip = (int) ((Math.abs(offset) - mTabMarginWidth) / mCachedTabWidth); + float effectiveWidth = mCachedTabWidth - mTabOverlapWidth; + float flipThreshold = effectiveWidth * REORDER_OVERLAP_SWITCH_PERCENTAGE; + float minFlipOffset = mTabMarginWidth + flipThreshold; + int numTabsToSkip = + 1 + (int) Math.floor((Math.abs(offset) - minFlipOffset) / effectiveWidth); mTabGroupModelFilter.mergeTabsToGroup(mInteractingTab.getId(), destinationTabId, true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java index 789f32a5..68f81a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SignInPreference.java
@@ -13,7 +13,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl; @@ -23,7 +22,6 @@ import org.chromium.chrome.browser.signin.services.SigninManager.SignInStateObserver; import org.chromium.chrome.browser.sync.SyncService; import org.chromium.chrome.browser.sync.SyncService.SyncStateChangedListener; -import org.chromium.chrome.browser.ui.signin.TangibleSyncCoordinator; import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils; import org.chromium.components.prefs.PrefService; import org.chromium.components.signin.AccountManagerFacade; @@ -34,7 +32,6 @@ import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.ui.base.ViewUtils; -import org.chromium.ui.modaldialog.ModalDialogManagerHolder; /** * A preference that displays "Sign in to Chrome" when the user is not sign in, and displays @@ -159,18 +156,9 @@ setFragment(null); setIcon(AppCompatResources.getDrawable(getContext(), R.drawable.logo_avatar_anonymous)); setViewEnabled(true); - setOnPreferenceClickListener(pref -> { - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TANGIBLE_SYNC)) { - TangibleSyncCoordinator.start(getContext(), - ((ModalDialogManagerHolder) getContext()).getModalDialogManager(), - SyncConsentActivityLauncherImpl.get(), - SigninAccessPoint.SETTINGS_SYNC_OFF_ROW); - return true; - } else { - return SyncConsentActivityLauncherImpl.get().launchActivityIfAllowed( - getContext(), SigninAccessPoint.SETTINGS_SYNC_OFF_ROW); - } - }); + setOnPreferenceClickListener(pref + -> SyncConsentActivityLauncherImpl.get().launchActivityIfAllowed( + getContext(), SigninAccessPoint.SETTINGS_SYNC_OFF_ROW)); if (!mWasGenericSigninPromoDisplayed) { RecordUserAction.record("Signin_Impression_FromSettings");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java index eaf5fc64..8467f4e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java
@@ -12,6 +12,7 @@ import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; @@ -28,6 +29,7 @@ import androidx.annotation.IdRes; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; +import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import org.hamcrest.Matcher; @@ -40,18 +42,24 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.chromium.base.CommandLine; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; +import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Matchers; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManagerDelegate; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.SearchEnginePromoType; import org.chromium.chrome.browser.signin.SigninFirstRunFragment; +import org.chromium.chrome.browser.signin.services.FREMobileIdentityConsistencyFieldTrial; +import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; @@ -59,6 +67,10 @@ import org.chromium.chrome.test.util.browser.sync.SyncTestUtil; import org.chromium.components.externalauth.ExternalAuthUtils; import org.chromium.components.policy.test.annotations.Policies; +import org.chromium.components.signin.base.AccountInfo; +import org.chromium.components.signin.base.CoreAccountInfo; +import org.chromium.components.signin.identitymanager.ConsentLevel; +import org.chromium.components.signin.identitymanager.IdentityManager; import org.chromium.components.signin.test.util.FakeAccountManagerFacade; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -67,6 +79,7 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.FORCE_ENABLE_SIGNIN_FRE}) +@DoNotBatch(reason = "This test interacts with native initialization") public class FirstRunActivitySigninAndSyncTest { private static final String TEST_EMAIL = "test.account@gmail.com"; private static final String CHILD_EMAIL = "child.account@gmail.com"; @@ -140,6 +153,73 @@ } @Test + @LargeTest + public void continueButtonCanBeClickedBeforeNativeIsLoaded() { + FREMobileIdentityConsistencyFieldTrial.setFirstRunTrialGroupForTesting( + FREMobileIdentityConsistencyFieldTrial.INITIALIZATION_FLOW_NEW_GROUP); + // Suppress native initialization to verify that SigninFirstRunFragment doesn't require it + // to proceed past the initial loading spinner. + CommandLine.getInstance().appendSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION); + AccountInfo accountInfo = mAccountManagerTestRule.addAccount(TEST_EMAIL); + + launchFirstRunActivity(); + waitUntilCurrentPageIs(SigninFirstRunFragment.class); + onView(withId(R.id.signin_fre_selected_account)).check(matches(isDisplayed())); + + clickButton(R.id.signin_fre_continue_button); + + // Native should still be uninitialized. + assertFalse(ChromeBrowserInitializer.getInstance().isFullBrowserInitialized()); + + CommandLine.getInstance().removeSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION); + TestThreadUtils.runOnUiThreadBlocking( + () -> mFirstRunActivity.startDelayedNativeInitializationForTests()); + + waitUntilCurrentPageIs(SyncConsentFirstRunFragment.class); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( + Profile.getLastUsedRegularProfile()); + assertEquals(CoreAccountInfo.getIdFrom( + identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)), + accountInfo.getId()); + }); + } + + @Test + @LargeTest + public void dismissButtonCanBeClickedBeforeNativeIsLoaded() { + FREMobileIdentityConsistencyFieldTrial.setFirstRunTrialGroupForTesting( + FREMobileIdentityConsistencyFieldTrial.INITIALIZATION_FLOW_NEW_GROUP); + // Suppress native initialization to verify that SigninFirstRunFragment doesn't require it + // to proceed past the initial loading spinner. + CommandLine.getInstance().appendSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION); + mAccountManagerTestRule.addAccount(TEST_EMAIL); + + launchFirstRunActivity(); + waitUntilCurrentPageIs(SigninFirstRunFragment.class); + onView(withId(R.id.signin_fre_selected_account)).check(matches(isDisplayed())); + + clickButton(R.id.signin_fre_dismiss_button); + + // Native should still be uninitialized. + assertFalse(ChromeBrowserInitializer.getInstance().isFullBrowserInitialized()); + + CommandLine.getInstance().removeSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION); + TestThreadUtils.runOnUiThreadBlocking( + () -> mFirstRunActivity.startDelayedNativeInitializationForTests()); + + // When the native is loaded, First Run should be completed. + ApplicationTestUtils.waitForActivityState(mFirstRunActivity, Stage.DESTROYED); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( + Profile.getLastUsedRegularProfile()); + assertNull(identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)); + }); + } + + @Test @MediumTest // ChildAccountStatusSupplier uses AppRestrictions to quickly detect non-supervised cases, // adding at least one policy via AppRestrictions prevents that. @@ -329,6 +409,12 @@ } private void launchFirstRunActivityAndWaitForNativeInitialization() { + launchFirstRunActivity(); + CriteriaHelper.pollUiThread( + () -> mFirstRunActivity.getNativeInitializationPromise().isFulfilled()); + } + + private void launchFirstRunActivity() { final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); // The FirstRunActivity relaunches the original intent when it finishes, see // FirstRunActivityBase.EXTRA_FRE_COMPLETE_LAUNCH_INTENT. So to guarantee that @@ -339,8 +425,6 @@ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mFirstRunActivity = ApplicationTestUtils.waitForActivityWithClass( FirstRunActivity.class, Stage.RESUMED, () -> context.startActivity(intent)); - CriteriaHelper.pollUiThread( - () -> mFirstRunActivity.getNativeInitializationPromise().isFulfilled()); } private static class LinkClick implements ViewAction {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java index d14365a..8bbc9fa2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -328,34 +328,6 @@ } @Test - @MediumTest - public void testSigninRowLaunchesSignInFlowForSignedOutAccounts() { - launchSettingsActivity(); - - onView(withText(R.string.sync_promo_turn_on_sync)).perform(click()); - - verify(mMockSyncConsentActivityLauncher) - .launchActivityIfAllowed( - any(Activity.class), eq(SigninAccessPoint.SETTINGS_SYNC_OFF_ROW)); - } - - @Test - @MediumTest - @EnableFeatures(ChromeFeatureList.TANGIBLE_SYNC) - public void testSigninRowLaunchesTangibleSignInFlowForSignedOutAccounts() { - launchSettingsActivity(); - - onView(withText(R.string.sync_promo_turn_on_sync)).perform(click()); - - onView(withText(R.string.signin_account_picker_dialog_title)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.signin_add_account_to_device)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - } - - @Test @SmallTest public void testSyncRowLaunchesSignInFlowForSignedInAccounts() { CoreAccountInfo accountInfo = mSyncTestRule.setUpAccountAndSignInForTesting();
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index b82c3a1..c434df261 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1404,6 +1404,9 @@ <message name="IDS_SETTINGS_TRANSLATE_PAGE_TITLE" desc="Name of the settings page which displays translate preferences."> Google Translate </message> + <message name="IDS_SETTINGS_TARGET_TRANSLATE_LABEL" desc="Label for the element to select the target language"> + Translate into this language + </message> <message name="IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE" desc="Title of Translation settings that lists languages that should be automatically translated."> Automatically translate these languages </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_TARGET_TRANSLATE_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_TARGET_TRANSLATE_LABEL.png.sha1 new file mode 100644 index 0000000..ee8e67a --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_TARGET_TRANSLATE_LABEL.png.sha1
@@ -0,0 +1 @@ +455076c70b05a8779672aa71003a2b82ee20497e \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 7ceb48d..28fce67 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4470,6 +4470,7 @@ "//components/commerce/core:cart_db_content_proto", "//components/commerce/core:coupon_db_content_proto", "//components/commerce/core:public", + "//components/commerce/core/mojom:mojo_bindings", "//components/constrained_window", "//components/device_signals/core/browser", "//components/endpoint_fetcher:endpoint_fetcher",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 29fa3e8..5afadda 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3279,6 +3279,20 @@ }; #endif // !BUILDFLAG(IS_ANDROID) +const FeatureEntry::FeatureParam + kServiceWorkerSkipIgnorableFetchHandler_NotSkip[] = { + {"SkipEmptyFetchHandler", "false"}}; +const FeatureEntry::FeatureParam + kServiceWorkerSkipIgnorableFetchHandler_SkipEmpty[] = { + {"SkipEmptyFetchHandler", "true"}}; +const FeatureEntry::FeatureVariation + kServiceWorkerSkipIgnorableFetchHandlerVariations[] = { + {"Not Skip", kServiceWorkerSkipIgnorableFetchHandler_NotSkip, + std::size(kServiceWorkerSkipIgnorableFetchHandler_NotSkip), nullptr}, + {"Skip Empty", kServiceWorkerSkipIgnorableFetchHandler_SkipEmpty, + std::size(kServiceWorkerSkipIgnorableFetchHandler_SkipEmpty), nullptr}, +}; + // RECORDING USER METRICS FOR FLAGS: // ----------------------------------------------------------------------------- // The first line of the entry is the internal name. @@ -5535,6 +5549,9 @@ kOsCrOS, FEATURE_VALUE_TYPE( chromeos::features::kHandwritingLegacyRecognitionAllLang)}, + {"handwriting-library-dlc", flag_descriptions::kHandwritingLibraryDlcName, + flag_descriptions::kHandwritingLibraryDlcDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kHandwritingLibraryDlc)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) {"block-insecure-private-network-requests", @@ -9122,6 +9139,13 @@ FEATURE_VALUE_TYPE( password_manager::features::kBiometricAuthenticationForFilling)}, #endif + {"skip-service-worker-fetch-handler", + flag_descriptions::kSkipServiceWorkerFetchHandlerName, + flag_descriptions::kSkipServiceWorkerFetchHandlerDescription, kOsAll, + FEATURE_WITH_PARAMS_VALUE_TYPE( + features::kServiceWorkerSkipIgnorableFetchHandler, + kServiceWorkerSkipIgnorableFetchHandlerVariations, + "ServiceWorkerSkipIgnorableFetchHandler")}, #if BUILDFLAG(IS_ANDROID) {"reduce-gpu-priority-on-background",
diff --git a/chrome/browser/android/contextualsearch/native_contextual_search_context.cc b/chrome/browser/android/contextualsearch/native_contextual_search_context.cc index 5069c036..3ceaf299 100644 --- a/chrome/browser/android/contextualsearch/native_contextual_search_context.cc +++ b/chrome/browser/android/contextualsearch/native_contextual_search_context.cc
@@ -32,7 +32,7 @@ Java_ContextualSearchContext_getNativePointer( base::android::AttachCurrentThread(), j_contextual_search_context)); - return contextual_search_context->GetWeakPtr(); + return base::AsWeakPtr(contextual_search_context); } void NativeContextualSearchContext::SetResolveProperties( @@ -105,13 +105,6 @@ detected_language, target_language, fluent_languages); } -// Boilerplate. - -base::WeakPtr<NativeContextualSearchContext> -NativeContextualSearchContext::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - // Java wrapper boilerplate void NativeContextualSearchContext::Destroy(
diff --git a/chrome/browser/android/contextualsearch/native_contextual_search_context.h b/chrome/browser/android/contextualsearch/native_contextual_search_context.h index 845de02..9c78432 100644 --- a/chrome/browser/android/contextualsearch/native_contextual_search_context.h +++ b/chrome/browser/android/contextualsearch/native_contextual_search_context.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_ANDROID_CONTEXTUALSEARCH_NATIVE_CONTEXTUAL_SEARCH_CONTEXT_H_ #include "base/android/jni_android.h" -#include "base/memory/weak_ptr.h" #include "components/contextual_search/core/browser/contextual_search_context.h" #include "url/gurl.h" @@ -81,17 +80,9 @@ const base::android::JavaParamRef<jstring>& j_target_language, const base::android::JavaParamRef<jstring>& j_fluent_languages); - // Gets a WeakPtr to this instance. - base::WeakPtr<NativeContextualSearchContext> GetWeakPtr(); - private: // The linked Java object. base::android::ScopedJavaGlobalRef<jobject> java_object_; - - // Member variables should appear before the WeakPtrFactory, to ensure - // that any WeakPtrs to this instance are invalidated before its members - // variable's destructors are executed, rendering them invalid. - base::WeakPtrFactory<NativeContextualSearchContext> weak_factory_{this}; }; #endif // CHROME_BROWSER_ANDROID_CONTEXTUALSEARCH_NATIVE_CONTEXTUAL_SEARCH_CONTEXT_H_
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.cc b/chrome/browser/apps/app_service/app_service_proxy_base.cc index b6c8387..382dae36 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_base.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_base.cc
@@ -590,6 +590,14 @@ } void AppServiceProxyBase::StopApp(const std::string& app_id) { + if (base::FeatureList::IsEnabled(kAppServiceWithoutMojom)) { + auto* publisher = GetPublisher(app_registry_cache_.GetAppType(app_id)); + if (publisher) { + publisher->StopApp(app_id); + } + return; + } + if (!app_service_.is_connected()) { return; } @@ -616,6 +624,15 @@ int command_id, const std::string& shortcut_id, int64_t display_id) { + if (base::FeatureList::IsEnabled(kAppServiceWithoutMojom)) { + auto* publisher = GetPublisher(app_registry_cache_.GetAppType(app_id)); + if (publisher) { + publisher->ExecuteContextMenuCommand(app_id, command_id, shortcut_id, + display_id); + } + return; + } + if (!app_service_.is_connected()) { return; } @@ -627,6 +644,14 @@ } void AppServiceProxyBase::OpenNativeSettings(const std::string& app_id) { + if (base::FeatureList::IsEnabled(kAppServiceWithoutMojom)) { + auto* publisher = GetPublisher(app_registry_cache_.GetAppType(app_id)); + if (publisher) { + publisher->OpenNativeSettings(app_id); + } + return; + } + if (app_service_.is_connected()) { app_registry_cache_.ForOneApp( app_id, [this](const apps::AppUpdate& update) {
diff --git a/chrome/browser/apps/app_service/menu_util.cc b/chrome/browser/apps/app_service/menu_util.cc index 31aa6f5e..3f2fbae 100644 --- a/chrome/browser/apps/app_service/menu_util.cc +++ b/chrome/browser/apps/app_service/menu_util.cc
@@ -8,13 +8,11 @@ #include "ash/public/cpp/app_menu_constants.h" #include "base/check.h" -#include "base/notreached.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/extensions/menu_manager.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" @@ -24,6 +22,7 @@ #include "ui/base/models/image_model.h" #include "ui/color/color_id.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/vector_icon_types.h" namespace { const int kInvalidRadioGroupId = -1; @@ -91,18 +90,17 @@ menu_item->command_id = ash::LAUNCH_NEW; menu_item->string_id = string_id; - menu_item->submenu.push_back(CreateRadioItem( - ash::USE_LAUNCH_TYPE_REGULAR, - StringIdForUseLaunchTypeCommand(ash::USE_LAUNCH_TYPE_REGULAR), kGroupId)); - menu_item->submenu.push_back(CreateRadioItem( - ash::USE_LAUNCH_TYPE_WINDOW, - StringIdForUseLaunchTypeCommand(ash::USE_LAUNCH_TYPE_WINDOW), kGroupId)); + menu_item->submenu.push_back( + CreateRadioItem(ash::USE_LAUNCH_TYPE_REGULAR, + IDS_APP_LIST_CONTEXT_MENU_NEW_TAB, kGroupId)); + menu_item->submenu.push_back( + CreateRadioItem(ash::USE_LAUNCH_TYPE_WINDOW, + IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW, kGroupId)); if (base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip) && base::FeatureList::IsEnabled(features::kDesktopPWAsTabStripSettings)) { - menu_item->submenu.push_back(CreateRadioItem( - ash::USE_LAUNCH_TYPE_TABBED_WINDOW, - StringIdForUseLaunchTypeCommand(ash::USE_LAUNCH_TYPE_TABBED_WINDOW), - kGroupId)); + menu_item->submenu.push_back( + CreateRadioItem(ash::USE_LAUNCH_TYPE_TABBED_WINDOW, + IDS_APP_LIST_CONTEXT_MENU_NEW_TABBED_WINDOW, kGroupId)); } menu_item->radio_group_id = kInvalidRadioGroupId; @@ -149,7 +147,7 @@ const std::vector<apps::mojom::MenuItemPtr>& menu_items, ui::SimpleMenuModel* model, ui::SimpleMenuModel* submenu, - int* launch_new_string_id) { + GetVectorIconCallback get_vector_icon) { if (menu_items.empty()) { return false; } @@ -158,20 +156,26 @@ if (item->command_id != ash::LAUNCH_NEW) return false; - if (launch_new_string_id) - *launch_new_string_id = item->string_id; - + const ui::ColorId color_id = GetColorIdForMenuItemIcon(); switch (item->type) { case apps::mojom::MenuItemType::kCommand: { - model->AddItemWithStringId(item->command_id, item->string_id); + const gfx::VectorIcon& icon = + std::move(get_vector_icon).Run(item->command_id, item->string_id); + model->AddItemWithStringIdAndIcon( + item->command_id, item->string_id, + ui::ImageModel::FromVectorIcon(icon, color_id, + ash::kAppContextMenuIconSize)); break; } case apps::mojom::MenuItemType::kSubmenu: if (!item->submenu.empty()) { PopulateRadioItemFromMojoMenuItems(item->submenu, submenu); - model->AddActionableSubMenu(item->command_id, - l10n_util::GetStringUTF16(item->string_id), - submenu); + const gfx::VectorIcon& icon = + std::move(get_vector_icon).Run(item->command_id, item->string_id); + model->AddActionableSubmenuWithStringIdAndIcon( + item->command_id, item->string_id, submenu, + ui::ImageModel::FromVectorIcon(icon, color_id, + ash::kAppContextMenuIconSize)); } break; case apps::mojom::MenuItemType::kRadio: @@ -256,57 +260,4 @@ #endif } -bool MenuItemHasLauncherContext(const extensions::MenuItem* item) { - return item->contexts().Contains(extensions::MenuItem::LAUNCHER); -} - -uint32_t StringIdForUseLaunchTypeCommand(uint32_t command_id) { - DCHECK(command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && - command_id < ash::USE_LAUNCH_TYPE_COMMAND_END); - switch (command_id) { - case ash::USE_LAUNCH_TYPE_REGULAR: - return IDS_APP_LIST_CONTEXT_MENU_NEW_TAB; - case ash::USE_LAUNCH_TYPE_WINDOW: - return IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW; - case ash::USE_LAUNCH_TYPE_TABBED_WINDOW: - return IDS_APP_LIST_CONTEXT_MENU_NEW_TABBED_WINDOW; - default: - NOTREACHED(); - return 0; - } -} - -extensions::LaunchType ConvertLaunchTypeCommandToExtensionLaunchType( - uint32_t command_id) { - DCHECK(command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && - command_id < ash::USE_LAUNCH_TYPE_COMMAND_END); - switch (command_id) { - case ash::USE_LAUNCH_TYPE_PINNED: - return extensions::LAUNCH_TYPE_PINNED; - case ash::USE_LAUNCH_TYPE_REGULAR: - return extensions::LAUNCH_TYPE_REGULAR; - case ash::USE_LAUNCH_TYPE_WINDOW: - return extensions::LAUNCH_TYPE_WINDOW; - case ash::USE_LAUNCH_TYPE_FULLSCREEN: - return extensions::LAUNCH_TYPE_FULLSCREEN; - default: - return extensions::LAUNCH_TYPE_INVALID; - } -} - -apps::WindowMode ConvertLaunchTypeCommandToWindowMode(uint32_t command_id) { - DCHECK(command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && - command_id < ash::USE_LAUNCH_TYPE_COMMAND_END); - switch (command_id) { - case ash::USE_LAUNCH_TYPE_REGULAR: - return apps::WindowMode::kBrowser; - case ash::USE_LAUNCH_TYPE_WINDOW: - return apps::WindowMode::kWindow; - case ash::USE_LAUNCH_TYPE_TABBED_WINDOW: - return apps::WindowMode::kTabbedWindow; - default: - return apps::WindowMode::kUnknown; - } -} - } // namespace apps
diff --git a/chrome/browser/apps/app_service/menu_util.h b/chrome/browser/apps/app_service/menu_util.h index 4a9abbed..0d2a6de 100644 --- a/chrome/browser/apps/app_service/menu_util.h +++ b/chrome/browser/apps/app_service/menu_util.h
@@ -10,20 +10,15 @@ #include <string> #include <vector> +#include "base/callback.h" #include "base/strings/string_piece.h" #include "chrome/browser/apps/app_service/app_shortcut_item.h" -#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/mojom/types.mojom.h" -#include "extensions/common/constants.h" #include "ui/base/models/menu_separator_types.h" #include "ui/base/models/simple_menu_model.h" class Profile; -namespace extensions { -class MenuItem; -} - namespace gfx { class ImageSkia; } @@ -34,6 +29,9 @@ namespace apps { +using GetVectorIconCallback = + base::OnceCallback<const gfx::VectorIcon&(int command_id, int string_id)>; + // Adds a command menu item to |menu_items|. void AddCommandItem(uint32_t command_id, uint32_t string_id, @@ -74,14 +72,13 @@ Profile* profile); // Populates the LAUNCH_NEW menu item to a simple menu model |model| from mojo -// menu items |menu_items|. Also sets initial string id value to -// |launch_new_string_id|. Returns true if the LAUNCH_NEW menu item is added to +// menu items |menu_items|. Returns true if the LAUNCH_NEW menu item is added to // |model|, otherwise returns false. bool PopulateNewItemFromMojoMenuItems( const std::vector<apps::mojom::MenuItemPtr>& menu_items, ui::SimpleMenuModel* model, ui::SimpleMenuModel* submenu, - int* launch_new_string_id); + GetVectorIconCallback get_vector_icon); // Populates the menu item to a simple menu model |model| from mojo // menu items |menu_items|. @@ -101,19 +98,6 @@ ui::ColorId GetColorIdForMenuItemIcon(); -// Returns `true` if the provided menu item has a launcher context. -bool MenuItemHasLauncherContext(const extensions::MenuItem* item); - -// Converts `USE_LAUNCH_TYPE_*` commands to associated string ids. -uint32_t StringIdForUseLaunchTypeCommand(uint32_t command_id); - -// Converts `USE_LAUNCH_TYPE_*` commands to `extensions::LaunchType`. -extensions::LaunchType ConvertLaunchTypeCommandToExtensionLaunchType( - uint32_t command_id); - -// Converts `USE_LAUNCH_TYPE_*` commands to `apps::WindowMode`. -apps::WindowMode ConvertLaunchTypeCommandToWindowMode(uint32_t command_id); - } // namespace apps #endif // CHROME_BROWSER_APPS_APP_SERVICE_MENU_UTIL_H_
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc index ea9c435..91a3435 100644 --- a/chrome/browser/apps/app_service/metrics/website_metrics.cc +++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -548,7 +548,8 @@ UrlContent url_content, bool promotable, bool is_from_last_login) { - auto source_id = ukm::UkmRecorder::GetSourceIdForWebsiteUrl(url); + auto source_id = ukm::UkmRecorder::GetSourceIdForWebsiteUrl( + base::PassKey<WebsiteMetrics>(), url); if (source_id != ukm::kInvalidSourceId) { ukm::builders::ChromeOS_WebsiteUsageTime builder(source_id); builder.SetDuration(usage_time)
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.cc b/chrome/browser/apps/app_service/publishers/app_publisher.cc index 46064f82..72592b8 100644 --- a/chrome/browser/apps/app_service/publishers/app_publisher.cc +++ b/chrome/browser/apps/app_service/publishers/app_publisher.cc
@@ -74,6 +74,21 @@ LOG(ERROR) << "Uninstall failed, could not remove the app with id " << app_id; } +void AppPublisher::StopApp(const std::string& app_id) { + NOTIMPLEMENTED(); +} + +void AppPublisher::ExecuteContextMenuCommand(const std::string& app_id, + int command_id, + const std::string& shortcut_id, + int64_t display_id) { + NOTIMPLEMENTED(); +} + +void AppPublisher::OpenNativeSettings(const std::string& app_id) { + NOTIMPLEMENTED(); +} + #if !BUILDFLAG(IS_CHROMEOS_LACROS) void AppPublisher::Publish(AppPtr app) { if (!proxy_) {
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.h b/chrome/browser/apps/app_service/publishers/app_publisher.h index 2a35399c..22b0d22 100644 --- a/chrome/browser/apps/app_service/publishers/app_publisher.h +++ b/chrome/browser/apps/app_service/publishers/app_publisher.h
@@ -124,6 +124,15 @@ bool clear_site_data, bool report_abuse); + virtual void StopApp(const std::string& app_id); + + virtual void ExecuteContextMenuCommand(const std::string& app_id, + int command_id, + const std::string& shortcut_id, + int64_t display_id); + + virtual void OpenNativeSettings(const std::string& app_id); + // Indicates that the app identified by |app_id| has been set as a preferred // app for |intent_filter|, and the |replaced_app_preferences| is the apps // that are no longer preferred apps for their corresponding |intent_filters|.
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc index fbd7955..be8fb73 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps.cc +++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -599,6 +599,15 @@ }); return all_files_have_mime_type || intent->mime_type.has_value(); } + +// Returns true if the app with the given |app_id| should open supported links +// inside the browser by default. +bool AppShouldDefaultHandleLinksInBrowser(const std::string& app_id) { + // Play Store provides core system functionality and should handle links + // inside the app rather than in the browser. + return app_id != arc::kPlayStoreAppId; +} + } // namespace namespace apps { @@ -1631,10 +1640,11 @@ // When kDefaultLinkCapturingInBrowser is enabled, ignore any requests from // ARC to set an app as handling supported links by default. We allow // requests if they were initiated by user action, or if the app already - // has a non-default setting on the browser side. + // has a non-default setting on the Ash side. bool should_ignore_update = base::FeatureList::GetInstance()->IsEnabled( features::kDefaultLinkCapturingInBrowser) && + AppShouldDefaultHandleLinksInBrowser(app_id) && source == arc::mojom::SupportedLinkChangeSource::kArcSystem && !proxy()->PreferredAppsList().IsPreferredAppForSupportedLinks(app_id);
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc index 3ac1933b2..ad4abfce 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc +++ b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/apps/app_service/publishers/arc_apps.h" +#include "ash/components/arc/mojom/app.mojom.h" #include "ash/components/arc/mojom/intent_helper.mojom.h" #include "ash/components/arc/session/arc_bridge_service.h" #include "ash/components/arc/session/arc_service_manager.h" @@ -22,6 +23,7 @@ #include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_test.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/arc/intent.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" @@ -381,6 +383,39 @@ GURL("https://www.example.com/foo"))); } +// Verifies that when the behavior to open links in the browser by default is +// enabled, the Play Store app can still be set as preferred by the system. +TEST_F(ArcAppsPublisherTest, + SetSupportedLinksDefaultBrowserBehaviorAllowsPlayStore) { + base::test::ScopedFeatureList scoped_features( + features::kDefaultLinkCapturingInBrowser); + + constexpr char kTestAuthority[] = "play.google.com"; + + std::vector<arc::mojom::AppInfoPtr> apps; + apps.push_back(arc::mojom::AppInfo::New("Play Store", arc::kPlayStorePackage, + arc::kPlayStoreActivity)); + arc_test()->app_instance()->SendRefreshAppList(apps); + + // Update intent filters and supported links for the app, as if it was just + // installed. + intent_helper()->OnIntentFiltersUpdatedForPackage( + arc::kPlayStorePackage, + CreateFilterList(arc::kPlayStorePackage, {kTestAuthority})); + std::vector<arc::mojom::SupportedLinksPtr> added_links; + added_links.emplace_back( + absl::in_place, arc::kPlayStorePackage, + CreateFilterList(arc::kPlayStorePackage, {kTestAuthority})); + intent_helper()->OnSupportedLinksChanged( + std::move(added_links), {}, + arc::mojom::SupportedLinkChangeSource::kArcSystem); + + FlushMojoCalls(); + + ASSERT_EQ(arc::kPlayStoreAppId, preferred_apps().FindPreferredAppForUrl( + GURL("https://play.google.com/foo"))); +} + TEST_F(ArcAppsPublisherTest, LaunchAppWithIntent_EditIntent_SendsOpenUrlRequest) { SetUpFileSystemInstance();
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index b1d50d5..6ca7365 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -88,7 +88,6 @@ #include "content/public/test/find_test_utils.h" #include "content/public/test/hit_test_region_observer.h" #include "content/public/test/no_renderer_crashes_assertion.h" -#include "content/public/test/ppapi_test_utils.h" #include "content/public/test/test_file_error_injector.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" @@ -132,7 +131,7 @@ #include "ui/aura/window.h" #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PPAPI) #include "content/public/test/ppapi_test_utils.h" #endif @@ -5541,7 +5540,7 @@ entry->metrics.begin()->second); } -#if BUILDFLAG(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PPAPI) class WebViewPPAPITest : public WebViewTest { protected: void SetUpCommandLine(base::CommandLine* command_line) override { @@ -5562,7 +5561,7 @@ IN_PROC_BROWSER_TEST_P(WebViewPPAPITest, Shim_TestPluginLoadPermission) { TestHelper("testPluginLoadPermission", "web_view/shim", NO_TEST_SERVER); } -#endif // BUILDFLAG(ENABLE_PLUGINS) +#endif // BUILDFLAG(ENABLE_PPAPI) // Helper class to set up a fake Chrome Web Store URL which can be loaded in // tests.
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index e672c60..d55a72c 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -1228,8 +1228,8 @@ "input_method/diacritics_insensitive_string_comparator.h", "input_method/emoji_suggester.cc", "input_method/emoji_suggester.h", - "input_method/get_browser_url.cc", - "input_method/get_browser_url.h", + "input_method/get_current_window_properties.cc", + "input_method/get_current_window_properties.h", "input_method/grammar_manager.cc", "input_method/grammar_manager.h", "input_method/grammar_service_client.cc",
diff --git a/chrome/browser/ash/arc/arc_util_unittest.cc b/chrome/browser/ash/arc/arc_util_unittest.cc index 3c804e6..4aae6969 100644 --- a/chrome/browser/ash/arc/arc_util_unittest.cc +++ b/chrome/browser/ash/arc/arc_util_unittest.cc
@@ -285,7 +285,8 @@ {"", "--arc-availability=officially-supported"}); ScopedLogIn login( GetFakeUserManager(), - AccountId::AdFromObjGuid("f04557de-5da2-40ce-ae9d-b8874d8da96e"), + AccountId::AdFromUserEmailObjGuid("testing_profile@test", + "f04557de-5da2-40ce-ae9d-b8874d8da96e"), user_manager::USER_TYPE_ACTIVE_DIRECTORY); EXPECT_FALSE( ash::ProfileHelper::Get()->GetUserByProfile(profile())->HasGaiaAccount()); @@ -296,7 +297,8 @@ base::CommandLine::ForCurrentProcess()->InitFromArgv({""}); ScopedLogIn login( GetFakeUserManager(), - AccountId::AdFromObjGuid("f04557de-5da2-40ce-ae9d-b8874d8da96e"), + AccountId::AdFromUserEmailObjGuid("testing_profile@test", + "f04557de-5da2-40ce-ae9d-b8874d8da96e"), user_manager::USER_TYPE_ACTIVE_DIRECTORY); EXPECT_FALSE( ash::ProfileHelper::Get()->GetUserByProfile(profile())->HasGaiaAccount());
diff --git a/chrome/browser/ash/arc/input_overlay/ui/input_menu_view.cc b/chrome/browser/ash/arc/input_overlay/ui/input_menu_view.cc index e60be66..1d89f71 100644 --- a/chrome/browser/ash/arc/input_overlay/ui/input_menu_view.cc +++ b/chrome/browser/ash/arc/input_overlay/ui/input_menu_view.cc
@@ -410,7 +410,8 @@ GURL url = GetAssembleUrl(*display_overlay_controller_); ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } gfx::Insets InputMenuView::CalculateInsets(views::View* view,
diff --git a/chrome/browser/ash/borealis/borealis_context.cc b/chrome/browser/ash/borealis/borealis_context.cc index 9e39d9d6..83b7f33 100644 --- a/chrome/browser/ash/borealis/borealis_context.cc +++ b/chrome/browser/ash/borealis/borealis_context.cc
@@ -135,7 +135,8 @@ [](GURL gurl, Profile* profile) { ash::NewWindowDelegate::GetPrimary()->OpenUrl( gurl, - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); NotificationDisplayService::GetForProfile(profile)->Close( NotificationHandler::Type::TRANSIENT,
diff --git a/chrome/browser/ash/child_accounts/website_approval_notifier.cc b/chrome/browser/ash/child_accounts/website_approval_notifier.cc index dc720bf..2a617544 100644 --- a/chrome/browser/ash/child_accounts/website_approval_notifier.cc +++ b/chrome/browser/ash/child_accounts/website_approval_notifier.cc
@@ -59,7 +59,8 @@ void OnNotificationClick(const GURL& url) { base::RecordAction(base::UserMetricsAction(kNotificationClickedActionName)); NewWindowDelegate::GetPrimary()->OpenUrl( - url, NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } } // namespace
diff --git a/chrome/browser/ash/child_accounts/website_approval_notifier_unittest.cc b/chrome/browser/ash/child_accounts/website_approval_notifier_unittest.cc index 1cd4e88..36b45e4 100644 --- a/chrome/browser/ash/child_accounts/website_approval_notifier_unittest.cc +++ b/chrome/browser/ash/child_accounts/website_approval_notifier_unittest.cc
@@ -24,7 +24,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; } // namespace @@ -114,7 +117,8 @@ EXPECT_TRUE(HasApprovalNotification(host)); EXPECT_CALL(new_window_delegate_primary(), OpenUrl(GURL(expected_url), - NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab)); notification_tester_.SimulateClick(NotificationHandler::Type::TRANSIENT, GetNotificationId(host), /*action_index=*/absl::nullopt,
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index 553bc236..dbc5224a 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -679,12 +679,11 @@ base::DoNothing()); } -void BrowserManager::OpenUrl(const GURL& url, - crosapi::mojom::OpenUrlFrom from) { - OpenUrlImpl( - url, - crosapi::mojom::OpenUrlParams::WindowOpenDisposition::kNewForegroundTab, - from, NavigateParams::RESPECT); +void BrowserManager::OpenUrl( + const GURL& url, + crosapi::mojom::OpenUrlFrom from, + crosapi::mojom::OpenUrlParams::WindowOpenDisposition disposition) { + OpenUrlImpl(url, disposition, from, NavigateParams::RESPECT); } void BrowserManager::SwitchToTab(const GURL& url,
diff --git a/chrome/browser/ash/crosapi/browser_manager.h b/chrome/browser/ash/crosapi/browser_manager.h index c019de2..38ab67f 100644 --- a/chrome/browser/ash/crosapi/browser_manager.h +++ b/chrome/browser/ash/crosapi/browser_manager.h
@@ -181,7 +181,10 @@ // Opens the specified URL in lacros-chrome. If it is not running, // it launches lacros-chrome with the given URL. // See crosapi::mojom::BrowserService::OpenUrl for more details. - void OpenUrl(const GURL& url, crosapi::mojom::OpenUrlFrom from); + void OpenUrl( + const GURL& url, + crosapi::mojom::OpenUrlFrom from, + crosapi::mojom::OpenUrlParams::WindowOpenDisposition disposition); // If there's already a tab opening the URL in lacros-chrome, in some window // of the primary profile, activate the tab. Otherwise, opens a tab for
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index b091718..a451b290 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -628,6 +628,16 @@ return base::FeatureList::IsEnabled(chromeos::features::kLacrosPrimary); } +LacrosMode GetLacrosMode() { + if (!IsAshWebBrowserEnabled()) + return LacrosMode::kOnly; + if (IsLacrosPrimaryBrowser()) + return LacrosMode::kPrimary; + if (IsLacrosEnabled()) + return LacrosMode::kSideBySide; + return LacrosMode::kDisabled; +} + void SetLacrosPrimaryBrowserForTest(absl::optional<bool> value) { g_lacros_primary_browser_for_test = value; }
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index d8edb49..1bc08e1 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -97,6 +97,24 @@ kMove = 1, // Migrate using `MoveMigrator`. }; +// Specifies the mode Lacros is currently running. +// This enum is different from LacrosAvailability in the way that +// it describes the mode Lacros is running at a given point in time +// which can be influenced by multiple factors such as flags, +// while LacrosAvailability describes the policy that dictates how +// Lacros is supposed to be launched. +enum class LacrosMode { + // Indicates that Lacros is disabled. Ash is the only browser. + kDisabled = 0, + // Indicates that Lacros is enabled but Ash browser is the + // primary browser. + kSideBySide = 1, + // Indicates that Lacros is the primary browser. Ash is also available. + kPrimary = 2, + // Indicates that Lacros is the only available browser. + kOnly = 3, +}; + extern const ComponentInfo kLacrosDogfoodCanaryInfo; extern const ComponentInfo kLacrosDogfoodDevInfo; extern const ComponentInfo kLacrosDogfoodBetaInfo; @@ -207,6 +225,10 @@ bool IsLacrosPrimaryBrowserForMigration(const user_manager::User* user, PolicyInitState policy_init_state); +// Returns the current mode Lacros is running. +// See LacrosMode definition for a full list of modes. +LacrosMode GetLacrosMode(); + // Forces IsLacrosPrimaryBrowser() to return true or false for testing. // Passing absl::nullopt will reset the state. void SetLacrosPrimaryBrowserForTest(absl::optional<bool> value);
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc index f8f59c7..3e987a4 100644 --- a/chrome/browser/ash/crosapi/browser_util_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -404,7 +404,7 @@ } } -TEST_F(LacrosSupportBrowserUtilTest, LacrosPrimaryBrowserByFlags) { +TEST_F(LacrosSupportBrowserUtilTest, LacrosPrimaryOrOnlyBrowserByFlags) { AddRegularUser("user@test.com"); const user_manager::User* const user = ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); @@ -412,6 +412,19 @@ EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kDisabled, + browser_util::GetLacrosMode()); + } + + // Just enabling LacrosSupport feature is not enough. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(chromeos::features::kLacrosSupport); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kSideBySide, + browser_util::GetLacrosMode()); } // Just enabling LacrosPrimary feature is not enough. @@ -421,9 +434,11 @@ EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kDisabled, + browser_util::GetLacrosMode()); } - // Both LacrosPrimary and LacrosSupport are needed. + // Both LacrosPrimary and LacrosSupport are needed for LacrosPrimary { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures({chromeos::features::kLacrosPrimary, @@ -432,6 +447,21 @@ EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kPrimary, + browser_util::GetLacrosMode()); + } + + // All LacrosPrimary, LacrosOnly and LacrosSupport are needed for LacrosOnly + { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {chromeos::features::kLacrosPrimary, chromeos::features::kLacrosSupport, + chromeos::features::kLacrosOnly}, + {}); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kOnly, browser_util::GetLacrosMode()); } } @@ -449,6 +479,7 @@ EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kPrimary, browser_util::GetLacrosMode()); } TEST_F(BrowserUtilTest, LacrosPrimaryBrowserAllowed) { @@ -476,6 +507,8 @@ EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kDisabled, + browser_util::GetLacrosMode()); } { @@ -486,6 +519,8 @@ EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_FALSE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kSideBySide, + browser_util::GetLacrosMode()); } { @@ -496,6 +531,8 @@ EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kPrimary, + browser_util::GetLacrosMode()); } { @@ -506,6 +543,7 @@ EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kOnly, browser_util::GetLacrosMode()); } } @@ -997,6 +1035,36 @@ EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( user, browser_util::PolicyInitState::kAfterInit)); + // What you see here is Finch overrides policy. + // This is due to a special logic only to Googlers. + // See IsAshWebBrowserEnabled() impl for more details. + EXPECT_EQ(browser_util::LacrosMode::kOnly, browser_util::GetLacrosMode()); + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); + EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( + user, browser_util::PolicyInitState::kAfterInit)); +} + +TEST_F(BrowserUtilTest, LacrosGoogleRolloutOnly) { + AddRegularUser("user@google.com"); + const user_manager::User* const user = + ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_); + // Lacros availability is set by policy to only. + ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly); + + // We enable 3 features: LacrosSupport, LacrosPrimary, LacrosOnly + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {chromeos::features::kLacrosSupport, chromeos::features::kLacrosPrimary, + chromeos::features::kLacrosOnly}, + {}); + + // Check that Lacros is allowed, enabled, and set to lacros-only. + EXPECT_TRUE(browser_util::IsLacrosAllowedToBeEnabled()); + EXPECT_TRUE(browser_util::IsLacrosEnabled()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowser()); + EXPECT_TRUE(browser_util::IsLacrosPrimaryBrowserForMigration( + user, browser_util::PolicyInitState::kAfterInit)); + EXPECT_EQ(browser_util::LacrosMode::kOnly, browser_util::GetLacrosMode()); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled()); EXPECT_FALSE(browser_util::IsAshWebBrowserEnabledForMigration( user, browser_util::PolicyInitState::kAfterInit));
diff --git a/chrome/browser/ash/crosapi/environment_provider.cc b/chrome/browser/ash/crosapi/environment_provider.cc index 00f3534..fbd79bfd 100644 --- a/chrome/browser/ash/crosapi/environment_provider.cc +++ b/chrome/browser/ash/crosapi/environment_provider.cc
@@ -125,7 +125,7 @@ // CrosDisksClient already has a convention for its removable media directory // when running on Linux workstations. default_paths->removable_media = - chromeos::CrosDisksClient::GetRemovableDiskMountPoint(); + ash::CrosDisksClient::GetRemovableDiskMountPoint(); // Ash expects to find shared files in the share cache. default_paths->share_cache =
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc index cdd20ba..c64b7602 100644 --- a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc +++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/crostini/ansible/ansible_management_service.h" +#include <sstream> + #include "base/files/file_util.h" #include "base/logging.h" #include "base/task/task_traits.h" @@ -112,6 +114,7 @@ InstallLinuxPackageProgressStatus status, int progress_percent, const std::string& error_message) { + std::stringstream status_line; switch (status) { case InstallLinuxPackageProgressStatus::SUCCEEDED: { GetAnsiblePlaybookToApply(container_id); @@ -123,10 +126,21 @@ return; // TODO(okalitova): Report Ansible downloading/installation progress. case InstallLinuxPackageProgressStatus::DOWNLOADING: - VLOG(1) << "Ansible downloading progress: " << progress_percent << "%"; + status_line << "Ansible downloading progress: " << progress_percent + << "%"; + VLOG(1) << status_line.str(); + for (auto& observer : observers_) { + observer.OnAnsibleSoftwareConfigurationProgress( + container_id, std::vector<std::string>({status_line.str()})); + } return; case InstallLinuxPackageProgressStatus::INSTALLING: - VLOG(1) << "Ansible installing progress: " << progress_percent << "%"; + status_line << "Ansible installing progress: " << progress_percent << "%"; + VLOG(1) << status_line.str(); + for (auto& observer : observers_) { + observer.OnAnsibleSoftwareConfigurationProgress( + container_id, std::vector<std::string>({status_line.str()})); + } return; default: NOTREACHED();
diff --git a/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc b/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc index eb071a0..6a72435 100644 --- a/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc +++ b/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc
@@ -39,7 +39,10 @@ class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> { public: // TestNewWindowDelegate: - MOCK_METHOD(void, OpenUrl, (const GURL& url, OpenUrlFrom from), (override)); + MOCK_METHOD(void, + OpenUrl, + (const GURL& url, OpenUrlFrom from, Disposition disposition), + (override)); }; class EcheAppNotificationControllerTest : public BrowserWithTestWindowTest {
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index 8c36602d..7cb7f46 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -2063,13 +2063,11 @@ crostini::ContainerInfo(crostini::kCrostiniDefaultContainerName, "testuser", "/home/testuser", "PLACEHOLDER_IP")); - static_cast<chromeos::FakeCrosDisksClient*>( - chromeos::CrosDisksClient::Get()) + static_cast<ash::FakeCrosDisksClient*>(ash::CrosDisksClient::Get()) ->AddCustomMountPointCallback( base::BindRepeating(&FileManagerBrowserTestBase::MaybeMountCrostini, base::Unretained(this))); - static_cast<chromeos::FakeCrosDisksClient*>( - chromeos::CrosDisksClient::Get()) + static_cast<ash::FakeCrosDisksClient*>(ash::CrosDisksClient::Get()) ->AddCustomMountPointCallback( base::BindRepeating(&FileManagerBrowserTestBase::MaybeMountGuestOs, base::Unretained(this))); @@ -3170,8 +3168,7 @@ } if (name == "blockMounts") { - static_cast<chromeos::FakeCrosDisksClient*>( - chromeos::CrosDisksClient::Get()) + static_cast<ash::FakeCrosDisksClient*>(ash::CrosDisksClient::Get()) ->BlockMount(); return; }
diff --git a/chrome/browser/ash/file_manager/open_with_browser.cc b/chrome/browser/ash/file_manager/open_with_browser.cc index 009a74c..dd30962 100644 --- a/chrome/browser/ash/file_manager/open_with_browser.cc +++ b/chrome/browser/ash/file_manager/open_with_browser.cc
@@ -67,7 +67,8 @@ return; } ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
diff --git a/chrome/browser/ash/file_manager/trash_unittest_base.cc b/chrome/browser/ash/file_manager/trash_unittest_base.cc index 99f9b733..c28a9a6 100644 --- a/chrome/browser/ash/file_manager/trash_unittest_base.cc +++ b/chrome/browser/ash/file_manager/trash_unittest_base.cc
@@ -63,7 +63,7 @@ ash::ChunneldClient::InitializeFake(); ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); - chromeos::CrosDisksClient::InitializeFake(); + ash::CrosDisksClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); // Ensure Crostini is setup correctly. @@ -97,7 +97,7 @@ scoped_user_manager_.reset(); profile_.reset(); ash::SeneschalClient::Shutdown(); - chromeos::CrosDisksClient::Shutdown(); + ash::CrosDisksClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown(); ash::ChunneldClient::Shutdown();
diff --git a/chrome/browser/ash/hats/hats_config.cc b/chrome/browser/ash/hats/hats_config.cc index e1f7958..695569e 100644 --- a/chrome/browser/ash/hats/hats_config.cc +++ b/chrome/browser/ash/hats/hats_config.cc
@@ -167,4 +167,14 @@ prefs::kHatsCameraAppSurveyCycleEndTs, // cycle_end_timestamp_pref_name }; +// Chromebook Video/Image Editing/Viewing experience survey -- shown after a +// user opens and then subsequently closes the Google Photos Android App. +const HatsConfig kHatsPhotosExperienceSurvey = { + ::features::kHappinessTrackingPhotosExperience, // feature + "Browser.ChromeOS.HatsSatisfaction.PhotosExperience", // histogram_name + base::Days(7), // new_device_threshold + prefs::kHatsPhotosExperienceIsSelected, // hatsIsSelectedPrefName + prefs::kHatsPhotosExperienceCycleEndTs, // hatsCycleEndTimestampPrefName +}; + } // namespace ash
diff --git a/chrome/browser/ash/hats/hats_config.h b/chrome/browser/ash/hats/hats_config.h index 26f9a2b8..6087f0b 100644 --- a/chrome/browser/ash/hats/hats_config.h +++ b/chrome/browser/ash/hats/hats_config.h
@@ -58,6 +58,7 @@ extern const HatsConfig kHatsPersonalizationWallpaperSurvey; extern const HatsConfig kHatsMediaAppPdfSurvey; extern const HatsConfig kHatsCameraAppSurvey; +extern const HatsConfig kHatsPhotosExperienceSurvey; } // namespace ash
diff --git a/chrome/browser/ash/input_method/assistive_suggester.cc b/chrome/browser/ash/input_method/assistive_suggester.cc index 60b86e7..9610e513 100644 --- a/chrome/browser/ash/input_method/assistive_suggester.cc +++ b/chrome/browser/ash/input_method/assistive_suggester.cc
@@ -411,36 +411,42 @@ kDefaultLongpressEnabledKeys.contains(event.GetCharacter())) { return true; // Do not propagate this event. } - HandleLongpressEnabledKeyEvent(event); + suggester_switch_->FetchEnabledSuggestionsThen( + base::BindOnce(&AssistiveSuggester::HandleLongpressEnabledKeyEvent, + weak_ptr_factory_.GetWeakPtr(), event)); } return false; } void AssistiveSuggester::HandleLongpressEnabledKeyEvent( - const ui::KeyEvent& event) { - if (const char c = event.GetCharacter(); - kDefaultLongpressEnabledKeys.contains(c) && - IsDiacriticsOnPhysicalKeyboardLongpressEnabled()) { - // Process longpress keydown event. - if (current_longpress_char_ == absl::nullopt && - event.type() == ui::EventType::ET_KEY_PRESSED) { - current_longpress_char_ = c; - longpress_timer_.Start( - FROM_HERE, kLongpressActivationDelay, - base::BindOnce(&AssistiveSuggester::OnLongpressDetected, - weak_ptr_factory_.GetWeakPtr())); - return; - } + const ui::KeyEvent& event, + const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions) { + if (!IsDiacriticsOnPhysicalKeyboardLongpressEnabled() || + !enabled_suggestions.diacritic_suggestions || + !kDefaultLongpressEnabledKeys.contains(event.GetCharacter())) { + return; + } - // Process longpress interrupted event (key press up before timer callback - // fired) - if (current_longpress_char_.has_value() && - event.type() == ui::EventType::ET_KEY_RELEASED && - *current_longpress_char_ == c) { - current_longpress_char_ = absl::nullopt; - longpress_timer_.Stop(); - return; - } + const char c = event.GetCharacter(); + // Process longpress keydown event. + if (current_longpress_char_ == absl::nullopt && + event.type() == ui::EventType::ET_KEY_PRESSED) { + current_longpress_char_ = c; + longpress_timer_.Start( + FROM_HERE, kLongpressActivationDelay, + base::BindOnce(&AssistiveSuggester::OnLongpressDetected, + weak_ptr_factory_.GetWeakPtr())); + return; + } + + // Process longpress interrupted event (key press up before timer callback + // fired) + if (current_longpress_char_.has_value() && + event.type() == ui::EventType::ET_KEY_RELEASED && + *current_longpress_char_ == c) { + current_longpress_char_ = absl::nullopt; + longpress_timer_.Stop(); + return; } }
diff --git a/chrome/browser/ash/input_method/assistive_suggester.h b/chrome/browser/ash/input_method/assistive_suggester.h index 2717047d..c1c2cd41 100644 --- a/chrome/browser/ash/input_method/assistive_suggester.h +++ b/chrome/browser/ash/input_method/assistive_suggester.h
@@ -167,7 +167,9 @@ void RecordTextInputStateMetrics( const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions); - void HandleLongpressEnabledKeyEvent(const ui::KeyEvent& key_character); + void HandleLongpressEnabledKeyEvent( + const ui::KeyEvent& key_character, + const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions); void OnLongpressDetected();
diff --git a/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc b/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc index ae69907..a56b31c15 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc +++ b/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc
@@ -135,6 +135,10 @@ "mmfbcljfglbokpmkimbfghdkjmjhdgbg", // System text }; +const char* kDeniedAppsForDiacritics[] = { + "iodihamcpbpeioajjeobimgagajmlibd" // SSH app +}; + bool IsTestUrl(GURL url) { std::string filename = url.ExtractFileName(); for (const char* test_url : kTestUrls) { @@ -178,70 +182,22 @@ } template <size_t N> -bool IsAllowedUrlLegacy(const char* (&allowedDomainAndPaths)[N][2]) { - Browser* browser = chrome::FindLastActive(); - if (browser && browser->window() && browser->window()->IsActive() && - browser->tab_strip_model() && - browser->tab_strip_model()->GetActiveWebContents()) { - GURL url = browser->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL(); - if (IsTestUrl(url) || IsInternalWebsite(url)) - return true; - for (size_t i = 0; i < N; i++) { - auto domain = allowedDomainAndPaths[i][0]; - auto path_prefix = allowedDomainAndPaths[i][1]; - if (AtDomainWithPathPrefix(url, domain, path_prefix)) { - return true; - } - } - } - return false; -} - -template <size_t N> -bool IsMatchedApp(const char* (&allowedApps)[N]) { - // WMHelper is not available in Chrome on Linux. - if (!exo::WMHelper::HasInstance()) - return false; - - auto* wm_helper = exo::WMHelper::GetInstance(); - auto* window = wm_helper ? wm_helper->GetActiveWindow() : nullptr; - if (!window) - return false; - - // TODO(crbug/1094113): improve to cover more scenarios such as chat heads. - const std::string* arc_package_name = - window->GetProperty(ash::kArcPackageNameKey); - if (arc_package_name && std::find(allowedApps, allowedApps + N, - *arc_package_name) != allowedApps + N) { +bool IsMatchedApp(const char* (&allowedApps)[N], WindowProperties w) { + if (!w.arc_package_name.empty() && + std::find(allowedApps, allowedApps + N, w.arc_package_name) != + allowedApps + N) { return true; } - const std::string* app_id = window->GetProperty(ash::kAppIDKey); - if (app_id && - std::find(allowedApps, allowedApps + N, *app_id) != allowedApps + N) { + if (!w.app_id.empty() && + std::find(allowedApps, allowedApps + N, w.app_id) != allowedApps + N) { return true; } return false; } -bool IsAllowedUrlOrAppForPersonalInfoSuggestion() { - return IsAllowedUrlLegacy(kAllowedDomainAndPathsForPersonalInfoSuggester) || - IsMatchedApp(kAllowedAppsForPersonalInfoSuggester); -} - -bool IsAllowedUrlOrAppForEmojiSuggestion() { - return IsAllowedUrlLegacy(kAllowedDomainAndPathsForEmojiSuggester) || - IsMatchedApp(kAllowedAppsForEmojiSuggester); -} - -bool IsAllowedUrlOrAppForMultiWordSuggestion() { - return IsAllowedUrlLegacy(kAllowedDomainAndPathsForMultiWordSuggester) || - IsMatchedApp(kAllowedAppsForMultiWordSuggester); -} - void ReturnEnabledSuggestions( AssistiveSuggesterSwitch::FetchEnabledSuggestionsCallback callback, + WindowProperties window_properties, const absl::optional<GURL>& current_url) { if (!current_url.has_value()) { std::move(callback).Run(AssistiveSuggesterSwitch::EnabledSuggestions{}); @@ -252,38 +208,47 @@ bool emoji_suggestions_allowed = IsMatchedUrlWithPathPrefix(kAllowedDomainAndPathsForEmojiSuggester, *current_url) || - IsMatchedApp(kAllowedAppsForEmojiSuggester); + IsMatchedApp(kAllowedAppsForEmojiSuggester, window_properties); // Allow-list (will only allow if matched) bool multi_word_suggestions_allowed = IsMatchedUrlWithPathPrefix(kAllowedDomainAndPathsForMultiWordSuggester, *current_url) || - IsMatchedApp(kAllowedAppsForMultiWordSuggester); + IsMatchedApp(kAllowedAppsForMultiWordSuggester, window_properties); // Allow-list (will only allow if matched) bool personal_info_suggestions_allowed = IsMatchedUrlWithPathPrefix(kAllowedDomainAndPathsForPersonalInfoSuggester, *current_url) || - IsMatchedApp(kAllowedAppsForPersonalInfoSuggester); + IsMatchedApp(kAllowedAppsForPersonalInfoSuggester, window_properties); + + // Deny-list (will block if matched, otherwise allow) + bool diacritic_suggestions_allowed = + !IsMatchedApp(kDeniedAppsForDiacritics, window_properties); std::move(callback).Run(AssistiveSuggesterSwitch::EnabledSuggestions{ .emoji_suggestions = emoji_suggestions_allowed, .multi_word_suggestions = multi_word_suggestions_allowed, .personal_info_suggestions = personal_info_suggestions_allowed, + .diacritic_suggestions = diacritic_suggestions_allowed, }); } } // namespace AssistiveSuggesterClientFilter::AssistiveSuggesterClientFilter( - GetUrlCallback get_url) - : get_url_(std::move(get_url)) {} + GetUrlCallback get_url, + GetFocusedWindowPropertiesCallback get_window_properties) + : get_url_(std::move(get_url)), + get_window_properties_(std::move(get_window_properties)) {} AssistiveSuggesterClientFilter::~AssistiveSuggesterClientFilter() = default; void AssistiveSuggesterClientFilter::FetchEnabledSuggestionsThen( FetchEnabledSuggestionsCallback callback) { - get_url_.Run(base::BindOnce(ReturnEnabledSuggestions, std::move(callback))); + WindowProperties window_properties = get_window_properties_.Run(); + get_url_.Run(base::BindOnce(ReturnEnabledSuggestions, std::move(callback), + window_properties)); } } // namespace input_method
diff --git a/chrome/browser/ash/input_method/assistive_suggester_client_filter.h b/chrome/browser/ash/input_method/assistive_suggester_client_filter.h index b52dd2fc..58eef4e 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_client_filter.h +++ b/chrome/browser/ash/input_method/assistive_suggester_client_filter.h
@@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" namespace ash { namespace input_method { @@ -18,7 +18,12 @@ using GetUrlCallback = base::RepeatingCallback<void(GetFocusedTabUrlCallback)>; - explicit AssistiveSuggesterClientFilter(GetUrlCallback get_url); + using GetFocusedWindowPropertiesCallback = + base::RepeatingCallback<WindowProperties(void)>; + + AssistiveSuggesterClientFilter( + GetUrlCallback get_url, + GetFocusedWindowPropertiesCallback get_window_properties); ~AssistiveSuggesterClientFilter() override; @@ -29,7 +34,7 @@ private: // Used to fetch the url from the current browser instance. GetUrlCallback get_url_; - + GetFocusedWindowPropertiesCallback get_window_properties_; base::WeakPtrFactory<AssistiveSuggesterClientFilter> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ash/input_method/assistive_suggester_client_filter_unittest.cc b/chrome/browser/ash/input_method/assistive_suggester_client_filter_unittest.cc index bc97a48..35d076a 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_client_filter_unittest.cc +++ b/chrome/browser/ash/input_method/assistive_suggester_client_filter_unittest.cc
@@ -7,7 +7,7 @@ #include "base/callback.h" #include "base/test/bind.h" #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -24,9 +24,17 @@ }); } +base::RepeatingCallback<WindowProperties(void)> ReturnWindowProperty( + const WindowProperties& window_properties) { + return base::BindLambdaForTesting( + [window_properties]() { return window_properties; }); +} + struct VerifySuggesterTestCase { std::string test_name; std::string url; + std::string app_id; + std::string arc_package_name; EnabledSuggestions enabled_suggestions; }; @@ -34,7 +42,12 @@ TEST_P(SuggesterAllowlist, VerifySuggesterAllowedState) { const VerifySuggesterTestCase& test_case = GetParam(); - AssistiveSuggesterClientFilter filter(ReturnUrl(test_case.url)); + AssistiveSuggesterClientFilter filter( + ReturnUrl(test_case.url), + ReturnWindowProperty({ + .app_id = test_case.app_id, + .arc_package_name = test_case.arc_package_name, + })); EnabledSuggestions enabled_suggestions; filter.FetchEnabledSuggestionsThen( @@ -50,138 +63,336 @@ SuggesterAllowlist, testing::ValuesIn<VerifySuggesterTestCase>({ // Tests with https. - {"DiscordHttps", "https://www.discord.com", + {"DiscordHttps", /* url=*/"https://www.discord.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"MessengerHttps", "https://www.messenger.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MessengerHttps", /* url=*/"https://www.messenger.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"WhatsappHttps", "https://web.whatsapp.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"WhatsappHttps", /* url=*/"https://web.whatsapp.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"SkypeHttps", "https://web.skype.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"SkypeHttps", /* url=*/"https://web.skype.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = false, - .personal_info_suggestions = true}}, - {"DuoHttps", "https://duo.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"DuoHttps", /* url=*/"https://duo.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"HangoutsHttps", "https://hangouts.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"HangoutsHttps", /* url=*/"https://hangouts.google.com", + /* app_id=*/"", /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"MessagesHttps", "https://messages.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MessagesHttps", /* url=*/"https://messages.google.com", + /* app_id=*/"", /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"TelegramHttps", "https://web.telegram.org", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TelegramHttps", /* url=*/"https://web.telegram.org", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"VoiceHttps", "https://voice.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"VoiceHttps", /* url=*/"https://voice.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"DocsHttps", "https://docs.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"DocsHttps", /* url=*/"https://docs.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"RandomHttps", "https://www.abc.com", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"RandomHttps", /* url=*/"https://www.abc.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailHttps", "https://mail.google.com", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailHttps", /* url=*/"https://mail.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithPartialMailPathHttps", "https://mail.google.com/mail", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithPartialMailPathHttps", + /* url=*/"https://mail.google.com/mail", "", "", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithFullMailPathHttps", "https://mail.google.com/mail/u/0", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithFullMailPathHttps", + /* url=*/"https://mail.google.com/mail/u/0", "", "", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithPartialChatPathHttps", "https://mail.google.com/chat", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithPartialChatPathHttps", + /* url=*/"https://mail.google.com/chat", "", "", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, {"GmailWithFullChatPathHttps", - "https://mail.google.com/chat/u/0/#chat/space/ABC123", + /* url=*/"https://mail.google.com/chat/u/0/#chat/space/ABC123", + /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, // Tests with http. - {"DiscordHttp", "http://www.discord.com", + {"DiscordHttp", /* url=*/"http://www.discord.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"MessengerHttp", "http://www.messenger.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MessengerHttp", /* url=*/"http://www.messenger.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"WhatsappHttp", "http://web.whatsapp.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"WhatsappHttp", /* url=*/"http://web.whatsapp.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"SkypeHttp", "http://web.skype.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"SkypeHttp", /* url=*/"http://web.skype.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = false, - .personal_info_suggestions = true}}, - {"DuoHttp", "http://duo.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"DuoHttp", /* url=*/"http://duo.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"HangoutsHttp", "http://hangouts.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"HangoutsHttp", /* url=*/"http://hangouts.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"MessagesHttp", "http://messages.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MessagesHttp", /* url=*/"http://messages.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"TelegramHttp", "http://web.telegram.org", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TelegramHttp", /* url=*/"http://web.telegram.org", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"VoiceHttp", "http://voice.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"VoiceHttp", /* url=*/"http://voice.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, - {"DocsHttp", "http://docs.google.com", + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"DocsHttp", /* url=*/"http://docs.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"RandomHttp", "http://www.abc.com", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"RandomHttp", /* url=*/"http://www.abc.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailHttp", "http://mail.google.com", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailHttp", /* url=*/"http://mail.google.com", /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithPartialMailPathHttp", "http://mail.google.com/mail", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithPartialMailPathHttp", /* url=*/"http://mail.google.com/mail", + /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithFullMailPathHttp", "http://mail.google.com/mail/u/0", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithFullMailPathHttp", + /* url=*/"http://mail.google.com/mail/u/0", + /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = false, .multi_word_suggestions = false, - .personal_info_suggestions = false}}, - {"GmailWithPartialChatPathHttp", "http://mail.google.com/chat", + .personal_info_suggestions = false, + .diacritic_suggestions = true}}, + {"GmailWithPartialChatPathHttp", /* url=*/"http://mail.google.com/chat", + /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, {"GmailWithFullChatPathHttp", - "http://mail.google.com/chat/u/0/#chat/space/ABC123", + /* url=*/"http://mail.google.com/chat/u/0/#chat/space/ABC123", + /* app_id=*/"", + /* arc_package_name=*/"", EnabledSuggestions{.emoji_suggestions = true, .multi_word_suggestions = true, - .personal_info_suggestions = true}}, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"SystemTextApp", /* url=*/"", + /* app_id=*/"mmfbcljfglbokpmkimbfghdkjmjhdgbg", + /* arc_package_name=*/"", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"ChromeSSHApp", /* url=*/"", + /* app_id=*/"iodihamcpbpeioajjeobimgagajmlibd", + /* arc_package_name=*/"", + EnabledSuggestions{.emoji_suggestions = false, + .multi_word_suggestions = false, + .personal_info_suggestions = false, + .diacritic_suggestions = false}}, + {"DiscordApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.discord", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"OrcaFacebookApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.facebook.orca", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"WhatsappApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.whatsapp", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"RaiderSkypeApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.skype.raider", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TachyonGoogleApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.google.android.apps.tachyon", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TalkGoogleApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.google.android.talk", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TelegramApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"org.telegram.messenger", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"TextNowEnflickApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.enflick.android.TextNow", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MliteFacebookApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.facebook.mlite", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"VoipViberApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.viber.voip", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"M2SkypeApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.skype.m2", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"ImoimImoApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.imo.android.imoim", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"GooglevoiceGoogleApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.google.android.apps.googlevoice", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"MobilemessengerPlaystationApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.playstation.mobilemessenger", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"KikApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"kik.android", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"LinkApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.link.messages.sms", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"NaverApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"jp.naver.line.android", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"HappybitsApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"co.happybits.marcopolo", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, + {"ImoApp", /* url=*/"", /* app_id=*/"", + /* arc_package_name=*/"com.imo.android.imous", + EnabledSuggestions{.emoji_suggestions = true, + .multi_word_suggestions = true, + .personal_info_suggestions = true, + .diacritic_suggestions = true}}, }), [](const testing::TestParamInfo<SuggesterAllowlist::ParamType>& info) { return info.param.test_name;
diff --git a/chrome/browser/ash/input_method/assistive_suggester_switch.h b/chrome/browser/ash/input_method/assistive_suggester_switch.h index 71b27f4..702ecd45 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_switch.h +++ b/chrome/browser/ash/input_method/assistive_suggester_switch.h
@@ -18,11 +18,13 @@ bool emoji_suggestions = false; bool multi_word_suggestions = false; bool personal_info_suggestions = false; + bool diacritic_suggestions = false; bool operator==(const EnabledSuggestions& rhs) const { return emoji_suggestions == rhs.emoji_suggestions && multi_word_suggestions == rhs.multi_word_suggestions && - personal_info_suggestions == rhs.personal_info_suggestions; + personal_info_suggestions == rhs.personal_info_suggestions && + diacritic_suggestions == rhs.diacritic_suggestions; } };
diff --git a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc index 849d6a6..37da5391 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc +++ b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/ash/input_method/assistive_suggester_client_filter.h" #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" #include "chrome/browser/ash/input_method/fake_suggestion_handler.h" -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" #include "chrome/browser/ash/input_method/personal_info_suggester.h" #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" #include "chrome/common/pref_names.h" @@ -96,6 +96,7 @@ class FakeSuggesterSwitch : public AssistiveSuggesterSwitch { public: + // TODO(b/242472734): Allow enabled suggestions passed without replace. explicit FakeSuggesterSwitch(EnabledSuggestions enabled_suggestions) : enabled_suggestions_(enabled_suggestions) {} ~FakeSuggesterSwitch() override = default; @@ -116,10 +117,12 @@ void SetUp() override { suggestion_handler_ = std::make_unique<FakeSuggestionHandler>(); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<AssistiveSuggesterClientFilter>( - base::BindRepeating(&GetFocusedTabUrl))); + base::BindRepeating(&GetFocusedTabUrl), + base::BindRepeating(&GetFocusedWindowProperties))); histogram_tester_.ExpectUniqueSample( "InputMethod.Assistive.UserPref.PersonalInfo", true, 1); @@ -354,6 +357,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kAssistMultiWord}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{})); @@ -371,6 +375,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kAssistMultiWord}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{})); @@ -393,6 +398,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kAssistMultiWord}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>( @@ -417,6 +423,7 @@ /*enabled_features=*/{features::kAssistMultiWord, features::kLacrosSupport}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>( @@ -441,6 +448,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kAssistMultiWord}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>( @@ -464,6 +472,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kAssistMultiWord}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>( @@ -488,6 +497,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false, /*diacritics_on_longpress_enabled=*/true); assistive_suggester_->OnActivate(kUsEnglishEngineId); @@ -505,6 +519,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false, /*diacritics_on_longpress_enabled=*/true); assistive_suggester_->OnActivate(kUsEnglishEngineId); @@ -525,6 +544,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false, /*diacritics_on_longpress_enabled=*/false); assistive_suggester_->OnActivate(kUsEnglishEngineId); @@ -542,6 +566,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false, /*diacritics_on_longpress_enabled=*/true); assistive_suggester_->OnActivate(kSpainSpanishEngineId); @@ -559,6 +588,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); SetInputMethodOptions(*profile_, /*predictive_writing_enabled=*/false, /*diacritics_on_longpress_enabled=*/true); assistive_suggester_->OnActivate(kUsEnglishEngineId); @@ -578,6 +612,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); assistive_suggester_->OnActivate(kUsEnglishEngineId); EXPECT_FALSE(assistive_suggester_->OnKeyEvent(PressKey(ui::DomCode::US_A))); @@ -591,6 +630,11 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kDiacriticsOnPhysicalKeyboardLongpress}, /*disabled_features=*/{}); + // TODO(b/242472734): Allow enabled suggestions passed without replace. + assistive_suggester_ = std::make_unique<AssistiveSuggester>( + suggestion_handler_.get(), profile_.get(), + std::make_unique<FakeSuggesterSwitch>( + EnabledSuggestions{.diacritic_suggestions = true})); assistive_suggester_->OnActivate(kUsEnglishEngineId); assistive_suggester_->OnFocus(5); @@ -678,6 +722,7 @@ chrome_keyboard_controller_client_ = ChromeKeyboardControllerClient::CreateForTest(); chrome_keyboard_controller_client_->set_keyboard_visible_for_test(false); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -854,6 +899,7 @@ } TEST_P(AssistiveSuggesterPersonalInfoTest, ShouldNotSuggestWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -872,6 +918,7 @@ TEST_P(AssistiveSuggesterPersonalInfoTest, ShouldRecordNotAllowedWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -892,6 +939,7 @@ TEST_P(AssistiveSuggesterPersonalInfoTest, ShouldRecordDisabledReasonWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -933,6 +981,7 @@ void SetUp() override { suggestion_handler_ = std::make_unique<FakeSuggestionHandler>(); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -996,6 +1045,7 @@ } TEST_F(AssistiveSuggesterMultiWordTest, ShouldNotSuggestWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -1053,6 +1103,7 @@ TEST_F(AssistiveSuggesterMultiWordTest, DisableMetricNotRecordedWhenNoSuggestionAndMultiWordBlocked) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{}), nullptr); @@ -1068,6 +1119,7 @@ TEST_F(AssistiveSuggesterMultiWordTest, DisableMetricRecordedWhenGivenSuggestionAndMultiWordBlocked) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{}), nullptr); @@ -1232,6 +1284,7 @@ void SetUp() override { suggestion_handler_ = std::make_unique<FakeSuggestionHandler>(); + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -1290,6 +1343,7 @@ } TEST_F(AssistiveSuggesterEmojiTest, ShouldNotSuggestWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -1307,6 +1361,7 @@ } TEST_F(AssistiveSuggesterEmojiTest, ShouldRecordNotAllowedWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{ @@ -1327,6 +1382,7 @@ TEST_F(AssistiveSuggesterEmojiTest, ShouldRecordDisabledReasonWhenSwitchDisabled) { + // TODO(b/242472734): Allow enabled suggestions passed without replace. assistive_suggester_ = std::make_unique<AssistiveSuggester>( suggestion_handler_.get(), profile_.get(), std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{
diff --git a/chrome/browser/ash/input_method/get_browser_url.cc b/chrome/browser/ash/input_method/get_current_window_properties.cc similarity index 71% rename from chrome/browser/ash/input_method/get_browser_url.cc rename to chrome/browser/ash/input_method/get_current_window_properties.cc index bcc11c7..d4eccb6 100644 --- a/chrome/browser/ash/input_method/get_browser_url.cc +++ b/chrome/browser/ash/input_method/get_current_window_properties.cc
@@ -4,12 +4,14 @@ // // This file implements the input method candidate window used on Chrome OS. -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" +#include "ash/public/cpp/window_properties.h" #include "base/callback.h" #include "chrome/browser/ash/crosapi/browser_manager.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "components/exo/wm_helper.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" @@ -59,5 +61,26 @@ GetLacrosChromeUrl(std::move(callback)); } +WindowProperties GetFocusedWindowProperties() { + WindowProperties properties = {.app_id = "", .arc_package_name = ""}; + if (!exo::WMHelper::HasInstance()) + return properties; + + auto* wm_helper = exo::WMHelper::GetInstance(); + auto* window = wm_helper ? wm_helper->GetActiveWindow() : nullptr; + if (!window) + return properties; + + const std::string* arc_package_name = + window->GetProperty(ash::kArcPackageNameKey); + if (arc_package_name) { + properties.arc_package_name = *arc_package_name; + } + const std::string* app_id = window->GetProperty(ash::kAppIDKey); + if (app_id) { + properties.app_id = *app_id; + } + return properties; +} } // namespace input_method } // namespace ash
diff --git a/chrome/browser/ash/input_method/get_browser_url.h b/chrome/browser/ash/input_method/get_current_window_properties.h similarity index 62% rename from chrome/browser/ash/input_method/get_browser_url.h rename to chrome/browser/ash/input_method/get_current_window_properties.h index a335e25..7db5d2ebb0 100644 --- a/chrome/browser/ash/input_method/get_browser_url.h +++ b/chrome/browser/ash/input_method/get_current_window_properties.h
@@ -4,8 +4,8 @@ // // This file implements the input method candidate window used on Chrome OS. -#ifndef CHROME_BROWSER_ASH_INPUT_METHOD_GET_BROWSER_URL_H_ -#define CHROME_BROWSER_ASH_INPUT_METHOD_GET_BROWSER_URL_H_ +#ifndef CHROME_BROWSER_ASH_INPUT_METHOD_GET_CURRENT_WINDOW_PROPERTIES_H_ +#define CHROME_BROWSER_ASH_INPUT_METHOD_GET_CURRENT_WINDOW_PROPERTIES_H_ #include "base/callback.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -14,12 +14,19 @@ namespace ash { namespace input_method { +struct WindowProperties { + std::string app_id; + std::string arc_package_name; +}; + using GetFocusedTabUrlCallback = base::OnceCallback<void(const absl::optional<GURL>&)>; void GetFocusedTabUrl(GetFocusedTabUrlCallback callback); +WindowProperties GetFocusedWindowProperties(); + } // namespace input_method } // namespace ash -#endif // CHROME_BROWSER_ASH_INPUT_METHOD_GET_BROWSER_URL_H_ +#endif // CHROME_BROWSER_ASH_INPUT_METHOD_GET_CURRENT_WINDOW_PROPERTIES_H_
diff --git a/chrome/browser/ash/input_method/native_input_method_engine.cc b/chrome/browser/ash/input_method/native_input_method_engine.cc index a8527fb..8e159ba 100644 --- a/chrome/browser/ash/input_method/native_input_method_engine.cc +++ b/chrome/browser/ash/input_method/native_input_method_engine.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" #include "chrome/browser/ash/input_method/autocorrect_manager.h" #include "chrome/browser/ash/input_method/diacritics_checker.h" -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" #include "chrome/browser/ash/input_method/grammar_service_client.h" #include "chrome/browser/ash/input_method/input_method_quick_settings_helpers.h" #include "chrome/browser/ash/input_method/input_method_settings.h" @@ -75,9 +75,11 @@ std::unique_ptr<AssistiveSuggester> assistive_suggester = std::make_unique<AssistiveSuggester>( this, profile, - suggester_switch_ ? std::move(suggester_switch_) - : std::make_unique<AssistiveSuggesterClientFilter>( - base::BindRepeating(&GetFocusedTabUrl)), + suggester_switch_ + ? std::move(suggester_switch_) + : std::make_unique<AssistiveSuggesterClientFilter>( + base::BindRepeating(&GetFocusedTabUrl), + base::BindRepeating(&GetFocusedWindowProperties)), nullptr); assistive_suggester_ = assistive_suggester.get(); std::unique_ptr<AutocorrectManager> autocorrect_manager =
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc index ce1e201..d126df3 100644 --- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc +++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/ash/input_method/assistive_suggester_switch.h" #include "chrome/browser/ash/input_method/autocorrect_manager.h" #include "chrome/browser/ash/input_method/diacritics_checker.h" -#include "chrome/browser/ash/input_method/get_browser_url.h" +#include "chrome/browser/ash/input_method/get_current_window_properties.h" #include "chrome/browser/ash/input_method/grammar_service_client.h" #include "chrome/browser/ash/input_method/input_method_quick_settings_helpers.h" #include "chrome/browser/ash/input_method/input_method_settings.h"
diff --git a/chrome/browser/ash/sharesheet/drive_share_action.cc b/chrome/browser/ash/sharesheet/drive_share_action.cc index dd88aaa..d086bbb4 100644 --- a/chrome/browser/ash/sharesheet/drive_share_action.cc +++ b/chrome/browser/ash/sharesheet/drive_share_action.cc
@@ -44,7 +44,8 @@ } ash::NewWindowDelegate::GetPrimary()->OpenUrl( intent->drive_share_url.value(), - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); controller_->CloseBubble(::sharesheet::SharesheetResult::kSuccess); }
diff --git a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc index 9df01a7..ea8aa3d 100644 --- a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
@@ -15,6 +15,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/metrics/user_metrics.h" #include "base/path_service.h" #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" @@ -136,11 +137,6 @@ // Use a fake audio stream. Some tests make noise otherwise, and could fight // with parallel tests for access to the audio device. command_line->AppendSwitch(switches::kDisableAudioOutput); - - // Enable HaTS testing. - command_line->AppendSwitchASCII( - ash::switches::kForceHappinessTrackingSystem, - features::kHappinessTrackingMediaAppPdf.name); } void SetUpOnMainThread() override { @@ -162,6 +158,20 @@ // for the application to finish loading. content::WebContents* DirectlyLaunchWithFile(const base::FilePath& file_path); + struct DataArgsHelper { + const char* const open_image = "0"; + const char* const open_video = "0"; + const char* const edit_image = "0"; + const char* const edit_video = "0"; + }; + void ExpectProductSurveyData(DataArgsHelper expected_data) { + auto data = HatsProductSpecificDataForMediaApp(); + EXPECT_EQ(data["did_open_image_in_gallery"], expected_data.open_image); + EXPECT_EQ(data["did_open_video_in_gallery"], expected_data.open_video); + EXPECT_EQ(data["clicked_edit_image_in_photos"], expected_data.edit_image); + EXPECT_EQ(data["clicked_edit_video_in_photos"], expected_data.edit_video); + } + protected: ash::NetworkPortalDetectorMixin network_portal_detector_{&mixin_host_}; @@ -380,6 +390,47 @@ using MediaAppIntegrationWithFilesAppAllProfilesTest = MediaAppIntegrationWithFilesAppTest; +// Scoped observer of notifications that will spin a run loop until a +// notification is displayed. +class NotificationWatcher : public NotificationDisplayService::Observer { + public: + NotificationWatcher(Profile* profile, + ash::NetworkPortalDetectorMixin& network_portal_detector) + : profile_(profile) { + // Notifications only fire if the device is "online". Simulate that. + network_portal_detector.SimulateDefaultNetworkState( + ash::NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE); + + NotificationDisplayService::GetForProfile(profile_)->AddObserver(this); + } + ~NotificationWatcher() override { + NotificationDisplayService::GetForProfile(profile_)->RemoveObserver(this); + } + std::string NextSeenNotificationId() { + if (seen_notification_id_.empty()) + run_loop_.Run(); + return seen_notification_id_; + } + + private: + Profile* profile_; + base::RunLoop run_loop_; + std::string seen_notification_id_; + + void OnNotificationDisplayed( + const message_center::Notification& notification, + const NotificationCommon::Metadata* const metadata) override { + seen_notification_id_ = notification.id(); + if (run_loop_.IsRunningOnCurrentThread()) { + run_loop_.Quit(); + } + } + + void OnNotificationClosed(const std::string& notification_id) override {} + void OnNotificationDisplayServiceDestroyed( + NotificationDisplayService* service) override {} +}; + class BrowserWindowWaiter : public BrowserListObserver { public: void WaitForBrowserAdded() { @@ -569,6 +620,7 @@ PrepareAppForTest(app); EXPECT_EQ("800x600", WaitForImageAlt(app, kFilePng800x600)); + ExpectProductSurveyData({.open_image = "1"}); // Launch with a different file in a new window. app = DirectlyLaunchWithFile(TestFile(kFileJpeg640x480)); @@ -577,6 +629,7 @@ EXPECT_EQ("640x480", WaitForImageAlt(app, kFileJpeg640x480)); EXPECT_NE(first_browser, second_browser); + ExpectProductSurveyData({.open_image = "1"}); // The "1" is a bool. } // Test that the MediaApp successfully loads a file using @@ -594,6 +647,7 @@ content::WebContents* app = PrepareActiveBrowserForTest(); EXPECT_EQ("800x600", WaitForImageAlt(app, kFilePng800x600)); + ExpectProductSurveyData({.open_image = "1"}); // Launch the App for the second time. ash::SystemAppLaunchParams image_params; @@ -606,6 +660,7 @@ EXPECT_EQ("640x480", WaitForImageAlt(app, kFileJpeg640x480)); EXPECT_NE(first_browser, second_browser); + ExpectProductSurveyData({.open_image = "1"}); } // Test that the Media App launches a single window for images. @@ -625,6 +680,7 @@ browser_list->get(1)->tab_strip_model()->GetActiveWebContents(), u"image.png"); EXPECT_EQ(u"image.png", watcher.WaitAndGetTitle()); + ExpectProductSurveyData({.open_image = "1"}); } // Test that the Media App launches multiple windows for PDFs. @@ -648,6 +704,7 @@ u"img.pdf"); EXPECT_EQ(u"tall.pdf", watcher1.WaitAndGetTitle()); EXPECT_EQ(u"img.pdf", watcher2.WaitAndGetTitle()); + ExpectProductSurveyData({}); // Only images and video are tracked. } // Test that the Media App appears as a handler for files in the App Service. @@ -1049,6 +1106,8 @@ // Width and height should be swapped now. EXPECT_EQ("272x378", WaitForImageAlt(web_ui, kRaw378x272)); + // Raw files aren't tracked (they are not directly editable by Photos). + ExpectProductSurveyData({}); } // Ensures that chrome://media-app is available as a file task for the ChromeOS @@ -1684,6 +1743,13 @@ EXPECT_FALSE(result); } +IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, OpenVideoFile) { + content::WebContents* web_ui = LaunchWithOneTestFile(kFileVideoVP9); + + EXPECT_NE(web_ui, nullptr); + ExpectProductSurveyData({.open_video = "1"}); +} + IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, ToggleBrowserFullscreen) { content::WebContents* web_ui = LaunchWithOneTestFile(kFileVideoVP9); Browser* app_browser = chrome::FindBrowserWithActiveWindow(); @@ -1709,6 +1775,11 @@ // Note kForceHappinessTrackingSystem is set in the test fixture to ignore the // "dice roll" that would normally only show the prompt by chance. IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, MaybeTriggerPdfHats) { + // Enable HaTS testing for PDF editing. + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + ash::switches::kForceHappinessTrackingSystem, + features::kHappinessTrackingMediaAppPdf.name); + content::WebContents* web_ui = LaunchWithOneTestFile(kFilePdfTall); constexpr char kMaybeTriggerPdfHats[] = R"( @@ -1718,41 +1789,60 @@ })(); )"; - struct NotificationWatcher : public NotificationDisplayService::Observer { - base::RunLoop run_loop; - std::string seen_notification_id; - - void OnNotificationDisplayed( - const message_center::Notification& notification, - const NotificationCommon::Metadata* const metadata) override { - seen_notification_id = notification.id(); - if (run_loop.IsRunningOnCurrentThread()) { - run_loop.Quit(); - } - } - - void OnNotificationClosed(const std::string& notification_id) override {} - void OnNotificationDisplayServiceDestroyed( - NotificationDisplayService* service) override {} - } notification_watcher; - - auto* notification_display_service = - NotificationDisplayService::GetForProfile(profile()); - notification_display_service->AddObserver(¬ification_watcher); - - // Notifications only fire if the device is "online". Simulate that. - network_portal_detector_.SimulateDefaultNetworkState( - ash::NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE); + NotificationWatcher notification_watcher(profile(), network_portal_detector_); EXPECT_EQ("success", ExtractStringInGlobalScope(web_ui, kMaybeTriggerPdfHats)); + EXPECT_EQ(notification_watcher.NextSeenNotificationId(), "hats_notification"); +} - if (notification_watcher.seen_notification_id.empty()) { - notification_watcher.run_loop.Run(); - } - notification_display_service->RemoveObserver(¬ification_watcher); +// Tests that the Photos happiness tracking survey triggers when the monitored +// app is closed, after force-enabling display of the survey. +IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, MaybeTriggerPhotosHats) { + // Enable HaTS testing for the Photos Experience. + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + ash::switches::kForceHappinessTrackingSystem, + features::kHappinessTrackingPhotosExperience.name); - EXPECT_EQ(notification_watcher.seen_notification_id, "hats_notification"); + // Pretend the Gallery is the Android Photos app, so it can be tracked for + // survey triggers that fire when the app is closed. + std::string media_app_app_id = MediaAppAppId(); + SetPhotosExperienceSurveyTriggerAppIdForTesting(media_app_app_id.c_str()); + + NotificationWatcher notification_watcher(profile(), network_portal_detector_); + + LaunchWithNoFiles(); + chrome::FindBrowserWithActiveWindow()->window()->Close(); + + EXPECT_EQ(notification_watcher.NextSeenNotificationId(), "hats_notification"); + + // Avoid leaving a ref to the std::string about to be destroyed. + SetPhotosExperienceSurveyTriggerAppIdForTesting(""); +} + +IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, CapturesUserActionsForHats) { + ExpectProductSurveyData({}); // Initially nothing. + + using base::RecordAction; + using base::UserMetricsAction; + + // Actions aren't tracked when the app isn't running (the corresponding + // buttons are impossible to click). + RecordAction(UserMetricsAction("MediaApp.Image.Tool.EditInPhotos")); + RecordAction(UserMetricsAction("MediaApp.Video.Tool.EditInPhotos")); + + LaunchWithNoFiles(); + ExpectProductSurveyData({}); + + RecordAction(UserMetricsAction("MediaApp.Image.Tool.EditInPhotos")); + ExpectProductSurveyData({.edit_image = "1"}); + + RecordAction(UserMetricsAction("MediaApp.Video.Tool.EditInPhotos")); + ExpectProductSurveyData({.edit_image = "1", .edit_video = "1"}); + + // Actions are boolean, and never go back to false. + RecordAction(UserMetricsAction("MediaApp.Image.Tool.EditInPhotos")); + ExpectProductSurveyData({.edit_image = "1", .edit_video = "1"}); } IN_PROC_BROWSER_TEST_P(MediaAppIntegrationTest, GuestCanReadLocalFonts) {
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc index cee8447..5278b28 100644 --- a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc +++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
@@ -10,19 +10,29 @@ #include "ash/constants/ash_features.h" #include "ash/webui/grit/ash_media_app_resources.h" #include "ash/webui/media_app_ui/buildflags.h" +#include "ash/webui/media_app_ui/media_app_guest_ui.h" #include "ash/webui/media_app_ui/url_constants.h" #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ash/hats/hats_config.h" +#include "chrome/browser/ash/hats/hats_notification_controller.h" #include "chrome/browser/ash/web_applications/system_web_app_install_utils.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chromeos/grit/chromeos_media_app_bundle_resources.h" #include "chromeos/strings/grit/chromeos_strings.h" +#include "components/services/app_service/public/cpp/instance_registry.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/l10n/l10n_util.h" #include "ui/chromeos/styles/cros_styles.h" @@ -93,6 +103,15 @@ {"application/pdf", kPdfExtension}, }; +// The subset of supported image/video extensions that are watched for photos +// integration happiness tracking, and whether a file of that type was ever +// opened in Gallery since the start of this browser process. +constexpr const char* kWatchedImageExtensions[] = {".png", ".jpg", ".jpeg", + ".webp", ".bmp"}; +constexpr const char* kWatchedVideoExtensions[] = {".webm", ".mp4"}; +bool g_did_open_image_in_gallery = false; +bool g_did_open_video_in_gallery = false; + // Converts a FileHandlerConfig constexpr into the type needed to populate the // WebAppInstallInfo's `accept` property. std::vector<apps::FileHandler::AcceptEntry> MakeFileHandlerAccept( @@ -122,6 +141,88 @@ params.intent ? params.intent->Clone() : nullptr); } +// Watches a Profile's AppServiceProxy's InstanceRegistry and (possibly) +// triggers a happiness tracking survey (HaTS) when it observes the Photos +// Android app being closed. Owned by a Profile. Registration starts during +// AppServiceProxy initialization when the MediaApp is configured, but via an +// asynchronous task to ensure AppServiceProxy is fully initialized when +// observers are added. +class PhotosExperienceSurveyTrigger : public apps::InstanceRegistry::Observer, + public base::SupportsUserData::Data { + public: + PhotosExperienceSurveyTrigger(const PhotosExperienceSurveyTrigger&) = delete; + PhotosExperienceSurveyTrigger& operator=( + const PhotosExperienceSurveyTrigger&) = delete; + ~PhotosExperienceSurveyTrigger() override = default; + + static void Register(Profile* profile) { + if (profile->GetUserData(&profile_user_data_key)) + return; + + auto instance = + base::WrapUnique(new PhotosExperienceSurveyTrigger(profile)); + auto instance_ptr = instance->weak_ptr_factory_.GetWeakPtr(); + profile->SetUserData(&profile_user_data_key, std::move(instance)); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&PhotosExperienceSurveyTrigger::RegisterAsync, + instance_ptr)); + } + + static const char* google_photos_app_id; // Can be overridden for testing. + private: + explicit PhotosExperienceSurveyTrigger(Profile* profile) + : profile_(profile) {} + + void RegisterAsync() { + // This must be checked here (and not when scheduling the task), because the + // value can change in some tests while waiting to be executed. + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( + profile_)) { + profile_->SetUserData(&profile_user_data_key, nullptr); + return; + } + + apps::AppServiceProxyAsh* app_service_proxy = + apps::AppServiceProxyFactory::GetForProfile(profile_); + observation_.Observe(&app_service_proxy->InstanceRegistry()); + } + + void OnInstanceUpdate(const apps::InstanceUpdate& update) override { + // Trigger when the Photos app is closed, and no trigger has yet occurred. + if (update.AppId() != google_photos_app_id || !update.IsDestruction() || + hats_notification_controller_) { + return; + } + if (!ash::HatsNotificationController::ShouldShowSurveyToProfile( + profile_, ash::kHatsPhotosExperienceSurvey)) { + return; + } + + hats_notification_controller_ = new ash::HatsNotificationController( + profile_, ash::kHatsPhotosExperienceSurvey, + HatsProductSpecificDataForMediaApp()); + } + + void OnInstanceRegistryWillBeDestroyed(apps::InstanceRegistry*) override { + observation_.Reset(); + } + + // The memory address of this serves as the Profile user data key (which is OK + // -- nothing is persisted to disk). + static const int profile_user_data_key; + + raw_ptr<Profile> profile_; // Weak. Owns `this`. + base::ScopedObservation<apps::InstanceRegistry, + apps::InstanceRegistry::Observer> + observation_{this}; + scoped_refptr<ash::HatsNotificationController> hats_notification_controller_; + base::WeakPtrFactory<PhotosExperienceSurveyTrigger> weak_ptr_factory_{this}; +}; + +const int PhotosExperienceSurveyTrigger::profile_user_data_key = 0; +const char* PhotosExperienceSurveyTrigger::google_photos_app_id = + arc::kGooglePhotosAppId; + } // namespace MediaSystemAppDelegate::MediaSystemAppDelegate(Profile* profile) @@ -131,7 +232,11 @@ GURL("chrome://media-app/pwa.html"), profile, ash::OriginTrialsMap( - {{ash::GetOrigin("chrome://media-app"), {"FileHandling"}}})) {} + {{ash::GetOrigin("chrome://media-app"), {"FileHandling"}}})) { + // Tie survey registration to SWA registration. That is, the delegate map + // owned by SystemWebAppManager, which is created at startup. + PhotosExperienceSurveyTrigger::Register(profile); +} std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForMediaWebApp() { std::unique_ptr<WebAppInstallInfo> info = @@ -218,6 +323,24 @@ return info; } +base::flat_map<std::string, std::string> HatsProductSpecificDataForMediaApp() { + ash::MediaAppUserActions actions = + ash::GetMediaAppUserActionsForHappinessTracking(); + return base::flat_map<std::string, std::string>( + {{"did_open_image_in_gallery", + base::NumberToString(g_did_open_image_in_gallery)}, + {"did_open_video_in_gallery", + base::NumberToString(g_did_open_video_in_gallery)}, + {"clicked_edit_image_in_photos", + base::NumberToString(actions.clicked_edit_image_in_photos)}, + {"clicked_edit_video_in_photos", + base::NumberToString(actions.clicked_edit_video_in_photos)}}); +} + +void SetPhotosExperienceSurveyTriggerAppIdForTesting(const char* app_id) { + PhotosExperienceSurveyTrigger::google_photos_app_id = app_id; +} + std::unique_ptr<WebAppInstallInfo> MediaSystemAppDelegate::GetWebAppInfo() const { return CreateWebAppInfoForMediaWebApp(); @@ -272,6 +395,17 @@ web_app::WebAppProvider* provider, const GURL& url, const apps::AppLaunchParams& params) const { + if (!params.launch_files.empty()) { + const base::FilePath first_file = params.launch_files[0]; + for (const char* extension : kWatchedImageExtensions) { + g_did_open_image_in_gallery = + g_did_open_image_in_gallery || first_file.MatchesExtension(extension); + } + for (const char* extension : kWatchedVideoExtensions) { + g_did_open_video_in_gallery = + g_did_open_video_in_gallery || first_file.MatchesExtension(extension); + } + } // For zero/single-file launches, or non-PDF launches, launch a single window. if (params.launch_files.size() < 2 || !params.launch_files[0].MatchesExtension(kPdfExtension)) {
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.h b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h index 6cde6aa..a351dff 100644 --- a/chrome/browser/ash/web_applications/media_app/media_web_app_info.h +++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
@@ -5,6 +5,9 @@ #ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_ #define CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_ +#include <string> + +#include "base/containers/flat_map.h" #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h" #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h" @@ -34,4 +37,10 @@ // Return a WebAppInstallInfo used to install the app. std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForMediaWebApp(); +// Returns a snapshot of the product-specific data that is attached to HaTS for +// the MediaApp. +base::flat_map<std::string, std::string> HatsProductSpecificDataForMediaApp(); + +void SetPhotosExperienceSurveyTriggerAppIdForTesting(const char* app_id); + #endif // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/projector_app/OWNERS b/chrome/browser/ash/web_applications/projector_app/OWNERS index 37e8b09f..174c491 100644 --- a/chrome/browser/ash/web_applications/projector_app/OWNERS +++ b/chrome/browser/ash/web_applications/projector_app/OWNERS
@@ -1 +1 @@ -file://ash/webui/projector_app/OWNERS +file://ash/projector/OWNERS
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 4c074a7..8ec9e3b 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -176,6 +176,7 @@ #include "chrome/browser/ui/webui/tab_search/tab_search_ui.h" #include "chrome/browser/ui/webui/whats_new/whats_new_ui.h" #include "chrome/common/webui_url_constants.h" +#include "components/commerce/core/mojom/shopping_list.mojom.h" // nogncheck crbug.com/1125897 #include "components/search/ntp_features.h" #include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" #include "ui/webui/resources/cr_components/customize_themes/customize_themes.mojom.h" @@ -939,9 +940,14 @@ RegisterWebUIControllerInterfaceBinder< side_panel::mojom::BookmarksPageHandlerFactory, BookmarksSidePanelUI>( map); + RegisterWebUIControllerInterfaceBinder< + shopping_list::mojom::ShoppingListHandlerFactory, BookmarksSidePanelUI>( + map); } else { RegisterWebUIControllerInterfaceBinder< side_panel::mojom::BookmarksPageHandlerFactory, ReadingListUI>(map); + RegisterWebUIControllerInterfaceBinder< + shopping_list::mojom::ShoppingListHandlerFactory, ReadingListUI>(map); } if (base::FeatureList::IsEnabled(ntp_features::kCustomizeChromeSidePanel)) {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index f341631..b5f18e4 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -6727,7 +6727,8 @@ !url.SchemeIs(extensions::kExtensionScheme); if (should_open_in_lacros) { ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); return true; } #endif
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index cb53f59..816ccdcc 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2660,6 +2660,7 @@ "//chrome/test:test_support", "//chrome/test:test_support_ui", "//chromeos/ash/components/attestation:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/cicerone", "//chromeos/ash/components/dbus/concierge", @@ -2672,7 +2673,6 @@ "//chromeos/ash/components/dbus/session_manager", "//chromeos/ash/components/dbus/userdataauth:userdataauth", "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", - "//chromeos/dbus:test_support", "//chromeos/dbus/dlcservice", "//chromeos/printing", "//chromeos/system", @@ -3640,6 +3640,7 @@ "//chrome/test:test_support_ui", "//chrome/test:test_support_unit", "//chromeos/ash/components/attestation:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/anomaly_detector", "//chromeos/ash/components/dbus/attestation", "//chromeos/ash/components/dbus/attestation:attestation_proto", @@ -3666,7 +3667,6 @@ "//chromeos/ash/components/scanning", "//chromeos/ash/components/sync_wifi:test_support", "//chromeos/components/sensors:test_support", - "//chromeos/dbus:test_support", "//chromeos/dbus/dlcservice", "//chromeos/dbus/dlp", "//chromeos/dbus/missive",
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index ef92d68..88b887f 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -1972,6 +1972,22 @@ } } +// static +api::autotest_private::LacrosMode +AutotestPrivateGetLacrosInfoFunction::ToLacrosMode( + crosapi::browser_util::LacrosMode lacrosMode) { + switch (lacrosMode) { + case crosapi::browser_util::LacrosMode::kDisabled: + return api::autotest_private::LacrosMode::LACROS_MODE_DISABLED; + case crosapi::browser_util::LacrosMode::kSideBySide: + return api::autotest_private::LacrosMode::LACROS_MODE_SIDEBYSIDE; + case crosapi::browser_util::LacrosMode::kPrimary: + return api::autotest_private::LacrosMode::LACROS_MODE_PRIMARY; + case crosapi::browser_util::LacrosMode::kOnly: + return api::autotest_private::LacrosMode::LACROS_MODE_ONLY; + } +} + ExtensionFunction::ResponseAction AutotestPrivateGetLacrosInfoFunction::Run() { DVLOG(1) << "AutotestPrivateGetLacrosInfoFunction"; auto* browser_manager = crosapi::BrowserManager::Get(); @@ -1981,6 +1997,8 @@ result->SetBoolKey("isKeepAlive", browser_manager->IsKeepAliveEnabled()); result->SetStringKey("lacrosPath", browser_manager->lacros_path().MaybeAsASCII()); + result->SetStringKey("mode", api::autotest_private::ToString(ToLacrosMode( + crosapi::browser_util::GetLacrosMode()))); return RespondNow( OneArgument(base::Value::FromUniquePtrValue(std::move(result)))); }
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h index 3e3986bc..246620d4 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -336,6 +336,8 @@ ResponseAction Run() override; static api::autotest_private::LacrosState ToLacrosState( crosapi::BrowserManager::State state); + static api::autotest_private::LacrosMode ToLacrosMode( + crosapi::browser_util::LacrosMode lacrosMode); }; class AutotestPrivateGetArcAppFunction : public ExtensionFunction {
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc b/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc index d25a177..b39fcaf1 100644 --- a/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc +++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc
@@ -87,7 +87,7 @@ } } -void DeviceEventRouter::OnVolumeMounted(chromeos::MountError error_code, +void DeviceEventRouter::OnVolumeMounted(ash::MountError error_code, const Volume& volume) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -95,7 +95,7 @@ SetDeviceState(device_path, DEVICE_STATE_USUAL); } -void DeviceEventRouter::OnVolumeUnmounted(chromeos::MountError error_code, +void DeviceEventRouter::OnVolumeUnmounted(ash::MountError error_code, const Volume& volume) { // Do nothing. }
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h index 270899f7..76ac712 100644 --- a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h +++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
@@ -51,9 +51,9 @@ void OnDiskRemoved(const ash::disks::Disk& disk) override; void OnDeviceAdded(const std::string& device_path) override; void OnDeviceRemoved(const std::string& device_path) override; - void OnVolumeMounted(chromeos::MountError error_code, + void OnVolumeMounted(ash::MountError error_code, const Volume& volume) override; - void OnVolumeUnmounted(chromeos::MountError error_code, + void OnVolumeUnmounted(ash::MountError error_code, const Volume& volume) override; void OnFormatStarted(const std::string& device_path, const std::string& device_label,
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/device_event_router_unittest.cc index 80019b02..aa494f0 100644 --- a/chrome/browser/chromeos/extensions/file_manager/device_event_router_unittest.cc +++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router_unittest.cc
@@ -102,10 +102,8 @@ base::FilePath(FILE_PATH_LITERAL("/mount/path1")))); device_event_router->OnDeviceAdded("/device/test"); device_event_router->OnDiskAdded(disk1, true); - device_event_router->OnVolumeMounted(chromeos::MountError::kNone, - *volume.get()); - device_event_router->OnVolumeUnmounted(chromeos::MountError::kNone, - *volume.get()); + device_event_router->OnVolumeMounted(ash::MountError::kNone, *volume.get()); + device_event_router->OnVolumeUnmounted(ash::MountError::kNone, *volume.get()); device_event_router->OnDiskRemoved(disk1_unmounted); device_event_router->OnDeviceRemoved("/device/test"); ASSERT_EQ(1u, device_event_router->events.size());
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc index 7c104537..0af35244 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -485,62 +485,62 @@ } // namespace file_manager_private::MountCompletedStatus MountErrorToMountCompletedStatus( - chromeos::MountError error) { + ash::MountError error) { switch (error) { - case chromeos::MountError::kNone: + case ash::MountError::kNone: return file_manager_private::MOUNT_COMPLETED_STATUS_SUCCESS; - case chromeos::MountError::kUnknown: + case ash::MountError::kUnknown: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_UNKNOWN; - case chromeos::MountError::kInternal: + case ash::MountError::kInternal: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INTERNAL; - case chromeos::MountError::kInvalidArgument: + case ash::MountError::kInvalidArgument: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_INVALID_ARGUMENT; - case chromeos::MountError::kInvalidPath: + case ash::MountError::kInvalidPath: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INVALID_PATH; - case chromeos::MountError::kPathAlreadyMounted: + case ash::MountError::kPathAlreadyMounted: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_PATH_ALREADY_MOUNTED; - case chromeos::MountError::kPathNotMounted: + case ash::MountError::kPathNotMounted: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_PATH_NOT_MOUNTED; - case chromeos::MountError::kDirectoryCreationFailed: + case ash::MountError::kDirectoryCreationFailed: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_DIRECTORY_CREATION_FAILED; - case chromeos::MountError::kInvalidMountOptions: + case ash::MountError::kInvalidMountOptions: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_INVALID_MOUNT_OPTIONS; - case chromeos::MountError::kInvalidUnmountOptions: + case ash::MountError::kInvalidUnmountOptions: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_INVALID_UNMOUNT_OPTIONS; - case chromeos::MountError::kInsufficientPermissions: + case ash::MountError::kInsufficientPermissions: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_INSUFFICIENT_PERMISSIONS; - case chromeos::MountError::kMountProgramNotFound: + case ash::MountError::kMountProgramNotFound: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_MOUNT_PROGRAM_NOT_FOUND; - case chromeos::MountError::kMountProgramFailed: + case ash::MountError::kMountProgramFailed: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_MOUNT_PROGRAM_FAILED; - case chromeos::MountError::kInvalidDevicePath: + case ash::MountError::kInvalidDevicePath: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_INVALID_DEVICE_PATH; - case chromeos::MountError::kUnknownFilesystem: + case ash::MountError::kUnknownFilesystem: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_UNKNOWN_FILESYSTEM; - case chromeos::MountError::kUnsupportedFilesystem: + case ash::MountError::kUnsupportedFilesystem: return file_manager_private:: MOUNT_COMPLETED_STATUS_ERROR_UNSUPPORTED_FILESYSTEM; - case chromeos::MountError::kInvalidArchive: + case ash::MountError::kInvalidArchive: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_INVALID_ARCHIVE; - case chromeos::MountError::kNeedPassword: + case ash::MountError::kNeedPassword: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_NEED_PASSWORD; - case chromeos::MountError::kInProgress: + case ash::MountError::kInProgress: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_IN_PROGRESS; - case chromeos::MountError::kCancelled: + case ash::MountError::kCancelled: return file_manager_private::MOUNT_COMPLETED_STATUS_ERROR_CANCELLED; // Not a real error. - case chromeos::MountError::kCount: + case ash::MountError::kCount: NOTREACHED(); } NOTREACHED(); @@ -1015,7 +1015,7 @@ // Do nothing. } -void EventRouter::OnVolumeMounted(chromeos::MountError error_code, +void EventRouter::OnVolumeMounted(ash::MountError error_code, const Volume& volume) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // profile_ is NULL if ShutdownOnUIThread() is called earlier. This can @@ -1040,7 +1040,7 @@ extensions::file_system_api::DispatchVolumeListChangeEventAsh(profile_); } -void EventRouter::OnVolumeUnmounted(chromeos::MountError error_code, +void EventRouter::OnVolumeUnmounted(ash::MountError error_code, const Volume& volume) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DispatchMountCompletedEvent( @@ -1055,7 +1055,7 @@ void EventRouter::DispatchMountCompletedEvent( file_manager_private::MountCompletedEventType event_type, - chromeos::MountError error, + ash::MountError error, const Volume& volume) { // Build an event object. file_manager_private::MountCompletedEvent event;
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h index bbb396d..08dd93fc 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.h +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -154,9 +154,9 @@ void OnDiskRemoved(const ash::disks::Disk& disk) override; void OnDeviceAdded(const std::string& device_path) override; void OnDeviceRemoved(const std::string& device_path) override; - void OnVolumeMounted(chromeos::MountError error_code, + void OnVolumeMounted(ash::MountError error_code, const Volume& volume) override; - void OnVolumeUnmounted(chromeos::MountError error_code, + void OnVolumeUnmounted(ash::MountError error_code, const Volume& volume) override; void OnFormatStarted(const std::string& device_path, const std::string& device_label, @@ -250,7 +250,7 @@ // Dispatches the mount completed event. void DispatchMountCompletedEvent( extensions::api::file_manager_private::MountCompletedEventType event_type, - chromeos::MountError error, + ash::MountError error, const Volume& volume); // Send crostini path shared or unshared event. @@ -324,7 +324,7 @@ }; file_manager_private::MountCompletedStatus MountErrorToMountCompletedStatus( - chromeos::MountError error); + ash::MountError error); } // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc index 6aab7fc..505776d3 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -236,7 +236,7 @@ const TestMountPoint kTestMountPoints[] = { { "device_path1", - chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( + ash::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( "mount_path1").AsUTF8Unsafe(), ash::MountType::kDevice, ash::disks::MOUNT_CONDITION_NONE, @@ -244,7 +244,7 @@ }, { "device_path2", - chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( + ash::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( "mount_path2").AsUTF8Unsafe(), ash::MountType::kDevice, ash::disks::MOUNT_CONDITION_NONE, @@ -252,7 +252,7 @@ }, { "device_path3", - chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( + ash::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( "mount_path3").AsUTF8Unsafe(), ash::MountType::kDevice, ash::disks::MOUNT_CONDITION_NONE, @@ -260,9 +260,9 @@ }, { // Set source path inside another mounted volume. - chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( + ash::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII( "mount_path3/archive.zip").AsUTF8Unsafe(), - chromeos::CrosDisksClient::GetArchiveMountPoint().AppendASCII( + ash::CrosDisksClient::GetArchiveMountPoint().AppendASCII( "archive_mount_path").AsUTF8Unsafe(), ash::MountType::kArchive, ash::disks::MOUNT_CONDITION_NONE, @@ -325,15 +325,15 @@ const std::string& mount_label, const std::vector<std::string>& mount_options, ash::MountType type, - chromeos::MountAccessMode access_mode, + ash::MountAccessMode access_mode, DiskMountManager::MountPathCallback callback) { DiskMountManager::MountPoint mount_point_info{ source_path, "/media/fuse/" + mount_label, ash::MountType::kNetworkStorage}; disk_mount_manager_mock_->NotifyMountEvent( - DiskMountManager::MountEvent::MOUNTING, chromeos::MountError::kNone, + DiskMountManager::MountEvent::MOUNTING, ash::MountError::kNone, mount_point_info); - std::move(callback).Run(chromeos::MountError::kNone, mount_point_info); + std::move(callback).Run(ash::MountError::kNone, mount_point_info); } void ExpectCrostiniMount() { @@ -348,7 +348,7 @@ MountPath("sshfs://testuser@hostname:", "", "crostini_user_termina_penguin", mount_options, ash::MountType::kNetworkStorage, - chromeos::MountAccessMode::kReadWrite, _)) + ash::MountAccessMode::kReadWrite, _)) .WillOnce(Invoke(this, &FileManagerPrivateApiTest::SshfsMount)); } @@ -385,12 +385,11 @@ // verify them by name and occurrence count. int events[4] = {0, 0, 0, 0}; - EXPECT_CALL( - *disk_mount_manager_mock_, - UnmountPath(chromeos::CrosDisksClient::GetRemovableDiskMountPoint() - .AppendASCII("mount_path1") - .AsUTF8Unsafe(), - _)) + EXPECT_CALL(*disk_mount_manager_mock_, + UnmountPath(ash::CrosDisksClient::GetRemovableDiskMountPoint() + .AppendASCII("mount_path1") + .AsUTF8Unsafe(), + _)) .WillOnce(testing::Invoke( [&events](const std::string& path, DiskMountManager::UnmountPathCallback callback) { @@ -398,7 +397,7 @@ EXPECT_EQ("mount_path1", name.value()); ++events[0]; EXPECT_EQ(1, events[0]); - std::move(callback).Run(chromeos::MountError::kNone); + std::move(callback).Run(ash::MountError::kNone); })) .WillOnce(testing::Invoke( [&events](const std::string& path, @@ -407,11 +406,11 @@ EXPECT_EQ("mount_path1", name.value()); ++events[1]; EXPECT_EQ(1, events[1]); - std::move(callback).Run(chromeos::MountError::kCancelled); + std::move(callback).Run(ash::MountError::kCancelled); })); EXPECT_CALL(*disk_mount_manager_mock_, - UnmountPath(chromeos::CrosDisksClient::GetArchiveMountPoint() + UnmountPath(ash::CrosDisksClient::GetArchiveMountPoint() .AppendASCII("archive_mount_path") .AsUTF8Unsafe(), _)) @@ -422,7 +421,7 @@ EXPECT_EQ("archive_mount_path", name.value()); ++events[2]; EXPECT_EQ(1, events[2]); - std::move(callback).Run(chromeos::MountError::kNone); + std::move(callback).Run(ash::MountError::kNone); })) .WillOnce(testing::Invoke( [&events](const std::string& path, @@ -431,7 +430,7 @@ EXPECT_EQ("archive_mount_path", name.value()); ++events[3]; EXPECT_EQ(1, events[3]); - std::move(callback).Run(chromeos::MountError::kNeedPassword); + std::move(callback).Run(ash::MountError::kNeedPassword); })); ASSERT_TRUE(RunExtensionTest("file_browser/mount_test", {}, @@ -449,26 +448,26 @@ // other arguments that don't match the rules below. EXPECT_CALL(*disk_mount_manager_mock_, FormatMountedDevice(_, _, _)).Times(0); - EXPECT_CALL(*disk_mount_manager_mock_, - FormatMountedDevice( - chromeos::CrosDisksClient::GetRemovableDiskMountPoint() - .AppendASCII("mount_path1") - .AsUTF8Unsafe(), - FormatFileSystemType::kVfat, "NEWLABEL1")) + EXPECT_CALL( + *disk_mount_manager_mock_, + FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint() + .AppendASCII("mount_path1") + .AsUTF8Unsafe(), + FormatFileSystemType::kVfat, "NEWLABEL1")) .Times(1); - EXPECT_CALL(*disk_mount_manager_mock_, - FormatMountedDevice( - chromeos::CrosDisksClient::GetRemovableDiskMountPoint() - .AppendASCII("mount_path2") - .AsUTF8Unsafe(), - FormatFileSystemType::kExfat, "NEWLABEL2")) + EXPECT_CALL( + *disk_mount_manager_mock_, + FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint() + .AppendASCII("mount_path2") + .AsUTF8Unsafe(), + FormatFileSystemType::kExfat, "NEWLABEL2")) .Times(1); - EXPECT_CALL(*disk_mount_manager_mock_, - FormatMountedDevice( - chromeos::CrosDisksClient::GetRemovableDiskMountPoint() - .AppendASCII("mount_path3") - .AsUTF8Unsafe(), - FormatFileSystemType::kNtfs, "NEWLABEL3")) + EXPECT_CALL( + *disk_mount_manager_mock_, + FormatMountedDevice(ash::CrosDisksClient::GetRemovableDiskMountPoint() + .AppendASCII("mount_path3") + .AsUTF8Unsafe(), + FormatFileSystemType::kNtfs, "NEWLABEL3")) .Times(1); ASSERT_TRUE(RunExtensionTest("file_browser/format_test", {},
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc index e8bbfb91..aa35278 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -1322,7 +1322,8 @@ Error("Could not get NewWindowDelegate's primary browser")); } ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc index 4fb72af..a3d1b699 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
@@ -127,7 +127,7 @@ disk_mount_manager->MountPath(path_.AsUTF8Unsafe(), std::move(extension_), path_.BaseName().AsUTF8Unsafe(), std::move(options_), ash::MountType::kArchive, - chromeos::MountAccessMode::kReadWrite, + ash::MountAccessMode::kReadWrite, base::DoNothing()); } @@ -168,8 +168,8 @@ } void FileManagerPrivateCancelMountingFunction::OnCancelled( - chromeos::MountError error) { - if (error == chromeos::MountError::kNone) { + ash::MountError error) { + if (error == ash::MountError::kNone) { Respond(NoArguments()); } else { Respond(Error(file_manager_private::ToString( @@ -261,8 +261,8 @@ } void FileManagerPrivateRemoveMountFunction::OnDiskUnmounted( - chromeos::MountError error) { - if (error == chromeos::MountError::kNone) { + ash::MountError error) { + if (error == ash::MountError::kNone) { Respond(NoArguments()); } else { Respond(Error(file_manager_private::ToString(
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h index 330500b0..3dd5adf 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
@@ -65,7 +65,7 @@ // ExtensionFunction overrides. ResponseAction Run() override; - void OnCancelled(chromeos::MountError error); + void OnCancelled(ash::MountError error); }; // Implements chrome.fileManagerPrivate.removeMount method. @@ -81,7 +81,7 @@ // ExtensionFunction overrides. ResponseAction Run() override; - void OnDiskUnmounted(chromeos::MountError error); + void OnDiskUnmounted(ash::MountError error); void OnSshFsUnmounted(bool ok); };
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc index 78cb8d1..900aa1b3 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -105,11 +105,11 @@ system_mount_points_->RegisterFileSystem( kSystemMountNameArchive, storage::kFileSystemTypeLocal, storage::FileSystemMountOption(), - chromeos::CrosDisksClient::GetArchiveMountPoint()); + ash::CrosDisksClient::GetArchiveMountPoint()); system_mount_points_->RegisterFileSystem( kSystemMountNameRemovable, storage::kFileSystemTypeLocal, storage::FileSystemMountOption(storage::FlushPolicy::FLUSH_ON_COMPLETION), - chromeos::CrosDisksClient::GetRemovableDiskMountPoint()); + ash::CrosDisksClient::GetRemovableDiskMountPoint()); system_mount_points_->RegisterFileSystem( kSystemMountNameOem, storage::kFileSystemTypeRestrictedLocal, storage::FileSystemMountOption(),
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc index 270d6c1..b9f8dbe 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc
@@ -58,10 +58,10 @@ // By default there should be 3 mount points (in system mount points): EXPECT_EQ(3u, root_dirs.size()); - EXPECT_TRUE(root_dirs_set.count( - chromeos::CrosDisksClient::GetRemovableDiskMountPoint())); - EXPECT_TRUE(root_dirs_set.count( - chromeos::CrosDisksClient::GetArchiveMountPoint())); + EXPECT_TRUE( + root_dirs_set.count(ash::CrosDisksClient::GetRemovableDiskMountPoint())); + EXPECT_TRUE( + root_dirs_set.count(ash::CrosDisksClient::GetArchiveMountPoint())); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem")))); }
diff --git a/chrome/browser/chromeos/policy/dlp/clipboard_bubble.cc b/chrome/browser/chromeos/policy/dlp/clipboard_bubble.cc index 964eb072..102dfb5 100644 --- a/chrome/browser/chromeos/policy/dlp/clipboard_bubble.cc +++ b/chrome/browser/chromeos/policy/dlp/clipboard_bubble.cc
@@ -26,7 +26,9 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chrome/browser/lacros/browser_service_lacros.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_navigator_params.h" #include "ui/chromeos/styles/cros_styles.h" #include "ui/native_theme/native_theme_aura.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) @@ -131,17 +133,18 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kDlpLearnMoreUrl), - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); #elif BUILDFLAG(IS_CHROMEOS_LACROS) - // TODO(hidehiko): Instantiating BrowserServiceLacros here is an unexpected - // use case. Get rid of this by replacing with Navigate() API invocation - // directly. - auto browser_service = std::make_unique<BrowserServiceLacros>(); - using OpenUrlParams = crosapi::mojom::OpenUrlParams; - auto params = OpenUrlParams::New(); - params->disposition = OpenUrlParams::WindowOpenDisposition::kNewForegroundTab; - browser_service->OpenUrl(GURL(kDlpLearnMoreUrl), std::move(params), - base::DoNothing()); + // The dlp policy applies to the main profile, so use the main profile for + // opening the page. + NavigateParams navigate_params( + ProfileManager::GetPrimaryUserProfile(), GURL(kDlpLearnMoreUrl), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | + ui::PAGE_TRANSITION_FROM_API)); + navigate_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + navigate_params.window_action = NavigateParams::SHOW_WINDOW; + Navigate(&navigate_params); #endif // BUILDFLAG(IS_CHROMEOS_ASH) }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_clipboard_notifier.cc b/chrome/browser/chromeos/policy/dlp/dlp_clipboard_notifier.cc index d7d3054a..8145104 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_clipboard_notifier.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_clipboard_notifier.cc
@@ -96,7 +96,8 @@ void OnToastClicked() { ash::NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kDlpLearnMoreUrl), - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_notification_helper.cc b/chrome/browser/chromeos/policy/dlp/dlp_notification_helper.cc index cb770d5..0aaff1a 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_notification_helper.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_notification_helper.cc
@@ -24,7 +24,8 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chrome/browser/lacros/browser_service_lacros.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_navigator_params.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) namespace policy { @@ -47,17 +48,18 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kDlpLearnMoreUrl), - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); #elif BUILDFLAG(IS_CHROMEOS_LACROS) - // TODO(hidehiko): Instantiating BrowserServiceLacros here is an unexpected - // use case. Get rid of this by replacing with Navigate() API invocation - // directly. - auto browser_service = std::make_unique<BrowserServiceLacros>(); - using OpenUrlParams = crosapi::mojom::OpenUrlParams; - auto params = OpenUrlParams::New(); - params->disposition = OpenUrlParams::WindowOpenDisposition::kNewForegroundTab; - browser_service->OpenUrl(GURL(kDlpLearnMoreUrl), std::move(params), - base::DoNothing()); + // The dlp policy applies to the main profile, so use the main profile for + // opening the page. + NavigateParams navigate_params( + ProfileManager::GetPrimaryUserProfile(), GURL(kDlpLearnMoreUrl), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | + ui::PAGE_TRANSITION_FROM_API)); + navigate_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + navigate_params.window_action = NavigateParams::SHOW_WINDOW; + Navigate(&navigate_params); #endif // BUILDFLAG(IS_CHROMEOS_ASH) NotificationDisplayService::GetForProfile(
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingButtonController.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingButtonController.java index 0cfa08f..5dcd9eb 100644 --- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingButtonController.java +++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingButtonController.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.price_tracking; import android.app.Activity; +import android.content.res.Resources; import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; @@ -69,7 +70,11 @@ private void maybeSetActionChipResourceId() { if (FeatureList.isInitialized() && AdaptiveToolbarFeatures.shouldShowActionChip()) { + // OptionalButtonCoordinator may choose to not show this action chip. It uses feature + // engagement to rate limit this animation. mButtonData.updateActionChipResourceId(R.string.enable_price_tracking_menu_item); + } else { + mButtonData.updateActionChipResourceId(Resources.ID_NULL); } }
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 58646c0..a6296e3 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -47,7 +47,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_switches.h" -#include "base/command_line.h" #endif using content::DevToolsAgentHost;
diff --git a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc index ee8440f..453decd4 100644 --- a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc +++ b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
@@ -30,7 +30,6 @@ #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \ BUILDFLAG(IS_WIN) #include "components/ukm/test_ukm_recorder.h" -#include "testing/gmock/include/gmock/gmock.h" #endif namespace dom_distiller {
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index d2259c3..6bc746c 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -652,7 +652,7 @@ } // Allow removable media. - if (chromeos::CrosDisksClient::GetRemovableDiskMountPoint().IsParent(path)) + if (ash::CrosDisksClient::GetRemovableDiskMountPoint().IsParent(path)) return path; // Allow paths under the Android files mount point.
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc index c09c49c..9072283 100644 --- a/chrome/browser/download/download_prefs_unittest.cc +++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -536,7 +536,7 @@ base::FilePath linux_files_dir; #if BUILDFLAG(IS_CHROMEOS_ASH) - removable_media_dir = chromeos::CrosDisksClient::GetRemovableDiskMountPoint(); + removable_media_dir = ash::CrosDisksClient::GetRemovableDiskMountPoint(); android_files_dir = base::FilePath(file_manager::util::kAndroidFilesPath); linux_files_dir = file_manager::util::GetCrostiniMountDirectory(&profile); #elif BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc index 2571519..5a88913b 100644 --- a/chrome/browser/download/notification/download_notification_browsertest.cc +++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -41,6 +41,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/download/public/common/download_item.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/core/common/features.h" #include "components/session_manager/core/session_manager.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" @@ -301,6 +302,9 @@ scoped_feature_list_.InitWithFeatureState( ash::features::kHoldingSpaceInProgressDownloadsNotificationSuppression, IsHoldingSpaceInProgressDownloadsNotificationSuppressionEnabled()); +#else + scoped_feature_list_.InitWithFeatures( + {}, {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}); #endif }
diff --git a/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc b/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc index 5ecf5fcb..d183ee0c 100644 --- a/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc +++ b/chrome/browser/enterprise/browser_management/browser_management_status_provider.cc
@@ -17,7 +17,6 @@ #elif BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/profiles/profile_helper.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "components/user_manager/user_manager.h" #endif
diff --git a/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc b/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc index 77fc2665..a72f4fd66 100644 --- a/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc +++ b/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc
@@ -8,7 +8,6 @@ #include <string> #include <utility> #include "chrome/browser/enterprise/connectors/common.h" -#include "chrome/browser/enterprise/connectors/reporting/extension_install_event_router.h" #include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.h" #include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client_factory.h" #include "chrome/browser/enterprise/connectors/reporting/reporting_service_settings.h"
diff --git a/chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.cc b/chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.cc index b407311..dc7c105 100644 --- a/chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.cc +++ b/chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.cc
@@ -40,7 +40,6 @@ #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #else -#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "components/enterprise/browser/controller/browser_dm_token_storage.h" #include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h" #endif
diff --git a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc index 9385e7c..89d3ed0f 100644 --- a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc +++ b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
@@ -179,57 +179,57 @@ EXPECT_EQ(8u, id_to_meta_info_map.DictSize()); // Verify top level node. - const base::Value* value = NULL; - EXPECT_TRUE(id_to_meta_info_map.Get( - base::NumberToString(model_->other_node()->id()), &value)); - ASSERT_TRUE(NULL != value); - const base::DictionaryValue* dictionary_value = NULL; - EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); - ASSERT_TRUE(nullptr != dictionary_value); - EXPECT_EQ(0u, dictionary_value->DictSize()); + { + const base::Value* value = nullptr; + EXPECT_TRUE(id_to_meta_info_map.Get( + base::NumberToString(model_->other_node()->id()), &value)); + ASSERT_TRUE(nullptr != value); + ASSERT_TRUE(value->is_dict()); + const base::Value::Dict& dict = value->GetDict(); + EXPECT_EQ(0u, dict.size()); + } // Verify bookmark with two meta info key/value pairs. - value = NULL; - EXPECT_TRUE( - id_to_meta_info_map.Get(base::NumberToString(node_->id()), &value)); - ASSERT_TRUE(NULL != value); - dictionary_value = NULL; - EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); - ASSERT_TRUE(nullptr != dictionary_value); - EXPECT_EQ(2u, dictionary_value->DictSize()); - std::string string_value; - EXPECT_TRUE(dictionary_value->GetString("some_key1", &string_value)); - EXPECT_EQ("some_value1", string_value); - EXPECT_TRUE(dictionary_value->GetString("some_key2", &string_value)); - EXPECT_EQ("some_value2", string_value); + { + const base::Value* value = nullptr; + EXPECT_TRUE( + id_to_meta_info_map.Get(base::NumberToString(node_->id()), &value)); + ASSERT_TRUE(nullptr != value); + ASSERT_TRUE(value->is_dict()); + const base::Value::Dict& dict = value->GetDict(); + EXPECT_EQ(2u, dict.size()); + ASSERT_TRUE(dict.FindString("some_key1")); + EXPECT_EQ("some_value1", *(dict.FindString("some_key1"))); + ASSERT_TRUE(dict.FindString("some_key2")); + EXPECT_EQ("some_value2", *(dict.FindString("some_key2"))); + } // Verify folder with one meta info key/value pair. - value = NULL; - EXPECT_TRUE( - id_to_meta_info_map.Get(base::NumberToString(folder_->id()), &value)); - ASSERT_TRUE(NULL != value); - dictionary_value = NULL; - EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); - ASSERT_TRUE(nullptr != dictionary_value); - EXPECT_EQ(1u, dictionary_value->DictSize()); - EXPECT_TRUE(dictionary_value->GetString("some_key1", &string_value)); - EXPECT_EQ("some_value1", string_value); + { + const base::Value* value = nullptr; + EXPECT_TRUE( + id_to_meta_info_map.Get(base::NumberToString(folder_->id()), &value)); + ASSERT_TRUE(nullptr != value); + ASSERT_TRUE(value->is_dict()); + const base::Value::Dict& dict = value->GetDict(); + EXPECT_EQ(1u, dict.size()); + ASSERT_TRUE(dict.FindString("some_key1")); + EXPECT_EQ("some_value1", *(dict.FindString("some_key1"))); + } // Verify bookmark in a subfolder with one meta info key/value pairs. - value = NULL; - EXPECT_TRUE( - id_to_meta_info_map.Get(base::NumberToString(node2_->id()), &value)); - ASSERT_TRUE(NULL != value); - dictionary_value = NULL; - EXPECT_TRUE(value->GetAsDictionary(&dictionary_value)); - ASSERT_TRUE(nullptr != dictionary_value); - EXPECT_EQ(1u, dictionary_value->DictSize()); - string_value.clear(); - EXPECT_FALSE(dictionary_value->GetString("some_key1", &string_value)); - EXPECT_EQ("", string_value); - EXPECT_TRUE(dictionary_value->GetString("some_key2", &string_value)); - EXPECT_EQ("some_value2", string_value); - + { + const base::Value* value = nullptr; + EXPECT_TRUE( + id_to_meta_info_map.Get(base::NumberToString(node2_->id()), &value)); + ASSERT_TRUE(nullptr != value); + ASSERT_TRUE(value->is_dict()); + const base::Value::Dict& dict = value->GetDict(); + EXPECT_EQ(1u, dict.size()); + ASSERT_FALSE(dict.FindString("some_key1")); + ASSERT_TRUE(dict.FindString("some_key2")); + EXPECT_EQ("some_value2", *(dict.FindString("some_key2"))); + } } } // namespace bookmark_api_helpers
diff --git a/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chrome/browser/extensions/api/debugger/debugger_apitest.cc index 19eb2d1..6e3e8538 100644 --- a/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -156,7 +156,9 @@ if (id == tab_id) { const base::DictionaryValue& target_dict = base::Value::AsDictionaryValue(target_value); - EXPECT_TRUE(target_dict.GetString("id", &debugger_target_id)); + const std::string* id_str = target_dict.GetDict().FindString("id"); + EXPECT_TRUE(id_str); + debugger_target_id = *id_str; break; } }
diff --git a/chrome/browser/extensions/api/declarative_content/content_condition.cc b/chrome/browser/extensions/api/declarative_content/content_condition.cc index d85a098..121c39a0 100644 --- a/chrome/browser/extensions/api/declarative_content/content_condition.cc +++ b/chrome/browser/extensions/api/declarative_content/content_condition.cc
@@ -38,29 +38,29 @@ const std::map<std::string, ContentPredicateFactory*>& predicate_factories, const base::Value& api_condition, std::string* error) { - const base::DictionaryValue* api_condition_dict = nullptr; - if (!api_condition.GetAsDictionary(&api_condition_dict)) { + if (!api_condition.is_dict()) { *error = kExpectedDictionary; return nullptr; } + const base::Value::Dict& api_condition_dict = api_condition.GetDict(); + // Verify that we are dealing with a Condition whose type we understand. - std::string instance_type; - if (!api_condition_dict->GetString( - declarative_content_constants::kInstanceType, &instance_type)) { + const std::string* instance_type = api_condition_dict.FindString( + declarative_content_constants::kInstanceType); + if (!instance_type) { *error = kConditionWithoutInstanceType; return nullptr; } - if (instance_type != declarative_content_constants::kPageStateMatcherType) { + if (*instance_type != declarative_content_constants::kPageStateMatcherType) { *error = kExpectedOtherConditionType; return nullptr; } std::vector<std::unique_ptr<const ContentPredicate>> predicates; - for (base::DictionaryValue::Iterator iter(*api_condition_dict); - !iter.IsAtEnd(); iter.Advance()) { - const std::string& predicate_name = iter.key(); - const base::Value& predicate_value = iter.value(); + for (const auto iter : api_condition_dict) { + const std::string& predicate_name = iter.first; + const base::Value& predicate_value = iter.second; if (predicate_name == declarative_content_constants::kInstanceType) continue;
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chrome/browser/extensions/api/extension_action/extension_action_api.cc index bb6e8000..a105cbb 100644 --- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc +++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -485,9 +485,9 @@ ExtensionFunction::ResponseAction ExtensionActionSetTitleFunction::RunExtensionAction() { EXTENSION_FUNCTION_VALIDATE(details_); - std::string title; - EXTENSION_FUNCTION_VALIDATE(details_->GetString("title", &title)); - extension_action_->SetTitle(tab_id_, title); + const std::string* title = details_->GetDict().FindString("title"); + EXTENSION_FUNCTION_VALIDATE(title); + extension_action_->SetTitle(tab_id_, *title); NotifyChange(); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index c2cd6118..d2944efa 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -598,6 +598,10 @@ GenerateFeatureFlag("autocorrectparamstuning", base::FeatureList::IsEnabled( chromeos::features::kAutocorrectParamsTuning))); + features.Append( + GenerateFeatureFlag("handwritinglibrarydlc", + base::FeatureList::IsEnabled( + chromeos::features::kHandwritingLibraryDlc))); results.Set("features", std::move(features));
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc index 5fd8942..c250d73 100644 --- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -158,9 +158,9 @@ ++ix, ++it) { const base::Value& value = sink_list.GetListDeprecated()[ix]; EXPECT_TRUE(value.is_dict()); - const base::DictionaryValue& dict = base::Value::AsDictionaryValue(value); - std::string sink_id; - dict.GetString("sinkId", &sink_id); + const base::Value::Dict& dict = value.GetDict(); + const std::string* sink_id = dict.FindString("sinkId"); + EXPECT_TRUE(sink_id); std::string expected_id = media::AudioDeviceDescription::IsDefaultDevice(it->unique_id) @@ -170,16 +170,16 @@ url::Origin::Create(source_url_.DeprecatedGetOriginAsURL()), it->unique_id); - EXPECT_EQ(expected_id, sink_id); - std::string sink_label; - dict.GetString("sinkLabel", &sink_label); - EXPECT_EQ(it->device_name, sink_label); + EXPECT_EQ(expected_id, *sink_id); + const std::string* sink_label = dict.FindString("sinkLabel"); + EXPECT_TRUE(sink_label); + EXPECT_EQ(it->device_name, *sink_label); // TODO(joi): Verify the contents of these once we start actually // filling them in. - EXPECT_TRUE(dict.FindKey("isDefault")); - EXPECT_TRUE(dict.FindKey("isReady")); - EXPECT_TRUE(dict.FindKey("sampleRate")); + EXPECT_TRUE(dict.Find("isDefault")); + EXPECT_TRUE(dict.Find("isReady")); + EXPECT_TRUE(dict.Find("sampleRate")); } } #endif // BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 8c52b09..ce139e9 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -93,10 +93,11 @@ std::string GenerateId(const base::DictionaryValue* manifest, const base::FilePath& path) { - std::string raw_key; std::string id_input; - CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key)); - CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input)); + const std::string* raw_key = + manifest->GetDict().FindString(manifest_keys::kPublicKey); + CHECK(raw_key != nullptr); + CHECK(Extension::ParsePEMKeyBytes(*raw_key, &id_input)); std::string id = crx_file::id_util::GenerateId(id_input); return id; }
diff --git a/chrome/browser/extensions/component_loader_unittest.cc b/chrome/browser/extensions/component_loader_unittest.cc index b32a6b8..59d78a04 100644 --- a/chrome/browser/extensions/component_loader_unittest.cc +++ b/chrome/browser/extensions/component_loader_unittest.cc
@@ -140,10 +140,11 @@ EXPECT_EQ(1, manifest->FindIntPath("test.one")); EXPECT_EQ(2, manifest->FindIntKey("two")); - std::string string_value; manifest = component_loader_.ParseManifest(manifest_contents_); - ASSERT_TRUE(manifest->GetString("background.page", &string_value)); - EXPECT_EQ("backgroundpage.html", string_value); + const std::string* string_value = + manifest->GetDict().FindStringByDottedPath("background.page"); + ASSERT_TRUE(string_value); + EXPECT_EQ("backgroundpage.html", *string_value); } // Test that the extension isn't loaded if the extension service isn't ready.
diff --git a/chrome/browser/extensions/extension_action_storage_manager.cc b/chrome/browser/extensions/extension_action_storage_manager.cc index 29e2286f..14edad2 100644 --- a/chrome/browser/extensions/extension_action_storage_manager.cc +++ b/chrome/browser/extensions/extension_action_storage_manager.cc
@@ -93,36 +93,38 @@ } // Set |action|'s default values to those specified in |dict|. -void SetDefaultsFromValue(const base::DictionaryValue* dict, +void SetDefaultsFromValue(const base::Value::Dict& dict, ExtensionAction* action) { const int kDefaultTabId = ExtensionAction::kDefaultTabId; - std::string str_value; // For each value, don't set it if it has been modified already. - if (dict->GetString(kPopupUrlStorageKey, &str_value) && - !action->HasPopupUrl(kDefaultTabId)) { - action->SetPopupUrl(kDefaultTabId, GURL(str_value)); + const std::string* popup_url = dict.FindString(kPopupUrlStorageKey); + if (popup_url && !action->HasPopupUrl(kDefaultTabId)) { + action->SetPopupUrl(kDefaultTabId, GURL(*popup_url)); } - if (dict->GetString(kTitleStorageKey, &str_value) && - !action->HasTitle(kDefaultTabId)) { - action->SetTitle(kDefaultTabId, str_value); + const std::string* title = dict.FindString(kTitleStorageKey); + if (title && !action->HasTitle(kDefaultTabId)) { + action->SetTitle(kDefaultTabId, *title); } - if (dict->GetString(kBadgeTextStorageKey, &str_value) && - !action->HasBadgeText(kDefaultTabId)) { - action->SetBadgeText(kDefaultTabId, str_value); + const std::string* badge_text = dict.FindString(kBadgeTextStorageKey); + if (badge_text && !action->HasBadgeText(kDefaultTabId)) { + action->SetBadgeText(kDefaultTabId, *badge_text); } - if (dict->GetString(kBadgeBackgroundColorStorageKey, &str_value) && + const std::string* badge_background_color = + dict.FindString(kBadgeBackgroundColorStorageKey); + if (badge_background_color && !action->HasBadgeBackgroundColor(kDefaultTabId)) { - action->SetBadgeBackgroundColor(kDefaultTabId, - RawStringToSkColor(str_value)); + action->SetBadgeBackgroundColor( + kDefaultTabId, RawStringToSkColor(*badge_background_color)); } - if (dict->GetString(kBadgeTextColorStorageKey, &str_value) && - !action->HasBadgeTextColor(kDefaultTabId)) { - action->SetBadgeTextColor(kDefaultTabId, RawStringToSkColor(str_value)); + const std::string* badge_text_color = + dict.FindString(kBadgeTextColorStorageKey); + if (badge_text_color && !action->HasBadgeTextColor(kDefaultTabId)) { + action->SetBadgeTextColor(kDefaultTabId, + RawStringToSkColor(*badge_text_color)); } - absl::optional<int> appearance_storage = - dict->FindIntKey(kAppearanceStorageKey); + absl::optional<int> appearance_storage = dict.FindInt(kAppearanceStorageKey); if (appearance_storage && !action->HasIsVisible(kDefaultTabId)) { switch (*appearance_storage) { case INVISIBLE: @@ -135,17 +137,15 @@ } } - const base::DictionaryValue* icon_value = NULL; - if (dict->GetDictionary(kIconStorageKey, &icon_value) && - !action->HasIcon(kDefaultTabId)) { + const base::Value::Dict* icon_dict = dict.FindDict(kIconStorageKey); + if (icon_dict && !action->HasIcon(kDefaultTabId)) { gfx::ImageSkia icon; SkBitmap bitmap; - for (base::DictionaryValue::Iterator iter(*icon_value); !iter.IsAtEnd(); - iter.Advance()) { + for (const auto iter : *icon_dict) { int icon_size = 0; - if (base::StringToInt(iter.key(), &icon_size) && - iter.value().is_string() && - StringToSkBitmap(iter.value().GetString(), &bitmap)) { + if (base::StringToInt(iter.first, &icon_size) && + iter.second.is_string() && + StringToSkBitmap(iter.second.GetString(), &bitmap)) { CHECK(!bitmap.isNull()); float scale = static_cast<float>(icon_size) / ExtensionAction::ActionIconSize(); @@ -275,11 +275,10 @@ return; } - const base::DictionaryValue* dict = NULL; - if (!value.get() || !value->GetAsDictionary(&dict)) + if (!value.get() || !value->is_dict()) return; - SetDefaultsFromValue(dict, action); + SetDefaultsFromValue(value->GetDict(), action); } StateStore* ExtensionActionStorageManager::GetStateStore() {
diff --git a/chrome/browser/extensions/extension_get_views_apitest.cc b/chrome/browser/extensions/extension_get_views_apitest.cc index ed79c47..9731cd3 100644 --- a/chrome/browser/extensions/extension_get_views_apitest.cc +++ b/chrome/browser/extensions/extension_get_views_apitest.cc
@@ -4,7 +4,14 @@ #include "build/build_config.h" #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" +#include "content/public/test/test_navigation_observer.h" +#include "extensions/test/extension_test_message_listener.h" +#include "extensions/test/result_catcher.h" +#include "extensions/test/test_extension_dir.h" namespace extensions { @@ -18,4 +25,71 @@ ASSERT_TRUE(RunExtensionTest("get_views")) << message_; } +class ExtensionApiTestWithoutAutomationController : public ExtensionApiTest { + public: + void SetUpInProcessBrowserTestFixture() override { + // This switch must be removed in SetUpInProcessBrowserTestFixture() instead + // of SetUpCommandLine() because BrowserTestBase::SetUp() adds the switch + // after SetUpCommandLine() is called. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + base::CommandLine new_command_line(command_line->GetProgram()); + base::CommandLine::SwitchMap switches = command_line->GetSwitches(); + // Disable kDomAutomationController to avoid creating the V8 context for + // every frame. This interferes with the behavior we are trying to emulate + // for the regression test. + switches.erase(switches::kDomAutomationController); + + for (const auto& it : switches) + new_command_line.AppendSwitchNative(it.first, it.second); + + *command_line = new_command_line; + } +}; + +// Regression test for http://crbug.com/1349787. +IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithoutAutomationController, + GetWebAccessibleExtensionView) { + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/echo"))); + + TestExtensionDir test_dir; + test_dir.WriteManifest(R"({ + "name": "GetViews Test", + "manifest_version": 2, + "version": "0.1", + "background": {"scripts": ["background.js"]}, + "web_accessible_resources": ["page.html"] + })"); + test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), R"( + chrome.test.sendMessage('ready', function() { + var views = chrome.extension.getViews(); + chrome.test.assertEq(2, views.length); + + let paths = views.map((v) => v.location.pathname).sort(); + chrome.test.assertEq( + ['/_generated_background_page.html', '/page.html'], paths); + + chrome.test.notifyPass(); + }); + )"); + test_dir.WriteFile(FILE_PATH_LITERAL("page.html"), "<html></html>"); + + ResultCatcher result_catcher; + ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply); + const Extension* extension = LoadExtension(test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + EXPECT_TRUE(listener.WaitUntilSatisfied()); + + auto* tab = chrome::AddSelectedTabWithURL( + browser(), extension->GetResourceURL("page.html"), + ui::PAGE_TRANSITION_LINK); + content::TestNavigationObserver observer(tab); + observer.Wait(); + + listener.Reply("ok"); + EXPECT_TRUE(result_catcher.GetNextResult()) << result_catcher.message(); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/extension_override_apitest.cc b/chrome/browser/extensions/extension_override_apitest.cc index 5b26f72f..5cdb189 100644 --- a/chrome/browser/extensions/extension_override_apitest.cc +++ b/chrome/browser/extensions/extension_override_apitest.cc
@@ -57,12 +57,14 @@ std::set<std::string> seen_overrides; for (const auto& val : *values) { - const base::DictionaryValue* dict = nullptr; - std::string entry; - if (!val.GetAsDictionary(&dict) || !dict->GetString("entry", &entry) || - seen_overrides.count(entry) != 0) + if (!val.is_dict()) { return false; - seen_overrides.insert(entry); + } + const base::Value::Dict& dict = val.GetDict(); + const std::string* entry = dict.FindString("entry"); + if (!entry || seen_overrides.count(*entry) != 0) + return false; + seen_overrides.insert(*entry); } return true;
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc index 38c539e..5a38a28 100644 --- a/chrome/browser/extensions/extension_prefs_unittest.cc +++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -496,9 +496,10 @@ void VerifyIdleInfo(const std::string& id, int num) { std::unique_ptr<ExtensionInfo> info(prefs()->GetDelayedInstallInfo(id)); ASSERT_TRUE(info); - std::string version; - ASSERT_TRUE(info->extension_manifest->GetString("version", &version)); - ASSERT_EQ("1." + base::NumberToString(num), version); + const std::string* version = + info->extension_manifest->GetDict().FindString("version"); + ASSERT_TRUE(version); + ASSERT_EQ("1." + base::NumberToString(num), *version); ASSERT_EQ(base::NumberToString(num), info->extension_path.BaseName().MaybeAsASCII()); } @@ -629,12 +630,15 @@ const base::DictionaryValue* manifest; ASSERT_TRUE(prefs()->ReadPrefAsDictionary(id_, "manifest", &manifest)); ASSERT_TRUE(manifest); - std::string value; - EXPECT_TRUE(manifest->GetString(manifest_keys::kName, &value)); - EXPECT_EQ("test", value); - EXPECT_TRUE(manifest->GetString(manifest_keys::kVersion, &value)); - EXPECT_EQ("0.2", value); - EXPECT_FALSE(manifest->GetString(manifest_keys::kBackgroundPage, &value)); + ASSERT_TRUE(manifest->is_dict()); + const base::Value::Dict& dict = manifest->GetDict(); + const std::string* name = dict.FindString(manifest_keys::kName); + EXPECT_TRUE(name); + EXPECT_EQ("test", *name); + const std::string* version = dict.FindString(manifest_keys::kVersion); + EXPECT_TRUE(version); + EXPECT_EQ("0.2", *version); + EXPECT_FALSE(dict.FindString(manifest_keys::kBackgroundPage)); const base::ListValue* scripts; ASSERT_TRUE(manifest->GetList(manifest_keys::kBackgroundScripts, &scripts)); EXPECT_EQ(1u, scripts->GetListDeprecated().size()); @@ -1303,11 +1307,12 @@ EXPECT_EQ(prefs.prefs()->GetPrefAsString(kTestStringPref), "foo"); EXPECT_EQ(prefs.prefs()->GetPrefAsTime(kTestTimePref), time); EXPECT_EQ(prefs.prefs()->GetPrefAsGURL(kTestGURLPref), url); - std::string string_val = std::string(); - prefs.prefs() - ->GetPrefAsDictionary(kTestDictPref) - ->GetString("key", &string_val); - EXPECT_EQ(string_val, "val"); + const std::string* string_ptr = prefs.prefs() + ->GetPrefAsDictionary(kTestDictPref) + ->GetDict() + .FindString("key"); + EXPECT_TRUE(string_ptr); + EXPECT_EQ(*string_ptr, "val"); } TEST_F(ExtensionPrefsSimpleTest, ExtensionSpecificPrefsMapTest) { @@ -1356,8 +1361,9 @@ const base::DictionaryValue* dict_val = nullptr; prefs.prefs()->ReadPrefAsDictionary(extension_id, kTestDictPref, &dict_val); - dict_val->GetString("key", &string_value); - EXPECT_EQ(string_value, "val"); + const std::string* string_ptr = dict_val->GetDict().FindString("key"); + EXPECT_TRUE(string_ptr); + EXPECT_EQ(*string_ptr, "val"); const base::ListValue* list_val = nullptr; prefs.prefs()->ReadPrefAsList(extension_id, kTestListPref, &list_val);
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 370b4159..bd36e7a 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -452,9 +452,10 @@ EXPECT_FALSE(v1.get()); EXPECT_EQ(ManifestLocation::kExternalPrefDownload, location1); - std::string parsed_install_parameter; - pref->GetString("install_parameter", &parsed_install_parameter); - EXPECT_EQ(parsed_install_parameter, info.install_parameter); + const std::string* parsed_install_parameter = + pref->GetDict().FindString("install_parameter"); + EXPECT_TRUE(parsed_install_parameter); + EXPECT_EQ(*parsed_install_parameter, info.install_parameter); // Remove it so we won't count it again. prefs_->RemoveKey(info.extension_id);
diff --git a/chrome/browser/extensions/external_install_error.cc b/chrome/browser/extensions/external_install_error.cc index 9122b1b0..4f26eab 100644 --- a/chrome/browser/extensions/external_install_error.cc +++ b/chrome/browser/extensions/external_install_error.cc
@@ -428,12 +428,12 @@ void ExternalInstallError::OnWebstoreResponseParseSuccess( const std::string& extension_id, std::unique_ptr<base::DictionaryValue> webstore_data) { - std::string localized_user_count; absl::optional<double> average_rating = webstore_data->FindDoubleKey(kAverageRatingKey); absl::optional<int> rating_count = webstore_data->FindIntKey(kRatingCountKey); - if (!webstore_data->GetString(kUsersKey, &localized_user_count) || - !average_rating || !rating_count) { + const std::string* localized_user_count = + webstore_data->GetDict().FindString(kUsersKey); + if (!localized_user_count || !average_rating || !rating_count) { // If we don't get a valid webstore response, short circuit, and continue // to show a prompt without webstore data. OnFetchComplete(); @@ -445,8 +445,9 @@ absl::optional<bool> show_user_count = webstore_data->FindBoolKey(kShowUserCountKey); - prompt_->SetWebstoreData(localized_user_count, show_user_count.value_or(true), - *average_rating, *rating_count); + prompt_->SetWebstoreData(*localized_user_count, + show_user_count.value_or(true), *average_rating, + *rating_count); OnFetchComplete(); }
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc index c8696b69..751a515 100644 --- a/chrome/browser/extensions/external_provider_impl.cc +++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -252,7 +252,6 @@ // Discover all the extensions this provider has. for (auto pref : *prefs_) { const std::string& extension_id = pref.first; - const base::DictionaryValue* extension_dict = nullptr; #if BUILDFLAG(IS_CHROMEOS_ASH) if (extension_id == kCameraAppId) { @@ -282,7 +281,7 @@ continue; } - if (!pref.second.GetAsDictionary(&extension_dict)) { + if (!pref.second.is_dict()) { LOG(WARNING) << "Malformed extension dictionary: key " << extension_id.c_str() << " has a value that is not a dictionary."; @@ -292,19 +291,16 @@ continue; } - std::string external_crx; - const base::Value* external_version_value = nullptr; + const base::Value::Dict& extension_dict = pref.second.GetDict(); + const std::string* external_crx = extension_dict.FindString(kExternalCrx); std::string external_version; - std::string external_update_url; + const std::string* external_update_url = nullptr; - bool has_external_crx = - extension_dict->GetString(kExternalCrx, &external_crx); - - bool has_external_version = false; - if (extension_dict->Get(kExternalVersion, &external_version_value)) { + const base::Value* external_version_value = + extension_dict.Find(kExternalVersion); + if (external_version_value) { if (external_version_value->is_string()) { external_version = external_version_value->GetString(); - has_external_version = true; } else { install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason:: @@ -316,9 +312,8 @@ } } - bool has_external_update_url = - extension_dict->GetString(kExternalUpdateUrl, &external_update_url); - if (has_external_crx != has_external_version) { + external_update_url = extension_dict.FindString(kExternalUpdateUrl); + if ((external_crx != nullptr) != (external_version_value != nullptr)) { install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT); @@ -328,7 +323,7 @@ continue; } - if (has_external_crx == has_external_update_url) { + if ((external_crx != nullptr) == (external_update_url != nullptr)) { install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT); @@ -340,14 +335,15 @@ } // Check that extension supports current browser locale. - const base::ListValue* supported_locales = nullptr; - if (extension_dict->GetList(kSupportedLocales, &supported_locales)) { + const base::Value::List* supported_locales = + extension_dict.FindList(kSupportedLocales); + if (supported_locales) { std::vector<std::string> browser_locales; l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(), &browser_locales); bool locale_supported = false; - for (const base::Value& locale : supported_locales->GetListDeprecated()) { + for (const base::Value& locale : *supported_locales) { const std::string* current_locale = locale.GetIfString(); if (current_locale && l10n_util::IsValidLocaleSyntax(*current_locale)) { std::string normalized_locale = @@ -378,12 +374,12 @@ int creation_flags = creation_flags_; absl::optional<bool> is_bookmark_app = - extension_dict->FindBoolKey(kIsBookmarkApp); + extension_dict.FindBool(kIsBookmarkApp); if (is_bookmark_app.value_or(false)) { creation_flags |= Extension::FROM_BOOKMARK; } absl::optional<bool> is_from_webstore = - extension_dict->FindBoolKey(kIsFromWebstore); + extension_dict.FindBool(kIsFromWebstore); if (is_from_webstore.value_or(false)) { creation_flags |= Extension::FROM_WEBSTORE; } @@ -393,13 +389,13 @@ // the replacement web app has installed and migrated over user preferences. // TODO(crbug.com/1099150): Remove this field after migration is complete. const std::string* web_app_migration_flag = - extension_dict->FindStringPath(kWebAppMigrationFlag); + extension_dict.FindString(kWebAppMigrationFlag); bool is_migrating_to_web_app = web_app_migration_flag && web_app::IsPreinstalledAppInstallFeatureEnabled(*web_app_migration_flag, *profile_); bool keep_if_present = - extension_dict->FindBoolPath(kKeepIfPresent).value_or(false); + extension_dict.FindBool(kKeepIfPresent).value_or(false); if (keep_if_present || is_migrating_to_web_app) { ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_); const Extension* extension = @@ -419,12 +415,12 @@ } absl::optional<bool> was_installed_by_oem = - extension_dict->FindBoolKey(kWasInstalledByOem); + extension_dict.FindBool(kWasInstalledByOem); if (was_installed_by_oem.value_or(false)) { creation_flags |= Extension::WAS_INSTALLED_BY_OEM; } absl::optional<bool> may_be_untrusted = - extension_dict->FindBoolKey(kMayBeUntrusted); + extension_dict.FindBool(kMayBeUntrusted); if (may_be_untrusted.value_or(false)) { creation_flags |= Extension::MAY_BE_UNTRUSTED; } @@ -439,10 +435,10 @@ continue; } - std::string install_parameter; - extension_dict->GetString(kInstallParam, &install_parameter); + const std::string* install_parameter = + extension_dict.FindString(kInstallParam); - if (has_external_crx) { + if (external_crx) { if (crx_location_ == ManifestLocation::kInvalidLocation) { install_stage_tracker->ReportFailure( extension_id, @@ -452,14 +448,14 @@ continue; } - base::FilePath path = base::FilePath::FromUTF8Unsafe(external_crx); + base::FilePath path = base::FilePath::FromUTF8Unsafe(*external_crx); if (path.value().find(base::FilePath::kParentDirectory) != base::StringPiece::npos) { install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason:: MALFORMED_EXTENSION_DICT_FILE_PATH); LOG(WARNING) << "Path traversal not allowed in path: " - << external_crx.c_str(); + << external_crx->c_str(); continue; } @@ -472,7 +468,7 @@ install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason:: MALFORMED_EXTENSION_DICT_FILE_PATH); - LOG(WARNING) << "File path " << external_crx.c_str() + LOG(WARNING) << "File path " << external_crx->c_str() << " is relative. An absolute path is required."; continue; } @@ -492,8 +488,8 @@ external_file_extensions->emplace_back( extension_id, version, path, crx_location_, creation_flags, auto_acknowledge_, install_immediately_); - } else { // if (has_external_update_url) - CHECK(has_external_update_url); // Checking of keys above ensures this. + } else { // if (external_update_url) + CHECK(external_update_url); // Checking of keys above ensures this. if (download_location_ == ManifestLocation::kInvalidLocation) { install_stage_tracker->ReportFailure( extension_id, @@ -502,20 +498,21 @@ << "extensions from update URLs."; continue; } - GURL update_url(external_update_url); + GURL update_url(*external_update_url); if (!update_url.is_valid()) { install_stage_tracker->ReportFailure( extension_id, InstallStageTracker::FailureReason:: MALFORMED_EXTENSION_DICT_UPDATE_URL); LOG(WARNING) << "Malformed extension dictionary for extension: " << extension_id.c_str() << ". Key " << kExternalUpdateUrl - << " has value \"" << external_update_url + << " has value \"" << *external_update_url << "\", which is not a valid URL."; continue; } external_update_url_extensions->emplace_back( - extension_id, install_parameter, std::move(update_url), - download_location_, creation_flags, auto_acknowledge_); + extension_id, install_parameter != nullptr ? *install_parameter : "", + std::move(update_url), download_location_, creation_flags, + auto_acknowledge_); } } @@ -580,15 +577,15 @@ } bool ExternalProviderImpl::HandleMinProfileVersion( - const base::DictionaryValue* extension, + const base::Value::Dict& extension, const std::string& extension_id, std::set<std::string>* unsupported_extensions) { - std::string min_profile_created_by_version; - if (extension->GetString(kMinProfileCreatedByVersion, - &min_profile_created_by_version)) { + const std::string* min_profile_created_by_version = + extension.FindString(kMinProfileCreatedByVersion); + if (min_profile_created_by_version) { base::Version profile_version( profile_->GetPrefs()->GetString(prefs::kProfileCreatedByVersion)); - base::Version min_version(min_profile_created_by_version); + base::Version min_version(*min_profile_created_by_version); if (min_version.IsValid() && profile_version.CompareTo(min_version) < 0) { unsupported_extensions->insert(extension_id); InstallStageTracker::Get(profile_)->ReportFailure( @@ -597,7 +594,7 @@ << extension_id << " profile.created_by_version: " << profile_version.GetString() << " min_profile_created_by_version: " - << min_profile_created_by_version; + << *min_profile_created_by_version; return false; } } @@ -605,11 +602,11 @@ } bool ExternalProviderImpl::HandleDoNotInstallForEnterprise( - const base::DictionaryValue* extension, + const base::Value::Dict& extension, const std::string& extension_id, std::set<std::string>* unsupported_extensions) { absl::optional<bool> do_not_install_for_enterprise = - extension->FindBoolKey(kDoNotInstallForEnterprise); + extension.FindBool(kDoNotInstallForEnterprise); if (do_not_install_for_enterprise.value_or(false)) { const policy::ProfilePolicyConnector* const connector = profile_->GetProfilePolicyConnector();
diff --git a/chrome/browser/extensions/external_provider_impl.h b/chrome/browser/extensions/external_provider_impl.h index b28395f..e3459c5 100644 --- a/chrome/browser/extensions/external_provider_impl.h +++ b/chrome/browser/extensions/external_provider_impl.h
@@ -102,12 +102,12 @@ void set_allow_updates(bool allow_updates) { allow_updates_ = allow_updates; } private: - bool HandleMinProfileVersion(const base::DictionaryValue* extension, + bool HandleMinProfileVersion(const base::Value::Dict& extension, const std::string& extension_id, std::set<std::string>* unsupported_extensions); bool HandleDoNotInstallForEnterprise( - const base::DictionaryValue* extension, + const base::Value::Dict& extension, const std::string& extension_id, std::set<std::string>* unsupported_extensions);
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc index 8caea0e..a9c4178 100644 --- a/chrome/browser/extensions/install_signer.cc +++ b/chrome/browser/extensions/install_signer.cc
@@ -193,16 +193,17 @@ return result; } - std::string salt_base64; - std::string signature_base64; - if (!value.GetString(kExpireDateKey, &result->expire_date) || - !value.GetString(kSaltKey, &salt_base64) || - !value.GetString(kSignatureKey, &signature_base64) || - !base::Base64Decode(salt_base64, &result->salt) || - !base::Base64Decode(signature_base64, &result->signature)) { + const base::Value::Dict& dict = value.GetDict(); + const std::string* expire_date = dict.FindString(kExpireDateKey); + const std::string* salt_base64 = dict.FindString(kSaltKey); + const std::string* signature_base64 = dict.FindString(kSignatureKey); + if (!expire_date || !salt_base64 || !signature_base64 || + !base::Base64Decode(*salt_base64, &result->salt) || + !base::Base64Decode(*signature_base64, &result->signature)) { result.reset(); return result; } + result->expire_date = *expire_date; // Note: earlier versions of the code did not write out a timestamp value // so older entries will not necessarily have this.
diff --git a/chrome/browser/extensions/policy_handlers.cc b/chrome/browser/extensions/policy_handlers.cc index d83c57e..9d7a601 100644 --- a/chrome/browser/extensions/policy_handlers.cc +++ b/chrome/browser/extensions/policy_handlers.cc
@@ -252,20 +252,19 @@ DCHECK(entry.second.is_dict()); // Extracts sub dictionary. - const base::DictionaryValue* sub_dict = nullptr; - entry.second.GetAsDictionary(&sub_dict); + const base::Value::Dict& sub_dict = entry.second.GetDict(); - std::string installation_mode; - if (sub_dict->GetString(schema_constants::kInstallationMode, - &installation_mode)) { - if (installation_mode == schema_constants::kForceInstalled || - installation_mode == schema_constants::kNormalInstalled) { + const std::string* installation_mode = + sub_dict.FindString(schema_constants::kInstallationMode); + if (installation_mode) { + if (*installation_mode == schema_constants::kForceInstalled || + *installation_mode == schema_constants::kNormalInstalled) { DCHECK(entry.first != schema_constants::kWildcard); // Verifies that 'update_url' is specified for 'force_installed' and // 'normal_installed' mode. - std::string update_url; - if (!sub_dict->GetString(schema_constants::kUpdateUrl, &update_url) || - update_url.empty()) { + const std::string* update_url = + sub_dict.FindString(schema_constants::kUpdateUrl); + if (!update_url || update_url->empty()) { if (errors) { errors->AddError(policy_name(), entry.first + "." + schema_constants::kUpdateUrl, @@ -274,7 +273,7 @@ invalid_keys.insert(entry.first); continue; } - if (!GURL(update_url).is_valid()) { + if (!GURL(*update_url).is_valid()) { // Warns about an invalid update URL. if (errors) { errors->AddError(policy_name(), IDS_POLICY_INVALID_UPDATE_URL_ERROR, @@ -291,9 +290,9 @@ const int extension_scheme_mask = URLPattern::GetValidSchemeMaskForExtensions(); for (const char* key : host_keys) { - const base::Value* unparsed_urls = sub_dict->FindListKey(key); + const base::Value::List* unparsed_urls = sub_dict.FindList(key); if (unparsed_urls != nullptr) { - for (const auto& url_value : unparsed_urls->GetListDeprecated()) { + for (const auto& url_value : *unparsed_urls) { const std::string& unparsed_url = url_value.GetString(); URLPattern pattern(extension_scheme_mask); URLPattern::ParseResult parse_result = pattern.Parse(unparsed_url); @@ -331,10 +330,10 @@ } } - const base::Value* runtime_blocked_hosts = - sub_dict->FindListKey(schema_constants::kPolicyBlockedHosts); + const base::Value::List* runtime_blocked_hosts = + sub_dict.FindList(schema_constants::kPolicyBlockedHosts); if (runtime_blocked_hosts != nullptr && - runtime_blocked_hosts->GetListDeprecated().size() > + runtime_blocked_hosts->size() > schema_constants::kMaxItemsURLPatternSet) { if (errors) { errors->AddError( @@ -345,10 +344,10 @@ } } - const base::Value* runtime_allowed_hosts = - sub_dict->FindListKey(schema_constants::kPolicyAllowedHosts); + const base::Value::List* runtime_allowed_hosts = + sub_dict.FindList(schema_constants::kPolicyAllowedHosts); if (runtime_allowed_hosts != nullptr && - runtime_allowed_hosts->GetListDeprecated().size() > + runtime_allowed_hosts->size() > schema_constants::kMaxItemsURLPatternSet) { if (errors) { errors->AddError(
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc index 30d9064..ce5adb9 100644 --- a/chrome/browser/extensions/test_extension_prefs.cc +++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -175,9 +175,9 @@ const base::DictionaryValue& manifest, ManifestLocation location, int extra_flags) { - std::string name; - EXPECT_TRUE(manifest.GetString(manifest_keys::kName, &name)); - base::FilePath path = extensions_dir_.AppendASCII(name); + const std::string* name = manifest.GetDict().FindString(manifest_keys::kName); + EXPECT_TRUE(name); + base::FilePath path = extensions_dir_.AppendASCII(*name); std::string errors; scoped_refptr<Extension> extension = Extension::Create(path, location, manifest, extra_flags, &errors);
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc index b39abab..9836733 100644 --- a/chrome/browser/extensions/webstore_installer.cc +++ b/chrome/browser/extensions/webstore_installer.cc
@@ -320,18 +320,16 @@ } InstallVerifier::Get(profile_)->AddProvisional(ids); - std::string name; - if (!approval_->manifest->available_values().GetString(manifest_keys::kName, - &name)) { + const std::string* name = + approval_->manifest->available_values().GetDict().FindString( + manifest_keys::kName); + if (!name) { NOTREACHED(); } extensions::InstallTracker* tracker = extensions::InstallTrackerFactory::GetForBrowserContext(profile_); extensions::InstallObserver::ExtensionInstallParams params( - id_, - name, - approval_->installing_icon, - approval_->manifest->is_app(), + id_, *name, approval_->installing_icon, approval_->manifest->is_app(), approval_->manifest->is_platform_app()); tracker->OnBeginExtensionInstall(params);
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc index 913188d..cddddd4 100644 --- a/chrome/browser/extensions/webstore_standalone_installer.cc +++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -253,14 +253,17 @@ webstore_data->FindIntKey(kRatingCountKey); // Manifest, number of users, average rating and rating count are required. - std::string manifest; - if (!webstore_data->GetString(kManifestKey, &manifest) || - !webstore_data->GetString(kUsersKey, &localized_user_count_) || - !average_rating_setting || !rating_count_setting) { + const std::string* manifest = + webstore_data->GetDict().FindString(kManifestKey); + const std::string* localized_user_count = + webstore_data->GetDict().FindString(kUsersKey); + if (!manifest || !localized_user_count || !average_rating_setting || + !rating_count_setting) { CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, webstore_install::kInvalidWebstoreResponseError); return; } + localized_user_count_ = *localized_user_count; average_rating_ = *average_rating_setting; rating_count_ = *rating_count_setting; @@ -321,8 +324,8 @@ // Assume ownership of webstore_data. webstore_data_ = std::move(webstore_data); - auto helper = base::MakeRefCounted<WebstoreInstallHelper>(this, id_, manifest, - icon_url); + auto helper = base::MakeRefCounted<WebstoreInstallHelper>( + this, id_, *manifest, icon_url); // The helper will call us back via OnWebstoreParseSuccess() or // OnWebstoreParseFailure(). helper->Start(profile_->GetDefaultStoragePartition()
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8d85039..59c9039 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -35,8 +35,8 @@ }, { "name": "accessible-pdf-form", - "owners": [ "asku@microsoft.com", "mohitb@microsoft.com" ], - "expiry_milestone": 105 + "owners": [ "bravi@microsoft.com", "mohitb@microsoft.com" ], + "expiry_milestone": 110 }, { "name": "account-id-migration", @@ -1801,7 +1801,7 @@ { "name": "enable-cros-autocorrect-params-tuning", "owners": [ "tranbaoduy", "essential-inputs-team@google.com" ], - "expiry_milestone": 106 + "expiry_milestone": 111 }, { "name": "enable-cros-avatars-cloud-migration", @@ -1811,16 +1811,11 @@ { "name": "enable-cros-diacritics-on-physical-keyboard-longpress", "owners": ["jhtin", "essential-inputs-team@google.com" ], - "expiry_milestone": 106 - }, - { - "name": "enable-cros-ime-assist-autocorrect", - "owners": [ "jopalmer", "essential-inputs-team@google.com" ], - "expiry_milestone": 110 + "expiry_milestone": 111 }, { "name": "enable-cros-ime-assist-emoji-enhanced", - "owners": [ "myy", "curtismcmullan", "essential-inputs-team@google.com" ], + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], "expiry_milestone": 110 }, { @@ -1834,11 +1829,6 @@ "expiry_milestone": 110 }, { - "name": "enable-cros-ime-assist-multi-word-lacros", - "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], - "expiry_milestone": 120 - }, - { "name": "enable-cros-ime-assist-personal-info", "owners": [ "jiwan", "essential-inputs-team@google.com" ], "expiry_milestone": 110 @@ -1854,31 +1844,21 @@ "expiry_milestone" : 110 }, { - "name": "enable-cros-ime-system-emoji-picker", - "owners": [ "jopalmer", "essential-inputs-team@google.com" ], - "expiry_milestone": 100 - }, - { "name": "enable-cros-ime-system-emoji-picker-clipboard", "owners": [ "jopalmer", "essential-inputs-team@google.com" ], "expiry_milestone": 110 }, { "name": "enable-cros-ime-system-emoji-picker-extension", - "owners": [ "hdchuong", "curtismcmullan", "myy", "essential-inputs-team@google.com" ], + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], "expiry_milestone": 110 }, { "name": "enable-cros-ime-system-emoji-picker-search-extension", - "owners": [ "hdchuong", "curtismcmullan", "myy", "essential-inputs-team@google.com" ], + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], "expiry_milestone": 110 }, { - "name": "enable-cros-language-settings-ime-options-in-settings", - "owners": [ "jopalmer", "essential-inputs-team@google.com" ], - "expiry_milestone": 97 - }, - { "name": "enable-cros-language-settings-update-japanese", "owners": [ "keithlee", "essential-inputs-team@google.com" ], "expiry_milestone": 110 @@ -1886,7 +1866,7 @@ { "name": "enable-cros-multilingual-typing", "owners": [ "tranbaoduy", "essential-inputs-team@google.com" ], - "expiry_milestone": 105 + "expiry_milestone": 111 }, { "name": "enable-cros-on-device-grammar-check", @@ -1901,22 +1881,17 @@ { "name": "enable-cros-system-chinese-physical-typing", "owners": [ "shend", "essential-inputs-team@google.com" ], - "expiry_milestone": 105 + "expiry_milestone": 111 }, { "name": "enable-cros-system-japanese-physical-typing", "owners": [ "keithlee", "essential-inputs-team@google.com" ], "expiry_milestone": 108 }, - { - "name": "enable-cros-system-korean-physical-typing", - "owners": [ "shend", "essential-inputs-team@google.com" ], - "expiry_milestone": 97 - }, - { + { "name": "enable-cros-system-transliteration-physical-typing", "owners": [ "shend", "essential-inputs-team@google.com" ], - "expiry_milestone": 102 + "expiry_milestone": 111 }, { "name": "enable-cros-virtual-keyboard-api", @@ -3691,20 +3666,25 @@ "owners": [ "sidereal@google.com", "davidmunro@google.com", "clumptini@google.com" ], "expiry_milestone": 115 }, - { + { "name": "handwriting-gesture-editing", "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], - "expiry_milestone": 95 + "expiry_milestone": 111 }, { "name": "handwriting-legacy-recognition", - "owners": [ "essential-inputs-team@google.com" ], - "expiry_milestone": 105 + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], + "expiry_milestone": 111 }, { "name": "handwriting-legacy-recognition-all-lang", - "owners": [ "essential-inputs-team@google.com" ], - "expiry_milestone": 105 + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], + "expiry_milestone": 111 + }, + { + "name": "handwriting-library-dlc", + "owners": [ "shend@google.com", "essential-inputs-team@google.com" ], + "expiry_milestone": 110 }, { "name": "happiness-tracking-surveys-for-desktop-demo", @@ -5938,6 +5918,11 @@ "expiry_milestone": 110 }, { + "name": "skip-service-worker-fetch-handler", + "owners": [ "yyanagisawa@google.com", "chrome-worker@google.com" ], + "expiry_milestone": 116 + }, + { "name": "skip-undecryptable-passwords", "owners": [ "derinel@google.com", "mamir" ], "expiry_milestone": 102
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 435e3f7..1722c80 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1558,6 +1558,12 @@ "Enables new on-device recognition for handwriting legacy paths in all " "supported languages."; +const char kHandwritingLibraryDlcName[] = + "Handwriting recognition with library from DLC"; +const char kHandwritingLibraryDlcDescription[] = + "Enables new on-device recognition with the handwriting library installed " + "from DLC"; + const char kHardwareMediaKeyHandling[] = "Hardware Media Key Handling"; const char kHardwareMediaKeyHandlingDescription[] = "Enables using media keys to control the active media session. This " @@ -3186,6 +3192,12 @@ "The platform and oscpu in the User-Agent string will be reported as " "<unifiedPlatform>"; +const char kSkipServiceWorkerFetchHandlerName[] = + "Skip Service Worker Fetch Handler if skippable"; +const char kSkipServiceWorkerFetchHandlerDescription[] = + "Skips starting the service worker and run the fetch handler if the fetch " + "handler is recognized as skippable."; + const char kWebSQLAccessName[] = "Allows access to WebSQL APIs"; const char kWebSQLAccessDescription[] = "The WebSQL API is enabled by default, but can be disabled here.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index a65f41f..bf971123 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -873,6 +873,9 @@ extern const char kHandwritingLegacyRecognitionAllLangName[]; extern const char kHandwritingLegacyRecognitionAllLangDescription[]; +extern const char kHandwritingLibraryDlcName[]; +extern const char kHandwritingLibraryDlcDescription[]; + extern const char kHardwareMediaKeyHandling[]; extern const char kHardwareMediaKeyHandlingDescription[]; @@ -1795,6 +1798,9 @@ extern const char kReduceUserAgentPlatformOsCpuName[]; extern const char kReduceUserAgentPlatformOsCpuDescription[]; +extern const char kSkipServiceWorkerFetchHandlerName[]; +extern const char kSkipServiceWorkerFetchHandlerDescription[]; + extern const char kWebSQLAccessName[]; extern const char kWebSQLAccessDescription[];
diff --git a/chrome/browser/lacros/browser_service_lacros.cc b/chrome/browser/lacros/browser_service_lacros.cc index 3155c18..a8570adf 100644 --- a/chrome/browser/lacros/browser_service_lacros.cc +++ b/chrome/browser/lacros/browser_service_lacros.cc
@@ -452,6 +452,9 @@ case OpenUrlParams::WindowOpenDisposition::kNewForegroundTab: navigate_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; break; + case OpenUrlParams::WindowOpenDisposition::kNewWindow: + navigate_params.disposition = WindowOpenDisposition::NEW_WINDOW; + break; case OpenUrlParams::WindowOpenDisposition::kSwitchToTab: navigate_params.disposition = WindowOpenDisposition::SWITCH_TO_TAB; navigate_params.path_behavior =
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc index 6861cc69..842fee1e 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/containers/contains.h" #include "base/rand_util.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -684,19 +685,17 @@ } void CastMediaSinkServiceImpl::OnSinkRemoved(const MediaSinkInternal& sink) { - // No-op + // No-op. } void CastMediaSinkServiceImpl::TryConnectDialDiscoveredSink( const MediaSinkInternal& dial_sink) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/753175): Dual discovery should not try to open cast channel - // for non-Cast device. + // Dual discovery should not try to open cast channel for non-Cast device. if (IsProbablyNonCastDevice(dial_sink)) { return; } - MediaSinkInternal sink = CreateCastSinkFromDialSink(dial_sink); if (GetSinkById(sink.sink().id())) { metrics_.RecordCastSinkDiscoverySource(SinkSource::kMdnsDial); @@ -707,6 +706,13 @@ } return; } + if (HasSinkWithIPAddress(dial_sink.dial_data().ip_address)) { + // We're already connected to a Cast sink whose ID is different from that of + // |dial_sink| but has the same IP address. In this case we do not try to + // reopen a channel because that'd be redundant and would cause a teardown + // of any existing session. + return; + } OpenChannel(sink, nullptr, SinkSource::kDial, base::DoNothing(), CreateCastSocketOpenParams(sink)); @@ -764,4 +770,11 @@ sink.cast_data().cast_channel_id)); } +bool CastMediaSinkServiceImpl::HasSinkWithIPAddress( + const net::IPAddress& ip_address) const { + return base::Contains(GetSinks(), ip_address, [](const auto& sink) { + return sink.second.cast_data().ip_endpoint.address(); + }); +} + } // namespace media_router
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h index e1682cd..4cc4cab 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h
@@ -183,6 +183,10 @@ FRIEND_TEST_ALL_PREFIXES(CastMediaSinkServiceImplTest, TestOnSinkAddedOrUpdatedSkipsIfNonCastDevice); FRIEND_TEST_ALL_PREFIXES(CastMediaSinkServiceImplTest, + IgnoreDialSinkIfSameIdAsCast); + FRIEND_TEST_ALL_PREFIXES(CastMediaSinkServiceImplTest, + IgnoreDialSinkIfSameIpAddressAsCast); + FRIEND_TEST_ALL_PREFIXES(CastMediaSinkServiceImplTest, TestSuccessOnChannelErrorRetry); FRIEND_TEST_ALL_PREFIXES(CastMediaSinkServiceImplTest, TestFailureOnChannelErrorRetry); @@ -322,6 +326,8 @@ // long term solution for restricting dual discovery. bool IsProbablyNonCastDevice(const MediaSinkInternal& sink) const; + bool HasSinkWithIPAddress(const net::IPAddress& ip_address) const; + base::WeakPtr<CastMediaSinkServiceImpl> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc index 1af6dae..d44488c 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
@@ -744,6 +744,37 @@ EXPECT_TRUE(media_sink_service_impl_.dial_sink_failure_count_.empty()); } +TEST_P(CastMediaSinkServiceImplTest, IgnoreDialSinkIfSameIdAsCast) { + MediaSinkInternal cast_sink = CreateCastSink(1); + MediaSinkInternal dial_sink = CreateDialSink(1); + ASSERT_EQ(cast_sink.id(), + CastMediaSinkServiceImpl::GetCastSinkIdFromDial(dial_sink.id())); + + media_sink_service_impl_.AddOrUpdateSink(cast_sink); + + // Since there already exists a sink with the same ID, we should not try to + // open a channel again. + EXPECT_CALL(*mock_cast_socket_service_, OpenSocket_(_, _)).Times(0); + media_sink_service_impl_.OnSinkAddedOrUpdated(dial_sink); +} + +TEST_P(CastMediaSinkServiceImplTest, IgnoreDialSinkIfSameIpAddressAsCast) { + MediaSinkInternal cast_sink = CreateCastSink(1); + media_sink_service_impl_.AddOrUpdateSink(cast_sink); + + // Create a DIAL sink whose ID is different from that of |cast_sink| but the + // IP address is the same. + MediaSinkInternal dial_sink = CreateDialSink(2); + media_router::DialSinkExtraData extra_data = dial_sink.dial_data(); + extra_data.ip_address = cast_sink.cast_data().ip_endpoint.address(); + dial_sink.set_dial_data(extra_data); + + // Since there already exists a sink with the same IP address, we should + // not try to open a channel again. + EXPECT_CALL(*mock_cast_socket_service_, OpenSocket_(_, _)).Times(0); + media_sink_service_impl_.OnSinkAddedOrUpdated(dial_sink); +} + TEST_P(CastMediaSinkServiceImplTest, OpenChannelsNow) { MediaSinkInternal cast_sink1 = CreateCastSink(1); MediaSinkInternal cast_sink2 = CreateCastSink(2);
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc index 5bd2e42..26cad20 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc
@@ -711,7 +711,8 @@ fake_user_manager_->AddArcKioskAppUser(account_id); break; case user_manager::USER_TYPE_ACTIVE_DIRECTORY: - account_id = AccountId::AdFromObjGuid("guid"); + account_id = + AccountId::AdFromUserEmailObjGuid(account_id.GetUserEmail(), "guid"); fake_user_manager_->AddUserWithAffiliationAndTypeAndProfile( account_id, false, test_case.user_type, testing_profile.get()); break;
diff --git a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc index ff4ca18..9342096d 100644 --- a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc +++ b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc
@@ -102,8 +102,8 @@ absl::optional<base::Time> NearbyShareSchedulerBase::GetLastSuccessTime() const { - return base::ValueToTime(pref_service_->GetDictionary(pref_name_) - ->FindKey(kLastSuccessTimeKeyName)); + return base::ValueToTime( + pref_service_->GetValueDict(pref_name_).Find(kLastSuccessTimeKeyName)); } absl::optional<base::TimeDelta> @@ -126,14 +126,14 @@ } bool NearbyShareSchedulerBase::IsWaitingForResult() const { - return pref_service_->GetDictionary(pref_name_) - ->FindBoolKey(kIsWaitingForResultKeyName) + return pref_service_->GetValueDict(pref_name_) + .FindBool(kIsWaitingForResultKeyName) .value_or(false); } size_t NearbyShareSchedulerBase::GetNumConsecutiveFailures() const { - const std::string* str = pref_service_->GetDictionary(pref_name_) - ->FindStringKey(kNumConsecutiveFailuresKeyName); + const std::string* str = pref_service_->GetValueDict(pref_name_) + .FindString(kNumConsecutiveFailuresKeyName); if (!str) return 0; @@ -164,13 +164,13 @@ absl::optional<base::Time> NearbyShareSchedulerBase::GetLastAttemptTime() const { - return base::ValueToTime(pref_service_->GetDictionary(pref_name_) - ->FindKey(kLastAttemptTimeKeyName)); + return base::ValueToTime( + pref_service_->GetValueDict(pref_name_).Find(kLastAttemptTimeKeyName)); } bool NearbyShareSchedulerBase::HasPendingImmediateRequest() const { - return pref_service_->GetDictionary(pref_name_) - ->FindBoolKey(kHasPendingImmediateRequestKeyName) + return pref_service_->GetValueDict(pref_name_) + .FindBool(kHasPendingImmediateRequestKeyName) .value_or(false); }
diff --git a/chrome/browser/new_tab_page/modules/task_module/task_module_service.cc b/chrome/browser/new_tab_page/modules/task_module/task_module_service.cc index 8e3a67696..590bac3 100644 --- a/chrome/browser/new_tab_page/modules/task_module/task_module_service.cc +++ b/chrome/browser/new_tab_page/modules/task_module/task_module_service.cc
@@ -180,14 +180,15 @@ void TaskModuleService::DismissTask(const std::string& task_name) { ListPrefUpdate update(profile_->GetPrefs(), GetDismissedTasksPrefName()); + base::Value::List& update_list = update->GetList(); base::Value task_name_value(task_name); - if (!base::Contains(update->GetListDeprecated(), task_name_value)) - update->Append(std::move(task_name_value)); + if (!base::Contains(update_list, task_name_value)) + update_list.Append(std::move(task_name_value)); } void TaskModuleService::RestoreTask(const std::string& task_name) { ListPrefUpdate update(profile_->GetPrefs(), GetDismissedTasksPrefName()); - update->EraseListValue(base::Value(task_name)); + update->GetList().EraseValue(base::Value(task_name)); } void TaskModuleService::OnDataLoaded(network::SimpleURLLoader* loader, @@ -230,20 +231,20 @@ // We receive a list of tasks ordered from highest to lowest priority. We only // support showing a single task though. Therefore, pick the first task. - auto* tasks = - result->FindListPath(base::StringPrintf("update.%s", GetTasksKey())); - if (!tasks || tasks->GetListDeprecated().size() == 0) { + auto* tasks = result->GetDict().FindListByDottedPath( + base::StringPrintf("update.%s", GetTasksKey())); + if (!tasks || tasks->size() == 0) { std::move(callback).Run(nullptr); return; } - for (const auto& task : tasks->GetListDeprecated()) { - auto* title = task.FindStringPath("title"); - auto* task_name = task.FindStringPath("task_name"); - auto* task_items = task.FindListPath(GetTaskItemsKey()); - auto* related_searches = task.FindListPath("related_searches"); - if (!title || !task_name || !task_items || - task_items->GetListDeprecated().size() == 0) { + for (const auto& task : *tasks) { + const base::Value::Dict& task_dict = task.GetDict(); + auto* title = task_dict.FindString("title"); + auto* task_name = task_dict.FindString("task_name"); + auto* task_items = task_dict.FindListByDottedPath(GetTaskItemsKey()); + auto* related_searches = task_dict.FindList("related_searches"); + if (!title || !task_name || !task_items || task_items->size() == 0) { continue; } if (IsTaskDismissed(*task_name)) { @@ -251,13 +252,14 @@ } auto mojo_task = task_module::mojom::Task::New(); std::vector<task_module::mojom::TaskItemPtr> mojo_task_items; - for (const auto& task_item : task_items->GetListDeprecated()) { - const auto* name = task_item.FindStringPath("name"); - const auto* image_url = task_item.FindStringPath("image_url"); + for (const auto& task_item : *task_items) { + const base::Value::Dict& task_item_dict = task_item.GetDict(); + const auto* name = task_item_dict.FindString("name"); + const auto* image_url = task_item_dict.FindString("image_url"); const absl::optional<int> viewed_timestamp = - task_item.FindIntPath("viewed_timestamp.seconds"); - const auto* site_name = task_item.FindStringPath("site_name"); - const auto* target_url = task_item.FindStringPath("target_url"); + task_item_dict.FindIntByDottedPath("viewed_timestamp.seconds"); + const auto* site_name = task_item_dict.FindString("site_name"); + const auto* target_url = task_item_dict.FindString("target_url"); if (!name || !image_url || !target_url) { continue; } @@ -278,9 +280,10 @@ if (related_searches) { std::vector<task_module::mojom::RelatedSearchPtr> mojo_related_searches; - for (const auto& related_search : related_searches->GetListDeprecated()) { - auto* text = related_search.FindStringPath("text"); - auto* target_url = related_search.FindStringPath("target_url"); + for (const auto& related_search : *related_searches) { + const base::Value::Dict& related_search_dict = related_search.GetDict(); + auto* text = related_search_dict.FindString("text"); + auto* target_url = related_search_dict.FindString("target_url"); if (!text || !target_url) { continue; } @@ -315,9 +318,7 @@ if (base::FeatureList::IsEnabled(ntp_features::kNtpModulesRedesigned)) { return false; } - const base::Value* dismissed_tasks = - profile_->GetPrefs()->GetList(GetDismissedTasksPrefName()); - DCHECK(dismissed_tasks); - return base::Contains(dismissed_tasks->GetListDeprecated(), - base::Value(task_name)); + const base::Value::List& dismissed_tasks = + profile_->GetPrefs()->GetValueList(GetDismissedTasksPrefName()); + return base::Contains(dismissed_tasks, base::Value(task_name)); }
diff --git a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc index 603b8ab9..63dbf6a58b 100644 --- a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc
@@ -17,10 +17,10 @@ namespace internal { const char kHistogramLoadingPredictorFirstContentfulPaintPreconnectable[] = - "PageLoad.Clients.LoadingPredictor.PaintTiming." + "PageLoad.Clients.LoadingPredictor2.PaintTiming." "NavigationToFirstContentfulPaint.Preconnectable"; const char kHistogramLoadingPredictorFirstMeaningfulPaintPreconnectable[] = - "PageLoad.Clients.LoadingPredictor.Experimental.PaintTiming." + "PageLoad.Clients.LoadingPredictor2.Experimental.PaintTiming." "NavigationToFirstMeaningfulPaint.Preconnectable"; } // namespace internal @@ -77,6 +77,22 @@ } page_load_metrics::PageLoadMetricsObserver::ObservePolicy +LoadingPredictorPageLoadMetricsObserver::OnPrerenderStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) { + // This class is interested in the events after activation. + // Works as same as non prerendering case except for metrics correction. + return CONTINUE_OBSERVING; +} + +void LoadingPredictorPageLoadMetricsObserver::DidActivatePrerenderedPage( + content::NavigationHandle* navigation_handle) { + record_histogram_preconnectable_ = + GetDelegate().GetVisibilityTracker().currently_in_foreground() && + predictor_->IsUrlPreconnectable(navigation_handle->GetURL()); +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy LoadingPredictorPageLoadMetricsObserver::OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) { record_histogram_preconnectable_ = false; @@ -94,9 +110,13 @@ frame, GetDelegate().GetNavigationStart() + timing.paint_timing->first_contentful_paint.value()); if (record_histogram_preconnectable_) { + base::TimeDelta corrected = + page_load_metrics::CorrectEventAsNavigationOrActivationOrigined( + GetDelegate(), timing, + timing.paint_timing->first_contentful_paint.value()); PAGE_LOAD_HISTOGRAM( internal::kHistogramLoadingPredictorFirstContentfulPaintPreconnectable, - timing.paint_timing->first_contentful_paint.value()); + corrected); } } @@ -104,8 +124,12 @@ OnFirstMeaningfulPaintInMainFrameDocument( const page_load_metrics::mojom::PageLoadTiming& timing) { if (record_histogram_preconnectable_) { + base::TimeDelta corrected = + page_load_metrics::CorrectEventAsNavigationOrActivationOrigined( + GetDelegate(), timing, + timing.paint_timing->first_meaningful_paint.value()); PAGE_LOAD_HISTOGRAM( internal::kHistogramLoadingPredictorFirstMeaningfulPaintPreconnectable, - timing.paint_timing->first_meaningful_paint.value()); + corrected); } }
diff --git a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h index e69cd06e..0276c77f 100644 --- a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.h
@@ -57,6 +57,10 @@ ObservePolicy OnFencedFramesStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) override; + ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) override; + void DidActivatePrerenderedPage( + content::NavigationHandle* navigation_handle) override; ObservePolicy OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) override; void OnFirstContentfulPaintInPage(
diff --git a/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.cc index 9b5eb0eb..4e03c8fc 100644 --- a/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.cc
@@ -52,6 +52,20 @@ } page_load_metrics::PageLoadMetricsObserver::ObservePolicy +SideSearchPageLoadMetricsObserver::OnPrerenderStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) { + // There is no prerendering trigger for contents in the side panel. + + // Note that here is not reachable because this class is only registered for + // the WebContents of the side panel. Especially, the navigation is not + // prerendering. See + // chrome/browser/page_load_metrics/page_load_metrics_initialize.cc + NOTREACHED(); + return STOP_OBSERVING; +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy SideSearchPageLoadMetricsObserver::OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) { RecordSessionEndHistograms();
diff --git a/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.h index be9c3f86..7325143 100644 --- a/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/side_search_page_load_metrics_observer.h
@@ -34,6 +34,8 @@ ObservePolicy OnFencedFramesStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) override; + ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) override; ObservePolicy OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) override; void OnFirstInputInPage(
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc index 9005cfd..89b2445 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -27,7 +27,7 @@ #include "chrome/browser/password_manager/android/password_store_operation_target.h" #include "chrome/browser/password_manager/android/password_sync_controller_delegate_android.h" #include "chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.h" -#include "components/autofill/core/browser/autofill_regexes.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_store_backend.h"
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 d33c2b0f..81d332c 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
@@ -5,6 +5,7 @@ #include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" #include "base/feature_list.h" +#include "base/values.h" #include "chrome/browser/performance_manager/policies/high_efficiency_mode_policy.h" #include "components/performance_manager/public/features.h" #include "components/performance_manager/public/performance_manager.h" @@ -105,6 +106,23 @@ DCHECK(!g_user_performance_tuning_manager); g_user_performance_tuning_manager = this; + if (base::FeatureList::IsEnabled( + performance_manager::features::kHighEfficiencyModeAvailable)) { + // If the HEM pref is still the default (it wasn't configured by the user), + // look up what that default value should be in Finch and set it here. + // This is called in PostCreateThreads, which ensures the pref is in the + // correct state when views are created. + const PrefService::Preference* pref = local_state->FindPreference( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); + if (pref->IsDefaultValue()) { + local_state->SetDefaultPrefValue( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, + base::Value( + performance_manager::features::kHighEfficiencyModeDefaultState + .Get())); + } + } + pref_change_registrar_.Init(local_state); }
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc index bc81039d..6089802 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc
@@ -13,17 +13,36 @@ namespace performance_manager::user_tuning { +namespace { + +class FakeHighEfficiencyModeToggleDelegate + : public performance_manager::user_tuning::UserPerformanceTuningManager:: + HighEfficiencyModeToggleDelegate { + public: + void ToggleHighEfficiencyMode(bool enabled) override {} + ~FakeHighEfficiencyModeToggleDelegate() override = default; +}; + +} // namespace + class UserPerformanceTuningManagerTest : public testing::Test { public: void SetUp() override { - feature_list_.InitAndEnableFeature( - performance_manager::features::kBatterySaverModeAvailable); - performance_manager::user_tuning::prefs::RegisterLocalStatePrefs( local_state_.registry()); + } + + void StartManager( + std::vector<base::test::ScopedFeatureList::FeatureAndParams> + features_and_params = { + {performance_manager::features::kBatterySaverModeAvailable, {}}, + {performance_manager::features::kHighEfficiencyModeAvailable, {}}, + }) { + feature_list_.InitWithFeaturesAndParameters(features_and_params, {}); manager_.reset(new UserPerformanceTuningManager( &local_state_, - std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled_))); + std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled_), + std::make_unique<FakeHighEfficiencyModeToggleDelegate>())); manager()->Start(); } @@ -40,6 +59,7 @@ }; TEST_F(UserPerformanceTuningManagerTest, TemporaryBatterySaver) { + StartManager(); EXPECT_FALSE(manager()->IsBatterySaverActive()); EXPECT_FALSE(throttling_enabled()); @@ -53,6 +73,7 @@ } TEST_F(UserPerformanceTuningManagerTest, BatterySaverModePref) { + StartManager(); EXPECT_FALSE(manager()->IsBatterySaverActive()); EXPECT_FALSE(throttling_enabled()); @@ -72,6 +93,7 @@ } TEST_F(UserPerformanceTuningManagerTest, PrefSupersedesTemporary) { + StartManager(); local_state_.SetInteger( performance_manager::user_tuning::prefs::kBatterySaverModeState, static_cast<int>(performance_manager::user_tuning::prefs:: @@ -89,6 +111,7 @@ } TEST_F(UserPerformanceTuningManagerTest, InvalidPrefInStore) { + StartManager(); local_state_.SetInteger( performance_manager::user_tuning::prefs::kBatterySaverModeState, static_cast<int>(performance_manager::user_tuning::prefs:: @@ -110,4 +133,24 @@ EXPECT_FALSE(throttling_enabled()); } +TEST_F(UserPerformanceTuningManagerTest, HEMFinchDisabledByDefault) { + StartManager({ + {performance_manager::features::kHighEfficiencyModeAvailable, + {{"default_state", "false"}}}, + }); + + EXPECT_FALSE(local_state_.GetBoolean( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled)); +} + +TEST_F(UserPerformanceTuningManagerTest, HEMFinchEnabledByDefault) { + StartManager({ + {performance_manager::features::kHighEfficiencyModeAvailable, + {{"default_state", "true"}}}, + }); + + EXPECT_TRUE(local_state_.GetBoolean( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled)); +} + } // namespace performance_manager::user_tuning
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc index 183fc2a..38d7b00 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc
@@ -14,16 +14,15 @@ #include "content/public/browser/web_contents_observer.h" #include "ui/gfx/geometry/size.h" -// This is used only for video PiP. Document PiP is handled by the window -// controller internally. -class PictureInPictureWindowManager::ContentsObserver final +// This web contents observer is used only for video PiP. +class PictureInPictureWindowManager::VideoWebContentsObserver final : public content::WebContentsObserver { public: - ContentsObserver(PictureInPictureWindowManager* owner, - content::WebContents* web_contents) + VideoWebContentsObserver(PictureInPictureWindowManager* owner, + content::WebContents* web_contents) : content::WebContentsObserver(web_contents), owner_(owner) {} - ~ContentsObserver() final = default; + ~VideoWebContentsObserver() final = default; void PrimaryPageChanged(content::Page& page) final { // Closes the active Picture-in-Picture window if user navigates away. @@ -37,6 +36,23 @@ raw_ptr<PictureInPictureWindowManager> owner_ = nullptr; }; +// This web contents observer is used only for document PiP. +class PictureInPictureWindowManager::DocumentWebContentsObserver final + : public content::WebContentsObserver { + public: + DocumentWebContentsObserver(PictureInPictureWindowManager* owner, + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), owner_(owner) {} + + ~DocumentWebContentsObserver() final = default; + + void WebContentsDestroyed() final { owner_->DocumentWebContentsDestroyed(); } + + private: + // Owns |this|. + raw_ptr<PictureInPictureWindowManager> owner_ = nullptr; +}; + PictureInPictureWindowManager* PictureInPictureWindowManager::GetInstance() { return base::Singleton<PictureInPictureWindowManager>::get(); } @@ -63,6 +79,10 @@ if (pip_window_controller_) CloseWindowInternal(); + // Start observing the parent web contents. + document_web_contents_observer_ = + std::make_unique<DocumentWebContentsObserver>(this, parent_web_contents); + auto* controller = content::PictureInPictureWindowController:: GetOrCreateDocumentPictureInPictureController(parent_web_contents); @@ -106,7 +126,8 @@ void PictureInPictureWindowManager::CreateWindowInternal( content::WebContents* web_contents) { - contents_observer_ = std::make_unique<ContentsObserver>(this, web_contents); + video_web_contents_observer_ = + std::make_unique<VideoWebContentsObserver>(this, web_contents); pip_window_controller_ = content::PictureInPictureWindowController:: GetOrCreateVideoPictureInPictureController(web_contents); } @@ -114,11 +135,20 @@ void PictureInPictureWindowManager::CloseWindowInternal() { DCHECK(pip_window_controller_); - contents_observer_.reset(); + video_web_contents_observer_.reset(); pip_window_controller_->Close(false /* should_pause_video */); pip_window_controller_ = nullptr; } +void PictureInPictureWindowManager::DocumentWebContentsDestroyed() { + // Document PiP window controller also observes the parent and child web + // contents, so we only need to forget the controller here when user closes + // the parent web contents with the PiP window open. + document_web_contents_observer_.reset(); + if (pip_window_controller_) + pip_window_controller_ = nullptr; +} + PictureInPictureWindowManager::PictureInPictureWindowManager() = default; PictureInPictureWindowManager::~PictureInPictureWindowManager() = default;
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h index e87ac65..480b42b 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h
@@ -58,7 +58,8 @@ private: friend struct base::DefaultSingletonTraits<PictureInPictureWindowManager>; - class ContentsObserver; + class VideoWebContentsObserver; + class DocumentWebContentsObserver; // Create a Picture-in-Picture window and register it in order to be closed // when needed. @@ -71,10 +72,15 @@ // This is suffixed with "Internal" to keep consistency with the method above. void CloseWindowInternal(); + // Called when the document PiP parent web contents is being destroyed. + void DocumentWebContentsDestroyed(); + PictureInPictureWindowManager(); ~PictureInPictureWindowManager(); - std::unique_ptr<ContentsObserver> contents_observer_; + std::unique_ptr<VideoWebContentsObserver> video_web_contents_observer_; + std::unique_ptr<DocumentWebContentsObserver> document_web_contents_observer_; + raw_ptr<content::PictureInPictureWindowController> pip_window_controller_ = nullptr; };
diff --git a/chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc b/chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc index 16eb2b4..2fe5a3f1 100644 --- a/chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc +++ b/chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc
@@ -12,10 +12,10 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/plugins/plugin_info_host_impl.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pepper_permission_util.h" @@ -25,8 +25,6 @@ #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" -#include "ppapi/host/ppapi_host.h" -#include "ppapi/shared_impl/ppapi_switches.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" @@ -38,6 +36,12 @@ #include "extensions/common/permissions/socket_permission.h" #endif +#if BUILDFLAG(ENABLE_PPAPI) +#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/shared_impl/ppapi_switches.h" +#endif // BUILDFLAG(ENABLE_PPAPI) + #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/crostini/crostini_pref_names.h" #include "chrome/common/webui_url_constants.h" @@ -246,11 +250,13 @@ bool ChromeContentBrowserClientPluginsPart::IsPluginAllowedToUseDevChannelAPIs( content::BrowserContext* browser_context, const GURL& url) { +#if BUILDFLAG(ENABLE_PPAPI) // Allow access for tests. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePepperTesting)) { return true; } +#endif // BUILDFLAG(ENABLE_PPAPI) #if BUILDFLAG(ENABLE_EXTENSIONS) Profile* profile = Profile::FromBrowserContext(browser_context); @@ -275,9 +281,13 @@ void ChromeContentBrowserClientPluginsPart::DidCreatePpapiPlugin( content::BrowserPpapiHost* browser_host) { +#if BUILDFLAG(ENABLE_PPAPI) browser_host->GetPpapiHost()->AddHostFactoryFilter( std::unique_ptr<ppapi::host::HostFactory>( new ChromeBrowserPepperHostFactory(browser_host))); +#else + NOTREACHED(); +#endif // BUILDFLAG(ENABLE_PPAPI) } } // namespace plugins
diff --git a/chrome/browser/policy/networking/policy_cert_service_factory.cc b/chrome/browser/policy/networking/policy_cert_service_factory.cc index e5db3b6..ab4ff8c 100644 --- a/chrome/browser/policy/networking/policy_cert_service_factory.cc +++ b/chrome/browser/policy/networking/policy_cert_service_factory.cc
@@ -119,7 +119,7 @@ const std::string& user_email) { ListPrefUpdate update(g_browser_process->local_state(), prefs::kUsedPolicyCertificates); - return (update->EraseListValue(base::Value(user_email)) > 0); + return (update->GetList().EraseValue(base::Value(user_email)) > 0); } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/policy/networking/policy_cert_service_factory_ash_unittest.cc b/chrome/browser/policy/networking/policy_cert_service_factory_ash_unittest.cc index 9eeea69..3299290 100644 --- a/chrome/browser/policy/networking/policy_cert_service_factory_ash_unittest.cc +++ b/chrome/browser/policy/networking/policy_cert_service_factory_ash_unittest.cc
@@ -37,12 +37,12 @@ } void SetLocalState(std::vector<std::string> values) { - auto local_pref_value = std::make_unique<base::ListValue>(); + base::Value::List local_pref_value; for (auto&& value : values) { - local_pref_value->Append(base::Value(std::move(value))); + local_pref_value.Append(std::move(value)); } - local_state_.Get()->SetUserPref(prefs::kUsedPolicyCertificates, - std::move(local_pref_value)); + local_state_.Get()->SetList(prefs::kUsedPolicyCertificates, + std::move(local_pref_value)); } bool LocalStateContains(const char* value) {
diff --git a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc index e74e2518..e671021 100644 --- a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc +++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc
@@ -16,6 +16,7 @@ #include "components/google/core/common/google_util.h" #include "components/omnibox/browser/autocomplete_controller.h" #include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/base_search_provider.h" #include "components/omnibox/browser/omnibox_edit_model.h" #include "components/omnibox/browser/omnibox_view.h" #include "components/omnibox/common/omnibox_features.h" @@ -31,15 +32,26 @@ return url == GURL(chrome::kChromeUINewTabPageURL); } +// Returns whether or not the given URL represents a prefetch-eligible Web page. +bool IsEligibleWebPage(const GURL& url) { + return BaseSearchProvider::CanSendPageURLInRequest(url); +} + // Returns whether or not the given URL is eligible for ZPS prefetching. bool IsURLEligibleForZPSPrefetching(const GURL& url) { - bool is_ntp = - base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching) && - IsNTP(url); - bool is_srp = - base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) && - google_util::IsGoogleSearchUrl(url); - return is_ntp || is_srp; + if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching) && + IsNTP(url)) { + return true; + } else if (base::FeatureList::IsEnabled( + omnibox::kZeroSuggestPrefetchingOnSRP) && + google_util::IsGoogleSearchUrl(url)) { + return true; + } else if (base::FeatureList::IsEnabled( + omnibox::kZeroSuggestPrefetchingOnWeb) && + IsEligibleWebPage(url)) { + return true; + } + return false; } // Starts prefetching zero-prefix suggestions using the AutocompleteController @@ -52,13 +64,18 @@ auto* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); - auto page_classification = - IsNTP(page_url) - ? OEP::NTP_ZPS_PREFETCH - : (google_util::IsGoogleSearchUrl(page_url) ? OEP::SRP_ZPS_PREFETCH - : OEP::INVALID_SPEC); + + OEP::PageClassification page_classification = OEP::INVALID_SPEC; + if (IsNTP(page_url)) { + page_classification = OEP::NTP_ZPS_PREFETCH; + } else if (google_util::IsGoogleSearchUrl(page_url)) { + page_classification = OEP::SRP_ZPS_PREFETCH; + } else if (IsEligibleWebPage(page_url)) { + page_classification = OEP::OTHER_ZPS_PREFETCH; + } DCHECK(page_classification != OEP::INVALID_SPEC) << "Prefetch page classification undefined for given URL."; + AutocompleteInput autocomplete_input( u"", page_classification, ChromeAutocompleteSchemeClassifier(profile)); autocomplete_input.set_focus_type(OmniboxFocusType::ON_FOCUS);
diff --git a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc index fa4855c..0f05fe49 100644 --- a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc +++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
@@ -45,13 +45,6 @@ } // namespace class ZeroSuggestPrefetchTabHelperBrowserTest : public InProcessBrowserTest { - public: - ZeroSuggestPrefetchTabHelperBrowserTest() { - feature_list_.InitWithFeatures({omnibox::kZeroSuggestPrefetching, - omnibox::kZeroSuggestPrefetchingOnSRP}, - {}); - } - protected: void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); @@ -80,9 +73,33 @@ raw_ptr<testing::NiceMock<MockAutocompleteController>> controller_; }; +class ZeroSuggestPrefetchTabHelperBrowserTestOnNTP + : public ZeroSuggestPrefetchTabHelperBrowserTest { + public: + ZeroSuggestPrefetchTabHelperBrowserTestOnNTP() { + feature_list_.InitWithFeatures({omnibox::kZeroSuggestPrefetching}, {}); + } +}; + +class ZeroSuggestPrefetchTabHelperBrowserTestOnSRP + : public ZeroSuggestPrefetchTabHelperBrowserTest { + public: + ZeroSuggestPrefetchTabHelperBrowserTestOnSRP() { + feature_list_.InitWithFeatures({omnibox::kZeroSuggestPrefetchingOnSRP}, {}); + } +}; + +class ZeroSuggestPrefetchTabHelperBrowserTestOnWeb + : public ZeroSuggestPrefetchTabHelperBrowserTest { + public: + ZeroSuggestPrefetchTabHelperBrowserTestOnWeb() { + feature_list_.InitWithFeatures({omnibox::kZeroSuggestPrefetchingOnWeb}, {}); + } +}; + // Tests that navigating to or switching to the NTP starts a prefetch request. -IN_PROC_BROWSER_TEST_F(ZeroSuggestPrefetchTabHelperBrowserTest, - StartPrefetchOnNTP) { +IN_PROC_BROWSER_TEST_F(ZeroSuggestPrefetchTabHelperBrowserTestOnNTP, + StartPrefetch) { { // Opening a background NTP triggers prefetching. EXPECT_CALL(*controller_, StartPrefetch).Times(1); @@ -147,8 +164,8 @@ } // Tests that navigating to or switching to the SRP starts a prefetch request. -IN_PROC_BROWSER_TEST_F(ZeroSuggestPrefetchTabHelperBrowserTest, - StartPrefetchOnSRP) { +IN_PROC_BROWSER_TEST_F(ZeroSuggestPrefetchTabHelperBrowserTestOnSRP, + StartPrefetch) { const std::string srp_url = "https://www.google.com/search?q=hello+world"; { // Opening a background SRP triggers prefetching. @@ -175,7 +192,8 @@ testing::Mock::VerifyAndClearExpectations(controller_); } { - // Navigating to a url in a new foreground tab does not trigger prefetching. + // Navigating to a Web url in a new foreground tab does not trigger + // prefetching. EXPECT_CALL(*controller_, StartPrefetch).Times(0); EXPECT_CALL(*controller_, Start).Times(0); @@ -209,3 +227,69 @@ testing::Mock::VerifyAndClearExpectations(controller_); } } + +// Tests that navigating to or switching to a Web URL (non-NTP/non-SRP) starts a +// prefetch request. +IN_PROC_BROWSER_TEST_F(ZeroSuggestPrefetchTabHelperBrowserTestOnWeb, + StartPrefetch) { + const std::string web_url = "https://www.example.com"; + { + // Opening a background Web page triggers prefetching. + EXPECT_CALL(*controller_, StartPrefetch).Times(1); + EXPECT_CALL(*controller_, Start).Times(0); + + EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(web_url), WindowOpenDisposition::NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); + ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + + testing::Mock::VerifyAndClearExpectations(controller_); + } + { + // Opening a foreground Web page triggers prefetching. + EXPECT_CALL(*controller_, StartPrefetch).Times(1); + EXPECT_CALL(*controller_, Start).Times(0); + + EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(web_url), WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); + ASSERT_EQ(3, browser()->tab_strip_model()->GetTabCount()); + + testing::Mock::VerifyAndClearExpectations(controller_); + } + { + // Navigating to an ineligible url in a new foreground tab does not trigger + // prefetching. + EXPECT_CALL(*controller_, StartPrefetch).Times(0); + EXPECT_CALL(*controller_, Start).Times(0); + + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL("file://www.example.com"), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_NONE); + ASSERT_EQ(4, browser()->tab_strip_model()->GetTabCount()); + + testing::Mock::VerifyAndClearExpectations(controller_); + } + { + // Navigating to the Web in the current tab triggers prefetching. + EXPECT_CALL(*controller_, StartPrefetch).Times(1); + EXPECT_CALL(*controller_, Start).Times(0); + + EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(web_url), WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); + ASSERT_EQ(4, browser()->tab_strip_model()->GetTabCount()); + + testing::Mock::VerifyAndClearExpectations(controller_); + } + { + // Switching to a Web tab triggers prefetching. + EXPECT_CALL(*controller_, StartPrefetch).Times(1); + EXPECT_CALL(*controller_, Start).Times(0); + + browser()->tab_strip_model()->ActivateTabAt(1); + + testing::Mock::VerifyAndClearExpectations(controller_); + } +}
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 1bf7f1e..66d9176 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -255,6 +255,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" #include "ash/public/cpp/clipboard_history_controller.h" +#include "ash/public/cpp/new_window_delegate.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.h" #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h" @@ -2844,12 +2845,29 @@ break; case IDC_CONTENT_CONTEXT_SEARCHWEBFOR: - case IDC_CONTENT_CONTEXT_GOTOURL: - OpenURL(selection_navigation_url_, GURL(), - ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB), + case IDC_CONTENT_CONTEXT_GOTOURL: { + auto disposition = ui::DispositionFromEventFlags( + event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB); +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (!crosapi::browser_util::IsAshWebBrowserEnabled()) { + // TODO(neis): Support the other possible dispositions in crosapi and + // then preserve them here. + auto nwd_disposition = + ash::NewWindowDelegate::Disposition::kNewForegroundTab; + if (disposition == WindowOpenDisposition::NEW_WINDOW) { + nwd_disposition = ash::NewWindowDelegate::Disposition::kNewWindow; + } + ash::NewWindowDelegate::GetPrimary()->OpenUrl( + selection_navigation_url_, + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + nwd_disposition); + break; + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + OpenURL(selection_navigation_url_, GURL(), disposition, ui::PAGE_TRANSITION_LINK); break; + } case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: ExecLanguageSettings(event_flags);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index f3922ce1..4456d7f 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -117,6 +117,7 @@ "common/braille/braille_key_types.js", "common/braille/braille_table.js", "common/braille/nav_braille.js", + "common/bridge_callback_manager.js", "common/bridge_constants.js", "common/bridge_helper.js", "common/command_store.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js index 9178bff4..20f1683 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -418,10 +418,9 @@ AutomationUtil.getUniqueAncestors(prevRange.start.node, start); entered - .filter(f => { - return f.role === RoleType.PLUGIN_OBJECT || - f.role === RoleType.IFRAME; - }) + .filter( + ancestor => ancestor.role === RoleType.PLUGIN_OBJECT || + ancestor.role === RoleType.IFRAME) .forEach(container => { if (!container.state[StateType.FOCUSED]) { container.focus();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_input_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_input_handler_test.js index 6f0af8a..8d75eff 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_input_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_input_handler_test.js
@@ -177,11 +177,8 @@ const grabExtraCells = () => { const span = content.getSpanInstanceOf(ExtraCellsSpan); assertNotEquals(null, span); - // Convert the ArrayBuffer to a normal array for easier comparision. - this.extraCells_ = - Array.prototype.map.call(new Uint8Array(span.cells), function(a) { - return a; - }); + // Convert the ArrayBuffer to a normal array for easier comparison. + this.extraCells_ = Array.from(new Uint8Array(span.cells)); }; this.inputHandler_.onDisplayContentChanged(content, grabExtraCells); grabExtraCells(); @@ -304,7 +301,7 @@ */ constructor(table, opt_capitalize) { /** @private */ - this.table_ = table.map(function(entry) { + this.table_ = table.map(entry => { let cells = entry[0]; const result = []; if (cells[0] === '^') { @@ -411,7 +408,7 @@ if (!cells) { return []; } - return cells.split(/\s+/).map(function(cellString) { + return cells.split(/\s+/).map(cellString => { let cell = 0; assertTrue(cellString.length > 0); if (cellString !== '0') {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js index 9b19e29..2612234 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js
@@ -79,15 +79,13 @@ const currentLocale = chrome.i18n.getMessage('@@ui_locale').split(/[_-]/); const major = currentLocale[0]; const minor = currentLocale[1]; - const firstPass = tables.filter(function(table) { - return table.locale.split(/[_-]/)[0] === major; - }); + const firstPass = + tables.filter(table => table.locale.split(/[_-]/)[0] === major); if (firstPass.length > 0) { table = firstPass[0]; if (minor) { - const secondPass = firstPass.filter(function(table) { - return table.locale.split(/[_-]/)[1] === minor; - }); + const secondPass = firstPass.filter( + table => table.locale.split(/[_-]/)[1] === minor); if (secondPass.length > 0) { table = secondPass[0]; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js index bc72a54..f3dd7a0d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js
@@ -46,9 +46,7 @@ const tables = this.translatorManager.getTablesForTest(); let result = null; if (tables != null) { - const found = tables.filter(function(table) { - return table.fileNames === fileNames; - })[0]; + const found = tables.filter(table => table.fileNames === fileNames)[0]; if (found) { result = new FakeTranslator(found); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/expanding_braille_translator_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/expanding_braille_translator_test.js index 1479786..373052c9 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/expanding_braille_translator_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/expanding_braille_translator_test.js
@@ -313,9 +313,8 @@ contractedOutput: 'uuuuuucuuuuuu', }, ]; - const TESTDATA_WITH_SELECTION = TESTDATA.filter(function(testCase) { - return testCase.input.getSpanInstanceOf(ValueSelectionSpan); - }); + const TESTDATA_WITH_SELECTION = TESTDATA.filter( + testCase => testCase.input.getSpanInstanceOf(ValueSelectionSpan)); const expType = ExpandingBrailleTranslator.ExpansionType; for (let i = 0, testCase; testCase = TESTDATA[i]; ++i) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js index 4b4b42e..4918e282 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -98,14 +98,12 @@ chrome.automation.getDesktop(function(d) { // First, try speaking the on-screen time. const allTime = d.findAll({role: RoleType.TIME}); - allTime.filter(function(t) { - return t.root.role === RoleType.DESKTOP; - }); + allTime.filter(time => time.root.role === RoleType.DESKTOP); let timeString = ''; - allTime.forEach(function(t) { - if (t.name) { - timeString = t.name; + allTime.forEach(time => { + if (time.name) { + timeString = time.name; } }); if (timeString) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/earcon_engine.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/earcon_engine.js index 1d421a48..222ec18 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/earcon_engine.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/earcon_engine.js
@@ -134,11 +134,10 @@ // Initialization: load the base sound data files asynchronously. const allSoundFilesToLoad = EarconEngine.SOUNDS.concat(EarconEngine.REVERBS); - allSoundFilesToLoad.forEach((function(sound) { - const url = - EarconEngine.BASE_URL + sound + '.wav'; - this.loadSound(sound, url); - }).bind(this)); + allSoundFilesToLoad.forEach(sound => { + const url = `${EarconEngine.BASE_URL}${sound}.wav`; + this.loadSound(sound, url); + }); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js index 083574c..fcafb37 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js
@@ -224,7 +224,9 @@ // as follows. let textCountBeforeLineStart = 0; let finder = lineStart; - while (finder.previousSibling) { + while (finder.previousSibling && + (EditableLine.includeOffscreen || + !finder.previousSibling.state[StateType.OFFSCREEN])) { finder = finder.previousSibling; textCountBeforeLineStart += finder.name ? finder.name.length : 0; } @@ -273,7 +275,9 @@ // as follows. let textCountAfterLineEnd = 0; let finder = lineEnd; - while (finder.nextSibling) { + while (finder.nextSibling && + (EditableLine.includeOffscreen || + !finder.nextSibling.state[StateType.OFFSCREEN])) { finder = finder.nextSibling; textCountAfterLineEnd += finder.name ? finder.name.length : 0; } @@ -719,3 +723,10 @@ return new CursorRange(start, end); } } + +/** + * Controls whether line computations include offscreen inline text boxes. Note + * that a caller should have this set prior to creating a line. + * @public {boolean} + */ +EditableLine.includeOffscreen = true;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js index 4d0c987a..cbced16 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
@@ -65,6 +65,8 @@ this.inferredIntents_ = []; chrome.automation.getDesktop(function(desktop) { + const isTextArea = node.htmlTag === 'textarea'; + // ChromeVox handles two general groups of text fields: // A rich text field is one where selection gets placed on a DOM // descendant to a root text field. This is one of: @@ -87,7 +89,18 @@ (node.state[StateType.EDITABLE] && node.htmlAttributes && node.htmlAttributes['contenteditable'] !== undefined && node.htmlAttributes['contenteditable'] !== 'false') || - node.htmlTag === 'textarea'; + isTextArea; + + // Prior to creating the specific editable text handler, ensure that text + // areas exclude offscreen elements in line computations. This is because + // text areas from Blink expose a single large static text node which can + // have thousands or more inline text boxes. This is a very specific check + // because ignoring offscreen nodes can impact the way in which we convert + // from a tree position to a deep equivalent on the inline text boxes. + const MAX_INLINE_TEXT_BOXES = 500; + const firstStaticText = node.find({role: RoleType.STATIC_TEXT}); + EditableLine.includeOffscreen = !isTextArea || !firstStaticText || + firstStaticText.children.length < MAX_INLINE_TEXT_BOXES; this.editableText_ = useRichText ? new AutomationRichEditableText(node) : new AutomationEditableText(node); @@ -694,7 +707,7 @@ if (!this.node_.constructor) { return; } - value.getSpansInstanceOf(this.node_.constructor).forEach(function(span) { + value.getSpansInstanceOf(this.node_.constructor).forEach(span => { const style = span.role === RoleType.INLINE_TEXT_BOX ? span.parent : span; if (!style) { return; @@ -819,7 +832,7 @@ } if (msgs.length) { - msgs.forEach(function(msg) { + msgs.forEach(msg => { ChromeVox.tts.speak( Msgs.getMsg(msg), QueueMode.QUEUE, AbstractTts.PERSONALITY_ANNOTATION); @@ -889,9 +902,9 @@ } if (msgs.length) { - msgs.forEach(function(obj) { + msgs.forEach(msgObject => { ChromeVox.tts.speak( - Msgs.getMsg(obj.msg, obj.opt_subs), QueueMode.QUEUE, + Msgs.getMsg(msgObject.msg, msgObject.opt_subs), QueueMode.QUEUE, AbstractTts.PERSONALITY_ANNOTATION); }); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js index 806efee..8e56078 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
@@ -11,10 +11,6 @@ * Test fixture for editing tests. */ ChromeVoxEditingTest = class extends ChromeVoxNextE2ETest { - constructor() { - super(); - } - /** @override */ async setUpDeferred() { await super.setUpDeferred(); @@ -2347,3 +2343,35 @@ await mockFeedback.replay(); }); + +// Regression test that large text areas produce output. +AX_TEST_F('ChromeVoxEditingTest', 'GiantTextAreaPerformance', async function() { + const mockFeedback = this.createMockFeedback(); + const site = ` + <p>start</p> + <textarea></textarea> + <script> + const codepointCount = 35536 * 10; + const greeking1024Codepoints = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua elit.'; + + let value = ''; + while (value.length < codepointCount) { + value += greeking1024Codepoints; + } + let textarea = document.querySelector('textarea'); + textarea.value = value; + textarea.setSelectionRange(0, 0); + </script> + `; + const root = await this.runWithLoadedTree(site); + await this.focusFirstTextField(root); + + const textField = root.find({role: RoleType.TEXT_FIELD}); + mockFeedback.expectSpeech('Text area') + .call(this.press(KeyCode.DOWN)) + .expectSpeech('amet, consectetur') + .call(this.press(KeyCode.RIGHT)) + .expectSpeech('m') + + .replay(); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/find_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/find_handler.js index 6612116..bd4a2a9 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/find_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/find_handler.js
@@ -50,9 +50,8 @@ * @private */ onTextMatch_(evt) { - if (!evt.target.markers.some(function(marker) { - return marker.flags[chrome.automation.MarkerType.TEXT_MATCH]; - })) { + if (!evt.target.markers.some( + marker => marker.flags[chrome.automation.MarkerType.TEXT_MATCH])) { return; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/injected_script_loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/injected_script_loader.js index 3241d48..e252957 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/injected_script_loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/injected_script_loader.js
@@ -46,8 +46,6 @@ xhr.send(null); }; - files.forEach(function(f) { - loadScriptAsCode(f); - }); + files.forEach(file => loadScriptAsCode(file)); } }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js index 508376d..21067c4c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -207,9 +207,7 @@ * @return {boolean} True if there is only whitespace in this output. */ get isOnlyWhitespace() { - return this.speechBuffer_.every(function(buff) { - return !/\S+/.test(buff.toString()); - }); + return this.speechBuffer_.every(buff => !/\S+/.test(buff.toString())); } /** @return {Spannable} */ @@ -529,9 +527,7 @@ speechProps.startCallback = function() { const actions = scopedBuff.getSpansInstanceOf(OutputAction); if (actions) { - actions.forEach(function(a) { - a.run(); - }); + actions.forEach(action => action.run()); } }; }()); @@ -978,9 +974,7 @@ options.annotation.push(token); if (node.name && (node.nameFrom !== NameFromType.CONTENTS || - node.children.every(function(child) { - return child.role === RoleType.STATIC_TEXT; - }))) { + node.children.every(child => child.role === RoleType.STATIC_TEXT))) { this.append_(buff, node.name || '', options); ruleStr.writeTokenWithValue(token, node.name); } else { @@ -1092,18 +1086,18 @@ */ formatState_(node, token, buff, ruleStr) { if (node.state) { - Object.getOwnPropertyNames(node.state).forEach(function(s) { - const stateInfo = Output.STATE_INFO_[s]; + Object.getOwnPropertyNames(node.state).forEach(state => { + const stateInfo = Output.STATE_INFO_[state]; if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on) { ruleStr.writeToken(token); this.format_({ node, - outputFormat: '$' + s, + outputFormat: '$' + state, outputBuffer: buff, outputRuleString: ruleStr, }); } - }.bind(this)); + }); } } @@ -1567,13 +1561,13 @@ } // Tokens can have substitutions. const pieces = token.split('+'); - token = pieces.reduce(function(prev, cur) { + token = pieces.reduce((prev, cur) => { let lookup = cur; if (cur[0] === '$') { lookup = node[cur.slice(1)]; } return prev + lookup; - }.bind(this), ''); + }, ''); const msgId = token; let msgArgs = []; ruleStr.write(token + '{'); @@ -2354,33 +2348,30 @@ // Reject empty values without meaningful annotations. if ((!value || value.length === 0) && - opt_options.annotation.every(function(a) { - return !(a instanceof OutputAction) && - !(a instanceof OutputSelectionSpan); - })) { + opt_options.annotation.every( + annotation => !(annotation instanceof OutputAction) && + !(annotation instanceof OutputSelectionSpan))) { return; } const spannableToAdd = new Spannable(value); - opt_options.annotation.forEach(function(a) { - spannableToAdd.setSpan(a, 0, spannableToAdd.length); - }); + opt_options.annotation.forEach( + annotation => + spannableToAdd.setSpan(annotation, 0, spannableToAdd.length)); // |isUnique| specifies an annotation that cannot be duplicated. if (opt_options.isUnique) { - const annotationSansNodes = - opt_options.annotation.filter(function(annotation) { - return !(annotation instanceof OutputNodeSpan); - }); + const annotationSansNodes = opt_options.annotation.filter( + annotation => !(annotation instanceof OutputNodeSpan)); - const alreadyAnnotated = buff.some(function(s) { - return annotationSansNodes.some(function(annotation) { - if (!s.hasSpan(annotation)) { + const alreadyAnnotated = buff.some(spannable => { + annotationSansNodes.some(annotation => { + if (!spannable.hasSpan(annotation)) { return false; } - const start = s.getSpanStart(annotation); - const end = s.getSpanEnd(annotation); - const substr = s.substring(start, end); + const start = spannable.getSpanStart(annotation); + const end = spannable.getSpanEnd(annotation); + const substr = spannable.substring(start, end); if (substr && value) { return substr.toString() === value.toString(); } else { @@ -2406,7 +2397,7 @@ let separator = ''; // Changes to space as appropriate. let prevHasInlineNode = false; let prevIsName = false; - return spans.reduce(function(result, cur) { + return spans.reduce((result, cur) => { // Ignore empty spans except when they contain a selection. const hasSelection = cur.getSpanInstanceOf(OutputSelectionSpan); if (cur.length === 0 && !hasSelection) { @@ -2425,12 +2416,12 @@ // Keep track of if there's an inline node associated with // |cur|. const hasInlineNode = - cur.getSpansInstanceOf(OutputNodeSpan).some(function(s) { - if (!s.node) { + cur.getSpansInstanceOf(OutputNodeSpan).some(spannable => { + if (!spannable.node) { return false; } - return s.node.display === 'inline' || - s.node.role === RoleType.INLINE_TEXT_BOX; + return spannable.node.display === 'inline' || + spannable.node.role === RoleType.INLINE_TEXT_BOX; }); const isName = cur.hasSpan('name'); @@ -2501,7 +2492,7 @@ * @return {string} */ toString() { - return this.speechBuffer_.reduce(function(prev, cur) { + return this.speechBuffer_.reduce((prev, cur) => { if (prev === null || prev === '') { return cur.toString(); } @@ -2515,7 +2506,7 @@ * @return {!Spannable} */ get speechOutputForTest() { - return this.speechBuffer_.reduce(function(prev, cur) { + return this.speechBuffer_.reduce((prev, cur) => { if (prev === null) { return cur; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js index 62a962c4..d9395e9e 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_test.js
@@ -14,9 +14,8 @@ // Remove string annotations. These are tested in the speech output and // there's no need to clutter the tests with the corresponding braille // annotations. - const actualSpans = actualOutput.spans_.filter(function(span) { - return (typeof span.value !== 'string'); - }); + const actualSpans = + actualOutput.spans_.filter(span => (typeof span.value !== 'string')); checkOutput_( expectedText, expectedSpans, actualOutput.toString(), actualSpans); } @@ -361,7 +360,7 @@ assertEquals(expectedSpeechValues.length, expectedBrailleValues.length); let el = root.firstChild.firstChild; - expectedSpeechValues.forEach(function(expectedValue) { + expectedSpeechValues.forEach(expectedValue => { const range = CursorRange.fromNode(el); const o = new Output().withoutHints().withSpeechAndBraille( range, null, 'navigate'); @@ -379,7 +378,7 @@ }); el = root.firstChild.firstChild; - expectedBrailleValues.forEach(function(expectedValue) { + expectedBrailleValues.forEach(expectedValue => { const range = CursorRange.fromNode(el); const o = new Output().withoutHints().withBraille(range, null, 'navigate'); if (typeof expectedValue === 'string') { @@ -1029,15 +1028,11 @@ RoleType.STATIC_TEXT, RoleType.WINDOW, ]; - missingState = missingState.filter(function(state) { - return notStated.indexOf(state) === -1; - }); - missingRestriction = missingRestriction.filter(function(restriction) { - return notRestricted.indexOf(restriction) === -1; - }); - missingDescription = missingDescription.filter(function(desc) { - return notDescribed.indexOf(desc) === -1; - }); + missingState = missingState.filter(state => notStated.indexOf(state) === -1); + missingRestriction = missingRestriction.filter( + restriction => notRestricted.indexOf(restriction) === -1); + missingDescription = + missingDescription.filter(desc => notDescribed.indexOf(desc) === -1); assertEquals( 0, missingState.length,
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js index a45b77c..c5d74bfa 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js
@@ -74,10 +74,6 @@ PanelBackground.instance.incrementalSearch_( searchStr, dir, opt_nextObject)); BridgeHelper.registerHandler( - Constants.TARGET, Constants.Action.NODE_MENU_CALLBACK, - callbackNodeIndex => - PanelNodeMenuBackground.focusNodeCallback(callbackNodeIndex)); - BridgeHelper.registerHandler( Constants.TARGET, Constants.Action.PERFORM_CUSTOM_ACTION_ON_CURRENT_NODE, actionId => PanelBackground.instance.performCustomActionOnCurrentNode_(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background.js index 39d1a1c..d9ba1450 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background.js
@@ -11,6 +11,8 @@ import {constants} from '../../../common/constants.js'; import {CursorRange} from '../../../common/cursors/range.js'; import {AutomationTreeWalker} from '../../../common/tree_walker.js'; +import {BridgeCallbackId} from '../../common/bridge_callback_manager.js'; +import {BridgeContext} from '../../common/bridge_constants.js'; import {Msgs} from '../../common/msgs.js'; import {PanelBridge} from '../../common/panel_bridge.js'; import {PanelNodeMenuData, PanelNodeMenuId, PanelNodeMenuItemData} from '../../common/panel_menu_data.js'; @@ -45,16 +47,6 @@ this.isEmpty_ = true; } - /** @param {number} callbackNodeIndex */ - static focusNodeCallback(callbackNodeIndex) { - if (!PanelNodeMenuBackground.callbackNodes_[callbackNodeIndex]) { - return; - } - ChromeVoxState.instance.navigateToRange(CursorRange.fromNode( - /** @type {!AutomationNode} */ ( - PanelNodeMenuBackground.callbackNodes_[callbackNodeIndex]))); - } - /** * Create the AutomationTreeWalker and kick off the search to find * nodes that match the predicate for this menu. @@ -101,11 +93,13 @@ output.withSpeech(range, range, OutputEventType.NAVIGATE); const title = output.toString(); - const callbackNodeIndex = PanelNodeMenuBackground.callbackNodes_.length; - PanelNodeMenuBackground.callbackNodes_.push(node); + const callbackId = new BridgeCallbackId( + BridgeContext.BACKGROUND, + () => ChromeVoxState.instance.navigateToRange( + CursorRange.fromNode(node))); const isActive = node === this.node_ && this.isActivated_; const menuId = this.menuId_; - this.addMenuItemFromData_({title, callbackNodeIndex, isActive, menuId}); + this.addMenuItemFromData_({title, callbackId, isActive, menuId}); } if (!this.isActivated_) { @@ -129,7 +123,7 @@ if (this.isEmpty_) { this.addMenuItemFromData_({ title: Msgs.getMsg('panel_menu_item_none'), - callbackNodeIndex: -1, + callbackId: null, isActive: false, menuId: this.menuId_, }); @@ -151,10 +145,3 @@ * @const {number} */ PanelNodeMenuBackground.MAX_NODES_BEFORE_ASYNC = 100; - -/** - * An array of nodes associated with a PanelNodeMenuItem, saved so we can - * set the current ChromeVox range when the user selects an item. - * @private {!Array<chrome.automation.AutomationNode>} - */ -PanelNodeMenuBackground.callbackNodes_ = [];
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js index 22b5a02c..77eafe5 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/tts_background.js
@@ -437,9 +437,8 @@ switch (event.type) { case 'start': - this.capturingTtsEventListeners_.forEach(function(listener) { - listener.onTtsStart(); - }); + this.capturingTtsEventListeners_.forEach( + listener => listener.onTtsStart()); if (utterance.properties['startCallback']) { try { utterance.properties['startCallback'](); @@ -450,9 +449,8 @@ case 'end': // End callbacks could cause additional speech to queue up. this.currentUtterance_ = null; - this.capturingTtsEventListeners_.forEach(function(listener) { - listener.onTtsEnd(); - }); + this.capturingTtsEventListeners_.forEach( + listener => listener.onTtsEnd()); if (utterance.properties['endCallback']) { try { utterance.properties['endCallback'](); @@ -468,9 +466,8 @@ this.cancelUtterance_(this.utteranceQueue_[i]); } this.utteranceQueue_.length = 0; - this.capturingTtsEventListeners_.forEach(function(listener) { - listener.onTtsInterrupted(); - }); + this.capturingTtsEventListeners_.forEach( + listener => listener.onTtsInterrupted()); break; case 'error': this.onError_(event['errorMessage']); @@ -579,9 +576,8 @@ (new PanelCommand(PanelCommandType.CLEAR_SPEECH)).send(); chrome.tts.stop(); - this.capturingTtsEventListeners_.forEach(function(listener) { - listener.onTtsInterrupted(); - }); + this.capturingTtsEventListeners_.forEach( + listener => listener.onTtsInterrupted()); } /** @override */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js index 5c59b80..549c1876 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
@@ -281,17 +281,6 @@ }, /** - * @param {number} callbackNodeIndex - * @return {!Promise} - */ - async nodeMenuCallback(callbackNodeIndex) { - return BridgeHelper.sendMessage( - BridgeConstants.PanelBackground.TARGET, - BridgeConstants.PanelBackground.Action.NODE_MENU_CALLBACK, - callbackNodeIndex); - }, - - /** * @param {number} actionId * @return {!Promise} */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js index a619283..83ded41 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js
@@ -23,9 +23,7 @@ * @return {number} */ BrailleCommandData.makeDotPattern = function(dots) { - return dots.reduce(function(p, c) { - return p | (1 << c - 1); - }, 0); + return dots.reduce((pattern, cell) => pattern | (1 << cell - 1), 0); }; /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js index 390a534e..7d485b7 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js
@@ -46,7 +46,7 @@ BrailleTable.getAll = function(callback) { const needsDisambiguation = new Map(); function preprocess(tables) { - tables.forEach(function(table) { + tables.forEach(table => { // Append the common definitions to all table filenames. table.fileNames += (',' + BrailleTable.COMMON_DEFS_FILENAME_); @@ -95,10 +95,7 @@ * @return {BrailleTable.Table} The found table, or null if not found. */ BrailleTable.forId = function(tables, id) { - return tables.filter(function(table) { - return table.id === id; - })[0] || - null; + return tables.filter(table => table.id === id)[0] || null; };
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_callback_manager.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_callback_manager.js new file mode 100644 index 0000000..5c204e31 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_callback_manager.js
@@ -0,0 +1,104 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Manages callbacks across contexts by saving them and replacing + * them with BridgeCallbackIds. + */ + +import {BridgeAction, BridgeConstants, BridgeContext, BridgeTarget} from './bridge_constants.js'; +import {BridgeHelper} from './bridge_helper.js'; + +/** @type {!BridgeAction} */ +const CALLBACK_ACTION = 'callback'; + +/** + * @param {!BridgeContext} context + * @return {!BridgeTarget} + */ +function getCallbackTargetForContext(context) { + return /** @type {!BridgeTarget} */ ('callback_' + context); +} + +export const BridgeCallbackManager = { + /** @private {!Array<?function(*)>} */ + callbacks_: [], + + /** @private {boolean} */ + initialized_: false, + + /** + * This function is used by BridgeCallbackId to save the callback. + * All other classes should save callbacks by creating a new BridgeCallbackId + * rather than calling this function. + * + * @param {function(*)} callback + * @param {!BridgeContext} context The current context. + * @return {number} The index of the given callback in the array. + */ + addCallbackInternal(callback, context) { + const index = BridgeCallbackManager.callbacks_.length; + BridgeCallbackManager.callbacks_.push(callback); + + if (!BridgeCallbackManager.initialized_) { + BridgeCallbackManager.startListening_(context); + } + + return index; + }, + + /** + * @param {!BridgeCallbackId} callbackId + * + * Any arguments to be passed to the callback can be appended to the function. + * They will be converted to JSON in the message passing process, and so + * functions cannot be passed, type information will be stripped (so methods + * are no longer available), and source data cannot be directly modified. + * + * @return {!Promise} + */ + performCallback(callbackId, ...args) { + return BridgeHelper.sendMessage( + getCallbackTargetForContext(callbackId.context), CALLBACK_ACTION, + callbackId, args); + }, + + /** + * @param {!BridgeContext} context + * @private + */ + startListening_(context) { + BridgeHelper.registerHandler( + getCallbackTargetForContext(context), CALLBACK_ACTION, + (callbackId, args) => { + // Replace the callback with null to maintain the other indices. + const callback = + BridgeCallbackManager.callbacks_.splice(callbackId.index, 1, null) + .pop(); // splice() returns an array of the removed items. + if (typeof callback === 'function') { + callback(...args); + } + + // If there are no callbacks remaining, reset the array. + if (!BridgeCallbackManager.callbacks_.some(c => Boolean(c))) { + BridgeCallbackManager.callbacks_ = []; + } + }); + BridgeCallbackManager.initialized_ = true; + }, +}; + +export class BridgeCallbackId { + /** + * @param {!BridgeContext} context + * @param {function(*)} callback + */ + constructor(context, callback) { + /** @public {!BridgeContext} */ + this.context = context; + + /** @public {number} */ + this.index = BridgeCallbackManager.addCallbackInternal(callback, context); + } +}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js index 63a6307..83ee1a7 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js
@@ -7,6 +7,20 @@ */ /** + * Specifies one of the renderer contexts for the ChromeVox extension. Code + * specific to each of these contexts is contained in the corresponding + * directory, while code used by two or more contexts is found in common/. + * @enum {string} + */ +export const BridgeContext = { + BACKGROUND: 'background', + LEARN_MODE: 'learnMode', + LOG_PAGE: 'logPage', + OPTIONS: 'options', + PANEL: 'panel', +}; + +/** * The class that a message is being sent to. * @typedef {string} */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/composite_tts.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/composite_tts.js index 9170eb9..66157beb 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/composite_tts.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/composite_tts.js
@@ -51,41 +51,34 @@ * @override */ isSpeaking() { - return this.ttsEngines_.some(function(engine) { - return engine.isSpeaking(); - }); + return this.ttsEngines_.some(engine => engine.isSpeaking()); } /** * @override */ stop() { - this.ttsEngines_.forEach(function(engine) { - engine.stop(); - }); + this.ttsEngines_.forEach(engine => engine.stop()); } /** @override */ addCapturingEventListener(listener) { - this.ttsEngines_.forEach(function(engine) { - engine.addCapturingEventListener(listener); - }); + this.ttsEngines_.forEach( + engine => engine.addCapturingEventListener(listener)); } /** @override */ removeCapturingEventListener(listener) { - this.ttsEngines_.forEach(function(engine) { - engine.removeCapturingEventListener(listener); - }); + this.ttsEngines_.forEach( + engine => engine.removeCapturingEventListener(listener)); } /** * @override */ increaseOrDecreaseProperty(propertyName, increase) { - this.ttsEngines_.forEach(function(engine) { - engine.increaseOrDecreaseProperty(propertyName, increase); - }); + this.ttsEngines_.forEach( + engine => engine.increaseOrDecreaseProperty(propertyName, increase)); } /** @@ -117,16 +110,13 @@ /** @override */ toggleSpeechOnOrOff() { let value = false; - this.ttsEngines_.forEach(function(engine) { - value = value || engine.toggleSpeechOnOrOff(); - }); + this.ttsEngines_.forEach( + engine => value = value || engine.toggleSpeechOnOrOff()); return value; } /** @override */ resetTextToSpeechSettings() { - this.ttsEngines_.forEach(function(engine) { - engine.resetTextToSpeechSettings(); - }); + this.ttsEngines_.forEach(engine => engine.resetTextToSpeechSettings()); } }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_map.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_map.js index 1e25abc4..5d5a6a56 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_map.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_map.js
@@ -59,9 +59,7 @@ * @return {Array<KeySequence>} Array of all keys. */ keys() { - return this.bindings_.map(function(binding) { - return binding.sequence; - }); + return this.bindings_.map(binding => binding.sequence); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_sequence.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_sequence.js index 9a707fbb..1b3fd10 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_sequence.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_sequence.js
@@ -312,26 +312,22 @@ // For each modifier that is held down, remove it from the combo. // If the combo string becomes empty, then the user has activated the combo. if (this.isKeyModifierActive(keyEvent, 'ctrlKey')) { - modifierKeyCombo = modifierKeyCombo.filter(function(modifier) { - return modifier !== 'Ctrl'; - }); + modifierKeyCombo = + modifierKeyCombo.filter(modifier => modifier !== 'Ctrl'); } if (this.isKeyModifierActive(keyEvent, 'altKey')) { - modifierKeyCombo = modifierKeyCombo.filter(function(modifier) { - return modifier !== 'Alt'; - }); + modifierKeyCombo = + modifierKeyCombo.filter(modifier => modifier !== 'Alt'); } if (this.isKeyModifierActive(keyEvent, 'shiftKey')) { - modifierKeyCombo = modifierKeyCombo.filter(function(modifier) { - return modifier !== 'Shift'; - }); + modifierKeyCombo = + modifierKeyCombo.filter(modifier => modifier !== 'Shift'); } if (this.isKeyModifierActive(keyEvent, 'metaKey') || this.isKeyModifierActive(keyEvent, 'searchKeyHeld')) { const metaKeyName = this.getMetaKeyName_(); - modifierKeyCombo = modifierKeyCombo.filter(function(modifier) { - return modifier !== metaKeyName; - }); + modifierKeyCombo = + modifierKeyCombo.filter(modifier => modifier !== metaKeyName); } return (modifierKeyCombo.length === 0); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_util.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_util.js index 3d9866044..204f029d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_util.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/key_util.js
@@ -145,9 +145,8 @@ */ static cvoxModKeyCodes() { const modKeyCombo = KeySequence.modKeyStr.split(/\+/g); - const modKeyCodes = modKeyCombo.map(function(keyString) { - return KeyUtil.modStringToKeyCode(keyString); - }); + const modKeyCodes = + modKeyCombo.map(keyString => KeyUtil.modStringToKeyCode(keyString)); return modKeyCodes; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/panel_menu_data.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/panel_menu_data.js index 569d800..765ad949 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/panel_menu_data.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/panel_menu_data.js
@@ -9,6 +9,8 @@ import {AutomationPredicate} from '../../common/automation_predicate.js'; +import {BridgeCallbackId} from './bridge_callback_manager.js'; + /** @enum {number} */ export const PanelNodeMenuId = { HEADING: 1, @@ -30,7 +32,7 @@ /** * @typedef {{ * title: string, - * callbackNodeIndex: number, + * callbackId: ?BridgeCallbackId, * isActive: boolean, * menuId: !PanelNodeMenuId * }}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/spannable.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/spannable.js index c9840fd..365201fb 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/spannable.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/spannable.js
@@ -105,10 +105,10 @@ const otherSpannable = /** @type {!Spannable} */ (other); const originalLength = this.length; this.string_ += otherSpannable.string_; - other.spans_.forEach(function(span) { - this.setSpan( - span.value, span.start + originalLength, span.end + originalLength); - }.bind(this)); + other.spans_.forEach( + span => this.setSpan( + span.value, span.start + originalLength, + span.end + originalLength)); } else if (typeof other === 'string') { this.string_ += /** @type {string} */ (other); } @@ -187,13 +187,9 @@ * @return {!Array<{start: number, end: number}>} */ getSpanIntervals(value) { - return this.spans_ - .filter(function(s) { - return s.value === value; - }) - .map(function(s) { - return {start: s.start, end: s.end}; - }); + return this.spans_.filter(span => span.value === value).map(span => { + return {start: span.start, end: span.end}; + }); } /** @@ -240,7 +236,7 @@ } const result = new Spannable(this.string_.substring(start, end)); - this.spans_.forEach(function(span) { + this.spans_.forEach(span => { if (span.start <= end && span.end >= start) { const newStart = Math.max(0, span.start - start); const newEnd = Math.min(end - start, span.end - start); @@ -312,7 +308,7 @@ const result = {}; result.string = this.string_; result.spans = []; - this.spans_.forEach(function(span) { + this.spans_.forEach(span => { const serializeInfo = serializableSpansByConstructor.get(span.value.constructor); if (serializeInfo) { @@ -345,7 +341,7 @@ throw new Error('Invalid spannable json object: no spans array'); } const result = new Spannable(obj.string); - result.spans_ = obj.spans.map(function(span) { + result.spans_ = obj.spans.map(span => { if (typeof span.type !== 'string') { throw new Error( 'Invalid span in spannable json object: type not a string');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/bluetooth_braille_display_manager.js b/chrome/browser/resources/chromeos/accessibility/chromevox/options/bluetooth_braille_display_manager.js index 330d80b..4c503783 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/bluetooth_braille_display_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/bluetooth_braille_display_manager.js
@@ -236,9 +236,8 @@ this.handlePreferredDisplayConnectionStateChanged(display); } }); - this.listeners_.forEach(listener => { - listener.onDisplayListChanged(displayList); - }); + this.listeners_.forEach( + listener => listener.onDisplayListChanged(displayList)); }); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js index 23ec8af..9745282c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js
@@ -267,9 +267,7 @@ select.innerHTML = ''; // TODO(plundblad): voiceName can actually be omitted in the TTS engine. // We should generate a name in that case. - voices.forEach(function(voice) { - voice.voiceName = voice.voiceName || ''; - }); + voices.forEach(voice => voice.voiceName = voice.voiceName || ''); voices.sort(function(a, b) { // Prefer Google tts voices over all others. if (a.extensionId === GOOGLE_TTS_EXTENSION_ID && @@ -291,9 +289,8 @@ return 0; }); addVoiceOption(Msgs.getMsg('system_voice'), constants.SYSTEM_VOICE); - voices.forEach(voice => { - addVoiceOption(voice.voiceName, voice.voiceName); - }); + voices.forEach( + voice => addVoiceOption(voice.voiceName, voice.voiceName)); }); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js index bb0c090..37abd82 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -607,10 +607,8 @@ if (cell.tagName === 'TD') { cell.className = 'highlighted-cell'; const companionIDs = cell.getAttribute('data-companionIDs'); - companionIDs.split(' ').map(function(companionID) { - const companion = $(companionID); - companion.className = 'highlighted-cell'; - }); + companionIDs.split(' ').forEach( + companionID => $(companionID).className = 'highlighted-cell'); } }; @@ -619,10 +617,8 @@ if (cell.tagName === 'TD') { cell.className = 'unhighlighted-cell'; const companionIDs = cell.getAttribute('data-companionIDs'); - companionIDs.split(' ').map(function(companionID) { - const companion = $(companionID); - companion.className = 'unhighlighted-cell'; - }); + companionIDs.split(' ').forEach( + companionID => $(companionID).className = 'unhighlighted-cell'); } };
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu.js index edc2e408..39c195fc 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu.js
@@ -6,6 +6,7 @@ * @fileoverview A drop-down menu in the ChromeVox panel. */ import {BackgroundBridge} from '../common/background_bridge.js'; +import {BridgeCallbackManager} from '../common/bridge_callback_manager.js'; import {Msgs} from '../common/msgs.js'; import {PanelNodeMenuItemData} from '../common/panel_menu_data.js'; @@ -327,10 +328,11 @@ /** @param {!PanelNodeMenuItemData} data */ addItemFromData(data) { - this.addMenuItem( - data.title, '', '', '', - () => BackgroundBridge.PanelBackground.nodeMenuCallback( - data.callbackNodeIndex)); + this.addMenuItem(data.title, '', '', '', () => { + if (data.callbackId) { + BridgeCallbackManager.performCallback(data.callbackId); + } + }); if (data.isActive) { this.activeIndex_ = this.items_.length - 1; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js index 0999998..f7a8803 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js
@@ -18,13 +18,13 @@ this.isCommonClass = opt_isCommonClass || false; if (this.runtimeDeps.length > 0) { - chrome.extension.getViews().forEach(function(w) { - this.runtimeDeps.forEach(function(dep) { - if (w[dep]) { - window[dep] = w[dep]; + chrome.extension.getViews().forEach(view => { + this.runtimeDeps.forEach(dep => { + if (view[dep]) { + window[dep] = view[dep]; } - }.bind(this)); - }.bind(this)); + }); + }); } this.originalOutputContextValues_ = {};
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js index 6ea775a..9143e06 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback.js
@@ -162,17 +162,15 @@ expectSpeech() { assertFalse( this.replaying_, 'expectSpeech: Should not already be replaying.'); - Array.prototype.forEach.call(arguments, function(text) { + Array.prototype.forEach.call(arguments, text => { this.pendingActions_.push({ - perform: function() { - return Boolean( - MockFeedback.matchAndConsume_(text, {}, this.pendingUtterances_)); - }.bind(this), + perform: () => Boolean( + MockFeedback.matchAndConsume_(text, {}, this.pendingUtterances_)), toString() { return 'Speak \'' + text + '\''; }, }); - }.bind(this)); + }); return this; } @@ -236,18 +234,16 @@ assertFalse( this.replaying_, 'expectSpeechWithProperties: Should not already be replaying.'); - Array.prototype.forEach.call(rest, function(text) { + Array.prototype.forEach.call(rest, text => { this.pendingActions_.push({ - perform: function() { - return Boolean(MockFeedback.matchAndConsume_( - text, expectedProps, this.pendingUtterances_)); - }.bind(this), + perform: () => Boolean(MockFeedback.matchAndConsume_( + text, expectedProps, this.pendingUtterances_)), toString() { return 'Speak \'' + text + '\' with props ' + JSON.stringify(expectedProps); }, }); - }.bind(this)); + }); return this; } @@ -267,9 +263,9 @@ assertFalse( this.replaying_, 'expectNextSpeechUtteranceIsNot: Should not already be replaying.'); - Array.prototype.forEach.call(arguments, function(text) { + Array.prototype.forEach.call(arguments, text => { this.pendingActions_.push({ - perform: function() { + perform: () => { if (this.pendingUtterances_.length === 0) { return false; } @@ -278,12 +274,12 @@ assertFalse(true, 'Got denied utterance "' + text + '".'); } return true; - }.bind(this), + }, toString() { return 'Do not speak \'' + text + '\''; }, }); - }.bind(this)); + }); return this; } @@ -491,16 +487,16 @@ if (list.length > 0) { console.log( 'Pending ' + desc + ':\n ' + - list.map(function(i) { - let ret = '\'' + i.text + '\''; - if ('properties' in i) { - ret += ' properties=' + JSON.stringify(i.properties); + list.map(pending => { + let ret = '\'' + pending.text + '\''; + if ('properties' in pending) { + ret += ' properties=' + JSON.stringify(pending.properties); } - if ('startIndex' in i) { - ret += ' startIndex=' + i.startIndex; + if ('startIndex' in pending) { + ret += ' startIndex=' + pending.startIndex; } - if ('endIndex' in i) { - ret += ' endIndex=' + i.endIndex; + if ('endIndex' in pending) { + ret += ' endIndex=' + pending.endIndex; } return ret; }) @@ -550,7 +546,7 @@ } if (candidate) { const consumed = pending.splice(0, i + 1); - consumed.forEach(function(item) { + consumed.forEach(item => { if (item.callback) { item.callback(); }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js index dba74b81..74c7f6e 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js +++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
@@ -11,6 +11,7 @@ import {AutomationUtil} from '../automation_util.js'; import {constants} from '../constants.js'; import {StringUtil} from '../string_util.js'; +import {AutomationTreeWalker} from '../tree_walker.js'; import {AncestryRecoveryStrategy, RecoveryStrategy} from './recovery_strategy.js'; @@ -523,14 +524,17 @@ // This offset is a text offset into the descendant visible // text. Approximate this by indexing into the inline text boxes. isTextIndex = true; - const lines = this.getAllLeaves_(newNode); - if (!lines.length) { - break; - } + + const walker = new AutomationTreeWalker(newNode, Dir.FORWARD, { + visit: n => !n.firstChild, + root: n => n === newNode, + }); let targetLine; let targetIndex = 0; - for (let i = 0, line, cur = 0; line = lines[i]; i++) { + let cur = 0; + while (walker.next().node) { + const line = walker.node; const lineLength = line.name ? line.name.length : 1; cur += lineLength; if (cur > newIndex) { @@ -546,7 +550,10 @@ if (!targetLine) { // If we got here, that means the index is actually beyond the total // length of text. Just get the last line. - targetLine = lines[lines.length - 1]; + targetLine = newNode.lastChild; + while (targetLine && targetLine.lastChild) { + targetLine = targetLine.lastChild; + } targetIndex = targetLine ? targetLine.name.length : CURSOR_NODE_INDEX; } newNode = targetLine; @@ -578,25 +585,6 @@ } /** - * @private - * @param {!AutomationNode} node - * @return {!Array<!AutomationNode>} - */ - getAllLeaves_(node) { - let ret = []; - if (!node.firstChild) { - ret.push(node); - return ret; - } - - for (let i = 0; i < node.children.length; i++) { - ret = ret.concat(this.getAllLeaves_(node.children[i])); - } - - return ret; - } - - /** * Returns true if this cursor was created after wrapping. For example, moving * from a cursor at the end of a web contents to [this] range at the beginning * of the document.
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/BUILD.gn index c20a129..f613cbf 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/BUILD.gn
@@ -25,6 +25,7 @@ mode = "copy" dest_dir = enhanced_network_tts_dir sources = [ + "background.html", "background.js", "enhanced_network_tts.js", ]
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/background.html b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/background.html new file mode 100644 index 0000000..b731534 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/background.html
@@ -0,0 +1,5 @@ +<!-- Global scripts. --> +<script src="/common/closure_shim.js"></script> + +<!-- Module entry point. --> +<script type="module" src="/enhanced_network_tts/background.js"></script>
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts_manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts_manifest.json.jinja2 index 010065d..adc69e06 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts_manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts_manifest.json.jinja2
@@ -10,7 +10,7 @@ "incognito": "split", {% endif %} "background": { - "scripts": ["enhanced_network_tts/background.js"] + "page": "enhanced_network_tts/background.html" }, "permissions": [ "ttsEngine"
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.js b/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.js index fff7d53..01f7cc53 100644 --- a/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.js +++ b/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.js
@@ -6,11 +6,11 @@ import 'chrome://resources/cr_components/chromeos/network/network_icon.m.js'; import 'chrome://resources/cr_components/chromeos/network/network_shared_css.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_page_host_style.css.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import './strings.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn index 466108a1..4adc9f7 100644 --- a/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn
@@ -114,6 +114,7 @@ "../../components/buttons:oobe_next_button.m", "../../components/buttons:oobe_text_button.m", "../../components/dialogs:oobe_modal_dialog.m", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog", ] extra_deps = [ ":offline_login_module" ] } @@ -192,7 +193,7 @@ js_file = "offline_login.js" html_file = "offline_login.html" html_type = "dom-module" - auto_imports = oobe_auto_imports + auto_imports = oobe_auto_imports + [ "ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html|CrDialogElement" ] migrated_imports = oobe_migrated_imports namespace_rewrites = oobe_namespace_rewrites }
diff --git a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js index 38d4115..3c955f75 100644 --- a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js +++ b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js
@@ -13,12 +13,12 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_page_host_style.css.js'; import 'chrome://resources/cr_elements/md_select_css.m.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import './strings.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 184cc040..2ee4e89 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -407,7 +407,6 @@ ":web_components", # Sub-folder targets - "ambient_mode_page:web_components", "bluetooth_page:web_components", "crostini_page:web_components", "date_time_page:web_components", @@ -445,7 +444,6 @@ group("closure_compile_module") { deps = [ ":closure_compile_local_module", - "ambient_mode_page:closure_compile_module", "bluetooth_page:closure_compile_module", "crostini_page:closure_compile_module", "date_time_page:closure_compile_module",
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn deleted file mode 100644 index 4041452..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn +++ /dev/null
@@ -1,119 +0,0 @@ -# Copyright 2020 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") -import("../os_settings.gni") - -js_type_check("closure_compile_module") { - closure_flags = os_settings_closure_flags - is_polymer3 = true - deps = [ - ":album_item", - ":album_list", - ":ambient_mode_browser_proxy", - ":ambient_mode_page", - ":ambient_mode_photos_page", - ":art_album_dialog", - ":text_with_tooltip", - ":topic_source_item", - ":topic_source_list", - ] -} - -js_library("constants") { -} - -js_library("ambient_mode_browser_proxy") { - deps = [ ":constants" ] - externs_list = [ "$externs_path/chrome_send.js" ] -} - -js_library("ambient_mode_page") { - deps = [ - ":ambient_mode_browser_proxy", - ":constants", - "..:deep_linking_behavior", - "..:os_route", - "..:prefs_behavior", - "..:route_observer_behavior", - "../..:router", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/js:i18n_behavior.m", - "//ui/webui/resources/js:web_ui_listener_behavior.m", - ] -} - -js_library("ambient_mode_photos_page") { - deps = [ - ":ambient_mode_browser_proxy", - ":constants", - "..:os_route", - "..:route_observer_behavior", - "../..:router", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js:i18n_behavior.m", - "//ui/webui/resources/js:load_time_data.m", - "//ui/webui/resources/js:web_ui_listener_behavior.m", - ] -} - -js_library("text_with_tooltip") { - deps = [ - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("topic_source_item") { - deps = [ - ":constants", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/js:i18n_behavior.m", - ] -} - -js_library("topic_source_list") { - deps = [ - ":constants", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("album_item") { - deps = [ - ":constants", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/js:i18n_behavior.m", - ] -} - -js_library("album_list") { - deps = [ - ":constants", - "..:global_scroll_target_behavior", - "..:os_route", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("art_album_dialog") { - deps = [ - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/js:i18n_behavior.m", - ] -} - -html_to_js("web_components") { - js_files = [ - "album_item.js", - "album_list.js", - "ambient_mode_page.js", - "ambient_mode_photos_page.js", - "art_album_dialog.js", - "text_with_tooltip.js", - "topic_source_item.js", - "topic_source_list.js", - ] -}
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.html deleted file mode 100644 index 28d7e27..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.html +++ /dev/null
@@ -1,196 +0,0 @@ -<style include="settings-shared cr-shared-style iron-flex"> - :host(:not([disabled])) { - cursor: default; - display: block; - outline: none; - } - - #albumContainer { - /* For a grid iron-list the list template item must have both a fixed - width and height. */ - height: 236px; - line-height: 20px; - } - - #albumContainer.personal-album { - margin: 8px 0; - width: 184px; - } - - #albumContainer.art-album { - margin: 8px auto; - width: 280px; - } - - #albumTitle { - color: var(--cros-text-color-primary); - } - - #albumDescription { - color: var(--cros-text-color-secondary); - } - - #imageContainer { - background-color: var(--cros-highlight-color); - border-radius: 8px; - display: block; - margin: 0 12px; - position: relative; - } - - #imageContainer.personal-album { - height: 160px; - width: 160px; - } - - #imageContainer.art-album { - height: 160px; - width: 256px; - } - - #albumInfo { - margin: 16px 12px 0 12px; - } - - #image { - border-color: var(--cros-separator-color); - border-radius: 8px; - display: block; - height: 160px; - object-fit: cover; - position: absolute; - transform: scale(1.0); - transition: transform 240ms; - } - - #image.personal-album { - width: 160px; - } - - #image.art-album { - width: 256px; - } - - #rhImages { - border-radius: 8px; - display: block; - height: 160px; - position: absolute; - transform: scale(1.0); - transition: transform 240ms; - width: 160px; - } - - .image-rh { - border-radius: 8px; - display: block; - height: 78px; - position: absolute; - width: 78px; - } - - .top-left { - left: 0; - top: 0; - } - - .top-right { - left: 82px; - top: 0; - } - - .bottom-left { - left: 0; - top: 82px; - } - - .bottom-right { - left: 82px; - top: 82px; - } - - .check { - display: block; - position: absolute; - z-index: 1; - } - - .check.personal-album { - left: 134px; - top: 6px; - } - - .check.art-album { - left: 230px; - top: 0; - } - - :host([checked]) #image { - transition: transform 240ms; - } - - :host([checked]) #image.personal-album { - transform: scale(0.8); - } - - :host([checked]) #image.art-album { - transform: scale(0.875); - } - - :host([checked]) #rhImages { - transform: scale(0.8); - } -</style> -<div id="albumContainer" class$="[[computeClass_(topicSource)]]"> - <div id="imageContainer" class$="[[computeClass_(topicSource)]]" - aria-hidden="true"> - <iron-media-query query="(prefers-color-scheme: dark)" - query-matches="{{isDarkModeActive_}}"> - </iron-media-query> - <!-- Only shows the images and icon when the URLs are successfully - fetched --> - <template is="dom-if" if="[[album.recentHighlightsUrls]]"> - <div id="rhImages" actionable on-click="onImageClick_"> - <img class="image-rh top-left" - src="[[album.recentHighlightsUrls.0]]" - hidden="[[!album.recentHighlightsUrls.0]]"> - </img> - <img class="image-rh top-right" - src="[[album.recentHighlightsUrls.1]]" - hidden="[[!album.recentHighlightsUrls.1]]"> - </img> - <img class="image-rh bottom-left" - src="[[album.recentHighlightsUrls.2]]" - hidden="[[!album.recentHighlightsUrls.2]]"> - </img> - <img class="image-rh bottom-right" - src="[[album.recentHighlightsUrls.3]]" - hidden="[[!album.recentHighlightsUrls.3]]"> - </img> - </div> - <iron-icon icon="[[computeCheckedIcon_(isDarkModeActive_)]]" - class$="check [[computeClass_(topicSource)]]" - hidden="[[!album.checked]]"> - </iron-icon> - </template> - <template is="dom-if" if="[[album.url]]"> - <img id="image" class$="[[computeClass_(topicSource)]]" actionable - src="[[album.url]]" on-click="onImageClick_"> - </img> - <iron-icon icon="[[computeCheckedIcon_(isDarkModeActive_)]]" - class$="check [[computeClass_(topicSource)]]" - hidden="[[!album.checked]]"> - </iron-icon> - </template> - </div> - - <div id="albumInfo" class$="[[computeClass_(topicSource)]]" - aria-hidden="true"> - <text-with-tooltip id="albumTitle" text="[[album.title]]" - tooltip-is-visible="{{titleTooltipIsVisible}}"></text-with-tooltip> - <text-with-tooltip id="albumDescription" - text="[[album.description]]" line-clamp="2" - tooltip-is-visible="{{descriptionTooltipIsVisible}}" - text-style="cr-secondary-text"></text-with-tooltip> - </div> -</div>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js deleted file mode 100644 index 7e51bb5..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_item.js +++ /dev/null
@@ -1,180 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying photos preview in a list. - */ - -import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js'; -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import './text_with_tooltip.js'; -import '../../settings_shared.css.js'; - -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {AmbientModeAlbum, AmbientModeTopicSource} from './constants.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const AlbumItemElementBase = mixinBehaviors([I18nBehavior], PolymerElement); - -/** @polymer */ -class AlbumItemElement extends AlbumItemElementBase { - static get is() { - return 'album-item'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** @type {?AmbientModeAlbum} */ - album: { - type: AmbientModeAlbum, - value: null, - }, - - /** @private {!AmbientModeTopicSource} */ - topicSource: Number, - - /** @private */ - checked: { - type: Boolean, - value: false, - reflectToAttribute: true, - notify: true, - }, - - /** Aria label for the album. */ - ariaLabel: { - type: String, - computed: 'computeAriaLabel_(album.*, checked)', - reflectToAttribute: true, - }, - - titleTooltipIsVisible: { - type: Boolean, - observer: 'tooltipVisibilityChanged_', - }, - - descriptionTooltipIsVisible: { - type: Boolean, - observer: 'tooltipVisibilityChanged_', - }, - - /** - * Whether dark mode is the active preferred color scheme. - * @private {boolean} - */ - isDarkModeActive_: { - type: Boolean, - value: false, - }, - }; - } - - ready() { - super.ready(); - this.addEventListener('keydown', this.onKeydown_); - } - - /** - * @return {string} Class name of album type. - * @private - */ - computeClass_() { - return this.topicSource === AmbientModeTopicSource.GOOGLE_PHOTOS ? - 'personal-album' : - 'art-album'; - } - - /** - * @return {string} Checked icon for album. - * @private - */ - computeCheckedIcon_() { - return this.isDarkModeActive_ ? 'os-settings:ic-checked-filled-dark' : - 'os-settings:ic-checked-filled'; - } - - /** - * @return {string} Aria label string for ChromeVox to verbalize. - * @private - */ - computeAriaLabel_() { - if (!this.album) { - return ''; - } - - if (this.album.checked) { - return this.i18n( - 'ambientModeAlbumsSubpageAlbumSelected', this.album.title, - this.album.description); - } - - return this.i18n( - 'ambientModeAlbumsSubpageAlbumUnselected', this.album.title, - this.album.description); - } - - /** - * @param {!Event} event - * @private - */ - onKeydown_(/** @type {!KeyboardEvent}*/ event) { - // The only key event handled by this element is pressing Enter. - if (event.key !== 'Enter') { - return; - } - - this.fireSelectedAlbumsChanged_(); - event.preventDefault(); - event.stopPropagation(); - } - - /** - * Because of the paper-tooltips anchored in this item exceed the bounds of - * #albumItem and each 'grid' item in iron-list has it's own stacking - * context, we need to adjust the z-index of the items relative to each - * other so that the tooltip is not covered by adjacent albumItems. - * @private - */ - tooltipVisibilityChanged_() { - const tooltipIsVisible = - this.titleTooltipIsVisible || this.descriptionTooltipIsVisible; - this.style.zIndex = tooltipIsVisible ? '1' : '0'; - } - - /** - * @param {!MouseEvent} event - * @private - */ - onImageClick_(event) { - this.fireSelectedAlbumsChanged_(); - event.preventDefault(); - event.stopPropagation(); - } - - /** - * Fires a 'selected-albums-changed' event with |this.album| as the details. - * @private - */ - fireSelectedAlbumsChanged_() { - this.checked = !this.checked; - const event = new CustomEvent( - 'selected-albums-changed', - {bubbles: true, composed: true, detail: this.album}); - this.dispatchEvent(event); - } -} - -customElements.define(AlbumItemElement.is, AlbumItemElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.html deleted file mode 100644 index 0016c47a..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.html +++ /dev/null
@@ -1,28 +0,0 @@ -<style include="settings-shared cr-shared-style iron-flex"> - :host { - display: block; - } - - paper-spinner-lite { - display: block; - height: 28px; - margin: 150px auto; - width: 28px; - } - - iron-list > :focus { - background-color: var(--cr-focused-item-color); - } -</style> -<paper-spinner-lite active="[[!albums]]" hidden="[[albums]]"> -</paper-spinner-lite> - -<iron-list scroll-target="[[subpageScrollTarget]]" - grid items="{{albums}}"> - <template> - <album-item album="{{item}}" checked="{{item.checked}}" - topic-source="[[topicSource]]" tabindex$="[[tabIndex]]" - role="checkbox"> - </album-item> - </template> -</iron-list>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js deleted file mode 100644 index 67ea169..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying a list of photo previews. - */ - -/** - * Polymer class definition for 'album-list'. - */ -import './album_item.js'; -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; -import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js'; -import '../../settings_shared.css.js'; - -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {Route} from '../../router.js'; -import {GlobalScrollTargetBehavior, GlobalScrollTargetBehaviorInterface} from '../global_scroll_target_behavior.js'; -import {routes} from '../os_route.js'; - -import {AmbientModeAlbum, AmbientModeTopicSource} from './constants.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {GlobalScrollTargetBehaviorInterface} - */ -const AlbumListElementBase = - mixinBehaviors([GlobalScrollTargetBehavior], PolymerElement); - -/** @polymer */ -class AlbumListElement extends AlbumListElementBase { - static get is() { - return 'album-list'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** @private {!AmbientModeTopicSource} */ - topicSource: { - type: Number, - value() { - return AmbientModeTopicSource.UNKNOWN; - }, - }, - - /** @private {?Array<!AmbientModeAlbum>} */ - albums: { - type: Array, - value: null, - notify: true, - }, - - /** - * Needed by GlobalScrollTargetBehavior. - * @type {Route} - * @override - */ - subpageRoute: { - type: Object, - value: routes.AMBIENT_MODE_PHOTOS, - }, - }; - } - - /** - * @return {boolean} - * @private - */ - isGooglePhotos_() { - return this.topicSource === AmbientModeTopicSource.GOOGLE_PHOTOS; - } -} - -customElements.define(AlbumListElement.is, AlbumListElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js deleted file mode 100644 index 0cfac730..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {AmbientModeSettings, AmbientModeTemperatureUnit, AmbientModeTopicSource} from './constants.js'; - -/** - * @fileoverview A helper object used from the ambient mode section to interact - * with the browser. - */ - -/** @interface */ -export class AmbientModeBrowserProxy { - /** - * Retrieves the AmbientModeTopicSource and AmbientModeTemperatureUnit from - * server. As a response, the C++ sends the 'topic-source-changed' and - * 'temperature-unit-changed' events. - */ - requestSettings() {} - - /** - * Retrieves the albums from server. As a response, the C++ sends either the - * 'albums-changed' WebUIListener event. - * @param {!AmbientModeTopicSource} topicSource the topic source for which - * the albums requested. - */ - requestAlbums(topicSource) {} - - /** - * Updates the selected temperature unit to server. - * @param {!AmbientModeTemperatureUnit} temperatureUnit - */ - setSelectedTemperatureUnit(temperatureUnit) {} - - /** - * Updates the selected albums of Google Photos or art categories to server. - * @param {!AmbientModeSettings} settings the selected albums or categeries. - */ - setSelectedAlbums(settings) {} -} - -/** @type {?AmbientModeBrowserProxy} */ -let instance = null; - -/** @implements {AmbientModeBrowserProxy} */ -export class AmbientModeBrowserProxyImpl { - /** @return {!AmbientModeBrowserProxy} */ - static getInstance() { - return instance || (instance = new AmbientModeBrowserProxyImpl()); - } - - /** @param {!AmbientModeBrowserProxy} obj */ - static setInstanceForTesting(obj) { - instance = obj; - } - - /** @override */ - requestSettings() { - chrome.send('requestSettings'); - } - - /** @override */ - requestAlbums(topicSource) { - chrome.send('requestAlbums', [topicSource]); - } - - /** @override */ - setSelectedTemperatureUnit(temperatureUnit) { - chrome.send('setSelectedTemperatureUnit', [temperatureUnit]); - } - - /** @override */ - setSelectedAlbums(settings) { - chrome.send('setSelectedAlbums', [settings]); - } -}
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html deleted file mode 100644 index a22b6c2..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html +++ /dev/null
@@ -1,91 +0,0 @@ -<style include="cr-shared-style settings-shared iron-flex"> - #ambientModeEnable { - border-bottom: var(--cr-separator-line); - border-top: var(--cr-separator-line); - } - - #pageDescription { - padding-inline-end: var(--cr-section-padding); - padding-inline-start: var(--cr-section-padding); - padding-top: 0; - } - - #topicSourceListDiv { - border-bottom: var(--cr-separator-line); - } - - /* Set padding on children instead of the container itself to ensure that - * separator lines can fill the entire width of the page. */ - #topicSourceListDiv > *, - #weatherDiv > * { - /* Padded to the right to allow space for a ripple */ - padding-inline-end: calc(var(--cr-section-padding) - - var(--cr-icon-ripple-padding)); - padding-inline-start: var(--cr-section-padding); - } - - #weatherTitle { - padding-bottom: 16px; - padding-top: 16px; - } - - .list-item { - padding-inline-start: var(--cr-section-padding); - } - - paper-spinner-lite { - display: block; - height: 28px; - margin: 100px auto; - width: 28px; - } -</style> -<h2 id="pageDescription"> - $i18n{ambientModePageDescription} -</h2> - -<settings-toggle-button id="ambientModeEnable" - class="primary-toggle" - pref="{{prefs.settings.ambient_mode.enabled}}" - label="[[getAmbientModeOnOffLabel_( - prefs.settings.ambient_mode.enabled.value)]]" - deep-link-focus-id$="[[Setting.kAmbientModeOnOff]]"> -</settings-toggle-button> - -<paper-spinner-lite active='[[!showSettings_]]' hidden='[[showSettings_]]'> -</paper-spinner-lite> - -<template is="dom-if" if="[[showSettings_]]"> - <div id="topicSourceListDiv" class="layout vertical flex" - aria-hidden="[[disableSettings_]]"> - <topic-source-list topic-sources="[[topicSources_]]" - selected-topic-source="[[selectedTopicSource_]]" - has-google-photos-albums="[[hasGooglePhotosAlbums_]]" - disabled='[[disableSettings_]]'> - </topic-source-list> - </div> - <div id="weatherDiv" class="layout vertical flex" - aria-hidden="[[disableSettings_]]"> - <h2 id="weatherTitle" aria-hidden="true"> - $i18n{ambientModeWeatherTitle} - </h2> - <div class="list-frame"> - <cr-radio-group - id="ambientTemperatureUnit" - selected="{{selectedTemperatureUnit_}}" - disabled$='[[disableSettings_]]' - aria-labelledby="weatherTitle"> - <cr-radio-button - name="[[AmbientModeTemperatureUnit_.FAHRENHEIT]]" - class="list-item underbar" - label="$i18n{ambientModeTemperatureUnitFahrenheit}"> - </cr-radio-button> - <cr-radio-button - name="[[AmbientModeTemperatureUnit_.CELSIUS]]" - class="list-item" - label="$i18n{ambientModeTemperatureUnitCelsius}"> - </cr-radio-button> - </cr-radio-group> - </div> - </div> -</template>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js deleted file mode 100644 index b5f378f..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js +++ /dev/null
@@ -1,284 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview 'settings-ambient-mode-page' is the settings page containing - * ambient mode settings. - */ -import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js'; -import './topic_source_list.js'; -import '../../prefs/prefs.js'; -import '../../controls/settings_radio_group.js'; -import '../../controls/settings_toggle_button.js'; -import '../../settings_shared.css.js'; - -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {afterNextRender, flush, html, 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 {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 {AmbientModeBrowserProxy, AmbientModeBrowserProxyImpl} from './ambient_mode_browser_proxy.js'; -import {AmbientModeTemperatureUnit, AmbientModeTopicSource, TopicSourceItem} from './constants.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {DeepLinkingBehaviorInterface} - * @implements {I18nBehaviorInterface} - * @implements {PrefsBehaviorInterface} - * @implements {RouteObserverBehaviorInterface} - * @implements {WebUIListenerBehaviorInterface} - */ -const SettingsAmbientModePageElementBase = mixinBehaviors( - [ - DeepLinkingBehavior, - I18nBehavior, - PrefsBehavior, - RouteObserverBehavior, - WebUIListenerBehavior, - ], - PolymerElement); - -/** @polymer */ -class SettingsAmbientModePageElement extends - SettingsAmbientModePageElementBase { - static get is() { - return 'settings-ambient-mode-page'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** Preferences state. */ - prefs: Object, - - /** - * Used to refer to the enum values in the HTML. - * @private {!Object} - */ - AmbientModeTopicSource: { - type: Object, - value: AmbientModeTopicSource, - }, - - /** - * Used to refer to the enum values in the HTML. - * @private {!Object<string, AmbientModeTemperatureUnit>} - */ - AmbientModeTemperatureUnit_: { - type: Object, - value: AmbientModeTemperatureUnit, - }, - - // TODO(b/160632748): Dynamically generate topic source of Google Photos. - /** @private {!Array<!AmbientModeTopicSource>} */ - topicSources_: { - type: Array, - value: [ - AmbientModeTopicSource.GOOGLE_PHOTOS, - AmbientModeTopicSource.ART_GALLERY, - ], - }, - - /** @private {!AmbientModeTopicSource} */ - selectedTopicSource_: { - type: AmbientModeTopicSource, - value: AmbientModeTopicSource.UNKNOWN, - }, - - /** @private */ - hasGooglePhotosAlbums_: Boolean, - - /** @private {!AmbientModeTemperatureUnit} */ - selectedTemperatureUnit_: { - type: AmbientModeTemperatureUnit, - value: AmbientModeTemperatureUnit.UNKNOWN, - observer: 'onSelectedTemperatureUnitChanged_', - }, - - /** - * Used by DeepLinkingBehavior to focus this page's deep links. - * @type {!Set<!Setting>} - */ - supportedSettingIds: { - type: Object, - value: () => new Set([ - Setting.kAmbientModeOnOff, - Setting.kAmbientModeSource, - ]), - }, - - /** @private */ - showSettings_: { - type: Boolean, - computed: 'computeShowSettings_(' + - 'selectedTopicSource_, selectedTemperatureUnit_)', - }, - - /** @private */ - disableSettings_: { - type: Boolean, - computed: 'computeDisableSettings_(prefs.settings.ambient_mode.*)', - }, - }; - } - - /** @override */ - constructor() { - super(); - - /** @private {!AmbientModeBrowserProxy} */ - this.browserProxy_ = AmbientModeBrowserProxyImpl.getInstance(); - } - - /** @override */ - ready() { - super.ready(); - - this.addWebUIListener( - 'topic-source-changed', - (/** @type {!TopicSourceItem} */ topicSourceItem) => { - this.selectedTopicSource_ = topicSourceItem.topicSource; - this.hasGooglePhotosAlbums_ = topicSourceItem.hasGooglePhotosAlbums; - }, - ); - this.addWebUIListener( - 'temperature-unit-changed', - (/** @type {!AmbientModeTemperatureUnit} */ temperatureUnit) => { - this.selectedTemperatureUnit_ = temperatureUnit; - }, - ); - - this.addEventListener('show-albums', this.onShowAlbums_); - } - - /** - * Overridden from DeepLinkingBehavior. - * @param {!Setting} settingId - */ - beforeDeepLinkAttempt(settingId) { - if (settingId !== Setting.kAmbientModeSource) { - // Continue with deep link attempt. - return true; - } - - // Wait for element to load. - afterNextRender(this, () => { - flush(); - - const topicList = this.shadowRoot.querySelector('topic-source-list'); - const listItem = - topicList && topicList.shadowRoot.querySelector('topic-source-item'); - if (listItem) { - this.showDeepLinkElement(listItem); - return; - } - - console.warn(`Element with deep link id ${settingId} not focusable.`); - }); - // Stop deep link attempt since we completed it manually. - return false; - } - - /** - * RouteObserverBehavior - * @param {!Route} currentRoute - * @param {!Route=} prevRoute - * @protected - */ - currentRouteChanged(currentRoute, prevRoute) { - if (currentRoute !== routes.AMBIENT_MODE) { - return; - } - - this.browserProxy_.requestSettings(); - this.attemptDeepLink(); - } - - /** - * @param {boolean} toggleValue - * @return {string} - * @private - */ - getAmbientModeOnOffLabel_(toggleValue) { - return this.i18n(toggleValue ? 'ambientModeOn' : 'ambientModeOff'); - } - - /** - * @param {!AmbientModeTemperatureUnit} temperatureUnit - * @return {boolean} - * @private - */ - isValidTemperatureUnit_(temperatureUnit) { - return temperatureUnit === AmbientModeTemperatureUnit.FAHRENHEIT || - temperatureUnit === AmbientModeTemperatureUnit.CELSIUS; - } - - /** - * @param {number} topicSource - * @return {boolean} - * @private - */ - isValidTopicSource_(topicSource) { - return topicSource !== AmbientModeTopicSource.UNKNOWN; - } - - /** - * @param {!AmbientModeTemperatureUnit} newValue - * @param {!AmbientModeTemperatureUnit} oldValue - * @private - */ - onSelectedTemperatureUnitChanged_(newValue, oldValue) { - if (newValue && newValue !== AmbientModeTemperatureUnit.UNKNOWN && - newValue !== oldValue) { - this.browserProxy_.setSelectedTemperatureUnit(newValue); - } - } - - /** - * Open ambientMode/photos subpage. - * @param {!Event} event - * @private - */ - onShowAlbums_( - /** @type {CustomEvent<{item: !AmbientModeTopicSource}>} */ event) { - const params = new URLSearchParams(); - params.append('topicSource', JSON.stringify(event.detail)); - Router.getInstance().navigateTo(routes.AMBIENT_MODE_PHOTOS, params); - } - - /** - * Whether to show settings. - * @return {boolean} - * @private - */ - computeShowSettings_() { - return this.isValidTopicSource_(this.selectedTopicSource_) && - this.isValidTemperatureUnit_(this.selectedTemperatureUnit_); - } - - /** - * Whether to disable settings. - * @return {boolean} - * @private - */ - computeDisableSettings_() { - return !this.getPref('settings.ambient_mode.enabled').value; - } -} - -customElements.define( - SettingsAmbientModePageElement.is, SettingsAmbientModePageElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html deleted file mode 100644 index 8c2b14c..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html +++ /dev/null
@@ -1,42 +0,0 @@ -<style include="settings-shared"> - #pageDescription { - display: flex; - min-height: 32px; - padding: 0 var(--cr-section-padding); - } -</style> -<localized-link id="pageDescription" - localized-string="[[getTitleInnerHtml_(topicSource)]]"> -</localized-link> - -<template is="dom-if" if="[[hasNoAlbums_(albums)]]"> - <localized-link class="cr-row first" - localized-string= - $i18nPolymer{ambientModeAlbumsSubpageGooglePhotosNoAlbum} - </localized-link> -</template> - -<template is="dom-if" if="[[showArtAlbumDialog_]]" restamp> - <art-album-dialog on-close="onArtAlbumDialogClose_"></art-album-dialog> -</template> - -<!-- Text based album selection. --> -<template is="dom-if" if="[[!photoPreviewEnabled]]"> - <iron-list id="albums" class="list-frame" items="[[albums]]"> - <template> - <cr-checkbox class="list-item" - checked="[[item.checked]]" - on-change="onCheckboxChange_" - data-id$="[[item.albumId]]" - label="[[item.title]]"> - [[item.title]] - </cr-checkbox> - </template> - </iron-list> -</template> - -<!-- Photo based album selection. --> -<template is="dom-if" if="[[photoPreviewEnabled]]"> - <album-list albums="{{albums}}" topic-source="[[topicSource]]"> - </album-list> -</template>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js deleted file mode 100644 index 3313c23f..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js +++ /dev/null
@@ -1,252 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview 'settings-ambient-mode-photos-page' is the settings page to - * select personal albums in Google Photos or categories in Art gallary. - */ -import './album_list.js'; -import './art_album_dialog.js'; -import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; -import 'chrome://resources/cr_components/localized_link/localized_link.js'; -import '../../settings_shared.css.js'; - -import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {Route, Router} from '../../router.js'; -import {routes} from '../os_route.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; - -import {AmbientModeBrowserProxy, AmbientModeBrowserProxyImpl} from './ambient_mode_browser_proxy.js'; -import {AmbientModeAlbum, AmbientModeSettings, AmbientModeTopicSource} from './constants.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {RouteObserverBehaviorInterface} - * @implements {WebUIListenerBehaviorInterface} - */ -const SettingsAmbientModePhotosPageElementBase = mixinBehaviors( - [I18nBehavior, RouteObserverBehavior, WebUIListenerBehavior], - PolymerElement); - -/** @polymer */ -class SettingsAmbientModePhotosPageElement extends - SettingsAmbientModePhotosPageElementBase { - static get is() { - return 'settings-ambient-mode-photos-page'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - photoPreviewEnabled: { - type: Boolean, - value() { - return loadTimeData.getBoolean('isAmbientModePhotoPreviewEnabled'); - }, - readOnly: true, - }, - - /** @type {!AmbientModeTopicSource} */ - topicSource: { - type: Number, - value: AmbientModeTopicSource.UNKNOWN, - }, - - /** @type {?Array<!AmbientModeAlbum>} */ - albums: { - type: Array, - notify: true, - // Set to null to differentiate from an empty album. - value: null, - }, - - /** @private */ - showArtAlbumDialog_: { - type: Boolean, - value: false, - }, - }; - } - - /** @override */ - constructor() { - super(); - - /** @private {!AmbientModeBrowserProxy} */ - this.browserProxy_ = AmbientModeBrowserProxyImpl.getInstance(); - } - - /** @override */ - ready() { - super.ready(); - - this.addWebUIListener('albums-changed', this.onAlbumsChanged_.bind(this)); - this.addWebUIListener( - 'album-preview-changed', this.onAlbumPreviewChanged_.bind(this)); - - this.addEventListener( - 'selected-albums-changed', this.onSelectedAlbumsChanged_); - } - - /** - * RouteObserverBehavior - * @param {!Route} currentRoute - * @param {!Route=} prevRoute - * @protected - */ - currentRouteChanged(currentRoute, prevRoute) { - if (currentRoute !== routes.AMBIENT_MODE_PHOTOS) { - return; - } - - const topicSourceParam = - Router.getInstance().getQueryParameters().get('topicSource'); - const topicSourceInt = parseInt(topicSourceParam, 10); - - if (isNaN(topicSourceInt)) { - assertNotReached(); - return; - } - - this.topicSource = /** @type {!AmbientModeTopicSource} */ (topicSourceInt); - if (this.topicSource === AmbientModeTopicSource.GOOGLE_PHOTOS) { - this.parentNode.pageTitle = - this.i18n('ambientModeTopicSourceGooglePhotos'); - } else if (this.topicSource === AmbientModeTopicSource.ART_GALLERY) { - this.parentNode.pageTitle = this.i18n('ambientModeTopicSourceArtGallery'); - } else { - assertNotReached(); - return; - } - - // TODO(b/162793904): Have a better plan to cache the UI data. - // Reset to null to distinguish empty albums fetched from server. - this.albums = null; - this.browserProxy_.requestAlbums(this.topicSource); - } - - /** - * @param {!AmbientModeSettings} settings - * @private - */ - onAlbumsChanged_(settings) { - // This page has been reused by other topic source since the last time - // requesting the albums. Do not update on this stale event. - if (settings.topicSource !== this.topicSource) { - return; - } - this.albums = settings.albums; - } - - /** - * @param {!AmbientModeAlbum} album - * @private - */ - onAlbumPreviewChanged_(album) { - if (album.topicSource !== this.topicSource) { - return; - } - - for (let i = 0; i < this.albums.length; ++i) { - if (this.albums[i].albumId === album.albumId) { - if (album.url) { - this.set('albums.' + i + '.url', album.url); - continue; - } - this.set( - 'albums.' + i + '.recentHighlightsUrls', - album.recentHighlightsUrls); - } - } - } - - /** - * @param {number} topicSource - * @return {string} - * @private - */ - getTitleInnerHtml_(topicSource) { - if (topicSource === AmbientModeTopicSource.GOOGLE_PHOTOS) { - return this.i18nAdvanced('ambientModeAlbumsSubpageGooglePhotosTitle'); - } else { - return this.i18n('ambientModeTopicSourceArtGalleryDescription'); - } - } - - /** - * @param {!Event} event - * @private - */ - onSelectedAlbumsChanged_( - /** @type {CustomEvent<{item: !AmbientModeAlbum}>} */ event) { - const albums = []; - let eventAlbumIndex = -1; - for (let i = 0; i < this.albums.length; ++i) { - const album = this.albums[i]; - if (album.checked) { - albums.push({albumId: album.albumId}); - } - - if (album.albumId === event.detail.albumId) { - eventAlbumIndex = i; - } - } - - assert(eventAlbumIndex >= 0, 'Wrong album index.'); - - // For art gallery, cannot deselect the last album. Show a dialog to users - // and select the album automatically. - if (this.topicSource === AmbientModeTopicSource.ART_GALLERY && - albums.length === 0) { - this.showArtAlbumDialog_ = true; - this.set('albums.' + eventAlbumIndex + '.checked', true); - return; - } - - this.browserProxy_.setSelectedAlbums( - {topicSource: this.topicSource, albums: albums}); - } - - /** @private */ - onArtAlbumDialogClose_() { - this.showArtAlbumDialog_ = false; - } - - /** @private */ - onCheckboxChange_() { - const checkboxes = - this.shadowRoot.querySelector('#albums').querySelectorAll( - 'cr-checkbox'); - const albums = []; - checkboxes.forEach((checkbox) => { - if (checkbox.checked && !checkbox.hidden) { - albums.push({albumId: checkbox.dataset.id}); - } - }); - this.browserProxy_.setSelectedAlbums( - {topicSource: this.topicSource, albums: albums}); - } - - /** - * @return {boolean} - * @private - */ - hasNoAlbums_() { - return !!this.albums && !this.albums.length; - } -} - -customElements.define( - SettingsAmbientModePhotosPageElement.is, - SettingsAmbientModePhotosPageElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.html deleted file mode 100644 index 29aef94..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.html +++ /dev/null
@@ -1,14 +0,0 @@ -<style include="settings-shared"> - cr-dialog::part(dialog) { - min-width: 288px; - width: 288px; - } -</style> -<cr-dialog id="dialog"> - <div slot="body">$i18n{ambientModeLastArtAlbumMessage}</div> - <div slot="button-container"> - <cr-button class="action-button" on-click="onClose_"> - $i18n{ambientModeArtAlbumDialogCloseButtonLabel} - </cr-button> - </div> -</cr-dialog>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js deleted file mode 100644 index 49b68b8a..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/art_album_dialog.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying information for art albums. - */ - -import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; -import '../../settings_shared.css.js'; - -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const ArtAlbumDialogElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); - -/** @polymer */ -class ArtAlbumDialogElement extends ArtAlbumDialogElementBase { - static get is() { - return 'art-album-dialog'; - } - - static get template() { - return html`{__html_template__}`; - } - - /** @override */ - connectedCallback() { - super.connectedCallback(); - - this.$.dialog.showModal(); - } - - /** - * Closes the dialog. - * @private - */ - onClose_() { - if (this.$.dialog.open) { - this.$.dialog.close(); - } - } -} - -customElements.define(ArtAlbumDialogElement.is, ArtAlbumDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js deleted file mode 100644 index 2ec002c..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Enumeration of the topic source, i.e. where the photos come from. - * Values need to stay in sync with the enum |ash::AmbientModeTopicSource|. - * @enum {number} - */ -export const AmbientModeTopicSource = { - UNKNOWN: -1, - GOOGLE_PHOTOS: 0, - ART_GALLERY: 1, -}; - -/** @enum {string} */ -export const AmbientModeTemperatureUnit = { - UNKNOWN: 'unknown', - FAHRENHEIT: 'fahrenheit', - CELSIUS: 'celsius', -}; - -/** - * Item of AmbientModeTopicSource. - * - * @typedef {{ - * topicSource: AmbientModeTopicSource, - * hasGooglePhotosAlbums: boolean, - * }} - */ -export let TopicSourceItem; - -/** - * Album metadata for UI. - * - * @typedef {{ - * topicSource: AmbientModeTopicSource, - * albumId: string, - * checked: boolean, - * description: string, - * title: string, - * url: string, - * recentHighlightsUrls: Array<string>, - * }} - */ -export let AmbientModeAlbum; - -/** - * Settings containing topic source and the albums. - * - * @typedef {{ - * albums: !Array<!AmbientModeAlbum>, - * topicSource: !AmbientModeTopicSource, - * }} - */ -export let AmbientModeSettings;
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.html deleted file mode 100644 index 34257911..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.html +++ /dev/null
@@ -1,16 +0,0 @@ -<style include="settings-shared cr-shared-style"> - .line-clamp { - -webkit-box-orient: vertical; - display: -webkit-box; - overflow: hidden; - } -</style> -<div id="textDiv" style$="-webkit-line-clamp: [[lineClamp]];" - class$="line-clamp [[textStyle]]"> - [[text]] -</div> -<template is="dom-if" if="[[textOverflowing_]]"> - <paper-tooltip for="textDiv" fit-to-visible-bounds> - [[text]] - </paper-tooltip> -</template>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js deleted file mode 100644 index 71c65bd..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/text_with_tooltip.js +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying clamped text, with a tooltip if - * the text overflows. - */ - -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import '../../settings_shared.css.js'; - -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -const TOOLTIP_ANIMATE_IN_DELAY = 500; -const TOOLTIP_ANIMATE_OUT_DURATION = 500; - -/** @polymer */ -class TextWithTooltipElement extends PolymerElement { - static get is() { - return 'text-with-tooltip'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** Text displayed in both div and tooltip.*/ - text: { - type: String, - observer: 'textChanged_', - }, - - /** Number of lines to limit to */ - lineClamp: { - type: String, - value: '1', - }, - - /** Style class(es) for the text */ - textStyle: { - type: String, - }, - - /** - * Whether #textDiv has overflowing content - * @private - */ - textOverflowing_: { - type: Boolean, - value: false, - }, - - /** Whether the tooltip is visible or animating */ - tooltipIsVisible: { - type: Boolean, - value: false, - notify: true, - }, - }; - } - - /** - * Called after property values are set and local DOM is initialized. - * @override - */ - ready() { - super.ready(); - - const resizeObserver = new ResizeObserver((mutations) => { - this.updateTextOverflowing_(); - }); - resizeObserver.observe(this.$.textDiv); - - this.addEventListener('mouseenter', this.onMouseEnter_); - this.addEventListener('mouseleave', this.onMouseLeave_); - } - - /** - * Called whenever the text has changed. - * @private - */ - textChanged_(newValue, oldValue) { - this.updateTextOverflowing_(); - } - - /** - * @param {Event} event - * @private - */ - onMouseEnter_(/** @type {!MouseEvent}*/ event) { - this.updateTooltipIsVisibleAfterDelay_(true, TOOLTIP_ANIMATE_IN_DELAY); - } - - /** - * @param {Event} event - * @private - */ - onMouseLeave_(/** @type {!MouseEvent}*/ event) { - const animationDurationOut = 500; - this.updateTooltipIsVisibleAfterDelay_(false, TOOLTIP_ANIMATE_OUT_DURATION); - } - - /** - * paper-tooltip doesn't have a reliable way of querying it's visibility - * (animations included). It animates in after a duration after mouseenter. - * And starts animating out on mouseleave. - * @param {boolean} visible tooltip visibility. - * @param {number} delay in ms to apply visibility. - * @private - */ - updateTooltipIsVisibleAfterDelay_(visible, delay) { - const tooltip = this.shadowRoot.querySelector('paper-tooltip'); - if (tooltip) { - setTimeout(() => this.tooltipIsVisible = visible, delay); - } - } - - /** - * Sets textOverflowing_ based on the #textDiv element. - * @private - */ - updateTextOverflowing_() { - const textElement = this.$.textDiv; - this.textOverflowing_ = textElement.scrollHeight > textElement.offsetHeight; - } -} - -customElements.define(TextWithTooltipElement.is, TextWithTooltipElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.html deleted file mode 100644 index 4ae9c84..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.html +++ /dev/null
@@ -1,36 +0,0 @@ -<style include="settings-shared cr-shared-style iron-flex - cr-radio-button-style"> - :host { - display: inline-flex; - } - - #rowContainer { - /* Set height to 100% of parent to always capture click events. */ - height: 100%; - padding-inline-end: var(--cr-icon-ripple-padding); - padding-inline-start: var(--cr-section-padding); - } -</style> - -<div id="rowContainer" class="layout horizontal center flex" - on-click="onItemClick_"> - <!-- This item behaviors similar to a radio button and reuses disc and - label style in cr-radio-button-style. --> - <div class="disc-wrapper" aria-hidden="true"> - <div class="disc-border"></div> - <div class="disc"></div> - </div> - - <div id="labelWrapper" aria-hidden="true"> - <div>[[getItemName_(item)]]</div> - <div class="cr-secondary-text"> - [[getItemDescription_(item, hasGooglePhotosAlbums)]] - </div> - </div> - - <cr-icon-button class="subpage-arrow" id="subpage-button" - on-click="onSubpageArrowClick_" tabindex$="[[tabindex]]" - aria-label$="[[buttonLabel]]" - disabled$="[[disabled]]"> - </cr-icon-button> -</div>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js deleted file mode 100644 index fb996ec8..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_item.js +++ /dev/null
@@ -1,183 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying options to select a - * AmbientModeTopicSource in a list. - */ - -import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js'; -import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import '../../settings_shared.css.js'; - -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {AmbientModeTopicSource} from './constants.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const TopicSourceItemElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); - -/** @polymer */ -class TopicSourceItemElement extends TopicSourceItemElementBase { - static get is() { - return 'topic-source-item'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** - * Whether this item is selected. This property is related to - * cr_radio_button_style and used to style the disc appearance. - */ - checked: { - type: Boolean, - value: false, - reflectToAttribute: true, - }, - - hasGooglePhotosAlbums: { - type: Boolean, - value: false, - }, - - /** @type {!AmbientModeTopicSource} */ - item: Object, - - buttonLabel: { - type: String, - computed: 'getButtonLabel_(item)', - }, - - /** Aria label for the row. */ - ariaLabel: { - type: String, - computed: 'computeAriaLabel_(item, checked)', - reflectToAttribute: true, - }, - }; - } - - ready() { - super.ready(); - - this.addEventListener('keydown', this.onKeydown_); - } - - /** - * @return {string} - * @private - */ - getItemName_() { - if (this.item === AmbientModeTopicSource.GOOGLE_PHOTOS) { - return this.i18n('ambientModeTopicSourceGooglePhotos'); - } else if (this.item === AmbientModeTopicSource.ART_GALLERY) { - return this.i18n('ambientModeTopicSourceArtGallery'); - } else { - return ''; - } - } - - /** - * @return {string} - * @private - */ - getItemDescription_() { - if (this.item === AmbientModeTopicSource.GOOGLE_PHOTOS) { - if (this.hasGooglePhotosAlbums) { - return this.i18n('ambientModeTopicSourceGooglePhotosDescription'); - } else { - return this.i18n( - 'ambientModeTopicSourceGooglePhotosDescriptionNoAlbum'); - } - } else if (this.item === AmbientModeTopicSource.ART_GALLERY) { - return this.i18n('ambientModeTopicSourceArtGalleryDescription'); - } else { - return ''; - } - } - - /** - * The aria label for the subpage button. - * @return {string} - * @private - */ - getButtonLabel_() { - return this.i18n('ambientModeTopicSourceSubpage', this.getItemName_()); - } - - /** - * @return {string} Aria label string for ChromeVox to verbalize. - * @private - */ - computeAriaLabel_() { - if (this.checked) { - return this.i18n( - 'ambientModeTopicSourceSelectedRow', this.getItemName_(), - this.getItemDescription_()); - } - return this.i18n( - 'ambientModeTopicSourceUnselectedRow', this.getItemName_(), - this.getItemDescription_()); - } - - /** - * @param {!Event} event - * @private - */ - onKeydown_(/** @type {!KeyboardEvent}*/ event) { - // The only key event handled by this element is pressing Enter. - // Pressing anywhere leads to the subpage. - if (event.key !== 'Enter') { - return; - } - - this.fireShowAlbums_(); - event.preventDefault(); - event.stopPropagation(); - } - - /** - * @param {!MouseEvent} event - * @private - */ - onItemClick_(event) { - // Clicking anywhere leads to the subpage. - this.fireShowAlbums_(); - event.stopPropagation(); - } - - /** - * @param {!MouseEvent} event - * @private - */ - onSubpageArrowClick_(event) { - this.fireShowAlbums_(); - event.stopPropagation(); - } - - /** - * Fires a 'show-albums' event with |this.item| as the details. - * @private - */ - fireShowAlbums_() { - const event = new CustomEvent( - 'show-albums', {bubbles: true, composed: true, detail: this.item}); - this.dispatchEvent(event); - } -} - -customElements.define(TopicSourceItemElement.is, TopicSourceItemElement);
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.html deleted file mode 100644 index a0407e6..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.html +++ /dev/null
@@ -1,33 +0,0 @@ -<style include="settings-shared cr-shared-style iron-flex"> - #topicSourceTitle { - padding-bottom: 16px; - padding-top: 16px; - } - - topic-source-item { - align-items: center; - height: 64px; - } - - iron-list > *:not(:first-of-type) { - border-top: var(--cr-separator-line); - } - - iron-list > :focus { - background-color: var(--cr-focused-item-color); - } -</style> -<h2 id="topicSourceTitle" aria-hidden="true"> - $i18n{ambientModeTopicSourceTitle} -</h2> - -<iron-list id="topicSourceList" items="[[topicSources]]" - aria-describedby="topicSourceTitle"> - <template> - <topic-source-item item="[[item]]" disabled$="[[disabled]]" - tabindex$="[[computeTabIndex_(tabIndex, disabled)]]" - has-google-photos-albums="[[hasGooglePhotosAlbums]]" - checked="[[isSelected_(item, selectedTopicSource)]]"> - </topic-source-item> - </template> -</iron-list>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js deleted file mode 100644 index 480c39a3..0000000 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/topic_source_list.js +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying a list of - * AmbientModeTopicSource. - */ - -/** - * Polymer class definition for 'topic-source-list'. - */ -import './topic_source_item.js'; -import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; -import '../../settings_shared.css.js'; - -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {AmbientModeTopicSource} from './constants.js'; - -/** @polymer */ -class TopicSourceListElement extends PolymerElement { - static get is() { - return 'topic-source-list'; - } - - static get template() { - return html`{__html_template__}`; - } - - static get properties() { - return { - /** - * Contains topic sources. - * @type {!Array<!AmbientModeTopicSource>} - */ - topicSources: { - type: Array, - value: [], - }, - - /** @type {!AmbientModeTopicSource} */ - selectedTopicSource: { - type: AmbientModeTopicSource, - value: AmbientModeTopicSource.UNKNOWN, - }, - - hasGooglePhotosAlbums: Boolean, - - /** - * The items in this list will be disabled when |selectedTopicSource| is - * |AmbientModeTopicSource.UNKNOWN|. - */ - disabled: Boolean, - }; - } - - /** - * @param {!AmbientModeTopicSource} topic_source - * @private - */ - isSelected_(topic_source) { - return this.selectedTopicSource === topic_source; - } - - /** - * @param {number} tabIndex - * @param {boolean} disabled - * @return {number} - * @private - */ - computeTabIndex_(tabIndex, disabled) { - // Disabled "topic-source-item" cannot be navigated into. - if (disabled) { - return -1; - } - return tabIndex; - } -} - -customElements.define(TopicSourceListElement.is, TopicSourceListElement);
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js index 773af41..3f0ad6da 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_confirmation_dialog.js
@@ -8,9 +8,9 @@ * By clicking 'Reserve size', the user agrees to start the operation. */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import '../../settings_shared.css.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; /** @polymer */
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js index cee5cf5c7..6531661 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js
@@ -8,11 +8,11 @@ */ import 'chrome://resources/cr_components/chromeos/network/network_config.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import './internet_shared_css.js'; import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {HTMLEscape} from 'chrome://resources/js/util.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js b/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js index 654b071..149ecd6f 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/tether_connection_dialog.js
@@ -4,7 +4,6 @@ import 'chrome://resources/cr_components/chromeos/network/network_icon.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-lite.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; @@ -13,6 +12,7 @@ import '../../settings_shared.css.js'; import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {HTMLEscape} from 'chrome://resources/js/util.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js index 48c21ec..0bf71e0 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js
@@ -9,10 +9,10 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import '../../shared/nearby_onboarding_page.js'; import '../../shared/nearby_visibility_page.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js index cda61206d..035e9fc 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js
@@ -9,10 +9,10 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js index d294284..059eb1ad 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js
@@ -9,9 +9,9 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js index aa0292a..79cb12c 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js
@@ -20,7 +20,6 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import '../../prefs/prefs.js'; import '../../shared/nearby_onboarding_one_page.js'; import '../../shared/nearby_onboarding_page.js'; @@ -29,6 +28,7 @@ import './nearby_share_high_visibility_page.js'; import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.html index 3969062..fd00c16 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.html +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/cursor_and_touchpad_page.html
@@ -19,6 +19,7 @@ <settings-toggle-button pref="{{prefs.settings.a11y.autoclick}}" + icon="os-settings:autoclick" label="$i18n{clickOnStopLabel}" sub-label="$i18n{clickOnStopDescription}" deep-link-focus-id$="[[Setting.kAutoClickWhenCursorStops]]">
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.html index d325f12..b03d1f64b 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.html +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/display_and_magnification_page.html
@@ -27,6 +27,7 @@ } </style> <settings-toggle-button + icon="os-settings:contrast" pref="{{prefs.settings.a11y.high_contrast_enabled}}" label="$i18n{highContrastLabel}" sub-label="$i18n{highContrastDescription}" @@ -34,6 +35,7 @@ </settings-toggle-button> <settings-toggle-button class="hr" + icon="os-settings:fullscreen-magnifier" pref="{{prefs.settings.a11y.screen_magnifier}}" label="$i18n{screenMagnifierLabel}" sub-label="[[getScreenMagnifierDescription_( @@ -94,6 +96,7 @@ </template> <settings-toggle-button class="hr" + icon="os-settings:docked-magnifier" pref="{{prefs.ash.docked_magnifier.enabled}}" label="$i18n{dockedMagnifierLabel}" sub-label="$i18n{dockedMagnifierDescription}"
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.html index 431842bf..62e8a00 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.html +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/keyboard_and_text_input_page.html
@@ -40,6 +40,7 @@ </settings-toggle-button> <settings-toggle-button class="hr" + icon="os-settings:on-screen-keyboard" pref="{{prefs.settings.a11y.virtual_keyboard}}" label="$i18n{onScreenKeyboardLabel}" sub-label="$i18n{onScreenKeyboardDescription}" @@ -48,6 +49,7 @@ <settings-toggle-button id="enableDictation" class="hr" + icon="os-settings:dictation" pref="{{prefs.settings.a11y.dictation}}" label="$i18n{dictationLabel}" sub-label="$i18n{dictationDescription}" @@ -102,6 +104,7 @@ <settings-toggle-button id="enableSwitchAccess" class="hr" + icon="os-settings:switch-access" pref="{{prefs.settings.a11y.switch_access.enabled}}" label="$i18n{switchAccessLabel}" sub-label="$i18n{switchAccessLabelSubtext}"
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html index 41c14f4..ee7fe9b5 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
@@ -17,6 +17,7 @@ } </style> <settings-toggle-button + icon="os-settings:chromevox" pref="{{prefs.settings.accessibility}}" label="$i18n{chromeVoxLabel}" sub-label="[[getChromeVoxDescription_(prefs.settings.accessibility.value)]]" @@ -37,6 +38,7 @@ </div> </iron-collapse> <settings-toggle-button + icon="os-settings:select-to-speak" pref="{{prefs.settings.a11y.select_to_speak}}" class="hr" label="$i18n{selectToSpeakTitle}"
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index ded5bd0e..e9a0d7b 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -39,8 +39,6 @@ } non_web_component_files = [ - "chromeos/ambient_mode_page/ambient_mode_browser_proxy.js", - "chromeos/ambient_mode_page/constants.js", "chromeos/bluetooth_page/bluetooth_page_browser_proxy.js", "chromeos/combined_search_handler.js", "chromeos/crostini_page/crostini_browser_proxy.js", @@ -137,14 +135,6 @@ # Files that are generated by html_to_js(). gen_web_component_files = [ - "chromeos/ambient_mode_page/album_item.js", - "chromeos/ambient_mode_page/album_list.js", - "chromeos/ambient_mode_page/ambient_mode_page.js", - "chromeos/ambient_mode_page/ambient_mode_photos_page.js", - "chromeos/ambient_mode_page/art_album_dialog.js", - "chromeos/ambient_mode_page/text_with_tooltip.js", - "chromeos/ambient_mode_page/topic_source_item.js", - "chromeos/ambient_mode_page/topic_source_list.js", "chromeos/bluetooth_page/bluetooth_device_list_item.js", "chromeos/bluetooth_page/bluetooth_page.js", "chromeos/bluetooth_page/bluetooth_subpage.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index 6b1edc7..657acd6b 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -3,7 +3,6 @@ // found in the LICENSE file. import '../prefs/prefs.js'; -import './ambient_mode_page/ambient_mode_page.js'; import './bluetooth_page/bluetooth_device_list_item.js'; import './bluetooth_page/bluetooth_page.js'; import './bluetooth_page/bluetooth_subpage.js'; @@ -126,8 +125,6 @@ export {getContactManager, observeContactManager, setContactManagerForTesting} from '../shared/nearby_contact_manager.js'; export {getNearbyShareSettings, observeNearbyShareSettings, setNearbyShareSettingsForTesting} from '../shared/nearby_share_settings.js'; export {NearbySettings, NearbyShareSettingsBehavior} from '../shared/nearby_share_settings_behavior.js'; -export {AmbientModeBrowserProxyImpl} from './ambient_mode_page/ambient_mode_browser_proxy.js'; -export {AmbientModeTemperatureUnit, AmbientModeTopicSource} from './ambient_mode_page/constants.js'; export {bluetoothApis} from './bluetooth_page/bluetooth_page.js'; export {BluetoothPageBrowserProxyImpl} from './bluetooth_page/bluetooth_page_browser_proxy.js'; export {setCrosAudioConfigForTesting} from './device_page/cros_audio_config.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js index b81407b..0a84757 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -18,8 +18,6 @@ * ACCOUNTS: !Route, * ACCOUNT_MANAGER: !Route, * ADVANCED: !Route, - * AMBIENT_MODE: !Route, - * AMBIENT_MODE_PHOTOS: !Route, * APP_NOTIFICATIONS: !Route, * APP_MANAGEMENT: !Route, * APP_MANAGEMENT_DETAIL: !Route,
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn index 5e7bbd6..a6c320c 100644 --- a/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn
@@ -54,7 +54,6 @@ "..:prefs_behavior", "..:route_observer_behavior", "../..:router", - "../ambient_mode_page:ambient_mode_browser_proxy", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:load_time_data.m", ]
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html index d1d2282..00e7383 100644 --- a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html +++ b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html
@@ -28,19 +28,6 @@ </cr-policy-indicator> </template> </cr-link-row> - - <!-- Ambient mode --> - <template is="dom-if" if="[[isAmbientModeEnabled_]]"> - <cr-link-row - class="hr" - id="ambientModeRow" - label="$i18n{ambientModeTitle}" - sub-label="[[getAmbientModeRowSubLabel_( - prefs.settings.ambient_mode.enabled.value)]]" - on-click="navigateToAmbientMode_" - role-description="$i18n{subpageArrowRoleDescription}"> - </cr-link-row> - </template> </template> </div> @@ -49,21 +36,4 @@ <settings-change-picture></settings-change-picture> </settings-subpage> </template> - - <template is="dom-if" if="[[isAmbientModeEnabled_]]"> - <template is="dom-if" route-path="/ambientMode"> - <settings-subpage page-title="$i18n{ambientModeTitle}"> - <settings-ambient-mode-page prefs="{{prefs}}"> - </settings-ambient-mode-page> - </settings-subpage> - </template> - - <template is="dom-if" route-path="/ambientMode/photos"> - <settings-subpage> - <settings-ambient-mode-photos-page> - </settings-ambient-mode-photos-page> - </settings-subpage> - </template> - - </template> </settings-animated-pages>
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js index 2ea729d..1418b0f 100644 --- a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js +++ b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.js
@@ -6,8 +6,6 @@ * 'settings-personalization-page' is the settings page containing * personalization settings. */ -import '../ambient_mode_page/ambient_mode_page.js'; -import '../ambient_mode_page/ambient_mode_photos_page.js'; import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; import './change_picture.js'; import '../../settings_page/settings_animated_pages.js'; @@ -62,15 +60,6 @@ isWallpaperPolicyControlled_: {type: Boolean, value: true}, /** @private */ - isAmbientModeEnabled_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('isAmbientModeEnabled'); - }, - readOnly: true, - }, - - /** @private */ isPersonalizationHubEnabled_: { type: Boolean, value() { @@ -86,8 +75,6 @@ const map = new Map(); if (routes.CHANGE_PICTURE) { map.set(routes.CHANGE_PICTURE.path, '#changePictureRow'); - } else if (routes.AMBIENT_MODE) { - map.set(routes.AMBIENT_MODE.path, '#ambientModeRow'); } return map; @@ -160,21 +147,6 @@ navigateToChangePicture_() { Router.getInstance().navigateTo(routes.CHANGE_PICTURE); } - - /** @private */ - navigateToAmbientMode_() { - Router.getInstance().navigateTo(routes.AMBIENT_MODE); - } - - /** - * @param {boolean} toggleValue - * @return {string} - * @private - */ - getAmbientModeRowSubLabel_(toggleValue) { - return this.i18n( - toggleValue ? 'ambientModeEnabled' : 'ambientModeDisabled'); - } } customElements.define(
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chrome/browser/resources/settings/controls/settings_toggle_button.html index c7214de..9526875 100644 --- a/chrome/browser/resources/settings/controls/settings_toggle_button.html +++ b/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -1,5 +1,6 @@ <style include="cr-actionable-row-style settings-shared iron-flex"> :host { + --cr-icon-button-margin-end: 20px; padding: 0 var(--cr-section-padding); } @@ -26,6 +27,12 @@ min-height: var(--settings-row-min-height); } +<if expr="chromeos_ash"> + #icon { + margin-inline-end: var(--cr-icon-button-margin-end); + } +</if> + #labelWrapper { padding: var(--cr-section-vertical-padding) 0; } @@ -40,6 +47,14 @@ } </style> <div id="outerRow" noSubLabel$="[[!subLabel]]"> + <if expr="chromeos_ash"> + <template is="dom-if" if="[[icon]]"> + <span id="icon" aria-hidden="true"> + <iron-icon slot="icon" icon="[[icon]]"> + </iron-icon> + </span> + </template> + </if> <div class="flex" id="labelWrapper" hidden$="[[!label]]"> <div class="label" aria-hidden="true">[[label]]</div> <div class="secondary label" id="sub-label">
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.ts b/chrome/browser/resources/settings/controls/settings_toggle_button.ts index cf00bdb2..ba56439 100644 --- a/chrome/browser/resources/settings/controls/settings_toggle_button.ts +++ b/chrome/browser/resources/settings/controls/settings_toggle_button.ts
@@ -67,6 +67,8 @@ type: String, reflectToAttribute: true, }, + + icon: String, // </if> subLabelIcon: String, @@ -81,6 +83,11 @@ override ariaLabel: string; elideLabel: boolean; + + // <if expr="chromeos_ash"> + icon: string; + // </if> + learnMoreUrl: string; // <if expr="chromeos_ash">
diff --git a/chrome/browser/resources/settings/languages_page/languages_types.ts b/chrome/browser/resources/settings/languages_page/languages_types.ts index 755f88a..76dee02 100644 --- a/chrome/browser/resources/settings/languages_page/languages_types.ts +++ b/chrome/browser/resources/settings/languages_page/languages_types.ts
@@ -139,6 +139,11 @@ disableTranslateLanguage(languageCode: string): void; /** + * Sets the translate target language. + */ + setTranslateTargetLanguage(languageCode: string): void; + + /** * Sets whether a given language should always be automatically translated. */ setLanguageAlwaysTranslateState(
diff --git a/chrome/browser/resources/settings/languages_page/translate_page.html b/chrome/browser/resources/settings/languages_page/translate_page.html index c85bf67..eee90ec8 100644 --- a/chrome/browser/resources/settings/languages_page/translate_page.html +++ b/chrome/browser/resources/settings/languages_page/translate_page.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style settings-shared iron-flex"></style> +<style include="cr-shared-style settings-shared md-select iron-flex"></style> <settings-toggle-button id="offerTranslateOtherLanguages" pref="{{prefs.translate.enabled}}" label="$i18n{offerToEnableTranslate}" @@ -8,6 +8,24 @@ <iron-collapse id="spellCheckCollapse" opened="[[prefs.translate.enabled.value]]"> <div class="cr-row continuation"> + <div id="targetLanguageLabel" class="flex cr-padded-text" + aria-hidden="true"> + $i18n{targetLanguageLabel} + </div> + <select id="targetLanguage" class="md-select" + aria-labelledby="targetLanguageLabel" + on-change="onTargetLanguageChange_"> + <template is="dom-repeat" items="[[languages.supported]]" + filter="isTranslateSupported_"> + <option value="[[item.code]]" + selected="[[translateLanguageEqual_( + item.code, languages.translateTarget)]]"> + [[getTargetLanguageDisplayOption_(item)]] + </option> + </template> + </select> + </div> + <div class="cr-row continuation"> <h2 class="flex">$i18n{automaticallyTranslateLanguages}</h2> <cr-button id="addAlwaysTranslate" class="header-aligned-button" on-click="onAddAlwaysTranslateLanguagesClick_"> @@ -43,6 +61,7 @@ <div class="list-item"> <div class="start cr-padded-text">[[item.displayName]]</div> <cr-icon-button class="icon-delete-gray" value="[[item.code]]" + disabled="[[isLanguageRemoveDisabled_()]]" on-click="onRemoveNeverTranslateLanguageClick_"> </cr-icon-button> </div>
diff --git a/chrome/browser/resources/settings/languages_page/translate_page.ts b/chrome/browser/resources/settings/languages_page/translate_page.ts index 3275a0f..06387de 100644 --- a/chrome/browser/resources/settings/languages_page/translate_page.ts +++ b/chrome/browser/resources/settings/languages_page/translate_page.ts
@@ -11,6 +11,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/icons.m.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/cr_elements/md_select_css.m.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js'; import './add_languages_dialog.js'; @@ -78,6 +79,35 @@ private languageSettingsMetricsProxy_: LanguageSettingsMetricsProxy = LanguageSettingsMetricsProxyImpl.getInstance(); + private onTargetLanguageChange_() { + this.languageHelper.setTranslateTargetLanguage( + this.shadowRoot!.querySelector<HTMLSelectElement>('#targetLanguage')! + .value); + } + + /** + * Helper function to get the text to display in the target language drop down + * list. Returns the display name in the current UI language and the native + * name of the language. + */ + private getTargetLanguageDisplayOption_( + item: chrome.languageSettingsPrivate.Language): string { + let formattedLanguage = item.displayName; + if (item.displayName !== item.nativeDisplayName) { + formattedLanguage += ' - ' + item.nativeDisplayName; + } + return formattedLanguage; + } + + /** + * Used in the translate language selector. If the item matches the translate + * target language, it will set that item as selected. + */ + private translateLanguageEqual_(itemCode: string, translateTarget: string): + boolean { + return itemCode === translateTarget; + } + /** * Stamps and opens the Add Languages dialog, registering a listener to * disable the dialog's dom-if again on close. @@ -119,12 +149,21 @@ } /** + * Never translate languages list length must always be greater than or equal + * to 1. If there is only one language, the icon is disabled. + */ + private isLanguageRemoveDisabled_(): boolean { + return this.languages!.neverTranslate.length === 1; + } + + /** * Stamps and opens the Add Languages dialog, registering a listener to * disable the dialog's dom-if again on close. */ private onAddNeverTranslateLanguagesClick_(e: Event) { e.preventDefault(); - this.addLanguagesDialogLanguages_ = this.languages!.supported.filter( + const translatableLanguages = this.getTranslatableLanguages_(); + this.addLanguagesDialogLanguages_ = translatableLanguages.filter( language => !this.languages!.neverTranslate.includes(language)); this.showAddNeverTranslateDialog_ = true; } @@ -176,6 +215,14 @@ return this.languageHelper.isLanguageTranslatable(language); }); } + + /** + * Filters only for translate supported languages + */ + private isTranslateSupported_( + language: chrome.languageSettingsPrivate.Language): boolean { + return this.languageHelper.isLanguageTranslatable(language); + } } declare global {
diff --git a/chrome/browser/resources/side_panel/BUILD.gn b/chrome/browser/resources/side_panel/BUILD.gn index c3938a82..e01f3b7e 100644 --- a/chrome/browser/resources/side_panel/BUILD.gn +++ b/chrome/browser/resources/side_panel/BUILD.gn
@@ -66,6 +66,12 @@ [ "$target_gen_dir/$preprocess_folder/reading_list/{{source_file_part}}" ] } +copy("copy_mojo_shopping_list") { + deps = [ "//components/commerce/core/mojom:mojo_bindings_webui_js" ] + sources = [ "$root_gen_dir/mojom-webui/components/commerce/core/mojom/shopping_list.mojom-webui.js" ] + outputs = [ "$target_gen_dir/$preprocess_folder/bookmarks/commerce/{{source_file_part}}" ] +} + ts_library("build_ts") { tsconfig_base = "tsconfig_base.json" root_dir = "$target_gen_dir/$preprocess_folder" @@ -87,6 +93,7 @@ extra_deps = [ ":copy_mojo_bookmarks", ":copy_mojo_reading_list", + ":copy_mojo_shopping_list", ":preprocess_gen", ":preprocess_src", ]
diff --git a/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts new file mode 100644 index 0000000..65be32a4 --- /dev/null +++ b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts
@@ -0,0 +1,35 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {BookmarkProductInfo, ShoppingListHandlerFactory, ShoppingListHandlerRemote} from './shopping_list.mojom-webui.js'; + +let instance: ShoppingListApiProxy|null = null; + +export interface ShoppingListApiProxy { + getAllBookmarkProductInfo(): Promise<{productInfos: BookmarkProductInfo[]}>; +} + +export class ShoppingListProxyImpl implements ShoppingListApiProxy { + handler: ShoppingListHandlerRemote; + + constructor() { + this.handler = new ShoppingListHandlerRemote(); + + const factory = ShoppingListHandlerFactory.getRemote(); + factory.createShoppingListHandler( + this.handler.$.bindNewPipeAndPassReceiver()); + } + + getAllBookmarkProductInfo() { + return this.handler.getAllBookmarkProductInfo(); + } + + static getInstance(): ShoppingListApiProxy { + return instance || (instance = new ShoppingListProxyImpl()); + } + + static setInstance(obj: ShoppingListApiProxy) { + instance = obj; + } +}
diff --git a/chrome/browser/resources/side_panel/history_clusters/OWNERS b/chrome/browser/resources/side_panel/history_clusters/OWNERS new file mode 100644 index 0000000..ddc3374 --- /dev/null +++ b/chrome/browser/resources/side_panel/history_clusters/OWNERS
@@ -0,0 +1,2 @@ +mfacey@chromium.org +tommycli@chromium.org \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/history_clusters/app.html b/chrome/browser/resources/side_panel/history_clusters/app.html new file mode 100644 index 0000000..81de604 --- /dev/null +++ b/chrome/browser/resources/side_panel/history_clusters/app.html
@@ -0,0 +1,15 @@ +<style> + :host { + --cr-toolbar-field-max-width: calc(100% - 8px); + } + + #searchbox { + margin: 4px auto; + } +</style> +<cr-toolbar-search-field id="searchbox" on-search-changed="onSearchChanged_"> +</cr-toolbar-search-field> +<history-clusters id="history-clusters" + query="[[query]]" + path="journeys"> +</history-clusters> \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/history_clusters/app.ts b/chrome/browser/resources/side_panel/history_clusters/app.ts new file mode 100644 index 0000000..d4d8c7b --- /dev/null +++ b/chrome/browser/resources/side_panel/history_clusters/app.ts
@@ -0,0 +1,53 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../strings.m.js'; +import 'chrome://resources/cr_components/history_clusters/clusters.js'; +import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js'; + +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './app.html.js'; + +export class HistoryClustersAppElement extends PolymerElement { + static get is() { + return 'history-clusters-app'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + /** + * The current query for which related clusters are requested and shown. + */ + query: { + type: String, + value: '', + }, + }; + } + + //============================================================================ + // Properties + //============================================================================ + + query: string; + + /** + * Called when the value of the search field changes. + */ + private onSearchChanged_(event: CustomEvent<string>) { + // Update the query based on the value of the search field, if necessary. + this.query = event.detail; + } +} +declare global { + interface HTMLElementTagNameMap { + 'history-clusters-app': HistoryClustersAppElement; + } +} +customElements.define(HistoryClustersAppElement.is, HistoryClustersAppElement); \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/history_clusters/history_clusters.html b/chrome/browser/resources/side_panel/history_clusters/history_clusters.html index 7de9aaa1..997aa763d 100644 --- a/chrome/browser/resources/side_panel/history_clusters/history_clusters.html +++ b/chrome/browser/resources/side_panel/history_clusters/history_clusters.html
@@ -26,13 +26,9 @@ } } </style> - <script type="module" src="strings.m.js"></script> - <script type="module" - src="chrome://resources/cr_components/history_clusters/clusters.js"> - </script> + <script type="module" src="history_clusters/app.js"></script> </head> <body> - <history-clusters id="history-clusters" query="" path="journeys"> - </history-clusters> + <history-clusters-app></history-clusters-app> </body> </html>
diff --git a/chrome/browser/resources/side_panel/read_anything/app.html b/chrome/browser/resources/side_panel/read_anything/app.html index 186c7b8..e203ed1f 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.html +++ b/chrome/browser/resources/side_panel/read_anything/app.html
@@ -1,10 +1,10 @@ <style> #container { background-color: var(--background-color); - color: var(--foreground-color); - padding: 20px; + color: var(--foreground-color); + font-family: var(--read-anything-font-family); + font-size: var(--read-anything-font-size); + padding: 20px; } </style> -<div id="container" - style$="font-size:[[fontSize_]]px; font-family:[[fontName_]];"> -</div> +<div id="container"></div>
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index 399d963..f2b0713f 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -45,19 +45,6 @@ return getTemplate(); } - static get properties() { - return { - fontName_: { - type: String, - }, - }; - } - - private fontName_: string; - private fontSize_: number; - private foregroundColor_: SkColor = new SkColor(); - private backgroundColor_: SkColor = new SkColor(); - // Defines the valid font names that can be passed to front-end and maps // them to a corresponding class style in app.html. Must stay in-sync with // the names set in read_anything_font_model.cc. @@ -180,14 +167,16 @@ } updateTheme() { - this.fontName_ = this.validatedFontName(); - this.fontSize_ = chrome.readAnything.fontSize; - this.foregroundColor_.value = chrome.readAnything.foregroundColor; - this.backgroundColor_.value = chrome.readAnything.backgroundColor; + const foregroundColor: + SkColor = {value: chrome.readAnything.foregroundColor}; + const backgroundColor: + SkColor = {value: chrome.readAnything.backgroundColor}; this.updateStyles({ - '--foreground-color': skColorToRgba(this.foregroundColor_), - '--background-color': skColorToRgba(this.backgroundColor_), + '--foreground-color': skColorToRgba(foregroundColor), + '--background-color': skColorToRgba(backgroundColor), + '--read-anything-font-family': this.validatedFontName(), + '--read-anything-font-size': chrome.readAnything.fontSize + 'px', }); } }
diff --git a/chrome/browser/resources/side_panel/side_panel.gni b/chrome/browser/resources/side_panel/side_panel.gni index 9e967e1..3ab7a74 100644 --- a/chrome/browser/resources/side_panel/side_panel.gni +++ b/chrome/browser/resources/side_panel/side_panel.gni
@@ -5,6 +5,7 @@ non_web_component_files = [ "bookmarks/bookmarks_api_proxy.ts", "bookmarks/bookmarks_drag_manager.ts", + "bookmarks/commerce/shopping_list_api_proxy.ts", "reading_list/reading_list_api_proxy.ts", ] @@ -13,6 +14,7 @@ "app.ts", "bookmarks/bookmark_folder.ts", "bookmarks/bookmarks_list.ts", + "history_clusters/app.ts", "read_anything/app.ts", "reading_list/app.ts", "reading_list/reading_list_item.ts", @@ -36,5 +38,6 @@ mojo_files = [ "bookmarks/bookmarks.mojom-webui.js", + "bookmarks/commerce/shopping_list.mojom-webui.js", "reading_list/reading_list.mojom-webui.js", ]
diff --git a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java index fead165b1..5fd7079 100644 --- a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java +++ b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java
@@ -101,19 +101,19 @@ @Override public void syncStateChanged() { mHasKeepEverythingSynced = mSyncService.hasKeepEverythingSynced(); - updateVisbility(); + updateVisibility(); } @Override public void onSignedIn() { mIsSignedIn = true; - updateVisbility(); + updateVisibility(); } @Override public void onSignedOut() { mIsSignedIn = false; - updateVisbility(); + updateVisibility(); } /** @@ -277,7 +277,7 @@ return true; } - private void updateVisbility() { + private void updateVisibility() { if (mModel != null) { mModel.set(SearchResumptionModuleProperties.IS_VISIBLE, mIsDefaultSearchEngineGoogle && mIsSignedIn && mHasKeepEverythingSynced); @@ -299,6 +299,6 @@ void onTemplateURLServiceChanged() { mIsDefaultSearchEngineGoogle = TemplateUrlServiceFactory.get().isDefaultSearchEngineGoogle(); - updateVisbility(); + updateVisibility(); } }
diff --git a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleView.java b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleView.java index 2b5ef85..813bca85 100644 --- a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleView.java +++ b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleView.java
@@ -39,13 +39,13 @@ !SharedPreferencesManager.getInstance().readBoolean( ChromePreferenceKeys.SEARCH_RESUMPTION_MODULE_COLLAPSE_ON_NTP, false) /* shouldExpand */, - false /* isAnimationEnabled */); + true /* isFirstSetup */); } void setExpandCollapseCallback(Callback<Boolean> callback) { mHeaderView.setOnClickListener(v -> { boolean shouldExpand = mTileContainerView.isExpanded() ? false : true; - configureExpandedCollapsed(shouldExpand, true /* isAnimationEnabled */); + configureExpandedCollapsed(shouldExpand, false /* isFirstSetup */); callback.onResult(shouldExpand); }); } @@ -57,21 +57,24 @@ /** * Configures expanding or collapsing the suggest sections. */ - private void configureExpandedCollapsed(boolean shouldExpand, boolean isAnimationEnabled) { - if (mTileContainerView.isExpanded() == shouldExpand) return; - - if (shouldExpand) { - mOptionView.setImageResource(org.chromium.ui.R.drawable.ic_expand_less_black_24dp); - } else { - mOptionView.setImageResource(org.chromium.ui.R.drawable.ic_expand_more_black_24dp); + private void configureExpandedCollapsed(boolean shouldExpand, boolean isFirstSetup) { + if (isFirstSetup || mTileContainerView.isExpanded() != shouldExpand) { + if (shouldExpand) { + mOptionView.setImageResource(org.chromium.ui.R.drawable.ic_expand_less_black_24dp); + } else { + mOptionView.setImageResource(org.chromium.ui.R.drawable.ic_expand_more_black_24dp); + } + String collapseOrExpandedText = getContext().getResources().getString(shouldExpand + ? R.string.accessibility_expanded + : R.string.accessibility_collapsed); + String description = getContext().getResources().getString( + R.string.search_resumption_module_title_short); + mHeaderView.setContentDescription(description + collapseOrExpandedText); } - String collapseOrExpandedText = getContext().getResources().getString( - shouldExpand ? R.string.accessibility_expanded : R.string.accessibility_collapsed); - String description = getContext().getResources().getString( - R.string.search_resumption_module_title_short); - mHeaderView.setContentDescription(description + collapseOrExpandedText); + if (mTileContainerView.isExpanded() == shouldExpand) return; - mTileContainerView.configureExpandedCollapsed(shouldExpand, isAnimationEnabled); + mTileContainerView.configureExpandedCollapsed( + shouldExpand, !isFirstSetup /* isAnimationEnabled */); } }
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/FREMobileIdentityConsistencyFieldTrial.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/FREMobileIdentityConsistencyFieldTrial.java index e0432d11..b1317d93 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/FREMobileIdentityConsistencyFieldTrial.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/FREMobileIdentityConsistencyFieldTrial.java
@@ -42,6 +42,27 @@ public static final String OLD_FRE_WITH_UMA_DIALOG_GROUP = "OldFreWithUmaDialog6"; /** + * Shows the new flow with separate sign-in and sync pages. Uses the new initialization logic + * that doesn't require native initialization to be finished for showing continue/dismiss + * buttons on the welcome screen. + */ + @VisibleForTesting + public static final String INITIALIZATION_FLOW_NEW_GROUP = "InitializationFlowNew"; + /** + * Shows the new flow with separate sign-in and sync pages. Uses the old initialization logic + * in which continue/dismiss buttons on the welcome screen are shown after native is + * initialized. This group is used to check the effect of the delay introduced by the native + * initialization. + */ + public static final String INITIALIZATION_FLOW_OLD_GROUP = "InitializationFlowOld"; + /** + * Shows the flow without the sign-in page but with UMA controls in a dialog. + * This group is used as control for {@link #INITIALIZATION_FLOW_NEW_GROUP} and + * {@link #INITIALIZATION_FLOW_OLD_GROUP}. + */ + private static final String INITIALIZATION_FLOW_CONTROL_GROUP = "InitializationFlowControl"; + + /** * The group variation values should be consecutive starting from zero. WELCOME_TO_CHROME acts * as the control group of the experiment. * If a new group needs to be added then another control group must also be added. @@ -111,10 +132,17 @@ if (CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_DISABLE_SIGNIN_FRE)) { return false; } + if (CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_ENABLE_SIGNIN_FRE)) { + return true; + } + if (getFirstRunTrialGroup().equals(INITIALIZATION_FLOW_NEW_GROUP) + || getFirstRunTrialGroup().equals(INITIALIZATION_FLOW_OLD_GROUP)) { + return true; + } + // Group names were changed from 'Enabled' to 'Enabled2' starting from Beta experiment. // getFirstRunTrialGroup.startWith() matches old groups alongside new groups. - return CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_ENABLE_SIGNIN_FRE) - || getFirstRunTrialGroup().startsWith("Enabled"); + return getFirstRunTrialGroup().startsWith("Enabled"); } @MainThread @@ -123,7 +151,16 @@ if (CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_DISABLE_SIGNIN_FRE)) { return false; } - return OLD_FRE_WITH_UMA_DIALOG_GROUP.equals(getFirstRunTrialGroup()); + return OLD_FRE_WITH_UMA_DIALOG_GROUP.equals(getFirstRunTrialGroup()) + || INITIALIZATION_FLOW_CONTROL_GROUP.equals(getFirstRunTrialGroup()); + } + + @MainThread + public static boolean shouldUseNewInitializationFlow() { + if (CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_DISABLE_SIGNIN_FRE)) { + return false; + } + return getFirstRunTrialGroup().equals(INITIALIZATION_FLOW_NEW_GROUP); } @CalledByNative
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc index b41064e..0d31842f4 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -91,9 +91,8 @@ return prefs_->GetValue(key, value); } -std::unique_ptr<base::DictionaryValue> SupervisedUserPrefStore::GetValues() - const { - return prefs_->AsDictionaryValue(); +base::Value::Dict SupervisedUserPrefStore::GetValues() const { + return prefs_->AsDict(); } void SupervisedUserPrefStore::AddObserver(PrefStore::Observer* observer) {
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.h b/chrome/browser/supervised_user/supervised_user_pref_store.h index fa34b3e..242c11c 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.h +++ b/chrome/browser/supervised_user/supervised_user_pref_store.h
@@ -10,6 +10,7 @@ #include "base/callback_list.h" #include "base/observer_list.h" +#include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/supervised_user/supervised_users.h" #include "components/prefs/pref_store.h" @@ -32,7 +33,7 @@ // PrefStore overrides: bool GetValue(const std::string& key, const base::Value** value) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc index d828f4a2..50585b6 100644 --- a/chrome/browser/translate/chrome_translate_client.cc +++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -260,8 +260,7 @@ if (!translate_message_) { translate_message_ = std::make_unique<translate::TranslateMessage>( web_contents(), translate_manager_->GetWeakPtr(), - base::BindOnce(&ChromeTranslateClient::OnTranslateMessageDismissed, - base::Unretained(this))); + base::BindRepeating([]() {})); } translate_message_->ShowTranslateStep(step, source_language, target_language); @@ -433,10 +432,4 @@ } #endif -#if BUILDFLAG(IS_ANDROID) -void ChromeTranslateClient::OnTranslateMessageDismissed() { - translate_message_.reset(); -} -#endif // BUILDFLAG(IS_ANDROID) - WEB_CONTENTS_USER_DATA_KEY_IMPL(ChromeTranslateClient);
diff --git a/chrome/browser/translate/chrome_translate_client.h b/chrome/browser/translate/chrome_translate_client.h index c27ec96a..7bbd12c 100644 --- a/chrome/browser/translate/chrome_translate_client.h +++ b/chrome/browser/translate/chrome_translate_client.h
@@ -146,10 +146,6 @@ bool is_user_gesture); #endif -#if BUILDFLAG(IS_ANDROID) - void OnTranslateMessageDismissed(); -#endif - std::unique_ptr<translate::ContentTranslateDriver> translate_driver_; std::unique_ptr<translate::PerFrameContentTranslateDriver> per_frame_translate_driver_;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3768a06..5d5718d1 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1794,6 +1794,8 @@ "//components/commerce/content/browser:hint", "//components/commerce/core:cart_db_content_proto", "//components/commerce/core:feature_list", + "//components/commerce/core/mojom:mojo_bindings", + "//components/commerce/core/webui", "//components/enterprise/common:download_item_reroute_info", "//components/feedback/proto", "//components/keep_alive_registry",
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java index fcacbf4..0685448 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.browser.firstrun.MobileFreProgress; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.signin.services.FREMobileIdentityConsistencyFieldTrial; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.ProfileDataCache; import org.chromium.chrome.browser.signin.services.SigninManager; @@ -74,7 +75,8 @@ private boolean mDestroyed; private @LoadPoint int mSlowestLoadPoint; - private boolean mNativePolicyAndChildStatusLoaded; + /** Whether the initial load phase has been completed. See {@link #onInitialLoadCompleted}. */ + private boolean mInitialLoadCompleted; private AccountPickerDialogCoordinator mDialogCoordinator; private @Nullable String mSelectedAccountName; @@ -128,42 +130,62 @@ mSlowestLoadPoint = LoadPoint.NATIVE_INITIALIZATION; mDelegate.recordNativeInitializedHistogram(); - checkWhetherNativePolicyAndChildStatusAreLoaded(); + checkWhetherInitialLoadCompleted(); } private void onChildAccountStatusAvailable() { mSlowestLoadPoint = LoadPoint.CHILD_STATUS_LOAD; - checkWhetherNativePolicyAndChildStatusAreLoaded(); + checkWhetherInitialLoadCompleted(); } private void onPolicyLoad() { mSlowestLoadPoint = LoadPoint.POLICY_LOAD; - checkWhetherNativePolicyAndChildStatusAreLoaded(); + checkWhetherInitialLoadCompleted(); } - private void checkWhetherNativePolicyAndChildStatusAreLoaded() { + /** Checks the initial load status. See {@link #onInitialLoadCompleted} for details. */ + private void checkWhetherInitialLoadCompleted() { // This happens asynchronously, so this check is necessary to ensure we don't interact with // the delegate after the mediator is destroyed. See https://crbug.com/1294998. if (mDestroyed) return; - if (mDelegate.getNativeInitializationPromise().isFulfilled() - && mDelegate.getChildAccountStatusSupplier().get() != null - && mDelegate.getPolicyLoadListener().get() != null - && !mNativePolicyAndChildStatusLoaded) { - mNativePolicyAndChildStatusLoaded = true; - onNativeAndPolicyLoaded(mDelegate.getPolicyLoadListener().get()); + if (!shouldUseNewInitializationFlow()) { + // Old initialization flow requires native to be ready before the initial loading + // spinner can be hidden. + if (!mDelegate.getNativeInitializationPromise().isFulfilled()) return; + } + + if (mDelegate.getChildAccountStatusSupplier().get() != null + && mDelegate.getPolicyLoadListener().get() != null && !mInitialLoadCompleted) { + mInitialLoadCompleted = true; + onInitialLoadCompleted(mDelegate.getPolicyLoadListener().get()); + // TODO(https://crbug.com/1353330): Rename this method and the corresponding histogram. mDelegate.recordNativePolicyAndChildStatusLoadedHistogram(); RecordHistogram.recordEnumeratedHistogram( "MobileFre.SlowestLoadPoint", mSlowestLoadPoint, LoadPoint.MAX); } } - void onNativeAndPolicyLoaded(boolean hasPolicies) { + /** + * Called when the initial load phase is completed. + * + * After creation, {@link SigninFirstRunView} displays a loading spinner that is shown until + * policies and the child account status are being checked. If needed, that phase also waits for + * the native to be loaded (for example, if any app restrictions are detected). This method is + * invoked when this initial waiting phase is over and the "Continue" button can be displayed. + * It checks policies and child accounts to decide which version of the UI to display. + * + * @param hasPolicies Whether any enterprise policies have been found on the device. 'true' here + * also means that native has been initialized. + */ + void onInitialLoadCompleted(boolean hasPolicies) { mModel.set(SigninFirstRunProperties.SHOW_INITIAL_LOAD_PROGRESS_SPINNER, false); boolean isSigninDisabledByPolicy = false; boolean isMetricsReportingDisabledByPolicy = false; if (hasPolicies) { + assert mDelegate.getNativeInitializationPromise().isFulfilled() + : "Must wait for native initialization if enterprise policies were found!"; isSigninDisabledByPolicy = IdentityServicesProvider.get() .getSigninManager(Profile.getLastUsedRegularProfile()) @@ -232,9 +254,22 @@ */ private void onContinueAsClicked() { if (isContinueOrDismissClicked()) return; + assert !mModel.get(SigninFirstRunProperties.SHOW_INITIAL_LOAD_PROGRESS_SPINNER) + : "The continue button shouldn't be visible while the load spinner is shown!"; + if (!mModel.get(SigninFirstRunProperties.IS_SIGNIN_SUPPORTED)) { - mDelegate.acceptTermsOfService(mAllowCrashUpload); - mDelegate.advanceToNextPage(); + if (mDelegate.getNativeInitializationPromise().isFulfilled()) { + mDelegate.acceptTermsOfService(mAllowCrashUpload); + mDelegate.advanceToNextPage(); + } else { + // Show the progress spinner while the native finishes loading. + mModel.set(SigninFirstRunProperties.SHOW_SIGNIN_PROGRESS_SPINNER, true); + mDelegate.getNativeInitializationPromise().then(ignored -> { + // When the native is loaded - mark ToS as accepted and move to the next page. + mDelegate.acceptTermsOfService(mAllowCrashUpload); + mDelegate.advanceToNextPage(); + }); + } return; } if (mSelectedAccountName == null) { @@ -242,7 +277,17 @@ return; } - // In all other cases, the button text is "Continue as ...", so mark ToS as accepted. + if (mDelegate.getNativeInitializationPromise().isFulfilled()) { + handleContinueWithNative(); + return; + } + mModel.set(SigninFirstRunProperties.SHOW_SIGNIN_PROGRESS_SPINNER_WITH_TEXT, true); + mDelegate.getNativeInitializationPromise().then(ignored -> { handleContinueWithNative(); }); + } + + private void handleContinueWithNative() { + assert mDelegate.getNativeInitializationPromise().isFulfilled(); + // This is needed to get metrics/crash reports from the sign-in flow itself. mDelegate.acceptTermsOfService(mAllowCrashUpload); if (mModel.get(SigninFirstRunProperties.IS_SELECTED_ACCOUNT_SUPERVISED)) { @@ -250,8 +295,6 @@ mDelegate.advanceToNextPage(); return; } - assert !mModel.get(SigninFirstRunProperties.SHOW_INITIAL_LOAD_PROGRESS_SPINNER) - : "The continue button shouldn't be visible while the load spinner is shown!"; mDelegate.recordFreProgressHistogram( TextUtils.equals(mDefaultAccountName, mSelectedAccountName) ? MobileFreProgress.WELCOME_SIGNIN_WITH_DEFAULT_ACCOUNT @@ -297,6 +340,18 @@ if (isContinueOrDismissClicked()) return; assert !mModel.get(SigninFirstRunProperties.SHOW_INITIAL_LOAD_PROGRESS_SPINNER) : "The dismiss button shouldn't be visible while the load spinner is shown!"; + + if (mDelegate.getNativeInitializationPromise().isFulfilled()) { + handleDismissWithNative(); + return; + } + mModel.set(SigninFirstRunProperties.SHOW_SIGNIN_PROGRESS_SPINNER, true); + mDelegate.getNativeInitializationPromise().then(ignored -> { handleDismissWithNative(); }); + } + + private void handleDismissWithNative() { + assert mDelegate.getNativeInitializationPromise().isFulfilled(); + mDelegate.recordFreProgressHistogram(MobileFreProgress.WELCOME_DISMISS); mDelegate.acceptTermsOfService(mAllowCrashUpload); if (IdentityServicesProvider.get() @@ -394,4 +449,8 @@ // Apply spans to footer string. return SpanApplier.applySpans(footerString, spans.toArray(new SpanApplier.SpanInfo[0])); } + + private static boolean shouldUseNewInitializationFlow() { + return FREMobileIdentityConsistencyFieldTrial.shouldUseNewInitializationFlow(); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java index 944dccc6c..3c24a82 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinator.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.toolbar.optional_button; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; @@ -15,11 +16,15 @@ import org.chromium.base.Callback; import org.chromium.base.supplier.BooleanSupplier; import org.chromium.chrome.browser.toolbar.ButtonData; +import org.chromium.chrome.browser.toolbar.ButtonDataImpl; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant; import org.chromium.chrome.browser.user_education.IPHCommandBuilder; import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.components.browser_ui.widget.highlight.PulseDrawable.Bounds; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter.HighlightParams; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter.HighlightShape; +import org.chromium.components.feature_engagement.FeatureConstants; +import org.chromium.components.feature_engagement.Tracker; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.widget.ViewRectProvider; @@ -35,6 +40,7 @@ private final OptionalButtonMediator mMediator; private final OptionalButtonView mView; private final UserEducationHelper mUserEducationHelper; + private final Tracker mFeatureEngagementTracker; private Callback<Integer> mTransitionFinishedCallback; private IPHCommandBuilder mIphCommandBuilder; @@ -59,7 +65,8 @@ * determine if said transition should be animated or not. */ public OptionalButtonCoordinator(View view, UserEducationHelper userEducationHelper, - ViewGroup transitionRoot, BooleanSupplier isAnimationAllowedPredicate) { + ViewGroup transitionRoot, BooleanSupplier isAnimationAllowedPredicate, + Tracker featureEngagementTracker) { mUserEducationHelper = userEducationHelper; PropertyModel model = new PropertyModel.Builder(OptionalButtonProperties.ALL_KEYS) @@ -77,6 +84,7 @@ PropertyModelChangeProcessor.create(model, mView, OptionalButtonViewBinder::bind); mMediator = new OptionalButtonMediator(model); + mFeatureEngagementTracker = featureEngagementTracker; } public void setPaddingStart(int paddingStart) { @@ -120,6 +128,17 @@ mIphCommandBuilder = null; } + if (buttonData != null + && buttonData.getButtonSpec().getButtonVariant() + == AdaptiveToolbarButtonVariant.PRICE_TRACKING + && buttonData.getButtonSpec().getActionChipLabelResId() != Resources.ID_NULL) { + if (!mFeatureEngagementTracker.isInitialized() + || !mFeatureEngagementTracker.shouldTriggerHelpUI( + FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING_ACTION_CHIP)) { + ((ButtonDataImpl) buttonData).updateActionChipResourceId(Resources.ID_NULL); + } + } + mMediator.updateButton(buttonData); } @@ -193,6 +212,16 @@ mTransitionFinishedCallback.onResult(transitionType); } + if (transitionType == TransitionType.EXPANDING_ACTION_CHIP) { + // Record an event in feature engagement to limit the amount of times we show the action + // chip. + mFeatureEngagementTracker.addOnInitializedCallback(isReady -> { + if (!isReady) return; + mFeatureEngagementTracker.dismissed( + FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING_ACTION_CHIP); + }); + } + if (mIphCommandBuilder != null) { mUserEducationHelper.requestShowIPH(mIphCommandBuilder.build()); mIphCommandBuilder = null;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinatorTest.java index cc15a16..cf3d7da 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinatorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonCoordinatorTest.java
@@ -42,7 +42,7 @@ import org.chromium.chrome.browser.toolbar.optional_button.OptionalButtonCoordinator.TransitionType; import org.chromium.chrome.browser.user_education.IPHCommandBuilder; import org.chromium.chrome.browser.user_education.UserEducationHelper; - +import org.chromium.components.feature_engagement.Tracker; /** * Unit tests for OptionalButtonCoordinator. */ @@ -58,6 +58,8 @@ private UserEducationHelper mMockUserEducationHelper; @Mock private Callback<Transition> mMockBeginDelayedTransition; + @Mock + private Tracker mMockTracker; @Captor ArgumentCaptor<Callback<Integer>> mCallbackArgumentCaptor; @@ -68,8 +70,9 @@ public void setUp() { MockitoAnnotations.initMocks(this); - mOptionalButtonCoordinator = new OptionalButtonCoordinator(mMockOptionalButtonView, - mMockUserEducationHelper, mMockRootView, mMockIsAnimationAllowedDelegate); + mOptionalButtonCoordinator = + new OptionalButtonCoordinator(mMockOptionalButtonView, mMockUserEducationHelper, + mMockRootView, mMockIsAnimationAllowedDelegate, mMockTracker); } @Test
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 6ca8e94..0634733d 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
@@ -84,6 +84,7 @@ import org.chromium.components.browser_ui.widget.animation.Interpolators; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.feature_engagement.EventConstants; +import org.chromium.components.feature_engagement.Tracker; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.ViewUtils; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -2565,8 +2566,11 @@ } }; + Profile profile = Profile.getLastUsedRegularProfile(); + Tracker featureEngagementTracker = TrackerFactory.getTrackerForProfile(profile); mOptionalButton = new OptionalButtonCoordinator(optionalButton, userEducationHelper, - /* transitionRoot= */ mToolbarButtonsContainer, isAnimationAllowedPredicate); + /* transitionRoot= */ mToolbarButtonsContainer, isAnimationAllowedPredicate, + featureEngagementTracker); // Set the button's background to the same color as the URL bar background. This color // is only used when showing dynamic actions.
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index eb8fa9f..f32dfbf 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -672,7 +672,8 @@ } else { // Send the url to the current primary browser. ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } } else { NavigateParams params(profile, url, transition);
diff --git a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc index a988c9c..26a215f 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/new_window_delegate.h" +#include "ash/strings/grit/ash_strings.h" #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" @@ -24,6 +25,7 @@ #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h" #include "chrome/browser/extensions/context_menu_matcher.h" #include "chrome/browser/extensions/menu_manager.h" +#include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" @@ -36,6 +38,7 @@ #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/settings/ash/app_management/app_management_uma.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/ui/base/tablet_state.h" #include "components/app_constants/constants.h" #include "components/services/app_service/public/cpp/types_util.h" #include "content/public/browser/browser_task_traits.h" @@ -55,6 +58,27 @@ model_updater->RequestAppListSort(order); } +bool MenuItemHasLauncherContext(const extensions::MenuItem* item) { + return item->contexts().Contains(extensions::MenuItem::LAUNCHER); +} + +apps::WindowMode ConvertUseLaunchTypeCommandToWindowMode(int command_id) { + DCHECK(command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && + command_id < ash::USE_LAUNCH_TYPE_COMMAND_END); + switch (command_id) { + case ash::USE_LAUNCH_TYPE_REGULAR: + return apps::WindowMode::kBrowser; + case ash::USE_LAUNCH_TYPE_WINDOW: + return apps::WindowMode::kWindow; + case ash::USE_LAUNCH_TYPE_TABBED_WINDOW: + return apps::WindowMode::kTabbedWindow; + case ash::USE_LAUNCH_TYPE_PINNED: + case ash::USE_LAUNCH_TYPE_FULLSCREEN: + default: + return apps::WindowMode::kUnknown; + } +} + void CreateNewWindow(bool incognito, bool post_task) { if (post_task) { content::GetUIThreadTaskRunner({})->PostTask( @@ -232,9 +256,6 @@ default: if (command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && command_id < ash::USE_LAUNCH_TYPE_COMMAND_END) { - launch_new_string_id_ = - apps::StringIdForUseLaunchTypeCommand(command_id); - if (app_type_ == apps::AppType::kWeb && command_id == ash::USE_LAUNCH_TYPE_TABBED_WINDOW) { proxy_->SetWindowMode(app_id(), @@ -263,25 +284,6 @@ } } -ui::ImageModel AppServiceContextMenu::GetIconForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - const gfx::VectorIcon& icon = - GetMenuItemVectorIcon(command_id, launch_new_string_id_); - return ui::ImageModel::FromVectorIcon( - icon, apps::GetColorIdForMenuItemIcon(), ash::kAppContextMenuIconSize); - } - return AppContextMenu::GetIconForCommandId(command_id); -} - -std::u16string AppServiceContextMenu::GetLabelForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - return l10n_util::GetStringUTF16(launch_new_string_id_); - } - return AppContextMenu::GetLabelForCommandId(command_id); -} - bool AppServiceContextMenu::IsCommandIdChecked(int command_id) const { // StandaloneBrowserExtension handles its own context menus. Forward to that // class. @@ -301,15 +303,17 @@ }); return user_window_mode != apps::WindowMode::kUnknown && user_window_mode == - apps::ConvertLaunchTypeCommandToWindowMode(command_id); + ConvertUseLaunchTypeCommandToWindowMode(command_id); } return AppContextMenu::IsCommandIdChecked(command_id); case apps::AppType::kChromeApp: if (command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && command_id < ash::USE_LAUNCH_TYPE_COMMAND_END) { - return controller()->GetExtensionLaunchType(profile(), app_id()) == - apps::ConvertLaunchTypeCommandToExtensionLaunchType(command_id); + return static_cast<int>( + controller()->GetExtensionLaunchType(profile(), app_id())) + + ash::USE_LAUNCH_TYPE_COMMAND_START == + command_id; } else if (extensions::ContextMenuMatcher::IsExtensionsCustomCommandId( command_id)) { return extension_menu_items_->IsCommandIdChecked(command_id); @@ -345,21 +349,15 @@ return AppContextMenu::IsCommandIdEnabled(command_id); } -bool AppServiceContextMenu::IsItemForCommandIdDynamic(int command_id) const { - return command_id == ash::LAUNCH_NEW || - AppContextMenu::IsItemForCommandIdDynamic(command_id); -} - void AppServiceContextMenu::OnGetMenuModel( GetMenuModelCallback callback, apps::mojom::MenuItemsPtr menu_items) { auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); submenu_ = std::make_unique<ui::SimpleMenuModel>(this); size_t index = 0; - - if (apps::PopulateNewItemFromMojoMenuItems(menu_items->items, - menu_model.get(), submenu_.get(), - &launch_new_string_id_)) { + if (apps::PopulateNewItemFromMojoMenuItems( + menu_items->items, menu_model.get(), submenu_.get(), + base::BindOnce(&AppServiceContextMenu::GetMenuItemVectorIcon))) { index = 1; } @@ -434,7 +432,7 @@ ui::SimpleMenuModel* menu_model) { extension_menu_items_ = std::make_unique<extensions::ContextMenuMatcher>( profile(), this, menu_model, - base::BindRepeating(apps::MenuItemHasLauncherContext)); + base::BindRepeating(MenuItemHasLauncherContext)); // Assign unique IDs to commands added by the app itself. int index = ash::USE_LAUNCH_TYPE_COMMAND_END; @@ -466,7 +464,7 @@ // Web apps and standalone browser hosted apps can only toggle between // kWindow and kBrowser. apps::WindowMode user_window_mode = - apps::ConvertLaunchTypeCommandToWindowMode(command_id); + ConvertUseLaunchTypeCommandToWindowMode(command_id); if (user_window_mode != apps::WindowMode::kUnknown) { proxy_->SetWindowMode( app_id(),
diff --git a/chrome/browser/ui/app_list/app_service/app_service_context_menu.h b/chrome/browser/ui/app_list/app_service/app_service_context_menu.h index 745daccf..dc351f0 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_context_menu.h +++ b/chrome/browser/ui/app_list/app_service/app_service_context_menu.h
@@ -45,11 +45,8 @@ // AppContextMenu overrides: void GetMenuModel(GetMenuModelCallback callback) override; void ExecuteCommand(int command_id, int event_flags) override; - ui::ImageModel GetIconForCommandId(int command_id) const override; - std::u16string GetLabelForCommandId(int command_id) const override; bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; - bool IsItemForCommandIdDynamic(int command_id) const override; private: void OnGetMenuModel(GetMenuModelCallback callback, @@ -89,11 +86,6 @@ // Where this item is being shown (e.g. the apps grid or recent apps). const ash::AppListItemContext item_context_; - // String id for the `LAUNCH_NEW` command / menu item tracked so the menu icon - // and label can be changed dynamically after the app launch type changes - // using the launch new item submenu. - int launch_new_string_id_ = 0; - base::WeakPtrFactory<AppServiceContextMenu> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc index f141518e..6a5c29d 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -72,7 +72,6 @@ constexpr bool kUseWeightedRatio = false; constexpr bool kUseEditDistance = false; constexpr double kRelevanceThreshold = 0.32; -constexpr double kPartialMatchPenaltyRate = 0.9; // Default recommended apps in descending order of priority. constexpr const char* const ranked_default_app_ids[] = { @@ -219,7 +218,7 @@ FuzzyTokenizedStringMatch match; for (auto& curr_text : tokenized_indexed_searchable_text_) { if (match.Relevance(query, *curr_text, kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate) >= + kUseEditDistance) >= std::max(kRelevanceThreshold, relevance_threshold())) { return true; } @@ -604,9 +603,8 @@ MaybeAddResult(&new_results, std::move(result), &seen_or_filtered_apps); } else { FuzzyTokenizedStringMatch match; - const double relevance = - match.Relevance(query_terms, *indexed_name, kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate); + const double relevance = match.Relevance( + query_terms, *indexed_name, kUseWeightedRatio, kUseEditDistance); if (relevance >= kRelevanceThreshold || app->MatchSearchableText(query_terms, use_exact_match)) { std::unique_ptr<AppResult> result = app->data_source()->CreateResult(
diff --git a/chrome/browser/ui/app_list/search/games/game_provider.cc b/chrome/browser/ui/app_list/search/games/game_provider.cc index 0668db1..b730dd0 100644 --- a/chrome/browser/ui/app_list/search/games/game_provider.cc +++ b/chrome/browser/ui/app_list/search/games/game_provider.cc
@@ -40,7 +40,6 @@ // Parameters for FuzzyTokenizedStringMatch. constexpr bool kUseWeightedRatio = false; constexpr bool kUseEditDistance = false; -constexpr double kPartialMatchPenaltyRate = 0.9; constexpr double kRelevanceThreshold = 0.65; constexpr size_t kMaxResults = 3u; @@ -83,8 +82,9 @@ // text in a separate post-processing step. std::u16string GetStrippedText(const std::u16string& text) { std::u16string stripped_text; - // In order, these are: apostrophe, left quote, right quote, TM, circled R. - base::RemoveChars(text, u"\'\u2018\u2019\u2122\u24C7", &stripped_text); + // In order, these are: apostrophe, left quote, right quote, TM, registered + // sign. + base::RemoveChars(text, u"\'\u2018\u2019\u2122\u00AE", &stripped_text); return stripped_text; } @@ -101,7 +101,7 @@ FuzzyTokenizedStringMatch match; return match.Relevance(tokenized_query, tokenized_title, kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate); + kUseEditDistance); } std::vector<std::pair<const apps::Result*, double>> SearchGames(
diff --git a/chrome/browser/ui/app_list/search/games/game_result.cc b/chrome/browser/ui/app_list/search/games/game_result.cc index aefee10..20046f4 100644 --- a/chrome/browser/ui/app_list/search/games/game_result.cc +++ b/chrome/browser/ui/app_list/search/games/game_result.cc
@@ -135,11 +135,6 @@ ui::DispositionFromEventFlags(event_flags)); } -void GameResult::OnColorModeChanged(bool dark_mode_enabled) { - if (uses_generic_icon_) - SetGenericIcon(); -} - void GameResult::UpdateText(const apps::Result& game, const std::u16string& query) { SetTitle(game.GetAppTitle()); @@ -158,7 +153,8 @@ apps::DiscoveryError error) { // TODO(crbug.com/1305880): Report the error to UMA. if (error != apps::DiscoveryError::kSuccess) { - SetGenericIcon(); + // Don't display results that have no icon. + scoring().filter = true; return; } @@ -186,15 +182,4 @@ SetIcon(IconInfo(icon, GetAppIconDimension(), IconShape::kCircle)); } -void GameResult::SetGenericIcon() { - uses_generic_icon_ = true; - const auto color = cros_styles::ResolveColor( - cros_styles::ColorName::kIconColorPrimary, IsDarkModeEnabled(), - /*use_debug_colors=*/false); - const gfx::ImageSkia icon = - gfx::CreateVectorIcon(ash::kGameGenericIcon, kSystemIconDimension, color); - - SetIcon(IconInfo(icon, kSystemIconDimension)); -} - } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/games/game_result.h b/chrome/browser/ui/app_list/search/games/game_result.h index 744deb3..a313670 100644 --- a/chrome/browser/ui/app_list/search/games/game_result.h +++ b/chrome/browser/ui/app_list/search/games/game_result.h
@@ -43,11 +43,8 @@ void Open(int event_flags) override; private: - // ash::ColorModeObserver: - void OnColorModeChanged(bool dark_mode_enabled) override; void UpdateText(const apps::Result& game, const std::u16string& query); void OnIconLoaded(const gfx::ImageSkia& image, apps::DiscoveryError error); - void SetGenericIcon(); Profile* profile_; AppListControllerDelegate* list_controller_; @@ -56,9 +53,6 @@ bool is_icon_masking_allowed_; const int dimension_; - // Whether this game result uses a generic backup icon. - bool uses_generic_icon_ = false; - base::WeakPtrFactory<GameResult> weak_factory_{this}; };
diff --git a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc b/chrome/browser/ui/app_list/search/games/game_result_unittest.cc index 81e0b7cd..94b7007 100644 --- a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc +++ b/chrome/browser/ui/app_list/search/games/game_result_unittest.cc
@@ -54,8 +54,20 @@ int32_t size_hint_in_dip, apps::ResultType result_type, apps::GetIconCallback callback) override { - std::move(callback).Run(GetTestIcon(), apps::DiscoveryError::kSuccess); + if (icons_available_) { + std::move(callback).Run(GetTestIcon(), apps::DiscoveryError::kSuccess); + } else { + std::move(callback).Run(gfx::ImageSkia(), + apps::DiscoveryError::kErrorRequestFailed); + } } + + void set_icons_available(bool icons_available) { + icons_available_ = icons_available; + } + + private: + bool icons_available_ = true; }; apps::Result MakeAppsResult(bool masking_allowed) { @@ -98,6 +110,7 @@ } TEST_F(GameResultTest, Icons) { + // The maskable icon should not be modified from its original form. apps::Result maskable_app = MakeAppsResult(/*masking_allowed=*/true); GameResult maskable_result(profile_.get(), &list_controller_, app_discovery_service_.get(), maskable_app, 0.6, @@ -105,10 +118,10 @@ EXPECT_EQ(maskable_result.icon().dimension, GetAppIconDimension()); EXPECT_EQ(maskable_result.icon().shape, ash::SearchResultIconShape::kCircle); - // The maskable icon should not be modified from its original form. EXPECT_TRUE(gfx::BitmapsAreEqual(*maskable_result.icon().icon.bitmap(), *GetTestIcon().bitmap())); + // The non-maskable icon must be resized and placed on a white circle. apps::Result non_maskable_app = MakeAppsResult(/*masking_allowed=*/false); GameResult non_maskable_result(profile_.get(), &list_controller_, app_discovery_service_.get(), non_maskable_app, @@ -117,9 +130,17 @@ EXPECT_EQ(non_maskable_result.icon().dimension, GetAppIconDimension()); EXPECT_EQ(non_maskable_result.icon().shape, ash::SearchResultIconShape::kCircle); - // The non-maskable icon must be resized and placed on a white circle. EXPECT_TRUE(gfx::BitmapsAreEqual(*non_maskable_result.icon().icon.bitmap(), *GetExpectedNonMaskableIcon().bitmap())); + + // If there is no icon, then the result should be filtered out. + app_discovery_service_->set_icons_available(false); + apps::Result no_icon_app = MakeAppsResult(/*masking_allowed=*/false); + GameResult no_icon_result(profile_.get(), &list_controller_, + app_discovery_service_.get(), no_icon_app, 0.6, + u"SomeGame"); + + EXPECT_TRUE(no_icon_result.scoring().filter); } } // namespace app_list
diff --git a/chrome/browser/ui/ash/app_access_notifier.cc b/chrome/browser/ui/ash/app_access_notifier.cc index f4da269..481ac0f 100644 --- a/chrome/browser/ui/ash/app_access_notifier.cc +++ b/chrome/browser/ui/ash/app_access_notifier.cc
@@ -7,7 +7,11 @@ #include <string> #include "ash/constants/ash_features.h" +#include "ash/root_window_controller.h" +#include "ash/shell.h" #include "ash/system/privacy/privacy_indicators_controller.h" +#include "ash/system/status_area_widget.h" +#include "ash/system/unified/unified_system_tray.h" #include "base/check.h" #include "base/containers/cxx20_erase.h" #include "base/strings/string_util.h" @@ -127,6 +131,17 @@ camera_is_used, microphone_is_used, base::MakeRefCounted<ash::PrivacyIndicatorsNotificationDelegate>( launch_app, launch_settings)); + + DCHECK(ash::Shell::HasInstance()); + for (auto* root_window_controller : + ash::Shell::Get()->GetAllRootWindowControllers()) { + DCHECK(root_window_controller && + root_window_controller->GetStatusAreaWidget()); + + root_window_controller->GetStatusAreaWidget() + ->unified_system_tray() + ->UpdatePrivacyIndicatorsTrayItem(camera_is_used, microphone_is_used); + } } if (microphone_is_used) {
diff --git a/chrome/browser/ui/ash/app_access_notifier_unittest.cc b/chrome/browser/ui/ash/app_access_notifier_unittest.cc index 7967ae1..6479283 100644 --- a/chrome/browser/ui/ash/app_access_notifier_unittest.cc +++ b/chrome/browser/ui/ash/app_access_notifier_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "ash/constants/ash_features.h" +#include "ash/test/ash_test_helper.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "components/account_id/account_id.h" @@ -18,6 +19,7 @@ #include "components/services/app_service/public/cpp/capability_access_update.h" #include "components/user_manager/fake_user_manager.h" #include "components/user_manager/scoped_user_manager.h" +#include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/message_center/message_center.h" @@ -50,12 +52,11 @@ ~AppAccessNotifierTest() override = default; void SetUp() override { - testing::Test::SetUp(); - message_center::MessageCenter::Initialize(); - scoped_feature_list_.InitWithFeatureState( ash::features::kPrivacyIndicators, IsPrivacyIndicatorsFeatureEnabled()); + ash_test_helper_.SetUp(); + auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>(); fake_user_manager_ = fake_user_manager.get(); scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( @@ -69,8 +70,7 @@ void TearDown() override { microphone_mute_notification_delegate_.reset(); - message_center::MessageCenter::Shutdown(); - testing::Test::TearDown(); + ash_test_helper_.TearDown(); } bool IsPrivacyIndicatorsFeatureEnabled() const { return GetParam(); } @@ -184,6 +184,12 @@ user_manager::FakeUserManager* fake_user_manager_ = nullptr; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; + // This instance is needed for setting up `ash_test_helper_`. + // See //docs/threading_and_tasks_testing.md. + content::BrowserTaskEnvironment task_environment_; + + ash::AshTestHelper ash_test_helper_; + base::test::ScopedFeatureList scoped_feature_list_; };
diff --git a/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc b/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc index d0ab7723..bd07d94 100644 --- a/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc +++ b/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc
@@ -287,7 +287,8 @@ GURL url_to_open = ConvertArcUrlToExternalFileUrlIfNeeded(url); ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url_to_open, ash::NewWindowDelegate::OpenUrlFrom::kArc); + url_to_open, ash::NewWindowDelegate::OpenUrlFrom::kArc, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } void ArcOpenUrlDelegateImpl::OpenWebAppFromArc(const GURL& url) {
diff --git a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc index 1a6824e..a400c0d 100644 --- a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc +++ b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc
@@ -171,7 +171,8 @@ // browser tab and Assistant UI state will be updated downstream to respect // |in_background|. ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } }
diff --git a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc index 85c8028..46bfbe8 100644 --- a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc +++ b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc
@@ -311,7 +311,7 @@ auto* download_prefs = DownloadPrefs::FromBrowserContext(browser()->profile()); const base::FilePath removable_path = - chromeos::CrosDisksClient::GetRemovableDiskMountPoint(); + ash::CrosDisksClient::GetRemovableDiskMountPoint(); const base::FilePath invalid_path = removable_path.Append(FILE_PATH_LITERAL("backup")); download_prefs->SetDownloadPath(invalid_path);
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc index c6cdbd1..8e8b8218 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -311,7 +311,23 @@ std::move(closure).Run(window); } -void ChromeNewWindowClient::OpenUrl(const GURL& url, OpenUrlFrom from) { +namespace { +WindowOpenDisposition ToWindowOpenDisposition( + ash::NewWindowDelegate::Disposition disposition) { + switch (disposition) { + case ash::NewWindowDelegate::Disposition::kNewForegroundTab: + return WindowOpenDisposition::NEW_FOREGROUND_TAB; + case ash::NewWindowDelegate::Disposition::kNewWindow: + return WindowOpenDisposition::NEW_WINDOW; + case ash::NewWindowDelegate::Disposition::kSwitchToTab: + return WindowOpenDisposition::SWITCH_TO_TAB; + } +} +} // namespace + +void ChromeNewWindowClient::OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) { // Opens a URL in a new tab. If the URL is for a chrome://settings page, // opens settings in a new window. Profile* profile = ProfileManager::GetActiveUserProfile(); @@ -337,6 +353,7 @@ profile, url, ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API)); + navigate_params.disposition = ToWindowOpenDisposition(disposition); // If the |from| is kUserInteraction, then the page will load with a user // activation. This means it will be able to autoplay media without
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.h b/chrome/browser/ui/ash/chrome_new_window_client.h index c6db2bd..a238e98 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.h +++ b/chrome/browser/ui/ash/chrome_new_window_client.h
@@ -33,7 +33,9 @@ aura::Window* source_window, const ui::OSExchangeData& drop_data, NewWindowForDetachingTabCallback closure) override; - void OpenUrl(const GURL& url, OpenUrlFrom from) override; + void OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) override; void OpenCalculator() override; void OpenFileManager() override; void OpenDownloadsFolder() override;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 6c9c130..8a8716a6 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -143,7 +143,8 @@ void ChromeShellDelegate::OpenKeyboardShortcutHelpPage() const { ash::NewWindowDelegate::GetPrimary()->OpenUrl( GURL(kKeyboardShortcutHelpPageUrl), - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); } bool ChromeShellDelegate::CanGoBack(gfx::NativeWindow window) const {
diff --git a/chrome/browser/ui/ash/crosapi_new_window_delegate.cc b/chrome/browser/ui/ash/crosapi_new_window_delegate.cc index ba66db4b..c2c9c824 100644 --- a/chrome/browser/ui/ash/crosapi_new_window_delegate.cc +++ b/chrome/browser/ui/ash/crosapi_new_window_delegate.cc
@@ -15,7 +15,8 @@ namespace { -crosapi::mojom::OpenUrlFrom ToMojom(ash::NewWindowDelegate::OpenUrlFrom from) { +crosapi::mojom::OpenUrlFrom OpenUrlFromToMojom( + ash::NewWindowDelegate::OpenUrlFrom from) { switch (from) { case ash::NewWindowDelegate::OpenUrlFrom::kUnspecified: case ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction: @@ -25,6 +26,19 @@ } } +crosapi::mojom::OpenUrlParams::WindowOpenDisposition DispositionToMojom( + ash::NewWindowDelegate::Disposition disposition) { + switch (disposition) { + case ash::NewWindowDelegate::Disposition::kNewForegroundTab: + return crosapi::mojom::OpenUrlParams::WindowOpenDisposition:: + kNewForegroundTab; + case ash::NewWindowDelegate::Disposition::kNewWindow: + return crosapi::mojom::OpenUrlParams::WindowOpenDisposition::kNewWindow; + case ash::NewWindowDelegate::Disposition::kSwitchToTab: + return crosapi::mojom::OpenUrlParams::WindowOpenDisposition::kSwitchToTab; + } +} + } // namespace CrosapiNewWindowDelegate::WindowObserver::WindowObserver( @@ -139,8 +153,11 @@ std::move(closure)); } -void CrosapiNewWindowDelegate::OpenUrl(const GURL& url, OpenUrlFrom from) { - crosapi::BrowserManager::Get()->OpenUrl(url, ToMojom(from)); +void CrosapiNewWindowDelegate::OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) { + crosapi::BrowserManager::Get()->OpenUrl(url, OpenUrlFromToMojom(from), + DispositionToMojom(disposition)); } void CrosapiNewWindowDelegate::OpenCalculator() {
diff --git a/chrome/browser/ui/ash/crosapi_new_window_delegate.h b/chrome/browser/ui/ash/crosapi_new_window_delegate.h index 3924ae1..2bbb699d 100644 --- a/chrome/browser/ui/ash/crosapi_new_window_delegate.h +++ b/chrome/browser/ui/ash/crosapi_new_window_delegate.h
@@ -32,7 +32,9 @@ aura::Window* source_window, const ui::OSExchangeData& drop_data, NewWindowForDetachingTabCallback closure) override; - void OpenUrl(const GURL& url, OpenUrlFrom from) override; + void OpenUrl(const GURL& url, + OpenUrlFrom from, + Disposition disposition) override; void OpenCalculator() override; void OpenFileManager() override; void OpenDownloadsFolder() override;
diff --git a/chrome/browser/ui/ash/desks/desks_client.cc b/chrome/browser/ui/ash/desks/desks_client.cc index 46bba5a..021c382b 100644 --- a/chrome/browser/ui/ash/desks/desks_client.cc +++ b/chrome/browser/ui/ash/desks/desks_client.cc
@@ -334,11 +334,14 @@ void DesksClient::LaunchEmptyDesk(LaunchDeskCallback callback, const std::u16string& customized_desk_name) { - desks_controller_->CreateNewDeskForTemplate( - /*activate_desk=*/true, - base::BindOnce(&DesksClient::OnLaunchEmptyDesk, - weak_ptr_factory_.GetWeakPtr(), std::move(callback)), - customized_desk_name); + if (!desks_controller_->CanCreateDesks()) { + std::move(callback).Run(kMaximumDesksOpenedError, {}); + return; + } + + const ash::Desk* new_desk = desks_controller_->CreateNewDeskForTemplate( + /*activate_desk=*/true, customized_desk_name); + std::move(callback).Run(/*error=*/"", new_desk->uuid()); } void DesksClient::RemoveDesk(const base::GUID& desk_uuid, @@ -517,63 +520,42 @@ std::u16string customized_desk_name, base::Time time_launch_started, desks_storage::DeskModel::GetEntryByUuidStatus status, - std::unique_ptr<ash::DeskTemplate> entry) { + std::unique_ptr<ash::DeskTemplate> saved_desk) { if (status != desks_storage::DeskModel::GetEntryByUuidStatus::kOk) { std::move(callback).Run(kStorageError, {}); return; } - // Launch the windows as specified in the template to a new desk. - const auto template_name = entry->template_name(); - const bool activate_desk = entry->type() == ash::DeskTemplateType::kTemplate; - desks_controller_->CreateNewDeskForTemplate( - activate_desk, - base::BindOnce(&DesksClient::OnCreateAndActivateNewDeskForTemplate, - weak_ptr_factory_.GetWeakPtr(), std::move(entry), - std::move(callback), time_launch_started), - // We prioritize `customized_desk_name` over `template_name`. An example - // is that for call center application use case, we launch the same - // template for different customer and assign desk name to be customer's - // name. - customized_desk_name.empty() ? template_name : customized_desk_name); -} - -void DesksClient::OnCreateAndActivateNewDeskForTemplate( - std::unique_ptr<ash::DeskTemplate> desk_template, - LaunchDeskCallback callback, - base::Time time_launch_started, - const ash::Desk* new_desk) { - if (new_desk == nullptr) { - // This will only fail if the number of desks is at a maximum. + if (!desks_controller_->CanCreateDesks()) { std::move(callback).Run(kMaximumDesksOpenedError, {}); return; } - DCHECK(desk_template); - if (!desk_template->desk_restore_data()) { + // We prioritize `customized_desk_name` over the saved desk's name. An example + // is that for call center application use case, we launch the same template + // for different customer and assign desk name to be customer's name. + const auto& template_name = customized_desk_name.empty() + ? saved_desk->template_name() + : customized_desk_name; + const bool activate_desk = + saved_desk->type() == ash::DeskTemplateType::kTemplate; + const ash::Desk* new_desk = + desks_controller_->CreateNewDeskForTemplate(activate_desk, template_name); + + if (!saved_desk->desk_restore_data()) { std::move(callback).Run(kMissingTemplateDataError, {}); return; } - // Copy the index of the newly created desk to the template. This ensures that - // apps appear on the right desk even if the user switches to another. - desk_template->SetDeskIndex(desks_controller_->GetDeskIndex(new_desk)); + // Copy the index of the newly created desk to the saved desk. This ensures + // that apps appear on the right desk even if the user switches to another. + saved_desk->SetDeskIndex(desks_controller_->GetDeskIndex(new_desk)); - LaunchAppsFromTemplate(std::move(desk_template), time_launch_started, + // Launch the windows as specified in the saved desk to a new desk. + LaunchAppsFromTemplate(std::move(saved_desk), time_launch_started, base::TimeDelta()); std::move(callback).Run("", new_desk->uuid()); } -void DesksClient::OnLaunchEmptyDesk(LaunchDeskCallback callback, - const ash::Desk* new_desk) { - if (!new_desk) { - // This will only fail if the number of desks is at a maximum. - std::move(callback).Run(kMaximumDesksOpenedError, {}); - return; - } - - std::move(callback).Run(/*error=*/"", new_desk->uuid()); -} - void DesksClient::OnCaptureActiveDeskAndSaveTemplate( DesksClient::CaptureActiveDeskAndSaveTemplateCallback callback, std::unique_ptr<ash::DeskTemplate> desk_template,
diff --git a/chrome/browser/ui/ash/desks/desks_client.h b/chrome/browser/ui/ash/desks/desks_client.h index abe35ab..818238e 100644 --- a/chrome/browser/ui/ash/desks/desks_client.h +++ b/chrome/browser/ui/ash/desks/desks_client.h
@@ -179,20 +179,7 @@ std::u16string customized_desk_name, base::Time time_launch_started, desks_storage::DeskModel::GetEntryByUuidStatus status, - std::unique_ptr<ash::DeskTemplate> entry); - - // Callback function that is run after a desk is created for a template, or - // has failed to be created. - void OnCreateAndActivateNewDeskForTemplate( - std::unique_ptr<ash::DeskTemplate> desk_template, - LaunchDeskCallback callback, - base::Time time_launch_started, - const ash::Desk* new_desk); - - // Callback function that is run after a desk is created, or has failed to - // be created. - void OnLaunchEmptyDesk(LaunchDeskCallback callback, - const ash::Desk* new_desk); + std::unique_ptr<ash::DeskTemplate> saved_desk); // Callback function that allows the |CaptureActiveDeskAndSaveTemplate| // |callback| to be called as a |desks_storage::AddOrUpdateEntryCallback|.
diff --git a/chrome/browser/ui/ash/projector/OWNERS b/chrome/browser/ui/ash/projector/OWNERS new file mode 100644 index 0000000..174c491 --- /dev/null +++ b/chrome/browser/ui/ash/projector/OWNERS
@@ -0,0 +1 @@ +file://ash/projector/OWNERS
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc index 2e297a7..fd3982b0 100644 --- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc +++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
@@ -9,10 +9,13 @@ #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" +#include "base/strings/string_util.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/extension_apps_utils.h" #include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/ash/app_restore/full_restore_service.h" +#include "chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.h" #include "chrome/browser/ash/borealis/borealis_window_manager.h" #include "chrome/browser/ash/crosapi/browser_manager.h" #include "chrome/browser/ash/crostini/crostini_manager.h" @@ -27,12 +30,16 @@ #include "chrome/browser/extensions/context_menu_matcher.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/extensions/menu_manager.h" +#include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/app_context_menu_delegate.h" +#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/extension_app_utils.h" #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h" #include "chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/views/crostini/crostini_app_restart_dialog.h" #include "chrome/browser/ui/webui/settings/ash/app_management/app_management_uma.h" @@ -40,12 +47,44 @@ #include "components/app_constants/constants.h" #include "content/public/browser/context_menu_params.h" #include "extensions/browser/extension_prefs.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/display/scoped_display_for_new_windows.h" #include "ui/gfx/vector_icon_types.h" namespace { +bool MenuItemHasLauncherContext(const extensions::MenuItem* item) { + return item->contexts().Contains(extensions::MenuItem::LAUNCHER); +} + +apps::WindowMode ConvertLaunchTypeCommandToWindowMode(int command_id) { + switch (command_id) { + case ash::USE_LAUNCH_TYPE_REGULAR: + return apps::WindowMode::kBrowser; + case ash::USE_LAUNCH_TYPE_WINDOW: + return apps::WindowMode::kWindow; + case ash::USE_LAUNCH_TYPE_TABBED_WINDOW: + return apps::WindowMode::kTabbedWindow; + default: + return apps::WindowMode::kUnknown; + } +} + +extensions::LaunchType ConvertLaunchTypeCommandToExtensionLaunchType( + int command_id) { + switch (command_id) { + case ash::USE_LAUNCH_TYPE_PINNED: + return extensions::LAUNCH_TYPE_PINNED; + case ash::USE_LAUNCH_TYPE_REGULAR: + return extensions::LAUNCH_TYPE_REGULAR; + case ash::USE_LAUNCH_TYPE_WINDOW: + return extensions::LAUNCH_TYPE_WINDOW; + case ash::USE_LAUNCH_TYPE_FULLSCREEN: + return extensions::LAUNCH_TYPE_FULLSCREEN; + default: + return extensions::LAUNCH_TYPE_INVALID; + } +} + std::string GetAppId(const ash::ShelfID& shelf_id) { // Remove the ARC shelf group prefix. const arc::ArcAppShelfId arc_shelf_id = @@ -152,7 +191,6 @@ case ash::USE_LAUNCH_TYPE_WINDOW: [[fallthrough]]; case ash::USE_LAUNCH_TYPE_FULLSCREEN: - launch_new_string_id_ = apps::StringIdForUseLaunchTypeCommand(command_id); SetLaunchType(command_id); break; @@ -194,25 +232,6 @@ } } -ui::ImageModel AppServiceShelfContextMenu::GetIconForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - const gfx::VectorIcon& icon = - GetCommandIdVectorIcon(command_id, launch_new_string_id_); - return ui::ImageModel::FromVectorIcon( - icon, apps::GetColorIdForMenuItemIcon(), ash::kAppContextMenuIconSize); - } - return ShelfContextMenu::GetIconForCommandId(command_id); -} - -std::u16string AppServiceShelfContextMenu::GetLabelForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - return l10n_util::GetStringUTF16(launch_new_string_id_); - } - return ShelfContextMenu::GetLabelForCommandId(command_id); -} - bool AppServiceShelfContextMenu::IsCommandIdChecked(int command_id) const { switch (app_type_) { case apps::AppType::kStandaloneBrowserChromeApp: @@ -229,7 +248,7 @@ }); return user_window_mode != apps::WindowMode::kUnknown && user_window_mode == - apps::ConvertLaunchTypeCommandToWindowMode(command_id); + ConvertLaunchTypeCommandToWindowMode(command_id); } return ShelfContextMenu::IsCommandIdChecked(command_id); } @@ -237,7 +256,7 @@ if (command_id >= ash::USE_LAUNCH_TYPE_COMMAND_START && command_id < ash::USE_LAUNCH_TYPE_COMMAND_END) { return GetExtensionLaunchType() == - apps::ConvertLaunchTypeCommandToExtensionLaunchType(command_id); + ConvertLaunchTypeCommandToExtensionLaunchType(command_id); } else if (command_id < ash::COMMAND_ID_COUNT) { return ShelfContextMenu::IsCommandIdChecked(command_id); } else { @@ -269,22 +288,18 @@ return true; } -bool AppServiceShelfContextMenu::IsItemForCommandIdDynamic( - int command_id) const { - return command_id == ash::LAUNCH_NEW || - ShelfContextMenu::IsItemForCommandIdDynamic(command_id); -} - void AppServiceShelfContextMenu::OnGetMenuModel( GetMenuModelCallback callback, apps::mojom::MenuItemsPtr menu_items) { auto menu_model = GetBaseMenuModel(); submenu_ = std::make_unique<ui::SimpleMenuModel>(this); size_t index = 0; - - if (apps::PopulateNewItemFromMojoMenuItems(menu_items->items, - menu_model.get(), submenu_.get(), - &launch_new_string_id_)) { + // Unretained is safe here because PopulateNewItemFromMojoMenuItems should + // call GetVectorIcon synchronously. + if (apps::PopulateNewItemFromMojoMenuItems( + menu_items->items, menu_model.get(), submenu_.get(), + base::BindOnce(&AppServiceShelfContextMenu::GetCommandIdVectorIcon, + base::Unretained(this)))) { ++index; } @@ -363,7 +378,7 @@ ui::SimpleMenuModel* menu_model) { extension_menu_items_ = std::make_unique<extensions::ContextMenuMatcher>( controller()->profile(), this, menu_model, - base::BindRepeating(apps::MenuItemHasLauncherContext)); + base::BindRepeating(MenuItemHasLauncherContext)); int index = 0; extension_menu_items_->AppendExtensionItems( @@ -475,7 +490,7 @@ case apps::AppType::kSystemWeb: { // Web apps can only toggle between kWindow, kTabbed and kBrowser. apps::WindowMode user_window_mode = - apps::ConvertLaunchTypeCommandToWindowMode(command_id); + ConvertLaunchTypeCommandToWindowMode(command_id); if (user_window_mode != apps::WindowMode::kUnknown) { apps::AppServiceProxyFactory::GetForProfile(controller()->profile()) ->SetWindowMode(
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.h b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.h index 1d96b393..c2e4ba3 100644 --- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.h +++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.h
@@ -35,11 +35,8 @@ // ShelfContextMenu: void GetMenuModel(GetMenuModelCallback callback) override; void ExecuteCommand(int command_id, int event_flags) override; - ui::ImageModel GetIconForCommandId(int command_id) const override; - std::u16string GetLabelForCommandId(int command_id) const override; bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; - bool IsItemForCommandIdDynamic(int command_id) const override; private: void OnGetMenuModel(GetMenuModelCallback callback, @@ -92,11 +89,6 @@ std::unique_ptr<extensions::ContextMenuMatcher> extension_menu_items_; - // String id for the `LAUNCH_NEW` command / menu item tracked so the menu icon - // and label can be changed dynamically after the app launch type changes - // using the launch new item submenu. - int launch_new_string_id_ = 0; - base::WeakPtrFactory<AppServiceShelfContextMenu> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.cc index 9c032441..c7c41a6 100644 --- a/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.cc +++ b/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.cc
@@ -9,8 +9,8 @@ #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/new_window_delegate.h" #include "base/bind.h" -#include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/extensions/context_menu_matcher.h" +#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -18,15 +18,27 @@ #include "chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/app_constants/constants.h" #include "content/public/browser/context_menu_params.h" #include "extensions/browser/extension_prefs.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/color/color_id.h" #include "ui/display/scoped_display_for_new_windows.h" +#include "ui/display/screen.h" +#include "ui/gfx/paint_vector_icon.h" + +namespace { + +// A helper used to filter which menu items added by the extension are shown. +bool MenuItemHasLauncherContext(const extensions::MenuItem* item) { + return item->contexts().Contains(extensions::MenuItem::LAUNCHER); +} + +} // namespace ExtensionShelfContextMenu::ExtensionShelfContextMenu( ChromeShelfController* controller, @@ -43,7 +55,7 @@ extension_items_ = std::make_unique<extensions::ContextMenuMatcher>( profile, this, menu_model.get(), - base::BindRepeating(apps::MenuItemHasLauncherContext)); + base::BindRepeating(MenuItemHasLauncherContext)); if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { CreateOpenNewSubmenu(menu_model.get()); @@ -95,6 +107,46 @@ std::move(callback).Run(std::move(menu_model)); } +bool ExtensionShelfContextMenu::IsCommandIdChecked(int command_id) const { + switch (command_id) { + case ash::USE_LAUNCH_TYPE_PINNED: + return GetLaunchType() == extensions::LAUNCH_TYPE_PINNED; + case ash::USE_LAUNCH_TYPE_REGULAR: + return GetLaunchType() == extensions::LAUNCH_TYPE_REGULAR; + case ash::USE_LAUNCH_TYPE_WINDOW: + return GetLaunchType() == extensions::LAUNCH_TYPE_WINDOW; + case ash::USE_LAUNCH_TYPE_FULLSCREEN: + return GetLaunchType() == extensions::LAUNCH_TYPE_FULLSCREEN; + default: + if (command_id < ash::COMMAND_ID_COUNT) + return ShelfContextMenu::IsCommandIdChecked(command_id); + return (extension_items_ && + extension_items_->IsCommandIdChecked(command_id)); + } +} + +bool ExtensionShelfContextMenu::IsCommandIdEnabled(int command_id) const { + switch (command_id) { + case ash::UNINSTALL: + return controller()->UninstallAllowed(item().id.app_id); + case ash::APP_CONTEXT_MENU_NEW_WINDOW: + // "Normal" windows are not allowed when incognito is enforced. + return IncognitoModePrefs::GetAvailability( + controller()->profile()->GetPrefs()) != + IncognitoModePrefs::Availability::kForced; + case ash::APP_CONTEXT_MENU_NEW_INCOGNITO_WINDOW: + // Incognito windows are not allowed when incognito is disabled. + return IncognitoModePrefs::GetAvailability( + controller()->profile()->GetPrefs()) != + IncognitoModePrefs::Availability::kDisabled; + default: + if (command_id < ash::COMMAND_ID_COUNT) + return ShelfContextMenu::IsCommandIdEnabled(command_id); + return (extension_items_ && + extension_items_->IsCommandIdEnabled(command_id)); + } +} + void ExtensionShelfContextMenu::ExecuteCommand(int command_id, int event_flags) { if (ExecuteCommonCommand(command_id, event_flags)) @@ -144,71 +196,6 @@ } } -ui::ImageModel ExtensionShelfContextMenu::GetIconForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - const gfx::VectorIcon& icon = - GetCommandIdVectorIcon(command_id, GetLaunchTypeStringId()); - return ui::ImageModel::FromVectorIcon( - icon, apps::GetColorIdForMenuItemIcon(), ash::kAppContextMenuIconSize); - } - return ShelfContextMenu::GetIconForCommandId(command_id); -} - -std::u16string ExtensionShelfContextMenu::GetLabelForCommandId( - int command_id) const { - if (command_id == ash::LAUNCH_NEW) { - return l10n_util::GetStringUTF16(GetLaunchTypeStringId()); - } - return ShelfContextMenu::GetLabelForCommandId(command_id); -} - -bool ExtensionShelfContextMenu::IsCommandIdChecked(int command_id) const { - switch (command_id) { - case ash::USE_LAUNCH_TYPE_PINNED: - return GetLaunchType() == extensions::LAUNCH_TYPE_PINNED; - case ash::USE_LAUNCH_TYPE_REGULAR: - return GetLaunchType() == extensions::LAUNCH_TYPE_REGULAR; - case ash::USE_LAUNCH_TYPE_WINDOW: - return GetLaunchType() == extensions::LAUNCH_TYPE_WINDOW; - case ash::USE_LAUNCH_TYPE_FULLSCREEN: - return GetLaunchType() == extensions::LAUNCH_TYPE_FULLSCREEN; - default: - if (command_id < ash::COMMAND_ID_COUNT) - return ShelfContextMenu::IsCommandIdChecked(command_id); - return (extension_items_ && - extension_items_->IsCommandIdChecked(command_id)); - } -} - -bool ExtensionShelfContextMenu::IsCommandIdEnabled(int command_id) const { - switch (command_id) { - case ash::UNINSTALL: - return controller()->UninstallAllowed(item().id.app_id); - case ash::APP_CONTEXT_MENU_NEW_WINDOW: - // "Normal" windows are not allowed when incognito is enforced. - return IncognitoModePrefs::GetAvailability( - controller()->profile()->GetPrefs()) != - IncognitoModePrefs::Availability::kForced; - case ash::APP_CONTEXT_MENU_NEW_INCOGNITO_WINDOW: - // Incognito windows are not allowed when incognito is disabled. - return IncognitoModePrefs::GetAvailability( - controller()->profile()->GetPrefs()) != - IncognitoModePrefs::Availability::kDisabled; - default: - if (command_id < ash::COMMAND_ID_COUNT) - return ShelfContextMenu::IsCommandIdEnabled(command_id); - return (extension_items_ && - extension_items_->IsCommandIdEnabled(command_id)); - } -} - -bool ExtensionShelfContextMenu::IsItemForCommandIdDynamic( - int command_id) const { - return command_id == ash::LAUNCH_NEW || - ShelfContextMenu::IsItemForCommandIdDynamic(command_id); -} - void ExtensionShelfContextMenu::CreateOpenNewSubmenu( ui::SimpleMenuModel* menu_model) { // Touchable extension context menus use an actionable submenu for @@ -221,9 +208,11 @@ open_new_submenu_model_->AddRadioItemWithStringId( ash::USE_LAUNCH_TYPE_WINDOW, IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW, kGroupId); - menu_model->AddActionableSubMenu( - ash::LAUNCH_NEW, l10n_util::GetStringUTF16(GetLaunchTypeStringId()), - open_new_submenu_model_.get()); + menu_model->AddActionableSubmenuWithStringIdAndIcon( + ash::LAUNCH_NEW, GetLaunchTypeStringId(), open_new_submenu_model_.get(), + ui::ImageModel::FromVectorIcon( + GetCommandIdVectorIcon(ash::LAUNCH_NEW, GetLaunchTypeStringId()), + ui::kColorAshSystemUIMenuIcon, ash::kAppContextMenuIconSize)); } extensions::LaunchType ExtensionShelfContextMenu::GetLaunchType() const {
diff --git a/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.h b/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.h index 5083292..7f1f266 100644 --- a/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.h +++ b/chrome/browser/ui/ash/shelf/extension_shelf_context_menu.h
@@ -31,12 +31,9 @@ void GetMenuModel(GetMenuModelCallback callback) override; // ui::SimpleMenuModel::Delegate overrides: - void ExecuteCommand(int command_id, int event_flags) override; - ui::ImageModel GetIconForCommandId(int command_id) const override; - std::u16string GetLabelForCommandId(int command_id) const override; bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; - bool IsItemForCommandIdDynamic(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; private: // Creates the actionable submenu for MENU_OPEN_NEW.
diff --git a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc index 1fb818f..3c0e1db 100644 --- a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc +++ b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc
@@ -52,16 +52,15 @@ void OpenUrl(const GURL& url) { #if BUILDFLAG(IS_CHROMEOS_ASH) ash::NewWindowDelegate::GetPrimary()->OpenUrl( - url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction, + ash::NewWindowDelegate::Disposition::kNewForegroundTab); #elif BUILDFLAG(IS_CHROMEOS_LACROS) Profile* profile = ProfileManager::GetPrimaryUserProfile(); - NavigateParams navigate_params( profile, url, ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API)); navigate_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; - navigate_params.window_action = NavigateParams::SHOW_WINDOW; Navigate(&navigate_params); #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/chrome_typography.h b/chrome/browser/ui/views/chrome_typography.h index b5036de..a3d6be9e 100644 --- a/chrome/browser/ui/views/chrome_typography.h +++ b/chrome/browser/ui/views/chrome_typography.h
@@ -88,14 +88,6 @@ // A solid shade of green. STYLE_GREEN, - - // Used to draw attention to a section of body text such as an extension name - // or hostname. - STYLE_EMPHASIZED, - - // Emphasized secondary style. Like STYLE_EMPHASIZED but styled to match - // surrounding STYLE_SECONDARY text. - STYLE_EMPHASIZED_SECONDARY, }; // Takes a desired font size and returns the size delta to request from
diff --git a/chrome/browser/ui/views/chrome_typography_provider.cc b/chrome/browser/ui/views/chrome_typography_provider.cc index c76bd5f4..9fdc667 100644 --- a/chrome/browser/ui/views/chrome_typography_provider.cc +++ b/chrome/browser/ui/views/chrome_typography_provider.cc
@@ -39,6 +39,9 @@ constexpr int kDefaultSize = 12; constexpr int kStatusSize = 10; + DCHECK(StyleAllowedForContext(context, style)) + << "context: " << context << " style: " << style; + ui::ResourceBundle::FontDetails details; details.size_delta = kDefaultSize - gfx::PlatformFont::kDefaultBaseFontSize; @@ -78,7 +81,6 @@ } if (context == CONTEXT_TAB_HOVER_CARD_TITLE) { - DCHECK_EQ(views::style::STYLE_PRIMARY, style); details.weight = gfx::Font::Weight::SEMIBOLD; } @@ -94,14 +96,8 @@ #endif } - if (style == STYLE_EMPHASIZED || style == STYLE_EMPHASIZED_SECONDARY) { - // Limit emphasizing text to contexts where it's obviously correct. If you - // hit this DCHECK, ensure it's sane and UX-approved to extend it to your - // new case (e.g. don't add CONTEXT_BUTTON_MD). - DCHECK(context == views::style::CONTEXT_LABEL || - context == views::style::CONTEXT_DIALOG_BODY_TEXT || - context == CONTEXT_DIALOG_BODY_TEXT_SMALL || - context == CONTEXT_DOWNLOAD_SHELF); + if (style == views::style::STYLE_EMPHASIZED || + style == views::style::STYLE_EMPHASIZED_SECONDARY) { details.weight = gfx::Font::Weight::SEMIBOLD; } @@ -240,3 +236,31 @@ return default_height; } } + +bool ChromeTypographyProvider::StyleAllowedForContext(int context, + int style) const { + if (context == CONTEXT_TAB_HOVER_CARD_TITLE) { + return style == views::style::STYLE_PRIMARY; + } + + if (style == views::style::STYLE_EMPHASIZED || + style == views::style::STYLE_EMPHASIZED_SECONDARY) { + // Limit emphasizing text to contexts where it's obviously correct. If you + // hit this check, ensure it's sane and UX-approved to extend it to your + // new case (e.g. don't add CONTEXT_BUTTON_MD). +#if BUILDFLAG(IS_CHROMEOS_ASH) + // TODO(https://crbug.com/1352340): Limit emphasized text to more specific + // Ash contexts. + const bool is_ash_context = context >= ash::ASH_TEXT_CONTEXT_START && + context <= ash::ASH_TEXT_CONTEXT_END; +#else + const bool is_ash_context = false; +#endif + return is_ash_context || context == views::style::CONTEXT_LABEL || + context == views::style::CONTEXT_DIALOG_BODY_TEXT || + context == CONTEXT_DIALOG_BODY_TEXT_SMALL || + context == CONTEXT_DOWNLOAD_SHELF; + } + + return true; +}
diff --git a/chrome/browser/ui/views/chrome_typography_provider.h b/chrome/browser/ui/views/chrome_typography_provider.h index 6b341a8..da5ba522 100644 --- a/chrome/browser/ui/views/chrome_typography_provider.h +++ b/chrome/browser/ui/views/chrome_typography_provider.h
@@ -23,6 +23,7 @@ int context, int style) const override; int GetLineHeight(int context, int style) const override; + bool StyleAllowedForContext(int context, int style) const override; }; #endif // CHROME_BROWSER_UI_VIEWS_CHROME_TYPOGRAPHY_PROVIDER_H_
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc index 9eb4f90..56949e7 100644 --- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc +++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc
@@ -86,14 +86,8 @@ void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationProgress( const guest_os::GuestId& container_id, const std::vector<std::string>& status_lines) { - std::u16string status_string; - if (!base::UTF8ToUTF16(status_lines.back().c_str(), - status_lines.back().size(), &status_string)) { - LOG(ERROR) << "Failed to convert status line into a UTF16 string: " - << status_lines.back(); - } else { - progress_label_->SetText(status_string); - } + progress_label_->SetText(base::ASCIIToUTF16(status_lines.back())); + OnStateChanged(); } void CrostiniAnsibleSoftwareConfigView::OnAnsibleSoftwareConfigurationFinished(
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index 9ca83ff5..463da2b 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -190,7 +190,7 @@ int GetFilenameStyle(const views::Label& label) { #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) if (UseNewWarnings()) - return STYLE_EMPHASIZED; + return views::style::STYLE_EMPHASIZED; #endif return label.GetTextStyle(); } @@ -198,7 +198,7 @@ int GetFilenameStyle(const views::StyledLabel& label) { #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) if (UseNewWarnings()) - return STYLE_EMPHASIZED; + return views::style::STYLE_EMPHASIZED; #endif return label.GetDefaultTextStyle(); }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_view.cc index 9ca0927..232584ef 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
@@ -38,6 +38,7 @@ #include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/flex_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/view_class_properties.h" #include "ui/views/view_utils.h" @@ -217,7 +218,7 @@ auto header = std::make_unique<views::Label>( l10n_util::GetStringUTF16(section->header_string_id), ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, - ChromeTextStyle::STYLE_EMPHASIZED); + views::style::STYLE_EMPHASIZED); header->SetHorizontalAlignment(gfx::ALIGN_LEFT); header->SetBorder(views::CreateEmptyBorder( gfx::Insets::TLBR(ChromeLayoutProvider::Get()->GetDistanceMetric(
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc index 8d474f8..317926f 100644 --- a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc
@@ -49,6 +49,7 @@ #include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout_view.h" #include "ui/views/layout/layout_provider.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" #include "ui/views/view_utils.h" @@ -193,7 +194,7 @@ std::u16string current_site) { size_t offset = 0u; label.SetText(l10n_util::GetStringFUTF16(message_id, current_site, &offset)); - label.SetTextStyleRange(ChromeTextStyle::STYLE_EMPHASIZED, + label.SetTextStyleRange(views::style::STYLE_EMPHASIZED, gfx::Range(offset, offset + current_site.length())); }
diff --git a/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc b/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc index 0e3c4a7..255b5d6 100644 --- a/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/request_file_system_dialog_view.cc
@@ -11,7 +11,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" #include "content/public/browser/web_contents.h" @@ -21,6 +20,7 @@ #include "ui/gfx/range/range.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" namespace { @@ -96,7 +96,7 @@ AddChildView(std::make_unique<views::StyledLabel>()); label->SetText(message); views::StyledLabel::RangeStyleInfo bold_style; - bold_style.text_style = STYLE_EMPHASIZED; + bold_style.text_style = views::style::STYLE_EMPHASIZED; DCHECK_EQ(2u, placeholder_offsets.size()); label->AddStyleRange(gfx::Range(placeholder_offsets[0],
diff --git a/chrome/browser/ui/views/file_system_access/file_system_access_ui_helpers.cc b/chrome/browser/ui/views/file_system_access/file_system_access_ui_helpers.cc index 3b49e3e4..08d3bbd 100644 --- a/chrome/browser/ui/views/file_system_access/file_system_access_ui_helpers.cc +++ b/chrome/browser/ui/views/file_system_access/file_system_access_ui_helpers.cc
@@ -7,11 +7,11 @@ #include <string> #include "base/files/file_path.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "components/url_formatter/elide_url.h" #include "storage/common/file_system/file_system_util.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/controls/styled_label.h" +#include "ui/views/style/typography.h" namespace file_system_access_ui_helper { @@ -33,7 +33,7 @@ if (show_emphasis) { views::StyledLabel::RangeStyleInfo origin_style; - origin_style.text_style = STYLE_EMPHASIZED_SECONDARY; + origin_style.text_style = views::style::STYLE_EMPHASIZED_SECONDARY; label->AddStyleRange(gfx::Range(offset, offset + formatted_origin.length()), origin_style); } @@ -62,7 +62,7 @@ if (show_emphasis) { views::StyledLabel::RangeStyleInfo origin_style; - origin_style.text_style = STYLE_EMPHASIZED_SECONDARY; + origin_style.text_style = views::style::STYLE_EMPHASIZED_SECONDARY; // All but the last offset should be the origin. for (size_t i = 0; i < offsets.size() - 1; ++i) { label->AddStyleRange( @@ -73,7 +73,7 @@ views::StyledLabel::RangeStyleInfo path_style; if (show_emphasis) - path_style.text_style = STYLE_EMPHASIZED_SECONDARY; + path_style.text_style = views::style::STYLE_EMPHASIZED_SECONDARY; path_style.tooltip = path.LossyDisplayName(); label->AddStyleRange( gfx::Range(offsets.back(), offsets.back() + formatted_path.length()),
diff --git a/chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc b/chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc index 1384c94..62d3374 100644 --- a/chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc +++ b/chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/views/accessibility/theme_tracking_non_accessible_image_view.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" @@ -20,6 +19,7 @@ #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/layout/flex_layout.h" #include "ui/views/layout/layout_provider.h" +#include "ui/views/style/typography.h" IncognitoClearBrowsingDataDialog::IncognitoClearBrowsingDataDialog( views::View* anchor_view, @@ -64,13 +64,14 @@ void IncognitoClearBrowsingDataDialog::SetDialogForDefaultBubbleType() { // Text - AddChildView(views::Builder<views::Label>() - .SetText(l10n_util::GetStringUTF16( - IDS_INCOGNITO_CLEAR_BROWSING_DATA_DIALOG_PRIMARY_TEXT)) - .SetFontList(views::style::GetFont( - views::style::CONTEXT_LABEL, STYLE_EMPHASIZED)) - .SetHorizontalAlignment(gfx::ALIGN_LEFT) - .Build()); + AddChildView( + views::Builder<views::Label>() + .SetText(l10n_util::GetStringUTF16( + IDS_INCOGNITO_CLEAR_BROWSING_DATA_DIALOG_PRIMARY_TEXT)) + .SetFontList(views::style::GetFont(views::style::CONTEXT_LABEL, + views::style::STYLE_EMPHASIZED)) + .SetHorizontalAlignment(gfx::ALIGN_LEFT) + .Build()); AddChildView( views::Builder<views::Label>() @@ -99,13 +100,14 @@ void IncognitoClearBrowsingDataDialog:: SetDialogForHistoryDisclaimerBubbleType() { // Text - AddChildView(views::Builder<views::Label>() - .SetText(l10n_util::GetStringUTF16( - IDS_INCOGNITO_HISTORY_BUBBLE_PRIMARY_TEXT)) - .SetFontList(views::style::GetFont( - views::style::CONTEXT_LABEL, STYLE_EMPHASIZED)) - .SetHorizontalAlignment(gfx::ALIGN_LEFT) - .Build()); + AddChildView( + views::Builder<views::Label>() + .SetText(l10n_util::GetStringUTF16( + IDS_INCOGNITO_HISTORY_BUBBLE_PRIMARY_TEXT)) + .SetFontList(views::style::GetFont(views::style::CONTEXT_LABEL, + views::style::STYLE_EMPHASIZED)) + .SetHorizontalAlignment(gfx::ALIGN_LEFT) + .Build()); views::Label* label = AddChildView( views::Builder<views::Label>()
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc index 72bbb30..8da33b88 100644 --- a/chrome/browser/ui/views/payments/payment_request_views_util.cc +++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -54,6 +54,7 @@ #include "ui/views/controls/styled_label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/painter.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" namespace payments { @@ -151,9 +152,10 @@ container->SetLayoutManager(std::move(layout)); if (!s1.empty()) { - const int text_style = type == AddressStyleType::DETAILED - ? static_cast<int>(STYLE_EMPHASIZED) - : static_cast<int>(views::style::STYLE_PRIMARY); + const int text_style = + type == AddressStyleType::DETAILED + ? static_cast<int>(views::style::STYLE_EMPHASIZED) + : static_cast<int>(views::style::STYLE_PRIMARY); auto label = std::make_unique<ThemeTrackingLabel>(s1); label->SetTextContext(views::style::CONTEXT_LABEL); label->SetTextStyle(text_style); @@ -399,7 +401,7 @@ std::unique_ptr<views::Label> CreateBoldLabel(const std::u16string& text) { return std::make_unique<views::Label>(text, views::style::CONTEXT_LABEL, - STYLE_EMPHASIZED); + views::style::STYLE_EMPHASIZED); } std::unique_ptr<views::Label> CreateMediumLabel(const std::u16string& text) {
diff --git a/chrome/browser/ui/views/payments/secure_payment_confirmation_dialog_view.cc b/chrome/browser/ui/views/payments/secure_payment_confirmation_dialog_view.cc index 04fdfc85..41b9d26 100644 --- a/chrome/browser/ui/views/payments/secure_payment_confirmation_dialog_view.cc +++ b/chrome/browser/ui/views/payments/secure_payment_confirmation_dialog_view.cc
@@ -7,7 +7,6 @@ #include "base/metrics/histogram_functions.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/payments/payment_request_views_util.h" #include "chrome/browser/ui/views/payments/secure_payment_confirmation_views_util.h" #include "components/constrained_window/constrained_window_views.h" @@ -27,6 +26,7 @@ #include "ui/views/layout/box_layout_view.h" #include "ui/views/layout/layout_provider.h" #include "ui/views/layout/table_layout.h" +#include "ui/views/style/typography.h" namespace payments { namespace { @@ -378,7 +378,7 @@ std::unique_ptr<views::Label> label_text = std::make_unique<views::Label>( label, views::style::CONTEXT_DIALOG_BODY_TEXT, - ChromeTextStyle::STYLE_EMPHASIZED_SECONDARY); + views::style::STYLE_EMPHASIZED_SECONDARY); label_text->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); label_text->SetLineHeight(kDescriptionLineHeight); label_text->SetID(static_cast<int>(label_id));
diff --git a/chrome/browser/ui/views/permissions/permission_bubble_interactive_uitest.cc b/chrome/browser/ui/views/permissions/permission_bubble_interactive_uitest.cc index 94eccfd..879db698 100644 --- a/chrome/browser/ui/views/permissions/permission_bubble_interactive_uitest.cc +++ b/chrome/browser/ui/views/permissions/permission_bubble_interactive_uitest.cc
@@ -5,6 +5,7 @@ #include <memory> #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" @@ -19,6 +20,7 @@ #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/permissions/permission_request_manager_test_api.h" +#include "components/permissions/features.h" #include "components/permissions/request_type.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -29,7 +31,10 @@ class PermissionBubbleInteractiveUITest : public InProcessBrowserTest { public: - PermissionBubbleInteractiveUITest() = default; + PermissionBubbleInteractiveUITest() { + scoped_feature_list_.InitAndEnableFeature( + permissions::features::kPermissionChip); + } PermissionBubbleInteractiveUITest(const PermissionBubbleInteractiveUITest&) = delete; @@ -140,6 +145,9 @@ protected: std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc b/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc index 1a272f11..2f2a215 100644 --- a/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc +++ b/chrome/browser/ui/views/platform_keys_certificate_selector_chromeos.cc
@@ -11,13 +11,13 @@ #include "base/memory/ref_counted.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/grit/generated_resources.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/ssl_private_key.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/font.h" #include "ui/views/controls/styled_label.h" +#include "ui/views/style/typography.h" namespace chromeos { @@ -85,7 +85,7 @@ IDS_PLATFORM_KEYS_SELECT_CERT_DIALOG_TEXT, name, &offset)); views::StyledLabel::RangeStyleInfo bold_style; - bold_style.text_style = STYLE_EMPHASIZED; + bold_style.text_style = views::style::STYLE_EMPHASIZED; label->AddStyleRange(gfx::Range(offset, offset + name.size()), bold_style); CertificateSelector::InitWithText(std::move(label)); }
diff --git a/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.cc b/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.cc index 8e7367e..e3d68d1 100644 --- a/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.cc +++ b/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.cc
@@ -10,21 +10,19 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_controller.h" #include "chrome/grit/generated_resources.h" #include "components/signin/public/identity_manager/account_info.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/color/color_id.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/range/range.h" -#include "ui/views/background.h" #include "ui/views/controls/image_view.h" -#include "ui/views/controls/separator.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/layout_provider.h" @@ -45,26 +43,19 @@ } // namespace std::unique_ptr<views::View> BuildManageAccountDevicesLinkView( + bool show_link, base::WeakPtr<SendTabToSelfBubbleController> controller) { if (!controller) { return std::make_unique<views::View>(); } - auto view = std::make_unique<views::View>(); - view->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - view->AddChildView(std::make_unique<views::Separator>()); - - auto* container = view->AddChildView(std::make_unique<views::View>()); - container->SetBackground(views::CreateThemedSolidBackground( - ui::kColorMenuItemBackgroundHighlighted)); - auto* provider = ChromeLayoutProvider::Get(); gfx::Insets margins = provider->GetInsetsMetric(views::INSETS_DIALOG); margins.set_top(kManageDevicesLinkTopMargin); margins.set_bottom(kManageDevicesLinkBottomMargin); int between_child_spacing = provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL); + auto container = std::make_unique<views::View>(); container->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, margins, between_child_spacing)); @@ -89,22 +80,27 @@ container->AddChildView(std::make_unique<views::StyledLabel>()); link_view->SetDefaultTextStyle(views::style::STYLE_SECONDARY); - // Only part of the string in |link_view| must be styled as a link and - // clickable. This range is marked in the *.grd entry by the first 2 - // placeholders. This GetStringFUTF16() call replaces them with empty strings - // (no-op) and saves the range in |offsets[0]| and |offsets[1]|. - std::vector<size_t> offsets; - link_view->SetText(l10n_util::GetStringFUTF16( - IDS_SEND_TAB_TO_SELF_MANAGE_DEVICES_LINK, - {std::u16string(), std::u16string(), base::UTF8ToUTF16(account.email)}, - &offsets)); - DCHECK_EQ(3u, offsets.size()); - link_view->AddStyleRange( - gfx::Range(offsets[0], offsets[1]), - views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating( - &SendTabToSelfBubbleController::OnManageDevicesClicked, controller))); + if (show_link) { + // Only part of the string in |link_view| must be styled as a link and + // clickable. This range is marked in the *.grd entry by the first 2 + // placeholders. This GetStringFUTF16() call replaces them with empty + // strings (no-op) and saves the range in |offsets[0]| and |offsets[1]|. + std::vector<size_t> offsets; + link_view->SetText(l10n_util::GetStringFUTF16( + IDS_SEND_TAB_TO_SELF_MANAGE_DEVICES_LINK, + {std::u16string(), std::u16string(), base::UTF8ToUTF16(account.email)}, + &offsets)); + DCHECK_EQ(3u, offsets.size()); + link_view->AddStyleRange( + gfx::Range(offsets[0], offsets[1]), + views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating( + &SendTabToSelfBubbleController::OnManageDevicesClicked, + controller))); + } else { + link_view->SetText(base::UTF8ToUTF16(account.email)); + } - return view; + return container; } } // namespace send_tab_to_self
diff --git a/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.h b/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.h index 7c98f15..9accb17f 100644 --- a/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.h +++ b/chrome/browser/ui/views/send_tab_to_self/manage_account_devices_link_view.h
@@ -17,7 +17,12 @@ class SendTabToSelfBubbleController; +// TODO(crbug.com/1219433): Rename all platforms not to mention "link". +// Creates a view displaying the avatar and email of the signed-in account. +// If |show_link| is true, it also shows a link to the list of known devices for +// this account. std::unique_ptr<views::View> BuildManageAccountDevicesLinkView( + bool show_link, base::WeakPtr<SendTabToSelfBubbleController> controller); } // namespace send_tab_to_self
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_browsertest.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_browsertest.cc index 3ceb2ad..eab8654 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_browsertest.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_browsertest.cc
@@ -96,8 +96,8 @@ IN_PROC_BROWSER_TEST_F(SendTabToSelfBubbleTest, InvokeUi_ShowNoTargetDevicePromo) { - // Last updated in crrev.com/c/3776623. - set_baseline("3776623"); + // Last updated in crrev.com/c/3832669. + set_baseline("3832669"); ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_device_picker_bubble_view.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_device_picker_bubble_view.cc index d916dfe8..da73f04 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_device_picker_bubble_view.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_device_picker_bubble_view.cc
@@ -22,8 +22,11 @@ #include "content/public/browser/browser_thread.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_types.h" +#include "ui/color/color_id.h" #include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/background.h" #include "ui/views/controls/scroll_view.h" +#include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" #include "ui/views/style/typography.h" #include "ui/views/view_class_properties.h" @@ -122,7 +125,11 @@ CreateHintTextLabel(); CreateDevicesScrollView(); - AddChildView(BuildManageAccountDevicesLinkView(controller_)); + AddChildView(std::make_unique<views::Separator>()); + views::View* footer = AddChildView( + BuildManageAccountDevicesLinkView(/*show_link=*/true, controller_)); + footer->SetBackground(views::CreateThemedSolidBackground( + ui::kColorMenuItemBackgroundHighlighted)); } void SendTabToSelfDevicePickerBubbleView::AddedToWidget() {
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_promo_bubble_view.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_promo_bubble_view.cc index f10c5856..e6a7a01 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_promo_bubble_view.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_promo_bubble_view.cc
@@ -70,13 +70,13 @@ } SetButtons(ui::DIALOG_BUTTON_NONE); - auto* link_view = - AddChildView(BuildManageAccountDevicesLinkView(controller_)); + auto* link_view = AddChildView( + BuildManageAccountDevicesLinkView(/*show_link=*/false, controller_)); link_view->SetProperty( views::kMarginsKey, - gfx::Insets::TLBR(provider->GetDistanceMetric( - views::DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_TEXT), - 0, 0, 0)); + gfx::Insets::VH(provider->GetDistanceMetric( + views::DISTANCE_CONTROL_VERTICAL_TEXT_PADDING), + 0)); } SendTabToSelfPromoBubbleView::~SendTabToSelfPromoBubbleView() {
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc index c582316..b3dc2f4 100644 --- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc +++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" @@ -21,6 +20,7 @@ #include "ui/views/controls/label.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -83,7 +83,7 @@ dialog_label->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT); dialog_label->SetDefaultTextStyle(views::style::STYLE_SECONDARY); views::StyledLabel::RangeStyleInfo url_style; - url_style.text_style = STYLE_EMPHASIZED_SECONDARY; + url_style.text_style = views::style::STYLE_EMPHASIZED_SECONDARY; dialog_label->AddStyleRange(controller_->GetMainTextUrlRange(), url_style); }
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.cc index 7b38977..6e40507 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.cc
@@ -31,7 +31,11 @@ button->SetTooltipText(tooltip); // Add the button to the view. - AddChildView(std::move(button)); + button_ = AddChildView(std::move(button)); +} + +void ReadAnythingButtonView::UpdateIcon(const gfx::ImageSkia& icon) { + button_->SetImage(views::Button::STATE_NORMAL, icon); } ReadAnythingButtonView::~ReadAnythingButtonView() = default;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.h index cddbaa5..efd83df 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.h
@@ -25,6 +25,11 @@ ReadAnythingButtonView(const ReadAnythingButtonView&) = delete; ReadAnythingButtonView& operator=(const ReadAnythingButtonView&) = delete; ~ReadAnythingButtonView() override; + + void UpdateIcon(const gfx::ImageSkia& icon); + + private: + raw_ptr<views::ImageButton> button_; }; #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_BUTTON_VIEW_H_
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc index d2b60c52..a1bde10 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc
@@ -87,6 +87,16 @@ ReadAnythingCoordinator::Observer* observer) { observers_.RemoveObserver(observer); } +void ReadAnythingCoordinator::AddModelObserver( + ReadAnythingModel::Observer* observer) { + DCHECK(model_); + model_->AddObserver(observer); +} +void ReadAnythingCoordinator::RemoveModelObserver( + ReadAnythingModel::Observer* observer) { + DCHECK(model_); + model_->RemoveObserver(observer); +} void ReadAnythingCoordinator::OnEntryShown(SidePanelEntry* entry) { DCHECK(entry->id() == SidePanelEntry::Id::kReadAnything);
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h index 97b9284..7e7dbd9 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h
@@ -52,6 +52,8 @@ void AddObserver(ReadAnythingCoordinator::Observer* observer); void RemoveObserver(ReadAnythingCoordinator::Observer* observer); + void AddModelObserver(ReadAnythingModel::Observer* observer); + void RemoveModelObserver(ReadAnythingModel::Observer* observer); private: friend class BrowserUserData<ReadAnythingCoordinator>;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc index c9d0c4fd..e43579e 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.cc
@@ -47,6 +47,7 @@ std::unique_ptr<ComboboxMenuModel> new_model = std::make_unique<MenuModel>(this, GetModel()); + SetBorderColorId(ui::kColorSidePanelComboboxBorder); SetMenuModel(std::move(new_model)); }
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc index d1317d4..4a1f80e 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
@@ -12,12 +12,14 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h" #include "chrome/grit/component_extension_resources.h" +#include "components/vector_icons/vector_icons.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/paint_vector_icon.h" using read_anything::mojom::ReadAnythingTheme; @@ -106,7 +108,7 @@ void ReadAnythingModel::NotifyThemeChanged() { for (Observer& obs : observers_) { - obs.OnThemeChanged(ReadAnythingTheme::New( + obs.OnReadAnythingThemeChanged(ReadAnythingTheme::New( font_name_, kReadAnythingDefaultFontSize * font_scale_, foreground_color_, background_color_)); } @@ -117,6 +119,7 @@ /////////////////////////////////////////////////////////////////////////////// ReadAnythingFontModel::ReadAnythingFontModel() { + // TODO(1266555): i18n. font_choices_.emplace_back(u"Standard font"); font_choices_.emplace_back(u"Sans-serif"); font_choices_.emplace_back(u"Serif"); @@ -152,8 +155,7 @@ } std::u16string ReadAnythingFontModel::GetItemAt(size_t index) const { - // TODO(1266555): Placeholder text, replace when finalized. - return u"Default font"; + return GetDropDownTextAt(index); } std::u16string ReadAnythingFontModel::GetDropDownTextAt(size_t index) const { @@ -226,6 +228,13 @@ } ui::ImageModel ReadAnythingColorsModel::GetIconAt(size_t index) const { + // The dropdown should always show the color palette icon. + return ui::ImageModel::FromImageSkia( + gfx::CreateVectorIcon(vector_icons::kPaletteIcon, kColorsIconSize, + colors_choices_[index].foreground)); +} + +ui::ImageModel ReadAnythingColorsModel::GetDropDownIconAt(size_t index) const { const gfx::ImageSkia* icon_skia_asset = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( colors_choices_[index].icon_asset); @@ -238,8 +247,8 @@ } std::u16string ReadAnythingColorsModel::GetItemAt(size_t index) const { - // Only display the icon choice in the toolbar, so suppress name here. - return u""; + // Only display the icon choice in the toolbar, so return empty string here. + return std::u16string(); } std::u16string ReadAnythingColorsModel::GetDropDownTextAt(size_t index) const {
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h index 97b2696..5c02816 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h
@@ -89,6 +89,7 @@ absl::optional<size_t> GetDefaultIndex() const override; size_t GetItemCount() const override; ui::ImageModel GetIconAt(size_t index) const override; + ui::ImageModel GetDropDownIconAt(size_t index) const override; std::u16string GetItemAt(size_t index) const override; std::u16string GetDropDownTextAt(size_t index) const override; @@ -113,8 +114,8 @@ public: virtual void OnAXTreeDistilled( const ui::AXTreeUpdate& snapshot, - const std::vector<ui::AXNodeID>& content_node_ids) = 0; - virtual void OnThemeChanged( + const std::vector<ui::AXNodeID>& content_node_ids) {} + virtual void OnReadAnythingThemeChanged( read_anything::mojom::ReadAnythingThemePtr new_theme) = 0; };
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc index c8f85ec2..eedd1cc 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc
@@ -26,7 +26,7 @@ const std::vector<ui::AXNodeID>& content_node_ids), (override)); MOCK_METHOD(void, - OnThemeChanged, + OnReadAnythingThemeChanged, (ReadAnythingThemePtr new_theme), (override)); }; @@ -63,10 +63,10 @@ model_->AddObserver(&model_observer_1_); EXPECT_CALL(model_observer_1_, OnAXTreeDistilled(_, _)).Times(1); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); EXPECT_CALL(model_observer_2_, OnAXTreeDistilled(_, _)).Times(1); - EXPECT_CALL(model_observer_2_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_2_, OnReadAnythingThemeChanged(_)).Times(1); model_->AddObserver(&model_observer_2_); } @@ -76,13 +76,13 @@ model_->AddObserver(&model_observer_2_); EXPECT_CALL(model_observer_1_, OnAXTreeDistilled(_, _)).Times(1); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); EXPECT_CALL(model_observer_2_, OnAXTreeDistilled(_, _)).Times(0); - EXPECT_CALL(model_observer_2_, OnThemeChanged(_)).Times(0); + EXPECT_CALL(model_observer_2_, OnReadAnythingThemeChanged(_)).Times(0); EXPECT_CALL(model_observer_3_, OnAXTreeDistilled(_, _)).Times(1); - EXPECT_CALL(model_observer_3_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_3_, OnReadAnythingThemeChanged(_)).Times(1); model_->RemoveObserver(&model_observer_2_); model_->AddObserver(&model_observer_3_); @@ -91,7 +91,7 @@ TEST_F(ReadAnythingModelTest, NotificationsOnSetSelectedFontIndex) { model_->AddObserver(&model_observer_1_); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); model_->SetSelectedFontByIndex(2); } @@ -109,7 +109,7 @@ TEST_F(ReadAnythingModelTest, NotificationsOnDecreasedFontSize) { model_->AddObserver(&model_observer_1_); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); model_->DecreaseTextSize(); @@ -119,7 +119,7 @@ TEST_F(ReadAnythingModelTest, NotificationsOnIncreasedFontSize) { model_->AddObserver(&model_observer_1_); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); model_->IncreaseTextSize(); @@ -129,7 +129,7 @@ TEST_F(ReadAnythingModelTest, NotificationsOnSetSelectedColorsIndex) { model_->AddObserver(&model_observer_1_); - EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + EXPECT_CALL(model_observer_1_, OnReadAnythingThemeChanged(_)).Times(1); model_->SetSelectedColorsByIndex(2); }
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc index 250d702c..4c16515 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc
@@ -53,7 +53,7 @@ base::BindRepeating(&ReadAnythingToolbarView::DecreaseFontSizeCallback, weak_pointer_factory_.GetWeakPtr()), gfx::CreateVectorIcon(vector_icons::kTextDecreaseIcon, kSmallIconSize, - gfx::kGoogleGrey700), + gfx::kPlaceholderColor), l10n_util::GetStringUTF16( IDS_READ_ANYTHING_DECREASE_FONT_SIZE_BUTTON_LABEL)); @@ -61,7 +61,7 @@ base::BindRepeating(&ReadAnythingToolbarView::IncreaseFontSizeCallback, weak_pointer_factory_.GetWeakPtr()), gfx::CreateVectorIcon(vector_icons::kTextIncreaseIcon, kLargeIconSize, - gfx::kGoogleGrey700), + gfx::kPlaceholderColor), l10n_util::GetStringUTF16( IDS_READ_ANYTHING_INCREASE_FONT_SIZE_BUTTON_LABEL)); @@ -74,6 +74,8 @@ colors_combobox->SetCallback( base::BindRepeating(&ReadAnythingToolbarView::ChangeColorsCallback, weak_pointer_factory_.GetWeakPtr())); + colors_combobox->SetShouldShowArrow(false); + colors_combobox->SetBorderColorId(ui::kColorSidePanelComboboxBorder); // Add all views as children. font_combobox_ = AddChildView(std::move(combobox)); @@ -82,6 +84,9 @@ increase_text_size_button_ = AddChildView(std::move(increase_size_button)); AddChildView(Separator()); colors_combobox_ = AddChildView(std::move(colors_combobox)); + + // Start observing model after views creation so initial theme is applied. + coordinator_->AddModelObserver(this); } void ReadAnythingToolbarView::DecreaseFontSizeCallback() { @@ -107,6 +112,23 @@ font_combobox_->SetModel(nullptr); } +void ReadAnythingToolbarView::OnReadAnythingThemeChanged( + read_anything::mojom::ReadAnythingThemePtr new_theme) { + SetBackground(views::CreateSolidBackground(new_theme->background_color)); + font_combobox_->SetBackground( + views::CreateSolidBackground(new_theme->background_color)); + colors_combobox_->SetBackground( + views::CreateSolidBackground(new_theme->background_color)); + + decrease_text_size_button_->UpdateIcon( + gfx::CreateVectorIcon(vector_icons::kTextDecreaseIcon, kSmallIconSize, + new_theme->foreground_color)); + + increase_text_size_button_->UpdateIcon( + gfx::CreateVectorIcon(vector_icons::kTextIncreaseIcon, kLargeIconSize, + new_theme->foreground_color)); +} + std::unique_ptr<views::View> ReadAnythingToolbarView::Separator() { // Create a simple separator with padding to be inserted into views. auto separator_container = std::make_unique<views::View>(); @@ -139,5 +161,6 @@ // remove |this| as an observer. if (coordinator_) { coordinator_->RemoveObserver(this); + coordinator_->RemoveModelObserver(this); } }
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h index c01f769..e00b76ca 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_button_view.h" #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.h" #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_font_combobox.h" +#include "chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h" #include "ui/base/models/combobox_model.h" #include "ui/views/controls/combobox/combobox.h" #include "ui/views/view.h" @@ -22,6 +23,7 @@ // ReadAnythingContainerView. It has the same lifetime as the Side Panel view. // class ReadAnythingToolbarView : public views::View, + public ReadAnythingModel::Observer, public ReadAnythingCoordinator::Observer { public: class Delegate { @@ -39,6 +41,10 @@ ReadAnythingToolbarView& operator=(const ReadAnythingToolbarView&) = delete; ~ReadAnythingToolbarView() override; + // ReadAnythingModel::Observer: + void OnReadAnythingThemeChanged( + read_anything::mojom::ReadAnythingThemePtr new_theme) override; + // ReadAnythingCoordinator::Observer: void OnCoordinatorDestroyed() override;
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc index ba970c3..7da351df 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -303,8 +303,6 @@ 0, IDS_TUTORIAL_ADD_TAB_TO_GROUP_WITH_EXISTING_GROUP_IN_TAB_STRIP, ui::InteractionSequence::StepType::kShown, kTabStripRegionElementId, std::string(), HelpBubbleArrow::kNone); - without_group_description.steps.emplace_back( - create_tabgroup_with_existing_group_step); with_group_description.steps.emplace_back( create_tabgroup_with_existing_group_step);
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc index c518bba..56f104615 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -1086,3 +1086,43 @@ EXPECT_FALSE(browser_view->ShouldDescendIntoChildForEventHandling( browser_view->GetWidget()->GetNativeView(), draggable_point)); } + +IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_WindowControlsOverlay, + FencedFrame) { + InstallAndLaunchWebApp(); + ToggleWindowControlsOverlayAndWait(); + + BrowserView* browser_view = helper()->browser_view(); + gfx::Rect bounds = GetWindowControlOverlayBoundingClientRect(); + EXPECT_TRUE(GetWindowControlOverlayVisibility()); + EXPECT_FALSE(bounds.IsEmpty()); + EXPECT_NE(0, bounds.width()); + EXPECT_NE(0, bounds.height()); + + // Ensure window controls overlay values are not sent to a fenced frame. + const GURL fenced_frame_url = + embedded_test_server()->GetURL("/fenced_frames/title1.html"); + + content::RenderFrameHost* fenced_frame_rfh = + fenced_frame_helper_.CreateFencedFrame( + browser_view->GetActiveWebContents()->GetPrimaryMainFrame(), + fenced_frame_url); + ASSERT_NE(nullptr, fenced_frame_rfh); + + EXPECT_EQ(false, EvalJs(fenced_frame_rfh, + "window.navigator.windowControlsOverlay.visible")); + EXPECT_EQ( + 0, + EvalJs(fenced_frame_rfh, + "window.navigator.windowControlsOverlay.getTitlebarAreaRect().x")); + EXPECT_EQ( + 0, + EvalJs(fenced_frame_rfh, + "window.navigator.windowControlsOverlay.getTitlebarAreaRect().y")); + EXPECT_EQ(0, EvalJs(fenced_frame_rfh, + "window.navigator.windowControlsOverlay." + "getTitlebarAreaRect().width")); + EXPECT_EQ(0, EvalJs(fenced_frame_rfh, + "window.navigator.windowControlsOverlay." + "getTitlebarAreaRect().height")); +}
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_origin_text.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_origin_text.cc index 98742947..b88575f6 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_origin_text.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_origin_text.cc
@@ -20,6 +20,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/views/controls/label.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" namespace { @@ -36,7 +37,7 @@ label_ = std::make_unique<views::Label>( browser->app_controller()->GetLaunchFlashText(), ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, - ChromeTextStyle::STYLE_EMPHASIZED) + views::style::STYLE_EMPHASIZED) .release(); label_->SetElideBehavior(gfx::ELIDE_HEAD); label_->SetSubpixelRenderingEnabled(false);
diff --git a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc index c1b1257..65ec371 100644 --- a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc +++ b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc
@@ -42,6 +42,7 @@ {"historyClustersTabLabel", IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL}, {"historyListTabLabel", IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL}, {"loadMoreButtonLabel", IDS_HISTORY_CLUSTERS_LOAD_MORE_BUTTON_LABEL}, + {"noSearchResults", IDS_HISTORY_CLUSTERS_NO_SEARCH_RESULTS}, {"openAllInTabGroup", IDS_HISTORY_CLUSTERS_OPEN_ALL_IN_TABGROUP}, {"relatedSearchesHeader", IDS_HISTORY_CLUSTERS_RELATED_SEARCHES_HEADER}, {"removeAllFromHistory", IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS},
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index a7f5121..90909c5 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -367,7 +367,9 @@ !extension->is_platform_app() && is_locally_installed); // Any locally installed app can have shortcuts created. - dict.Set("mayCreateShortcuts", is_locally_installed); + dict.Set( + "mayCreateShortcuts", + is_locally_installed && extension->id() != extensions::kWebStoreAppId); dict.Set("isLocallyInstalled", is_locally_installed); auto icon_size = extension_misc::EXTENSION_ICON_LARGE;
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc index eb0abce..c5265f6 100644 --- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -48,15 +48,15 @@ "settings_account_manager_account_removed"; ::account_manager::AccountKey GetAccountKeyFromJsCallback( - const base::Value& dictionary) { - const base::Value* id_value = dictionary.FindKey("id"); - DCHECK(id_value); - const std::string id = id_value->GetString(); - DCHECK(!id.empty()); + const base::Value::Dict& dictionary) { + const std::string* id = dictionary.FindString("id"); + DCHECK(id); + DCHECK(!id->empty()); - const base::Value* account_type_value = dictionary.FindKey("accountType"); + const absl::optional<int> account_type_value = + dictionary.FindInt("accountType"); DCHECK(account_type_value); - const int account_type_int = account_type_value->GetInt(); + const int account_type_int = *account_type_value; DCHECK((account_type_int >= static_cast<int>(account_manager::AccountType::kGaia)) && (account_type_int <= @@ -64,13 +64,13 @@ const account_manager::AccountType account_type = static_cast<account_manager::AccountType>(account_type_int); - return ::account_manager::AccountKey{id, account_type}; + return ::account_manager::AccountKey{*id, account_type}; } ::account_manager::Account GetAccountFromJsCallback( - const base::Value& dictionary) { + const base::Value::Dict& dictionary) { ::account_manager::AccountKey key = GetAccountKeyFromJsCallback(dictionary); - const std::string* email = dictionary.FindStringKey("email"); + const std::string* email = dictionary.FindString("email"); DCHECK(email); return ::account_manager::Account{key, *email}; } @@ -102,80 +102,80 @@ ~AccountBuilder() = default; - void PopulateFrom(base::DictionaryValue account) { + void PopulateFrom(base::Value::Dict account) { account_ = std::move(account); } - bool IsEmpty() const { return account_.DictEmpty(); } + bool IsEmpty() const { return account_.empty(); } AccountBuilder& SetId(const std::string& value) { - account_.SetStringKey("id", value); + account_.Set("id", value); return *this; } AccountBuilder& SetEmail(const std::string& value) { - account_.SetStringKey("email", value); + account_.Set("email", value); return *this; } AccountBuilder& SetFullName(const std::string& value) { - account_.SetStringKey("fullName", value); + account_.Set("fullName", value); return *this; } AccountBuilder& SetAccountType(const int& value) { - account_.SetIntKey("accountType", value); + account_.Set("accountType", value); return *this; } AccountBuilder& SetIsDeviceAccount(const bool& value) { - account_.SetBoolKey("isDeviceAccount", value); + account_.Set("isDeviceAccount", value); return *this; } AccountBuilder& SetIsSignedIn(const bool& value) { - account_.SetBoolKey("isSignedIn", value); + account_.Set("isSignedIn", value); return *this; } AccountBuilder& SetUnmigrated(const bool& value) { - account_.SetBoolKey("unmigrated", value); + account_.Set("unmigrated", value); return *this; } AccountBuilder& SetIsManaged(const bool& value) { - account_.SetBoolKey("isManaged", value); + account_.Set("isManaged", value); return *this; } AccountBuilder& SetPic(const std::string& value) { - account_.SetStringKey("pic", value); + account_.Set("pic", value); return *this; } AccountBuilder& SetOrganization(const std::string& value) { - account_.SetStringKey("organization", value); + account_.Set("organization", value); return *this; } AccountBuilder& SetIsAvailableInArc(bool value) { - account_.SetBoolKey("isAvailableInArc", value); + account_.Set("isAvailableInArc", value); return *this; } // Should be called only once. - base::DictionaryValue Build() { + base::Value::Dict Build() { // Check that values were set. - DCHECK(account_.FindStringKey("id")); - DCHECK(account_.FindStringKey("email")); - DCHECK(account_.FindStringKey("fullName")); - DCHECK(account_.FindIntKey("accountType")); - DCHECK(account_.FindBoolKey("isDeviceAccount")); - DCHECK(account_.FindBoolKey("isSignedIn")); - DCHECK(account_.FindBoolKey("unmigrated")); - DCHECK(account_.FindStringKey("pic")); + DCHECK(account_.FindString("id")); + DCHECK(account_.FindString("email")); + DCHECK(account_.FindString("fullName")); + DCHECK(account_.FindInt("accountType")); + DCHECK(account_.FindBool("isDeviceAccount")); + DCHECK(account_.FindBool("isSignedIn")); + DCHECK(account_.FindBool("unmigrated")); + DCHECK(account_.FindString("pic")); if (ash::AccountAppsAvailability::IsArcAccountRestrictionsEnabled()) { - DCHECK(account_.FindBoolKey("isAvailableInArc")); + DCHECK(account_.FindBool("isAvailableInArc")); } // "organization" is an optional field. @@ -183,7 +183,7 @@ } private: - base::DictionaryValue account_; + base::Value::Dict account_; }; } // namespace @@ -278,8 +278,8 @@ user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile_); DCHECK(user); - base::DictionaryValue gaia_device_account; - base::ListValue accounts = GetSecondaryGaiaAccounts( + base::Value::Dict gaia_device_account; + base::Value::List accounts = GetSecondaryGaiaAccounts( account_dummy_token_list, arc_accounts, user->GetAccountId(), profile_->IsChild(), &gaia_device_account); @@ -328,21 +328,20 @@ } // Device account must show up at the top. - accounts.Insert(accounts.GetListDeprecated().begin(), - device_account.Build()); + accounts.Insert(accounts.begin(), base::Value(device_account.Build())); } ResolveJavascriptCallback(callback_id, accounts); } -base::ListValue AccountManagerUIHandler::GetSecondaryGaiaAccounts( +base::Value::List AccountManagerUIHandler::GetSecondaryGaiaAccounts( const std::vector<std::pair<::account_manager::Account, bool>>& account_dummy_token_list, const base::flat_set<account_manager::Account>& arc_accounts, const AccountId device_account_id, const bool is_child_user, - base::DictionaryValue* device_account) { - base::ListValue accounts; + base::Value::Dict* device_account) { + base::Value::List accounts; for (const auto& account_token_pair : account_dummy_token_list) { const ::account_manager::Account& stored_account = account_token_pair.first; const ::account_manager::AccountKey& account_key = stored_account.key; @@ -432,13 +431,13 @@ AllowJavascript(); CHECK(!args.empty()); - const base::Value& dictionary = args[0]; - CHECK(dictionary.is_dict()); + const base::Value::Dict* dictionary = args[0].GetIfDict(); + CHECK(dictionary); const AccountId device_account_id = ProfileHelper::Get()->GetUserByProfile(profile_)->GetAccountId(); const ::account_manager::AccountKey account_key = - GetAccountKeyFromJsCallback(dictionary); + GetAccountKeyFromJsCallback(*dictionary); if (IsSameAccount(account_key, device_account_id)) { // It should not be possible to remove a device account. return; @@ -447,14 +446,14 @@ account_manager_->RemoveAccount(account_key); // Show toast with removal message. - const base::Value* email_value = dictionary.FindKey("email"); - const std::string email = email_value->GetString(); - DCHECK(!email.empty()); + const std::string* email = dictionary->FindString("email"); + DCHECK(email); + DCHECK(!email->empty()); ShowToast(kAccountRemovedToastId, ash::ToastCatalogName::kAccountRemoved, l10n_util::GetStringFUTF16( IDS_SETTINGS_ACCOUNT_MANAGER_ACCOUNT_REMOVED_MESSAGE, - base::UTF8ToUTF16(email))); + base::UTF8ToUTF16(*email))); } void AccountManagerUIHandler::HandleChangeArcAvailability( @@ -463,13 +462,13 @@ // 2 args: account, is_available. CHECK_GT(args.size(), 1u); - const base::Value& account_dict = args[0]; - CHECK(account_dict.is_dict()); + const base::Value::Dict* account_dict = args[0].GetIfDict(); + CHECK(account_dict); const absl::optional<bool> is_available = args[1].GetIfBool(); CHECK(is_available.has_value()); const ::account_manager::Account account = - GetAccountFromJsCallback(account_dict); + GetAccountFromJsCallback(*account_dict); account_apps_availability_->SetIsAccountAvailableInArc(account, is_available.value()); // Note: the observer call will update the UI.
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h index 2ca8d2c6..331f90d 100644 --- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -9,6 +9,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" +#include "base/values.h" #include "chrome/browser/ash/account_manager/account_apps_availability.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/account_id/account_id.h" @@ -109,13 +110,13 @@ // If user (device account) is child - |is_child_user| should be set to true, // in this case "unmigrated" property will be always false for secondary // accounts. - base::ListValue GetSecondaryGaiaAccounts( + base::Value::List GetSecondaryGaiaAccounts( const std::vector<std::pair<::account_manager::Account, bool>>& account_dummy_token_list, const base::flat_set<account_manager::Account>& arc_accounts, const AccountId device_account_id, const bool is_child_user, - base::DictionaryValue* device_account); + base::Value::Dict* device_account); // Refreshes the UI. void RefreshUI();
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc index 70b6979..c8c6647 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -236,9 +236,9 @@ void StorageHandler::OnMountEvent( DiskMountManager::MountEvent event, - chromeos::MountError error_code, + ash::MountError error_code, const DiskMountManager::MountPoint& mount_info) { - if (error_code != chromeos::MountError::kNone) + if (error_code != ash::MountError::kNone) return; if (!IsEligibleForAndroidStorage(mount_info.source_path))
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h index 8f2c2cac..9800c93 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
@@ -65,7 +65,7 @@ // ash::disks::DiskMountManager::Observer: void OnMountEvent( ash::disks::DiskMountManager::MountEvent event, - chromeos::MountError error_code, + ash::MountError error_code, const ash::disks::DiskMountManager::MountPoint& mount_info) override; // chromeos::settings::calculator::SizeCalculator::Observer:
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index d244203..b946512 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -752,6 +752,7 @@ IDS_SETTINGS_LANGUAGES_OFFER_TO_ENABLE_TRANSLATE_SUBLABEL}, {"noLanguagesAdded", IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED}, {"translatePageTitle", IDS_SETTINGS_TRANSLATE_PAGE_TITLE}, + {"targetLanguageLabel", IDS_SETTINGS_TARGET_TRANSLATE_LABEL}, {"automaticallyTranslateLanguages", IDS_SETTINGS_LANGUAGES_AUTOMATIC_TRANSLATE}, {"neverTranslateLanguages", IDS_SETTINGS_LANGUAGES_NEVER_LANGUAGES},
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc index 81e2acf7..d712bfc 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc +++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -17,6 +17,7 @@ #include "chrome/grit/side_panel_resources.h" #include "chrome/grit/side_panel_resources_map.h" #include "components/bookmarks/common/bookmark_pref_names.h" +#include "components/commerce/core/webui/shopping_list_handler.h" #include "components/favicon_base/favicon_url_parser.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" @@ -78,8 +79,21 @@ bookmarks_page_factory_receiver_.Bind(std::move(receiver)); } +void BookmarksSidePanelUI::BindInterface( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> + receiver) { + shopping_list_factory_receiver_.reset(); + shopping_list_factory_receiver_.Bind(std::move(receiver)); +} + void BookmarksSidePanelUI::CreateBookmarksPageHandler( mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) { bookmarks_page_handler_ = std::make_unique<BookmarksPageHandler>(std::move(receiver), this); } + +void BookmarksSidePanelUI::CreateShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) { + shopping_list_handler_ = + std::make_unique<commerce::ShoppingListHandler>(std::move(receiver)); +}
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h index 0092c0d5..e377e47 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h +++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom.h" #include "chrome/browser/ui/webui/webui_load_timer.h" +#include "components/commerce/core/mojom/shopping_list.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -16,9 +17,14 @@ class BookmarksPageHandler; +namespace commerce { +class ShoppingListHandler; +} + class BookmarksSidePanelUI : public ui::MojoBubbleWebUIController, - public side_panel::mojom::BookmarksPageHandlerFactory { + public side_panel::mojom::BookmarksPageHandlerFactory, + public shopping_list::mojom::ShoppingListHandlerFactory { public: explicit BookmarksSidePanelUI(content::WebUI* web_ui); BookmarksSidePanelUI(const BookmarksSidePanelUI&) = delete; @@ -31,15 +37,27 @@ mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandlerFactory> receiver); + void BindInterface( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> + receiver); + private: - // side_panel::mojom::BookmarksPageHandlerFactory + // side_panel::mojom::BookmarksPageHandlerFactory: void CreateBookmarksPageHandler( mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) override; + // shopping_list::mojom::ShoppingListHandlerFactory: + void CreateShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) + override; + std::unique_ptr<BookmarksPageHandler> bookmarks_page_handler_; mojo::Receiver<side_panel::mojom::BookmarksPageHandlerFactory> bookmarks_page_factory_receiver_{this}; + std::unique_ptr<commerce::ShoppingListHandler> shopping_list_handler_; + mojo::Receiver<shopping_list::mojom::ShoppingListHandlerFactory> + shopping_list_factory_receiver_{this}; WEB_UI_CONTROLLER_TYPE_DECL(); };
diff --git a/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc index 5584fe57..f0191944 100644 --- a/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc +++ b/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc
@@ -33,8 +33,16 @@ profile, std::make_unique<FaviconSource>( profile, chrome::FaviconUrlFormat::kFavicon2)); + const webui::ResourcePath kHistoryClustersResources[] = { + {"history_clusters/history_clusters.html", + IDR_SIDE_PANEL_HISTORY_CLUSTERS_HISTORY_CLUSTERS_HTML}, + {"history_clusters/app.js", IDR_SIDE_PANEL_HISTORY_CLUSTERS_APP_JS}, + {"history_clusters/app.html.js", + IDR_SIDE_PANEL_HISTORY_CLUSTERS_APP_HTML_JS}, + }; + webui::SetupWebUIDataSource( - source, base::span<const webui::ResourcePath>(), + source, kHistoryClustersResources, IDR_SIDE_PANEL_HISTORY_CLUSTERS_HISTORY_CLUSTERS_HTML); content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), source);
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc index 072ea2278..3ea7ec7 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc
@@ -29,11 +29,11 @@ return; coordinator_ = ReadAnythingCoordinator::FromBrowser(browser_); - if (coordinator_) + if (coordinator_) { coordinator_->AddObserver(this); - model_ = coordinator_->GetModel(); - if (model_) - model_->AddObserver(this); + coordinator_->AddModelObserver(this); + } + delegate_ = static_cast<ReadAnythingPageHandler::Delegate*>( coordinator_->GetController()); if (delegate_) @@ -49,16 +49,14 @@ // If |this| is destroyed before the |ReadAnythingCoordinator|, then remove // |this| from the observer lists. In the cases where the coordinator is // destroyed first, these will have been destroyed before this call. - if (model_) - model_->RemoveObserver(this); - - if (coordinator_) + if (coordinator_) { coordinator_->RemoveObserver(this); + coordinator_->RemoveModelObserver(this); + } } void ReadAnythingPageHandler::OnCoordinatorDestroyed() { coordinator_ = nullptr; - model_ = nullptr; delegate_ = nullptr; } @@ -68,7 +66,7 @@ page_->OnAXTreeDistilled(snapshot, content_node_ids); } -void ReadAnythingPageHandler::OnThemeChanged( +void ReadAnythingPageHandler::OnReadAnythingThemeChanged( ReadAnythingThemePtr new_theme_ptr) { page_->OnThemeChanged(std::move(new_theme_ptr)); }
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h index 54df1ed..376d3cde 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h
@@ -49,7 +49,7 @@ void OnAXTreeDistilled( const ui::AXTreeUpdate& snapshot, const std::vector<ui::AXNodeID>& content_node_ids) override; - void OnThemeChanged( + void OnReadAnythingThemeChanged( read_anything::mojom::ReadAnythingThemePtr new_theme) override; // ReadAnythingCoordinator::Observer: @@ -57,7 +57,6 @@ private: raw_ptr<ReadAnythingCoordinator> coordinator_; - raw_ptr<ReadAnythingModel> model_; raw_ptr<ReadAnythingPageHandler::Delegate> delegate_; raw_ptr<Browser> browser_;
diff --git a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc index e7a16f8..3a09a12b 100644 --- a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc +++ b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
@@ -20,6 +20,7 @@ #include "chrome/grit/side_panel_resources.h" #include "chrome/grit/side_panel_resources_map.h" #include "components/bookmarks/common/bookmark_pref_names.h" +#include "components/commerce/core/webui/shopping_list_handler.h" #include "components/favicon_base/favicon_url_parser.h" #include "components/prefs/pref_service.h" #include "components/reading_list/core/reading_list_model.h" @@ -140,6 +141,19 @@ std::move(page), std::move(receiver)); } +void ReadingListUI::BindInterface( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> + receiver) { + shopping_list_factory_receiver_.reset(); + shopping_list_factory_receiver_.Bind(std::move(receiver)); +} + +void ReadingListUI::CreateShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) { + shopping_list_handler_ = + std::make_unique<commerce::ShoppingListHandler>(std::move(receiver)); +} + void ReadingListUI::SetActiveTabURL(const GURL& url) { if (page_handler_) page_handler_->SetActiveTabURL(url);
diff --git a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h index 674f2ee1..a55dda8 100644 --- a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h +++ b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/webui/side_panel/reading_list/reading_list.mojom.h" #include "chrome/browser/ui/webui/webui_load_timer.h" #include "chrome/common/accessibility/read_anything.mojom.h" +#include "components/commerce/core/mojom/shopping_list.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -20,10 +21,15 @@ class ReadAnythingPageHandler; class ReadingListPageHandler; +namespace commerce { +class ShoppingListHandler; +} + class ReadingListUI : public ui::MojoBubbleWebUIController, public reading_list::mojom::PageHandlerFactory, public side_panel::mojom::BookmarksPageHandlerFactory, - public read_anything::mojom::PageHandlerFactory { + public read_anything::mojom::PageHandlerFactory, + public shopping_list::mojom::ShoppingListHandlerFactory { public: explicit ReadingListUI(content::WebUI* web_ui); ReadingListUI(const ReadingListUI&) = delete; @@ -42,6 +48,10 @@ void BindInterface( mojo::PendingReceiver<read_anything::mojom::PageHandlerFactory> receiver); + void BindInterface( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> + receiver); + void SetActiveTabURL(const GURL& url); private: @@ -50,7 +60,7 @@ mojo::PendingReceiver<reading_list::mojom::PageHandler> receiver) override; - // side_panel::mojom::BookmarksPageHandlerFactory + // side_panel::mojom::BookmarksPageHandlerFactory: void CreateBookmarksPageHandler( mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) override; @@ -61,6 +71,11 @@ mojo::PendingReceiver<read_anything::mojom::PageHandler> receiver) override; + // shopping_list::mojom::ShoppingListHandlerFactory: + void CreateShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) + override; + std::unique_ptr<ReadingListPageHandler> page_handler_; mojo::Receiver<reading_list::mojom::PageHandlerFactory> page_factory_receiver_{this}; @@ -73,6 +88,10 @@ mojo::Receiver<read_anything::mojom::PageHandlerFactory> read_anything_page_factory_receiver_{this}; + std::unique_ptr<commerce::ShoppingListHandler> shopping_list_handler_; + mojo::Receiver<shopping_list::mojom::ShoppingListHandlerFactory> + shopping_list_factory_receiver_{this}; + WebuiLoadTimer webui_load_timer_; WEB_UI_CONTROLLER_TYPE_DECL();
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index b922eb7..51c7517 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -12,6 +12,8 @@ "commands/callback_command.h", "commands/clear_browsing_data_command.cc", "commands/clear_browsing_data_command.h", + "commands/externally_managed_install_command.cc", + "commands/externally_managed_install_command.h", "commands/fetch_manifest_and_install_command.cc", "commands/fetch_manifest_and_install_command.h", "commands/install_from_info_command.cc", @@ -20,8 +22,6 @@ "commands/install_from_sync_command.h", "commands/install_isolated_app_command.cc", "commands/install_isolated_app_command.h", - "commands/install_web_app_with_params_command.cc", - "commands/install_web_app_with_params_command.h", "commands/run_on_os_login_command.cc", "commands/run_on_os_login_command.h", "commands/sub_app_install_command.cc", @@ -502,6 +502,7 @@ sources = [ "commands/clear_browsing_data_command_unittest.cc", + "commands/externally_managed_install_command_unittest.cc", "commands/install_from_sync_command_unittest.cc", "commands/install_isolated_app_command_unittest.cc", "commands/run_on_os_login_command_unittest.cc", @@ -655,11 +656,11 @@ testonly = true sources = [ + "commands/externally_managed_install_command_browsertest.cc", "commands/fetch_manifest_and_install_command_browsertest.cc", "commands/install_from_info_command_browsertest.cc", "commands/install_from_sync_command_browsertest.cc", "commands/install_isolated_app_command_browsertest.cc", - "commands/install_web_app_with_params_command_browsertest.cc", "externally_installed_web_app_prefs_browsertest.cc", "externally_managed_app_manager_impl_browsertest.cc", "isolated_app_browsertest.cc",
diff --git a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc index 2d2db4e..d80f8e7 100644 --- a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc +++ b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
@@ -59,8 +59,7 @@ })); std::vector<base::FilePath> file_paths( - {chromeos::CrosDisksClient::GetArchiveMountPoint().Append( - "numbers.csv")}); + {ash::CrosDisksClient::GetArchiveMountPoint().Append("numbers.csv")}); std::vector<std::string> content_types({"text/csv"}); apps::IntentPtr intent = apps_util::CreateShareIntentFromFiles( profile, std::move(file_paths), std::move(content_types));
diff --git a/chrome/browser/web_applications/commands/externally_managed_install_command.cc b/chrome/browser/web_applications/commands/externally_managed_install_command.cc new file mode 100644 index 0000000..a5e2584f --- /dev/null +++ b/chrome/browser/web_applications/commands/externally_managed_install_command.cc
@@ -0,0 +1,285 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/commands/externally_managed_install_command.h" + +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/feature_list.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/external_install_options.h" +#include "chrome/browser/web_applications/install_bounce_metric.h" +#include "chrome/browser/web_applications/locks/app_lock.h" +#include "chrome/browser/web_applications/locks/noop_lock.h" +#include "chrome/browser/web_applications/locks/web_app_lock_manager.h" +#include "chrome/browser/web_applications/web_app_command_manager.h" +#include "chrome/browser/web_applications/web_app_data_retriever.h" +#include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_install_utils.h" +#include "chrome/browser/web_applications/web_app_logging.h" +#include "chrome/common/chrome_features.h" +#include "content/public/browser/web_contents.h" + +namespace web_app { + +ExternallyManagedInstallCommand::ExternallyManagedInstallCommand( + const ExternalInstallOptions& external_install_options, + OnceInstallCallback callback, + base::WeakPtr<content::WebContents> contents, + WebAppInstallFinalizer* install_finalizer, + std::unique_ptr<WebAppDataRetriever> data_retriever) + : noop_lock_(std::make_unique<NoopLock>()), + install_params_( + ConvertExternalInstallOptionsToParams(external_install_options)), + install_surface_(ConvertExternalInstallSourceToInstallSource( + external_install_options.install_source)), + install_callback_(std::move(callback)), + web_contents_(contents), + install_finalizer_(install_finalizer), + data_retriever_(std::move(data_retriever)), + install_error_log_entry_(/*background_installation=*/true, + install_surface_) { + if (!install_params_.locally_installed) { + DCHECK(!install_params_.add_to_applications_menu); + DCHECK(!install_params_.add_to_desktop); + DCHECK(!install_params_.add_to_quick_launch_bar); + } + DCHECK_NE(install_surface_, webapps::WebappInstallSource::SYNC); +} + +ExternallyManagedInstallCommand::~ExternallyManagedInstallCommand() = default; + +Lock& ExternallyManagedInstallCommand::lock() const { + DCHECK(noop_lock_ || app_lock_); + + if (noop_lock_ != nullptr) + return *noop_lock_; + + return *app_lock_; +} + +void ExternallyManagedInstallCommand::Start() { + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + data_retriever_->GetWebAppInstallInfo( + web_contents_.get(), + base::BindOnce( + &ExternallyManagedInstallCommand::OnGetWebAppInstallInfoInCommand, + weak_factory_.GetWeakPtr())); +} + +void ExternallyManagedInstallCommand::OnSyncSourceRemoved() { + // TODO(crbug.com/1320086): remove after uninstall from sync is async. + Abort(webapps::InstallResultCode::kAppNotInRegistrarAfterCommit); + return; +} + +void ExternallyManagedInstallCommand::OnShutdown() { + Abort(webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown); + return; +} + +base::Value ExternallyManagedInstallCommand::ToDebugValue() const { + base::Value::Dict params_info; + params_info.Set("ExternallyManagedInstallCommand ID:", id()); + params_info.Set("Title", + install_params_.fallback_app_name.has_value() + ? base::Value(install_params_.fallback_app_name.value()) + : base::Value()); + params_info.Set("Start URL", + install_params_.fallback_start_url.is_valid() + ? base::Value(install_params_.fallback_start_url.spec()) + : base::Value()); + return base::Value(std::move(params_info)); +} + +void ExternallyManagedInstallCommand::Abort(webapps::InstallResultCode code) { + if (!install_callback_) + return; + webapps::InstallableMetrics::TrackInstallResult(false); + SignalCompletionAndSelfDestruct( + CommandResult::kFailure, + base::BindOnce(std::move(install_callback_), AppId(), code)); +} + +void ExternallyManagedInstallCommand::OnGetWebAppInstallInfoInCommand( + std::unique_ptr<WebAppInstallInfo> web_app_info) { + web_app_info_ = std::move(web_app_info); + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + if (!web_app_info_) { + Abort(webapps::InstallResultCode::kGetWebAppInstallInfoFailed); + return; + } + + // Write values from install_params_ to web_app_info. + bypass_service_worker_check_ = install_params_.bypass_service_worker_check; + // Set start_url to fallback_start_url as web_contents may have been + // redirected. Will be overridden by manifest values if present. + DCHECK(install_params_.fallback_start_url.is_valid()); + web_app_info_->start_url = install_params_.fallback_start_url; + + if (install_params_.fallback_app_name.has_value()) + web_app_info_->title = install_params_.fallback_app_name.value(); + + ApplyParamsToWebAppInstallInfo(install_params_, *web_app_info_); + + data_retriever_->CheckInstallabilityAndRetrieveManifest( + web_contents_.get(), bypass_service_worker_check_, + base::BindOnce( + &ExternallyManagedInstallCommand::OnDidPerformInstallableCheck, + weak_factory_.GetWeakPtr())); +} + +void ExternallyManagedInstallCommand::OnDidPerformInstallableCheck( + blink::mojom::ManifestPtr opt_manifest, + const GURL& manifest_url, + bool valid_manifest_for_web_app, + bool is_installable) { + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + if (install_params_.require_manifest && !valid_manifest_for_web_app) { + LOG(WARNING) << "Did not install " << manifest_url.spec() + << " because it didn't have a manifest for web app"; + Abort(webapps::InstallResultCode::kNotValidManifestForWebApp); + return; + } + + // A system app should always have a manifest icon. + if (install_surface_ == webapps::WebappInstallSource::SYSTEM_DEFAULT) { + DCHECK(opt_manifest); + DCHECK(!opt_manifest->icons.empty()); + } + + if (opt_manifest) { + UpdateWebAppInfoFromManifest(*opt_manifest, manifest_url, + web_app_info_.get()); + } + + app_id_ = GenerateAppId(web_app_info_->manifest_id, web_app_info_->start_url); + + // If the manifest specified icons, don't use the page icons. + const bool skip_page_favicons = opt_manifest && !opt_manifest->icons.empty(); + + base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*web_app_info_); + data_retriever_->GetIcons( + web_contents_.get(), std::move(icon_urls), skip_page_favicons, + base::BindOnce( + &ExternallyManagedInstallCommand::OnIconsRetrievedUpgradeLock, + weak_factory_.GetWeakPtr())); +} + +void ExternallyManagedInstallCommand::OnIconsRetrievedUpgradeLock( + IconsDownloadedResult result, + IconsMap icons_map, + DownloadedIconsHttpResults icons_http_results) { + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + PopulateProductIcons(web_app_info_.get(), &icons_map); + PopulateOtherIcons(web_app_info_.get(), icons_map); + + RecordDownloadedIconsResultAndHttpStatusCodes(result, icons_http_results); + + install_error_log_entry_.LogDownloadedIconsErrors( + *web_app_info_, result, icons_map, icons_http_results); + + app_lock_ = command_manager()->lock_manager().UpgradeAndAcquireLock( + std::move(noop_lock_), {app_id_}, + base::BindOnce( + &ExternallyManagedInstallCommand::OnLockUpgradedFinalizeInstall, + weak_factory_.GetWeakPtr())); +} + +void ExternallyManagedInstallCommand::OnLockUpgradedFinalizeInstall() { + if (on_lock_upgraded_callback_for_testing_) + std::move(on_lock_upgraded_callback_for_testing_).Run(); + + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + WebAppInstallFinalizer::FinalizeOptions finalize_options(install_surface_); + + finalize_options.locally_installed = install_params_.locally_installed; + finalize_options.overwrite_existing_manifest_fields = + install_params_.force_reinstall; + finalize_options.parent_app_id = install_params_.parent_app_id; + + ApplyParamsToFinalizeOptions(install_params_, finalize_options); + + if (install_params_.user_display_mode.has_value()) + web_app_info_->user_display_mode = install_params_.user_display_mode; + finalize_options.add_to_applications_menu = + install_params_.add_to_applications_menu; + finalize_options.add_to_desktop = install_params_.add_to_desktop; + finalize_options.add_to_quick_launch_bar = + install_params_.add_to_quick_launch_bar; + + install_finalizer_->FinalizeInstall( + *web_app_info_, finalize_options, + base::BindOnce(&ExternallyManagedInstallCommand::OnInstallFinalized, + weak_factory_.GetWeakPtr())); + + // Check that the finalizer hasn't called OnInstallFinalizedMaybeReparentTab + // synchronously: + DCHECK(install_callback_); +} + +void ExternallyManagedInstallCommand::OnInstallFinalized( + const AppId& app_id, + webapps::InstallResultCode code, + OsHooksErrors os_hooks_errors) { + if (!web_contents_ || web_contents_->IsBeingDestroyed()) { + Abort(webapps::InstallResultCode::kWebContentsDestroyed); + return; + } + + if (code != webapps::InstallResultCode::kSuccessNewInstall) { + Abort(code); + return; + } + + RecordWebAppInstallationTimestamp( + Profile::FromBrowserContext(web_contents_->GetBrowserContext()) + ->GetPrefs(), + app_id, install_surface_); + + if (install_params_.locally_installed) { + RecordAppBanner(web_contents_.get(), web_app_info_->start_url); + } + + if (base::FeatureList::IsEnabled(features::kRecordWebAppDebugInfo)) { + base::Value task_error_dict = install_error_log_entry_.TakeErrorDict(); + if (!task_error_dict.DictEmpty()) + command_manager()->LogToInstallManager(std::move(task_error_dict)); + } + + webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code)); + SignalCompletionAndSelfDestruct( + CommandResult::kSuccess, + base::BindOnce(std::move(install_callback_), app_id, code)); +} + +void ExternallyManagedInstallCommand::SetOnLockUpgradedCallbackForTesting( + base::OnceClosure callback) { + on_lock_upgraded_callback_for_testing_ = std::move(callback); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/commands/externally_managed_install_command.h b/chrome/browser/web_applications/commands/externally_managed_install_command.h new file mode 100644 index 0000000..0eb286a7 --- /dev/null +++ b/chrome/browser/web_applications/commands/externally_managed_install_command.h
@@ -0,0 +1,100 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_EXTERNALLY_MANAGED_INSTALL_COMMAND_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_EXTERNALLY_MANAGED_INSTALL_COMMAND_H_ + +#include <memory> +#include <variant> + +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/external_install_options.h" +#include "chrome/browser/web_applications/locks/app_lock.h" +#include "chrome/browser/web_applications/os_integration/os_integration_manager.h" +#include "chrome/browser/web_applications/web_app_install_params.h" +#include "chrome/browser/web_applications/web_app_logging.h" +#include "components/webapps/browser/install_result_code.h" +#include "components/webapps/browser/installable/installable_metrics.h" + +namespace content { +class WebContents; +} + +namespace web_app { + +class NoopLock; +class WebAppDataRetriever; +class WebAppInstallFinalizer; + +// Command to install web_apps from param by the ExternallyInstalledAppsManager +class ExternallyManagedInstallCommand : public WebAppCommand { + public: + ExternallyManagedInstallCommand( + const ExternalInstallOptions& external_install_options, + OnceInstallCallback callback, + base::WeakPtr<content::WebContents> contents, + WebAppInstallFinalizer* install_finalizer, + std::unique_ptr<WebAppDataRetriever> data_retriever); + ~ExternallyManagedInstallCommand() override; + + Lock& lock() const override; + + void Start() override; + void OnSyncSourceRemoved() override; + void OnShutdown() override; + + base::Value ToDebugValue() const override; + + void SetOnLockUpgradedCallbackForTesting(base::OnceClosure callback); + + private: + void Abort(webapps::InstallResultCode code); + + void OnGetWebAppInstallInfoInCommand( + std::unique_ptr<WebAppInstallInfo> web_app_info); + void OnDidPerformInstallableCheck(blink::mojom::ManifestPtr opt_manifest, + const GURL& manifest_url, + bool valid_manifest_for_web_app, + bool is_installable); + void OnIconsRetrievedUpgradeLock( + IconsDownloadedResult result, + IconsMap icons_map, + DownloadedIconsHttpResults icons_http_results); + + void OnLockUpgradedFinalizeInstall(); + + void OnInstallFinalized(const AppId& app_id, + webapps::InstallResultCode code, + OsHooksErrors os_hooks_errors); + + std::unique_ptr<NoopLock> noop_lock_; + + std::unique_ptr<AppLock> app_lock_ = nullptr; + + WebAppInstallParams install_params_; + webapps::WebappInstallSource install_surface_; + OnceInstallCallback install_callback_; + + base::WeakPtr<content::WebContents> web_contents_; + base::raw_ptr<WebAppInstallFinalizer> install_finalizer_; + + bool bypass_service_worker_check_ = false; + + std::unique_ptr<WebAppDataRetriever> data_retriever_; + std::unique_ptr<WebAppInstallInfo> web_app_info_; + + InstallErrorLogEntry install_error_log_entry_; + + AppId app_id_; + + base::OnceClosure on_lock_upgraded_callback_for_testing_; + + base::WeakPtrFactory<ExternallyManagedInstallCommand> weak_factory_{this}; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_EXTERNALLY_MANAGED_INSTALL_COMMAND_H_
diff --git a/chrome/browser/web_applications/commands/install_web_app_with_params_command_browsertest.cc b/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc similarity index 72% rename from chrome/browser/web_applications/commands/install_web_app_with_params_command_browsertest.cc rename to chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc index f23c401..01c6841d 100644 --- a/chrome/browser/web_applications/commands/install_web_app_with_params_command_browsertest.cc +++ b/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" -#include "chrome/browser/web_applications/commands/install_web_app_with_params_command.h" +#include "chrome/browser/web_applications/commands/externally_managed_install_command.h" #include "chrome/browser/web_applications/external_install_options.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_data_retriever.h" @@ -22,9 +22,9 @@ namespace web_app { -using InstallWebAppWithParamsCommandBrowserTest = WebAppControllerBrowserTest; +using ExternallyManagedInstallCommandBrowserTest = WebAppControllerBrowserTest; -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, BasicInstallCommand) { const GURL kWebAppUrl = https_server()->GetURL( "/banners/" @@ -36,27 +36,24 @@ kWebAppUrl, /*user_display_mode=*/absl::nullopt, ExternalInstallSource::kInternalDefault); - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), - install_params, install_source, &provider().install_finalizer(), - &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + install_options, base::BindLambdaForTesting( [&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall); EXPECT_TRUE(provider().registrar().IsLocallyInstalled(app_id)); run_loop.Quit(); }), + browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), + &provider().install_finalizer(), std::make_unique<WebAppDataRetriever>())); run_loop.Run(); } -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, ExternalInstallWindowMode) { const GURL kWebAppUrl = https_server()->GetURL( "/banners/" @@ -67,15 +64,10 @@ ExternalInstallOptions install_options( kWebAppUrl, UserDisplayMode::kStandalone, ExternalInstallSource::kExternalDefault); - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), - install_params, install_source, &provider().install_finalizer(), - &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + install_options, base::BindLambdaForTesting([&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall); @@ -85,12 +77,14 @@ provider().registrar().GetAppUserDisplayMode(app_id).value()); run_loop.Quit(); }), + browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), + &provider().install_finalizer(), std::make_unique<WebAppDataRetriever>())); run_loop.Run(); } -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, ExternalInstallBrowserMode) { const GURL kWebAppUrl = https_server()->GetURL( "/banners/" @@ -101,15 +95,11 @@ ExternalInstallOptions install_options( kWebAppUrl, UserDisplayMode::kBrowser, ExternalInstallSource::kInternalDefault); - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), - install_params, install_source, &provider().install_finalizer(), - &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + + install_options, base::BindLambdaForTesting([&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall); @@ -119,12 +109,15 @@ provider().registrar().GetAppUserDisplayMode(app_id).value()); run_loop.Quit(); }), + browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), + &provider().install_finalizer(), + std::make_unique<WebAppDataRetriever>())); run_loop.Run(); } -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, InstallAppFromPolicy) { const GURL kWebAppUrl = https_server()->GetURL( "/banners/" @@ -135,15 +128,10 @@ ExternalInstallOptions install_options( kWebAppUrl, UserDisplayMode::kBrowser, ExternalInstallSource::kExternalPolicy); - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), - install_params, install_source, &provider().install_finalizer(), - &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + install_options, base::BindLambdaForTesting( [&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall); @@ -154,12 +142,14 @@ ->IsPolicyInstalledApp()); run_loop.Quit(); }), + browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(), + &provider().install_finalizer(), std::make_unique<WebAppDataRetriever>())); run_loop.Run(); } -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, InstallFailsWebContentsDestroyed) { const GURL kWebAppUrl("https://external_app.com"); EXPECT_FALSE(NavigateAndAwaitInstallabilityCheck(browser(), kWebAppUrl)); @@ -168,28 +158,26 @@ ExternalInstallOptions install_options( kWebAppUrl, UserDisplayMode::kBrowser, ExternalInstallSource::kExternalPolicy); - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - web_contents->GetWeakPtr(), install_params, install_source, - &provider().install_finalizer(), &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + install_options, base::BindLambdaForTesting([&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, webapps::InstallResultCode::kWebContentsDestroyed); EXPECT_FALSE(provider().registrar().IsLocallyInstalled(app_id)); run_loop.Quit(); }), + web_contents->GetWeakPtr(), &provider().install_finalizer(), + std::make_unique<WebAppDataRetriever>())); web_contents->Close(); run_loop.Run(); } -IN_PROC_BROWSER_TEST_F(InstallWebAppWithParamsCommandBrowserTest, +IN_PROC_BROWSER_TEST_F(ExternallyManagedInstallCommandBrowserTest, InstallFailsWithInvalidManifest) { const GURL kWebAppUrl("https://external_app.com"); EXPECT_FALSE(NavigateAndAwaitInstallabilityCheck(browser(), kWebAppUrl)); @@ -201,15 +189,11 @@ // This should force the install_params to have a valid manifest, otherwise // install will not happen. install_options.require_manifest = true; - auto install_params = ConvertExternalInstallOptionsToParams(install_options); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options.install_source); auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); provider().command_manager().ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - web_contents->GetWeakPtr(), install_params, install_source, - &provider().install_finalizer(), &provider().registrar(), + std::make_unique<ExternallyManagedInstallCommand>( + install_options, base::BindLambdaForTesting([&](const AppId& app_id, webapps::InstallResultCode code) { EXPECT_EQ(code, @@ -217,6 +201,8 @@ EXPECT_FALSE(provider().registrar().IsLocallyInstalled(app_id)); run_loop.Quit(); }), + web_contents->GetWeakPtr(), &provider().install_finalizer(), + std::make_unique<WebAppDataRetriever>())); run_loop.Run();
diff --git a/chrome/browser/web_applications/commands/externally_managed_install_command_unittest.cc b/chrome/browser/web_applications/commands/externally_managed_install_command_unittest.cc new file mode 100644 index 0000000..a4ca309 --- /dev/null +++ b/chrome/browser/web_applications/commands/externally_managed_install_command_unittest.cc
@@ -0,0 +1,264 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/commands/externally_managed_install_command.h" + +#include <memory> + +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "chrome/browser/web_applications/commands/callback_command.h" +#include "chrome/browser/web_applications/external_install_options.h" +#include "chrome/browser/web_applications/test/fake_data_retriever.h" +#include "chrome/browser/web_applications/test/fake_web_app_provider.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/test/web_app_test.h" +#include "chrome/browser/web_applications/user_display_mode.h" +#include "chrome/browser/web_applications/web_app_command_manager.h" +#include "chrome/browser/web_applications/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_data_retriever.h" +#include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "chrome/browser/web_applications/web_app_install_utils.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/webapps/browser/install_result_code.h" +#include "content/public/browser/web_contents.h" + +namespace web_app { +namespace { + +class ExternallyManagedInstallCommandTest : public WebAppTest { + public: + const GURL kWebAppUrl = GURL("https://example.com/path/index.html"); + const GURL kWebAppScope = GURL("https://example.com/path/"); + const AppId kWebAppId = + GenerateAppId(/*manifest_id=*/absl::nullopt, kWebAppUrl); + const GURL kWebAppManifestUrl = + GURL("https://example.com/path/manifest.json"); + + struct InstallResult { + AppId installed_app_id; + webapps::InstallResultCode install_code; + }; + + InstallResult InstallAndWait( + const ExternalInstallOptions& install_options, + std::unique_ptr<WebAppDataRetriever> data_retriever) { + base::RunLoop run_loop; + InstallResult result; + provider()->command_manager().ScheduleCommand( + std::make_unique<ExternallyManagedInstallCommand>( + install_options, + base::BindLambdaForTesting( + [&](const AppId& app_id, webapps::InstallResultCode code) { + result.install_code = code; + result.installed_app_id = app_id; + run_loop.Quit(); + }), + web_contents()->GetWeakPtr(), &provider()->install_finalizer(), + + std::move(data_retriever))); + run_loop.Run(); + return result; + } + + void SetUp() override { + WebAppTest::SetUp(); + + FakeWebAppProvider* provider = FakeWebAppProvider::Get(profile()); + provider->SetDefaultFakeSubsystems(); + provider->SetRunSubsystemStartupTasks(true); + + test::AwaitStartWebAppProviderAndSubsystems(profile()); + } + + WebAppProvider* provider() { return WebAppProvider::GetForTest(profile()); } +}; + +TEST_F(ExternallyManagedInstallCommandTest, Success) { + ExternalInstallOptions install_options( + kWebAppUrl, UserDisplayMode::kStandalone, + ExternalInstallSource::kExternalDefault); + + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(kWebAppUrl, kWebAppScope); + + auto result = InstallAndWait(install_options, std::move(data_retriever)); + EXPECT_EQ(result.install_code, + webapps::InstallResultCode::kSuccessNewInstall); + EXPECT_TRUE( + provider()->registrar().IsLocallyInstalled(result.installed_app_id)); +} + +TEST_F(ExternallyManagedInstallCommandTest, GetWebAppInstallInfoFailed) { + ExternalInstallOptions install_options( + kWebAppUrl, UserDisplayMode::kStandalone, + ExternalInstallSource::kExternalDefault); + + auto data_retriever = std::make_unique<FakeDataRetriever>(); + + auto result = InstallAndWait(install_options, std::move(data_retriever)); + EXPECT_EQ(result.install_code, + webapps::InstallResultCode::kGetWebAppInstallInfoFailed); + EXPECT_FALSE( + provider()->registrar().IsLocallyInstalled(result.installed_app_id)); +} + +TEST_F(ExternallyManagedInstallCommandTest, + InstallWebAppWithParams_DisplayModeFromWebAppInstallInfo) { + { + GURL url("https://example1.com/"); + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(url, url); + + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + web_app_info->user_display_mode = UserDisplayMode::kBrowser; + data_retriever->SetRendererWebAppInstallInfo(std::move(web_app_info)); + + ExternalInstallOptions install_options( + url, /*user_display_mode=*/absl::nullopt, + ExternalInstallSource::kExternalDefault); + auto result = InstallAndWait(install_options, std::move(data_retriever)); + + EXPECT_EQ(UserDisplayMode::kBrowser, + provider() + ->registrar() + .GetAppById(result.installed_app_id) + ->user_display_mode()); + } + { + GURL url("https://example2.com/"); + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(url, url); + + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + web_app_info->user_display_mode = UserDisplayMode::kStandalone; + data_retriever->SetRendererWebAppInstallInfo(std::move(web_app_info)); + + ExternalInstallOptions install_options( + url, /*user_display_mode=*/absl::nullopt, + ExternalInstallSource::kExternalDefault); + auto result = InstallAndWait(install_options, std::move(data_retriever)); + + EXPECT_EQ(UserDisplayMode::kStandalone, + provider() + ->registrar() + .GetAppById(result.installed_app_id) + ->user_display_mode()); + } +} + +TEST_F(ExternallyManagedInstallCommandTest, + InstallWebAppWithParams_DisplayModeOverrideByExternalInstallOptions) { + { + GURL url("https://example3.com/"); + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(url, url); + + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + web_app_info->user_display_mode = UserDisplayMode::kStandalone; + data_retriever->SetRendererWebAppInstallInfo(std::move(web_app_info)); + + ExternalInstallOptions install_options( + url, UserDisplayMode::kBrowser, + ExternalInstallSource::kExternalDefault); + auto result = InstallAndWait(install_options, std::move(data_retriever)); + + EXPECT_EQ(UserDisplayMode::kBrowser, + provider() + ->registrar() + .GetAppById(result.installed_app_id) + ->user_display_mode()); + } + { + GURL url("https://example4.com/"); + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(url, url); + + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + web_app_info->user_display_mode = UserDisplayMode::kBrowser; + data_retriever->SetRendererWebAppInstallInfo(std::move(web_app_info)); + + ExternalInstallOptions install_options( + url, UserDisplayMode::kStandalone, + ExternalInstallSource::kExternalDefault); + auto result = InstallAndWait(install_options, std::move(data_retriever)); + + EXPECT_EQ(UserDisplayMode::kStandalone, + provider() + ->registrar() + .GetAppById(result.installed_app_id) + ->user_display_mode()); + } +} + +TEST_F(ExternallyManagedInstallCommandTest, UpgradeLock) { + ExternalInstallOptions install_options( + kWebAppUrl, UserDisplayMode::kStandalone, + ExternalInstallSource::kExternalDefault); + + auto data_retriever = std::make_unique<FakeDataRetriever>(); + data_retriever->BuildDefaultDataToRetrieve(kWebAppUrl, kWebAppScope); + + base::flat_set<AppId> app_ids{ + GenerateAppId(/*manifest_id=*/absl::nullopt, kWebAppUrl)}; + + bool callback_command_run = false; + auto callback_command = std::make_unique<CallbackCommand>( + std::make_unique<AppLock>(app_ids), + base::BindLambdaForTesting([&]() { callback_command_run = true; })); + + bool callback_command_2_run = false; + base::RunLoop callback_runloop; + auto callback_command_2 = std::make_unique<CallbackCommand>( + std::make_unique<AppLock>(app_ids), base::BindLambdaForTesting([&]() { + callback_command_2_run = true; + callback_runloop.Quit(); + })); + + base::RunLoop run_loop; + InstallResult result; + auto command = std::make_unique<ExternallyManagedInstallCommand>( + install_options, + base::BindLambdaForTesting( + [&](const AppId& app_id, webapps::InstallResultCode code) { + result.install_code = code; + result.installed_app_id = app_id; + run_loop.Quit(); + }), + web_contents()->GetWeakPtr(), &provider()->install_finalizer(), + + std::move(data_retriever)); + + // Schedules another callback command that acquires the same app lock after + // current command upgrades to app lock. + command->SetOnLockUpgradedCallbackForTesting( + base::BindLambdaForTesting([&]() { + provider()->command_manager().ScheduleCommand( + std::move(callback_command_2)); + })); + + provider()->command_manager().ScheduleCommand(std::move(command)); + // Immediately schedule a callback command, this will request the app lock + // before the ExternallyManagedInstallCommand. + provider()->command_manager().ScheduleCommand(std::move(callback_command)); + + run_loop.Run(); + + EXPECT_EQ(result.install_code, + webapps::InstallResultCode::kSuccessNewInstall); + EXPECT_TRUE( + provider()->registrar().IsLocallyInstalled(result.installed_app_id)); + + EXPECT_TRUE(callback_command_run); + + EXPECT_FALSE(callback_command_2_run); + + callback_runloop.Run(); + EXPECT_TRUE(callback_command_2_run); +} + +} // namespace +} // namespace web_app
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc index 7aa38bef..fbae2d6 100644 --- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc +++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc
@@ -189,11 +189,11 @@ app_id_ = GenerateAppId(install_info_->manifest_id, install_info_->start_url); command_manager()->ScheduleCommand(std::make_unique<WebAppInstallCommand>( - app_id_, Profile::FromBrowserContext(web_contents_->GetBrowserContext()), - install_finalizer_, std::move(data_retriever_), registrar_, - install_surface_, web_contents_, std::move(dialog_callback_), - std::move(install_callback_), std::move(install_info_), - std::move(opt_manifest), manifest_url, flow_)); + app_id_, install_surface_, std::move(install_info_), + std::move(opt_manifest), manifest_url, flow_, std::move(dialog_callback_), + std::move(install_callback_), + Profile::FromBrowserContext(web_contents_->GetBrowserContext()), + install_finalizer_, std::move(data_retriever_), web_contents_)); SignalCompletionAndSelfDestruct(CommandResult::kSuccess, base::DoNothing()); }
diff --git a/chrome/browser/web_applications/commands/install_web_app_with_params_command.cc b/chrome/browser/web_applications/commands/install_web_app_with_params_command.cc deleted file mode 100644 index 61f3547..0000000 --- a/chrome/browser/web_applications/commands/install_web_app_with_params_command.cc +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/web_applications/commands/install_web_app_with_params_command.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/web_applications/commands/web_app_command.h" -#include "chrome/browser/web_applications/commands/web_app_install_command.h" -#include "chrome/browser/web_applications/locks/noop_lock.h" -#include "chrome/browser/web_applications/web_app_command_manager.h" -#include "chrome/browser/web_applications/web_app_helpers.h" -#include "chrome/browser/web_applications/web_app_install_utils.h" -#include "content/public/browser/web_contents.h" - -namespace web_app { - -InstallWebAppWithParamsCommand::InstallWebAppWithParamsCommand( - base::WeakPtr<content::WebContents> contents, - const WebAppInstallParams& install_params, - webapps::WebappInstallSource install_surface, - WebAppInstallFinalizer* install_finalizer, - WebAppRegistrar* registrar, - OnceInstallCallback callback, - std::unique_ptr<WebAppDataRetriever> data_retriever) - : lock_(std::make_unique<NoopLock>()), - web_contents_(contents), - install_params_(install_params), - install_surface_(install_surface), - install_finalizer_(install_finalizer), - registrar_(registrar), - install_callback_(std::move(callback)), - data_retriever_(std::move(data_retriever)) {} - -InstallWebAppWithParamsCommand::~InstallWebAppWithParamsCommand() = default; - -Lock& InstallWebAppWithParamsCommand::lock() const { - return *lock_; -} - -void InstallWebAppWithParamsCommand::Start() { - if (!web_contents_ || web_contents_->IsBeingDestroyed()) { - Abort(webapps::InstallResultCode::kWebContentsDestroyed); - return; - } - - data_retriever_->GetWebAppInstallInfo( - web_contents_.get(), - base::BindOnce( - &InstallWebAppWithParamsCommand::OnGetWebAppInstallInfoInCommand, - weak_factory_.GetWeakPtr())); -} - -void InstallWebAppWithParamsCommand::OnSyncSourceRemoved() { - // TODO(crbug.com/1320086): remove after uninstall from sync is async. - Abort(webapps::InstallResultCode::kAppNotInRegistrarAfterCommit); - return; -} - -void InstallWebAppWithParamsCommand::OnShutdown() { - Abort(webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown); - return; -} - -base::Value InstallWebAppWithParamsCommand::ToDebugValue() const { - base::Value::Dict params_info; - params_info.Set("InstallWebAppWithParamsCommand ID:", id()); - params_info.Set("Title", - install_params_.fallback_app_name.has_value() - ? base::Value(install_params_.fallback_app_name.value()) - : base::Value()); - params_info.Set("Start URL", - install_params_.fallback_start_url.is_valid() - ? base::Value(install_params_.fallback_start_url.spec()) - : base::Value()); - return base::Value(std::move(params_info)); -} - -void InstallWebAppWithParamsCommand::Abort(webapps::InstallResultCode code) { - if (!install_callback_) - return; - webapps::InstallableMetrics::TrackInstallResult(false); - SignalCompletionAndSelfDestruct( - CommandResult::kFailure, - base::BindOnce(std::move(install_callback_), AppId(), code)); -} - -void InstallWebAppWithParamsCommand::OnGetWebAppInstallInfoInCommand( - std::unique_ptr<WebAppInstallInfo> web_app_info) { - web_app_info_ = std::move(web_app_info); - if (!web_contents_ || web_contents_->IsBeingDestroyed()) { - Abort(webapps::InstallResultCode::kWebContentsDestroyed); - return; - } - - if (!web_app_info_) { - Abort(webapps::InstallResultCode::kGetWebAppInstallInfoFailed); - return; - } - - // Write values from install_params_ to web_app_info. - bypass_service_worker_check_ = install_params_.bypass_service_worker_check; - // Set start_url to fallback_start_url as web_contents may have been - // redirected. Will be overridden by manifest values if present. - DCHECK(install_params_.fallback_start_url.is_valid()); - web_app_info_->start_url = install_params_.fallback_start_url; - - if (install_params_.fallback_app_name.has_value()) - web_app_info_->title = install_params_.fallback_app_name.value(); - - ApplyParamsToWebAppInstallInfo(install_params_, *web_app_info_); - - data_retriever_->CheckInstallabilityAndRetrieveManifest( - web_contents_.get(), bypass_service_worker_check_, - base::BindOnce( - &InstallWebAppWithParamsCommand::OnDidPerformInstallableCheck, - weak_factory_.GetWeakPtr())); -} - -void InstallWebAppWithParamsCommand::OnDidPerformInstallableCheck( - blink::mojom::ManifestPtr opt_manifest, - const GURL& manifest_url, - bool valid_manifest_for_web_app, - bool is_installable) { - if (!web_contents_ || web_contents_->IsBeingDestroyed()) { - Abort(webapps::InstallResultCode::kWebContentsDestroyed); - return; - } - - if (install_params_.require_manifest && !valid_manifest_for_web_app) { - LOG(WARNING) << "Did not install " << manifest_url.spec() - << " because it didn't have a manifest for web app"; - Abort(webapps::InstallResultCode::kNotValidManifestForWebApp); - return; - } - - // A system app should always have a manifest icon. - if (install_surface_ == webapps::WebappInstallSource::SYSTEM_DEFAULT) { - DCHECK(opt_manifest); - DCHECK(!opt_manifest->icons.empty()); - } - - if (opt_manifest) { - if (opt_manifest->start_url.is_valid()) - web_app_info_->start_url = opt_manifest->start_url; - - if (opt_manifest->id.has_value()) { - web_app_info_->manifest_id = absl::optional<std::string>( - base::UTF16ToUTF8(opt_manifest->id.value())); - } - } - - command_manager()->ScheduleCommand(std::make_unique<WebAppInstallCommand>( - GenerateAppId(web_app_info_->manifest_id, web_app_info_->start_url), - Profile::FromBrowserContext(web_contents_->GetBrowserContext()), - install_finalizer_, std::move(data_retriever_), registrar_, - install_surface_, web_contents_, WebAppInstallDialogCallback(), - std::move(install_callback_), std::move(web_app_info_), - std::move(opt_manifest), manifest_url, WebAppInstallFlow::kUnknown, - install_params_)); - SignalCompletionAndSelfDestruct(CommandResult::kSuccess, base::DoNothing()); -} - -} // namespace web_app
diff --git a/chrome/browser/web_applications/commands/install_web_app_with_params_command.h b/chrome/browser/web_applications/commands/install_web_app_with_params_command.h deleted file mode 100644 index e92ab45..0000000 --- a/chrome/browser/web_applications/commands/install_web_app_with_params_command.h +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INSTALL_WEB_APP_WITH_PARAMS_COMMAND_H_ -#define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INSTALL_WEB_APP_WITH_PARAMS_COMMAND_H_ - -#include <memory> - -#include "base/memory/weak_ptr.h" -#include "base/values.h" -#include "chrome/browser/web_applications/commands/web_app_command.h" -#include "chrome/browser/web_applications/web_app_data_retriever.h" -#include "chrome/browser/web_applications/web_app_install_params.h" -#include "components/webapps/browser/install_result_code.h" -#include "components/webapps/browser/installable/installable_metrics.h" - -namespace content { -class WebContents; -} - -namespace web_app { - -class NoopLock; -class WebAppDataRetriever; -class WebAppInstallFinalizer; -class WebAppRegistrar; - -// Command to install web_apps from param by the ExternallyInstalledAppsManager -class InstallWebAppWithParamsCommand : public WebAppCommand { - public: - InstallWebAppWithParamsCommand( - base::WeakPtr<content::WebContents> contents, - const WebAppInstallParams& install_params, - webapps::WebappInstallSource install_surface, - WebAppInstallFinalizer* install_finalizer, - WebAppRegistrar* registrar, - OnceInstallCallback callback, - std::unique_ptr<WebAppDataRetriever> data_retriever); - ~InstallWebAppWithParamsCommand() override; - - Lock& lock() const override; - - void Start() override; - void OnSyncSourceRemoved() override; - void OnShutdown() override; - - base::Value ToDebugValue() const override; - - private: - void Abort(webapps::InstallResultCode code); - - void OnGetWebAppInstallInfoInCommand( - std::unique_ptr<WebAppInstallInfo> web_app_info); - void OnDidPerformInstallableCheck(blink::mojom::ManifestPtr opt_manifest, - const GURL& manifest_url, - bool valid_manifest_for_web_app, - bool is_installable); - - std::unique_ptr<NoopLock> lock_; - base::WeakPtr<content::WebContents> web_contents_; - WebAppInstallParams install_params_; - webapps::WebappInstallSource install_surface_; - base::raw_ptr<WebAppInstallFinalizer> install_finalizer_; - base::raw_ptr<WebAppRegistrar> registrar_; - OnceInstallCallback install_callback_; - - bool bypass_service_worker_check_ = false; - - std::unique_ptr<WebAppDataRetriever> data_retriever_; - std::unique_ptr<WebAppInstallInfo> web_app_info_; - - base::WeakPtrFactory<InstallWebAppWithParamsCommand> weak_factory_{this}; -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_INSTALL_WEB_APP_WITH_PARAMS_COMMAND_H_
diff --git a/chrome/browser/web_applications/commands/web_app_install_command.cc b/chrome/browser/web_applications/commands/web_app_install_command.cc index 6f859f6..df3b0e7 100644 --- a/chrome/browser/web_applications/commands/web_app_install_command.cc +++ b/chrome/browser/web_applications/commands/web_app_install_command.cc
@@ -129,45 +129,34 @@ WebAppInstallCommand::WebAppInstallCommand( const AppId& app_id, - Profile* profile, - WebAppInstallFinalizer* install_finalizer, - std::unique_ptr<WebAppDataRetriever> data_retriever, - WebAppRegistrar* registrar, webapps::WebappInstallSource install_surface, - base::WeakPtr<content::WebContents> contents, - WebAppInstallDialogCallback dialog_callback, - OnceInstallCallback callback, std::unique_ptr<WebAppInstallInfo> web_app_info, blink::mojom::ManifestPtr opt_manifest, const GURL& manifest_url, WebAppInstallFlow flow, - absl::optional<WebAppInstallParams> install_params) + WebAppInstallDialogCallback dialog_callback, + OnceInstallCallback callback, + Profile* profile, + WebAppInstallFinalizer* install_finalizer, + std::unique_ptr<WebAppDataRetriever> data_retriever, + base::WeakPtr<content::WebContents> contents) : lock_(std::make_unique<AppLock, base::flat_set<AppId>>({app_id})), - profile_(profile), - install_finalizer_(install_finalizer), - data_retriever_(std::move(data_retriever)), - registrar_(registrar), + app_id_(app_id), install_surface_(install_surface), - web_contents_(contents), - dialog_callback_(std::move(dialog_callback)), - install_callback_(std::move(callback)), web_app_info_(std::move(web_app_info)), opt_manifest_(std::move(opt_manifest)), manifest_url_(manifest_url), flow_(flow), - app_id_(app_id), - install_params_(install_params), - background_installation_(dialog_callback_.is_null()), - install_error_log_entry_(background_installation_, install_surface_) { - // TODO(https://crbug.com/1298130): move to InstallWebAppWithParams - if (install_params_.has_value() && !install_params_->locally_installed) { - DCHECK(!install_params_->add_to_applications_menu); - DCHECK(!install_params_->add_to_desktop); - DCHECK(!install_params_->add_to_quick_launch_bar); - DCHECK(dialog_callback_.is_null()); - } - + dialog_callback_(std::move(dialog_callback)), + install_callback_(std::move(callback)), + profile_(profile), + install_finalizer_(install_finalizer), + data_retriever_(std::move(data_retriever)), + web_contents_(contents), + install_error_log_entry_(/*background_installation=*/false, + install_surface_) { DCHECK_NE(install_surface_, webapps::WebappInstallSource::SYNC); + DCHECK_NE(install_surface_, webapps::WebappInstallSource::SUB_APP); } WebAppInstallCommand::~WebAppInstallCommand() = default; @@ -188,11 +177,7 @@ return; } - if (!background_installation_) { - // TODO(https://crbug.com/1298130): Move the DCHECK to the beginning of - // install commands when all install flows are denormalized. - DCHECK(AreWebAppsUserInstallable(profile_)); - } + DCHECK(AreWebAppsUserInstallable(profile_)); if (opt_manifest_) UpdateWebAppInfoFromManifest(*opt_manifest_, manifest_url_, @@ -208,25 +193,6 @@ web_contents_->GetLastCommittedURL(), *web_app_info_); } - // Duplicate installation check for SUB_APP installs (done here since the - // AppId isn't available beforehand). It's possible that the app was already - // installed, but from a different source (eg. by the user manually). In that - // case we proceed with the installation which adds the SUB_APP install source - // as well. - if (install_surface_ == webapps::WebappInstallSource::SUB_APP) { - DCHECK(install_params_ && install_params_->parent_app_id.has_value()); - if (registrar_->WasInstalledBySubApp(app_id_)) { - Abort(webapps::InstallResultCode::kSuccessAlreadyInstalled); - return; - } - } - - // A system app should always have a manifest icon. - if (install_surface_ == webapps::WebappInstallSource::SYSTEM_DEFAULT) { - DCHECK(opt_manifest_); - DCHECK(!opt_manifest_->icons.empty()); - } - base::flat_set<GURL> icon_urls = GetValidIconUrlsToDownload(*web_app_info_); // If the manifest specified icons, don't use the page icons. @@ -242,8 +208,7 @@ bool is_create_shortcut = flow_ == WebAppInstallFlow::kCreateShortcut; // Background installations are not a user-triggered installs, and thus // cannot be sent to the store. - bool skip_store = - is_create_shortcut || background_installation_ || !opt_manifest_; + bool skip_store = is_create_shortcut || !opt_manifest_; if (!skip_store) { #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -392,29 +357,11 @@ WebAppInstallFinalizer::FinalizeOptions finalize_options(install_surface_); - if (install_params_) { - finalize_options.locally_installed = install_params_->locally_installed; - finalize_options.overwrite_existing_manifest_fields = - install_params_->force_reinstall; - finalize_options.parent_app_id = install_params_->parent_app_id; - - ApplyParamsToFinalizeOptions(*install_params_, finalize_options); - - if (install_params_->user_display_mode.has_value()) - web_app_info_->user_display_mode = install_params_->user_display_mode; - finalize_options.add_to_applications_menu = - install_params_->add_to_applications_menu; - finalize_options.add_to_desktop = install_params_->add_to_desktop; - finalize_options.add_to_quick_launch_bar = - install_params_->add_to_quick_launch_bar; - } else { - finalize_options.locally_installed = true; - finalize_options.overwrite_existing_manifest_fields = true; - finalize_options.add_to_applications_menu = true; - finalize_options.add_to_desktop = true; - finalize_options.add_to_quick_launch_bar = - kAddAppsToQuickLaunchBarByDefault; - } + finalize_options.locally_installed = true; + finalize_options.overwrite_existing_manifest_fields = true; + finalize_options.add_to_applications_menu = true; + finalize_options.add_to_desktop = true; + finalize_options.add_to_quick_launch_bar = kAddAppsToQuickLaunchBarByDefault; install_finalizer_->FinalizeInstall( *web_app_info_, finalize_options, @@ -443,22 +390,17 @@ RecordWebAppInstallationTimestamp(profile_->GetPrefs(), app_id, install_surface_); - // TODO(https://crbug.com/1298130): update when denormalized. - if (!install_params_ || install_params_->locally_installed) { - RecordAppBanner(web_contents_.get(), web_app_info_->start_url); + RecordAppBanner(web_contents_.get(), web_app_info_->start_url); + + bool error = os_hooks_errors[OsHookType::kShortcuts]; + const bool can_reparent_tab = + install_finalizer_->CanReparentTab(app_id, !error); + + if (can_reparent_tab && + (web_app_info_->user_display_mode != UserDisplayMode::kBrowser)) { + install_finalizer_->ReparentTab(app_id, !error, web_contents_.get()); } - if (!background_installation_ && - install_surface_ != webapps::WebappInstallSource::SUB_APP) { - bool error = os_hooks_errors[OsHookType::kShortcuts]; - const bool can_reparent_tab = - install_finalizer_->CanReparentTab(app_id, !error); - - if (can_reparent_tab && - (web_app_info_->user_display_mode != UserDisplayMode::kBrowser)) { - install_finalizer_->ReparentTab(app_id, !error, web_contents_.get()); - } - } OnInstallCompleted(app_id, webapps::InstallResultCode::kSuccessNewInstall); } @@ -476,17 +418,6 @@ base::BindOnce(std::move(install_callback_), app_id_, code)); } -void WebAppInstallCommand::RecordDownloadedIconsResultAndHttpStatusCodes( - IconsDownloadedResult result, - const DownloadedIconsHttpResults& icons_http_results) { - RecordDownloadedIconsHttpResultsCodeClass( - "WebApp.Icon.HttpStatusCodeClassOnCreate", result, icons_http_results); - - UMA_HISTOGRAM_ENUMERATION("WebApp.Icon.DownloadedResultOnCreate", result); - RecordDownloadedIconHttpStatusCodes( - "WebApp.Icon.DownloadedHttpStatusCodeOnCreate", icons_http_results); -} - void WebAppInstallCommand::OnInstallCompleted(const AppId& app_id, webapps::InstallResultCode code) { if (base::FeatureList::IsEnabled(features::kRecordWebAppDebugInfo)) {
diff --git a/chrome/browser/web_applications/commands/web_app_install_command.h b/chrome/browser/web_applications/commands/web_app_install_command.h index 2101924..6ed3341 100644 --- a/chrome/browser/web_applications/commands/web_app_install_command.h +++ b/chrome/browser/web_applications/commands/web_app_install_command.h
@@ -33,7 +33,6 @@ class AppLock; class WebAppDataRetriever; class WebAppInstallFinalizer; -class WebAppRegistrar; // Install the web app after the manifest is retrieved and validated. class WebAppInstallCommand : public WebAppCommand { @@ -41,21 +40,18 @@ // When |dialog_callback| is null (aka |base::NullCallback|) the command // doesn't show installation prompt in UI and installs the application in // background. - WebAppInstallCommand( - const AppId& app_id, - Profile* profile, - WebAppInstallFinalizer* install_finalizer, - std::unique_ptr<WebAppDataRetriever> data_retriever, - WebAppRegistrar* registrar, - webapps::WebappInstallSource install_surface, - base::WeakPtr<content::WebContents> contents, - WebAppInstallDialogCallback dialog_callback, - OnceInstallCallback callback, - std::unique_ptr<WebAppInstallInfo> web_app_info, - blink::mojom::ManifestPtr opt_manifest, - const GURL& manifest_url, - WebAppInstallFlow flow, - absl::optional<WebAppInstallParams> install_params = absl::nullopt); + WebAppInstallCommand(const AppId& app_id, + webapps::WebappInstallSource install_surface, + std::unique_ptr<WebAppInstallInfo> web_app_info, + blink::mojom::ManifestPtr opt_manifest, + const GURL& manifest_url, + WebAppInstallFlow flow, + WebAppInstallDialogCallback dialog_callback, + OnceInstallCallback callback, + Profile* profile, + WebAppInstallFinalizer* install_finalizer, + std::unique_ptr<WebAppDataRetriever> data_retriever, + base::WeakPtr<content::WebContents> content); ~WebAppInstallCommand() override; Lock& lock() const override; @@ -73,10 +69,6 @@ void Abort(webapps::InstallResultCode code); - void RecordDownloadedIconsResultAndHttpStatusCodes( - IconsDownloadedResult result, - const DownloadedIconsHttpResults& icons_http_results); - void OnInstallCompleted(const AppId& app_id, webapps::InstallResultCode code); // Either dispatches an asynchronous check for whether this installation @@ -115,27 +107,20 @@ OsHooksErrors os_hooks_errors); std::unique_ptr<AppLock> lock_; - Profile* profile_; - WebAppInstallFinalizer* install_finalizer_; - std::unique_ptr<WebAppDataRetriever> data_retriever_; - WebAppRegistrar* registrar_; + AppId app_id_; webapps::WebappInstallSource install_surface_; - - base::WeakPtr<content::WebContents> web_contents_; - WebAppInstallDialogCallback dialog_callback_; - OnceInstallCallback install_callback_; - std::unique_ptr<WebAppInstallInfo> web_app_info_; blink::mojom::ManifestPtr opt_manifest_; GURL manifest_url_; WebAppInstallFlow flow_; + WebAppInstallDialogCallback dialog_callback_; + OnceInstallCallback install_callback_; - AppId app_id_; - absl::optional<WebAppInstallParams> install_params_; + Profile* profile_; + WebAppInstallFinalizer* install_finalizer_; + std::unique_ptr<WebAppDataRetriever> data_retriever_; - // TODO(https://crbug.com/1298130): remove after separate - // InstallWebAppWithParams - bool background_installation_; + base::WeakPtr<content::WebContents> web_contents_; InstallErrorLogEntry install_error_log_entry_;
diff --git a/chrome/browser/web_applications/commands/web_app_install_command_unittest.cc b/chrome/browser/web_applications/commands/web_app_install_command_unittest.cc index 425765be..709f28e0 100644 --- a/chrome/browser/web_applications/commands/web_app_install_command_unittest.cc +++ b/chrome/browser/web_applications/commands/web_app_install_command_unittest.cc
@@ -162,23 +162,21 @@ std::unique_ptr<WebAppInstallInfo> web_app_info, blink::mojom::ManifestPtr opt_manifest, const GURL& manifest_url, - WebAppInstallFlow flow, - absl::optional<WebAppInstallParams> install_params) { + WebAppInstallFlow flow) { webapps::InstallResultCode result; base::RunLoop run_loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppInstallCommand>( - app_id, profile(), &provider()->install_finalizer(), - std::move(data_retriever), &provider()->registrar(), - install_surface, web_contents()->GetWeakPtr(), + app_id, install_surface, std::move(web_app_info), + std::move(opt_manifest), manifest_url, flow, std::move(dialog_callback), base::BindLambdaForTesting( [&](const AppId& id, webapps::InstallResultCode code) { result = code; run_loop.Quit(); }), - std::move(web_app_info), std::move(opt_manifest), manifest_url, - flow, std::move(install_params))); + profile(), &provider()->install_finalizer(), + std::move(data_retriever), web_contents()->GetWeakPtr())); run_loop.Run(); return result; } @@ -201,8 +199,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(true, UserDisplayMode::kStandalone), std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kSuccessNewInstall); EXPECT_TRUE(provider()->registrar().IsLocallyInstalled(kWebAppId)); EXPECT_EQ(1, fake_ui_manager()->num_reparent_tab_calls()); @@ -214,8 +211,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(true, UserDisplayMode::kBrowser), std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kSuccessNewInstall); EXPECT_EQ(0, fake_ui_manager()->num_reparent_tab_calls()); } @@ -226,8 +222,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(false, UserDisplayMode::kStandalone), std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kUserInstallDeclined); EXPECT_FALSE(provider()->registrar().IsLocallyInstalled(kWebAppId)); EXPECT_EQ(0, fake_ui_manager()->num_reparent_tab_calls()); @@ -248,18 +243,17 @@ provider()->command_manager().ScheduleCommand( std::make_unique<WebAppInstallCommand>( - kWebAppId, profile(), &provider()->install_finalizer(), - std::make_unique<FakeDataRetriever>(), &provider()->registrar(), - webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, - web_contents()->GetWeakPtr(), std::move(dialog_callback), + kWebAppId, webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, + std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, + std::move(dialog_callback), base::BindLambdaForTesting( [&](const AppId& id, webapps::InstallResultCode code) { result_populated = true; result = code; }), - std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt)); + profile(), &provider()->install_finalizer(), + std::make_unique<FakeDataRetriever>(), web_contents()->GetWeakPtr())); dialog_runloop.Run(); provider()->command_manager().Shutdown(); @@ -276,19 +270,18 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppInstallCommand>( - kWebAppId, profile(), &provider()->install_finalizer(), - std::make_unique<FakeDataRetriever>(), &provider()->registrar(), - webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, - web_contents()->GetWeakPtr(), CreateDialogCallback(), + kWebAppId, webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, + std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, + CreateDialogCallback(), base::BindLambdaForTesting( [&](const AppId& id, webapps::InstallResultCode code) { result_populated = true; result = code; loop.Quit(); }), - std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt)); + profile(), &provider()->install_finalizer(), + std::make_unique<FakeDataRetriever>(), web_contents()->GetWeakPtr())); DeleteContents(); loop.Run(); @@ -363,8 +356,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(true), std::make_unique<WebAppInstallInfo>(), std::move(manifest), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kSuccessNewInstall); EXPECT_TRUE(file_utils().DirectoryExists(manifest_resources_directory)); @@ -443,7 +435,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(true), std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), kWebAppManifestUrl, - WebAppInstallFlow::kInstallSite, /*install_params=*/absl::nullopt), + WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kSuccessNewInstall); EXPECT_TRUE(file_utils().DirectoryExists(manifest_resources_directory)); @@ -497,17 +489,16 @@ IconsMap icons_map; AddEmptyIconToIconsMap(GURL("https://example.com/app.ico"), &icons_map); - EXPECT_EQ( - InstallAndWait( - kWebAppId, - SetupFakeDataRetriever(std::move(icons_map), - IconsDownloadedResult::kCompleted, - net::HttpStatusCode::HTTP_NOT_FOUND), - webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, - CreateDialogCallback(true), std::make_unique<WebAppInstallInfo>(), - CreateValidManifest(), kWebAppManifestUrl, - WebAppInstallFlow::kInstallSite, /*install_params=*/absl::nullopt), - webapps::InstallResultCode::kSuccessNewInstall); + EXPECT_EQ(InstallAndWait( + kWebAppId, + SetupFakeDataRetriever(std::move(icons_map), + IconsDownloadedResult::kCompleted, + net::HttpStatusCode::HTTP_NOT_FOUND), + webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, + CreateDialogCallback(true), + std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), + webapps::InstallResultCode::kSuccessNewInstall); EXPECT_TRUE(file_utils().DirectoryExists(manifest_resources_directory)); @@ -560,17 +551,16 @@ // Induce an error: Simulate "Disk Full" for writing icon files. file_utils().SetRemainingDiskSpaceSize(1024); - EXPECT_EQ( - InstallAndWait( - kWebAppId, - SetupFakeDataRetriever(std::move(icons_map), - IconsDownloadedResult::kCompleted, - net::HttpStatusCode::HTTP_OK), - webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, - CreateDialogCallback(true), std::make_unique<WebAppInstallInfo>(), - CreateValidManifest(), kWebAppManifestUrl, - WebAppInstallFlow::kInstallSite, /*install_params=*/absl::nullopt), - webapps::InstallResultCode::kWriteDataFailed); + EXPECT_EQ(InstallAndWait( + kWebAppId, + SetupFakeDataRetriever(std::move(icons_map), + IconsDownloadedResult::kCompleted, + net::HttpStatusCode::HTTP_OK), + webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, + CreateDialogCallback(true), + std::make_unique<WebAppInstallInfo>(), CreateValidManifest(), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), + webapps::InstallResultCode::kWriteDataFailed); const base::FilePath temp_dir = web_apps_dir.AppendASCII("Temp"); EXPECT_TRUE(file_utils().DirectoryExists(temp_dir)); @@ -596,8 +586,7 @@ webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, CreateDialogCallback(true), std::make_unique<WebAppInstallInfo>(), std::move(manifest), - kWebAppManifestUrl, WebAppInstallFlow::kInstallSite, - /*install_params=*/absl::nullopt), + kWebAppManifestUrl, WebAppInstallFlow::kInstallSite), webapps::InstallResultCode::kIntentToPlayStore); } #endif
diff --git a/chrome/browser/web_applications/daily_metrics_helper.cc b/chrome/browser/web_applications/daily_metrics_helper.cc index 55fc4f8..bb78566 100644 --- a/chrome/browser/web_applications/daily_metrics_helper.cc +++ b/chrome/browser/web_applications/daily_metrics_helper.cc
@@ -32,13 +32,15 @@ } // namespace -// This class exists just to be friended by |UkmRecorder|. +// This class exists just to be friended by |UkmRecorder| to control the +// emission of Web app UKMs in UkmRecorder. class DesktopWebAppUkmRecorder { public: static void Emit(const DailyInteraction& record) { DCHECK(record.start_url.is_valid()); ukm::SourceId source_id = - ukm::UkmRecorder::GetSourceIdForWebsiteUrl(record.start_url); + ukm::UkmRecorder::GetSourceIdForDesktopWebAppStartUrl( + base::PassKey<DesktopWebAppUkmRecorder>(), record.start_url); ukm::builders::WebApp_DailyInteraction builder(source_id); builder.SetUsed(true) .SetInstalled(record.installed)
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.cc b/chrome/browser/web_applications/externally_managed_app_install_task.cc index fe8884f1..80ee1ebd 100644 --- a/chrome/browser/web_applications/externally_managed_app_install_task.cc +++ b/chrome/browser/web_applications/externally_managed_app_install_task.cc
@@ -17,12 +17,13 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/security_state_tab_helper.h" +#include "chrome/browser/web_applications/commands/externally_managed_install_command.h" #include "chrome/browser/web_applications/commands/install_from_info_command.h" -#include "chrome/browser/web_applications/commands/install_web_app_with_params_command.h" #include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_data_retriever.h" #include "chrome/browser/web_applications/web_app_install_finalizer.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_install_utils.h" @@ -229,23 +230,19 @@ void ExternallyManagedAppInstallTask::ContinueWebAppInstall( content::WebContents* web_contents, ResultCallback result_callback) { - auto install_params = ConvertExternalInstallOptionsToParams(install_options_); - auto install_source = ConvertExternalInstallSourceToInstallSource( - install_options_.install_source); - if (!data_retriever_factory_) { data_retriever_factory_ = base::BindRepeating( []() { return std::make_unique<WebAppDataRetriever>(); }); } command_manager_->ScheduleCommand( - std::make_unique<InstallWebAppWithParamsCommand>( - web_contents->GetWeakPtr(), install_params, install_source, - install_finalizer_, registrar_, + std::make_unique<ExternallyManagedInstallCommand>( + install_options_, base::BindOnce(&ExternallyManagedAppInstallTask::OnWebAppInstalled, weak_ptr_factory_.GetWeakPtr(), /*is_placeholder=*/false, /*offline_install=*/false, std::move(result_callback)), + web_contents->GetWeakPtr(), install_finalizer_, data_retriever_factory_.Run())); }
diff --git a/chrome/browser/web_applications/locks/web_app_lock_manager.cc b/chrome/browser/web_applications/locks/web_app_lock_manager.cc index 62c60bd..300c431f 100644 --- a/chrome/browser/web_applications/locks/web_app_lock_manager.cc +++ b/chrome/browser/web_applications/locks/web_app_lock_manager.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/web_applications/locks/web_app_lock_manager.h" #include "base/strings/string_number_conversions.h" +#include "chrome/browser/web_applications/locks/app_lock.h" #include "chrome/browser/web_applications/locks/lock.h" +#include "chrome/browser/web_applications/locks/noop_lock.h" #include "chrome/browser/web_applications/locks/shared_web_contents_lock.h" #include "chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h" #include "chrome/browser/web_applications/web_app_id.h" @@ -126,4 +128,18 @@ return result_lock; } +std::unique_ptr<AppLock> WebAppLockManager::UpgradeAndAcquireLock( + std::unique_ptr<NoopLock> lock, + const base::flat_set<AppId>& app_ids, + base::OnceClosure on_lock_acquired) { + CHECK(lock->HasLockBeenRequested()); + std::unique_ptr<AppLock> result_lock = std::make_unique<AppLock>(app_ids); + result_lock->holder_ = std::move(lock->holder_); + bool success = lock_manager_.AcquireLocks(GetAppIdLocks(app_ids), + result_lock->holder_->AsWeakPtr(), + std::move(on_lock_acquired)); + DCHECK(success); + return result_lock; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/locks/web_app_lock_manager.h b/chrome/browser/web_applications/locks/web_app_lock_manager.h index 0849159..493646d 100644 --- a/chrome/browser/web_applications/locks/web_app_lock_manager.h +++ b/chrome/browser/web_applications/locks/web_app_lock_manager.h
@@ -14,7 +14,9 @@ namespace web_app { +class AppLock; class Lock; +class NoopLock; class SharedWebContentsLock; class SharedWebContentsWithAppLock; @@ -43,6 +45,11 @@ const base::flat_set<AppId>& app_ids, base::OnceClosure on_lock_acquired); + std::unique_ptr<AppLock> UpgradeAndAcquireLock( + std::unique_ptr<NoopLock> lock, + const base::flat_set<AppId>& app_ids, + base::OnceClosure on_lock_acquired); + private: content::DisjointRangeLockManager lock_manager_{2}; };
diff --git a/chrome/browser/web_applications/os_integration/web_app_run_on_os_login_win_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_run_on_os_login_win_unittest.cc index 992e0e2..c5d0b51 100644 --- a/chrome/browser/web_applications/os_integration/web_app_run_on_os_login_win_unittest.cc +++ b/chrome/browser/web_applications/os_integration/web_app_run_on_os_login_win_unittest.cc
@@ -58,9 +58,9 @@ base::FilePath GetStartupFolder() { base::FilePath location; - ShellUtil::GetShortcutPath( + EXPECT_TRUE(ShellUtil::GetShortcutPath( ShellUtil::ShortcutLocation::SHORTCUT_LOCATION_STARTUP, - ShellUtil::ShellChange::CURRENT_USER, &location); + ShellUtil::ShellChange::CURRENT_USER, &location)); return location; }
diff --git a/chrome/browser/web_applications/web_app_command_manager.h b/chrome/browser/web_applications/web_app_command_manager.h index a1f7093..040ca421 100644 --- a/chrome/browser/web_applications/web_app_command_manager.h +++ b/chrome/browser/web_applications/web_app_command_manager.h
@@ -83,6 +83,8 @@ return shared_web_contents_.get(); } + WebAppLockManager& lock_manager() const { return *lock_manager_; } + protected: friend class WebAppCommand;
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index f6f2009..d7663bcb 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -345,23 +345,6 @@ base::BindOnce(&WebAppInstallTask::OnInstallFinalized, GetWeakPtr())); } -void WebAppInstallTask::InstallWebAppWithParams( - content::WebContents* contents, - const WebAppInstallParams& install_params, - OnceInstallCallback install_callback) { - CheckInstallPreconditions(); - - Observe(contents); - SetInstallParams(install_params); - install_callback_ = std::move(install_callback); - background_installation_ = true; - log_entry_.set_background_installation(true); - - data_retriever_->GetWebAppInstallInfo( - web_contents(), - base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo, GetWeakPtr())); -} - void WebAppInstallTask::LoadAndRetrieveWebAppInstallInfoWithIcons( const GURL& start_url, WebAppUrlLoader* url_loader,
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h index aa110e4..b923673 100644 --- a/chrome/browser/web_applications/web_app_install_task.h +++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -120,14 +120,6 @@ bool overwrite_existing_manifest_fields, OnceInstallCallback callback); - // Starts a background web app installation process for a given - // |web_contents|. This method infers WebApp info from the blink renderer - // process and then retrieves a manifest in a way similar to - // |InstallWebAppFromManifestWithFallback|. - void InstallWebAppWithParams(content::WebContents* web_contents, - const WebAppInstallParams& install_params, - OnceInstallCallback callback); - // Obtains WebAppInstallInfo about web app located at |start_url|, fallbacks // to title/favicon if manifest is not present. void LoadAndRetrieveWebAppInstallInfoWithIcons(
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc index c63201c..986e6cd 100644 --- a/chrome/browser/web_applications/web_app_install_task_unittest.cc +++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -79,18 +79,6 @@ namespace web_app { -namespace { - -WebAppInstallParams MakeParams( - absl::optional<UserDisplayMode> display_mode = absl::nullopt) { - WebAppInstallParams params; - params.fallback_start_url = GURL("https://example.com/fallback"); - params.user_display_mode = display_mode; - return params; -} - -} // namespace - class WebAppInstallTaskTest : public WebAppTest { public: void SetUp() override { @@ -308,24 +296,6 @@ return result.app_id; } - AppId InstallWebAppWithParams(const WebAppInstallParams& params) { - AppId app_id; - base::RunLoop run_loop; - if (!install_task_) - InitializeInstallTaskAndRetriever( - webapps::WebappInstallSource::EXTERNAL_DEFAULT); - install_task_->InstallWebAppWithParams( - web_contents(), params, - base::BindLambdaForTesting([&](const AppId& installed_app_id, - webapps::InstallResultCode code) { - ASSERT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code); - app_id = installed_app_id; - run_loop.Quit(); - })); - run_loop.Run(); - return app_id; - } - void PrepareTestAppInstall(webapps::WebappInstallSource install_surface) { const GURL url{"https://example.com/path"}; InitializeInstallTaskAndRetriever(install_surface); @@ -822,83 +792,6 @@ run_loop.Run(); } -// Default apps should be installable for guest profiles. -TEST_F(WebAppInstallTaskTest, InstallWebAppWithParams_GuestProfile) { - SetInstallFinalizerForTesting(); - - TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); - ASSERT_TRUE(profile_manager.SetUp()); - Profile* guest_profile = profile_manager.CreateGuestProfile(); - - const GURL start_url("https://example.com/path"); - auto data_retriever = std::make_unique<FakeDataRetriever>(); - data_retriever->BuildDefaultDataToRetrieve(start_url, - /*scope=*/GURL{}); - - auto install_task = std::make_unique<WebAppInstallTask>( - guest_profile, install_finalizer_.get(), std::move(data_retriever), - ®istrar(), webapps::WebappInstallSource::EXTERNAL_DEFAULT); - - base::RunLoop run_loop; - install_task->InstallWebAppWithParams( - web_contents(), MakeParams(), - base::BindLambdaForTesting( - [&](const AppId& app_id, webapps::InstallResultCode code) { - EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code); - run_loop.Quit(); - })); - run_loop.Run(); -} - -TEST_F(WebAppInstallTaskTest, InstallWebAppWithParams_DisplayMode) { - { - InitializeInstallTaskAndRetriever( - webapps::WebappInstallSource::EXTERNAL_DEFAULT); - CreateDataToRetrieve(GURL("https://example.com/"), - /*user_display_mode=*/UserDisplayMode::kBrowser); - - auto app_id = InstallWebAppWithParams(MakeParams(absl::nullopt)); - - EXPECT_EQ(UserDisplayMode::kBrowser, - registrar().GetAppById(app_id)->user_display_mode()); - } - { - InitializeInstallTaskAndRetriever( - webapps::WebappInstallSource::EXTERNAL_DEFAULT); - CreateDataToRetrieve(GURL("https://example.org/"), - /*user_display_mode=*/UserDisplayMode::kStandalone); - - auto app_id = InstallWebAppWithParams(MakeParams(absl::nullopt)); - - EXPECT_EQ(UserDisplayMode::kStandalone, - registrar().GetAppById(app_id)->user_display_mode()); - } - { - InitializeInstallTaskAndRetriever( - webapps::WebappInstallSource::EXTERNAL_DEFAULT); - CreateDataToRetrieve(GURL("https://example.au/"), - /*user_display_mode=*/UserDisplayMode::kStandalone); - - auto app_id = - InstallWebAppWithParams(MakeParams(UserDisplayMode::kBrowser)); - - EXPECT_EQ(UserDisplayMode::kBrowser, - registrar().GetAppById(app_id)->user_display_mode()); - } - { - InitializeInstallTaskAndRetriever( - webapps::WebappInstallSource::EXTERNAL_DEFAULT); - CreateDataToRetrieve(GURL("https://example.app/"), - /*user_display_mode=*/UserDisplayMode::kBrowser); - - auto app_id = - InstallWebAppWithParams(MakeParams(UserDisplayMode::kStandalone)); - - EXPECT_EQ(UserDisplayMode::kStandalone, - registrar().GetAppById(app_id)->user_display_mode()); - } -} - TEST_F(WebAppInstallTaskTest, InstallWebAppFromManifest_ExpectAppId) { const auto url1 = GURL("https://example.com/"); const auto url2 = GURL("https://example.org/");
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc index 066a9ff..59671be 100644 --- a/chrome/browser/web_applications/web_app_install_utils.cc +++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -745,6 +745,17 @@ base::Time::Now()); } +void RecordDownloadedIconsResultAndHttpStatusCodes( + IconsDownloadedResult result, + const DownloadedIconsHttpResults& icons_http_results) { + RecordDownloadedIconsHttpResultsCodeClass( + "WebApp.Icon.HttpStatusCodeClassOnCreate", result, icons_http_results); + + base::UmaHistogramEnumeration("WebApp.Icon.DownloadedResultOnCreate", result); + RecordDownloadedIconHttpStatusCodes( + "WebApp.Icon.DownloadedHttpStatusCodeOnCreate", icons_http_results); +} + void RecordDownloadedIconsHttpResultsCodeClass( base::StringPiece histogram_name, IconsDownloadedResult result,
diff --git a/chrome/browser/web_applications/web_app_install_utils.h b/chrome/browser/web_applications/web_app_install_utils.h index 8ebbf54..b1db804ba 100644 --- a/chrome/browser/web_applications/web_app_install_utils.h +++ b/chrome/browser/web_applications/web_app_install_utils.h
@@ -81,6 +81,11 @@ // shown for this app. void RecordAppBanner(content::WebContents* contents, const GURL& app_url); +// Records downloaded icons result and http code and code class. +void RecordDownloadedIconsResultAndHttpStatusCodes( + IconsDownloadedResult result, + const DownloadedIconsHttpResults& icons_http_results); + // Records the class of http status code (2XX, 3XX, 4XX, 5XX) for each processed // icon url. void RecordDownloadedIconsHttpResultsCodeClass(
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index ea6385a..9ed3358 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -42,16 +42,28 @@ class WebAppTranslationManager; class WebAppCommandManager; +// WebAppProvider is the heart of Chrome web app code. +// // Connects Web App features, such as the installation of default and // policy-managed web apps, with Profiles (as WebAppProvider is a // Profile-linked KeyedService) and their associated PrefService. // // Lifecycle notes: -// All subsystems are constructed independently of each other in the -// WebAppProvider constructor. -// Subsystem construction should have no side effects and start no tasks. -// Tests can replace any of the subsystems before Start() is called. -// Similarly, in destruction, subsystems should not refer to each other. +// - WebAppProvider and its sub-managers are not ready for use until the +// on_registry_ready() event has fired. Its database must be loaded from +// disk before it can be interacted with. +// Example of waiting for on_registry_ready(): +// WebAppProvider* provider = WebAppProvider::GetForWebApps(profile); +// provider->on_registry_ready().Post( +// FROM_HERE, +// base::BindOnce([](WebAppProvider& provider) { +// ... +// }, std::ref(*provider)); +// - All subsystems are constructed independently of each other in the +// WebAppProvider constructor. +// - Subsystem construction should have no side effects and start no tasks. +// - Tests can replace any of the subsystems before Start() is called. +// - Similarly, in destruction, subsystems should not refer to each other. class WebAppProvider : public KeyedService { public: // Deprecated: Use GetForWebApps instead.
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index a10e091..3a4bd73 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1660669594-e1a98eac0424f7882f9f051b0b6d4d8ed43d1852.profdata +chrome-linux-main-1660694323-3b8689f41924fd0b08a6a97ee0a53899a85546f3.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 1e0cf01..7ed5ad0 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1660650975-30813d08c6ccb5b6f1a6077df2f97a642093a30b.profdata +chrome-mac-arm-main-1660694323-1852380f4185ea1ff9a2df04304a8be582950df2.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 516145b..19e0635 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1660669594-ab66c8ad86c45aa98b2a82524a1be164c1c793cf.profdata +chrome-mac-main-1660694323-0c813aed519ad7837d2488005b935b8bb4c28ab5.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index b9a2c5f..e5a0376a 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1660650975-ee2eda6f820d2789a82040d13a5e68a0c91b2dda.profdata +chrome-win32-main-1660694323-bf66eed84fef168c9923b22ad1faccf167b9ef65.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index a07a7c1e..1da3bea 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1660650975-11c0305a3d05e803f31899ae4eaf2cadee7a5b99.profdata +chrome-win64-main-1660694323-a0df662925b72bd3e97141633addc5c57296028b.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 140440f..6ed1cf6 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -550,6 +550,9 @@ // Enables or disables the Happiness Tracking System for Camera App survey. const base::Feature kHappinessTrackingSystemCameraApp{ "HappinessTrackingCameraApp", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the Happiness Tracking System for Photos Experience survey. +const base::Feature kHappinessTrackingPhotosExperience{ + "HappinessTrackingPhotosExperience", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // Hides the origin text from showing up briefly in WebApp windows.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 0566568..238fbb45 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -389,6 +389,9 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kHappinessTrackingSystemCameraApp; +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kHappinessTrackingPhotosExperience; + #endif COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index 6f55e84..2b8adf7 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -265,7 +265,7 @@ callback IsLacrosPrimaryBrowserCallback = void (boolean primary); - // crosapi::BrowserManager::State + // A mapping of crosapi::BrowserManager::State enum LacrosState { NotInitialized, Mounting, @@ -277,6 +277,14 @@ Terminating }; + // A mapping of crosapi::browser_util::LacrosMode + enum LacrosMode { + Disabled, + SideBySide, + Primary, + Only + }; + dictionary LacrosInfo { // The state of lacros. LacrosState state; @@ -285,6 +293,9 @@ // Path to lacros-chrome directory. Note that this may change over time if // omaha is used. This also may be empty if lacros is not running. DOMString lacrosPath; + // Specifies the mode Lacros is currently running. + // For a full list of supported mode, see LacrosMode enum definition. + LacrosMode mode; }; callback GetLacrosInfoCallback = void (LacrosInfo info);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index d2dd38c..26773b3 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -889,6 +889,15 @@ const char kHatsCameraAppDeviceIsSelected[] = "hats_camera_app_device_is_selected"; +// indicates the end of the most recent Photos Experience survey cycle. +const char kHatsPhotosExperienceCycleEndTs[] = + "hats_photos_experience_cycle_end_timestamp"; + +// A boolean pref. Indicates if the device is selected for the Photos Experience +// survey. +const char kHatsPhotosExperienceIsSelected[] = + "hats_photos_experience_is_selected"; + // A boolean pref. Indicates if we've already shown a notification to inform the // current user about the quick unlock feature. const char kPinUnlockFeatureNotificationShown[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index ffaf5fa..9186d5cb 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -306,6 +306,8 @@ extern const char kHatsMediaAppPdfIsSelected[]; extern const char kHatsCameraAppDeviceIsSelected[]; extern const char kHatsCameraAppSurveyCycleEndTs[]; +extern const char kHatsPhotosExperienceCycleEndTs[]; +extern const char kHatsPhotosExperienceIsSelected[]; extern const char kEolStatus[]; extern const char kEndOfLifeDate[]; extern const char kEolNotificationDismissed[];
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 8f61451..a7ffa18 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -56,7 +56,6 @@ #include "chrome/renderer/media/webrtc_logging_agent_impl.h" #include "chrome/renderer/net/net_error_helper.h" #include "chrome/renderer/net_benchmarking_extension.h" -#include "chrome/renderer/pepper/pepper_helper.h" #include "chrome/renderer/plugins/non_loadable_plugin_placeholder.h" #include "chrome/renderer/plugins/pdf_plugin_placeholder.h" #include "chrome/renderer/plugins/plugin_uma.h" @@ -219,9 +218,11 @@ #if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/renderer/plugins/chrome_plugin_placeholder.h" +#endif // BUILDFLAG(ENABLE_PLUGINS) + +#if BUILDFLAG(ENABLE_PPAPI) +#include "chrome/renderer/pepper/pepper_helper.h" #include "ppapi/shared_impl/ppapi_switches.h" // nogncheck crbug.com/1125897 -#else -#include "components/plugins/renderer/plugin_placeholder.h" #endif #if BUILDFLAG(ENABLE_PRINTING) @@ -576,7 +577,7 @@ render_frame, registry); #endif -#if BUILDFLAG(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PPAPI) new PepperHelper(render_frame); #endif @@ -1558,9 +1559,11 @@ bool ChromeContentRendererClient::IsPluginAllowedToUseCameraDeviceAPI( const GURL& url) { #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_PPAPI) if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePepperTesting)) return true; +#endif // BUILDFLAG(ENABLE_PPAPI) if (IsExtensionOrSharedModuleAllowed(url, allowed_camera_device_origins_)) return true;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 8963d3d..554baed 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4182,6 +4182,7 @@ "//chromeos/ash/components/assistant:buildflags", "//chromeos/ash/components/attestation", "//chromeos/ash/components/attestation:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/attestation", "//chromeos/ash/components/dbus/attestation:attestation_proto", "//chromeos/ash/components/dbus/authpolicy", @@ -4212,7 +4213,6 @@ "//chromeos/components/onc:test_support", "//chromeos/components/quick_answers/public/cpp:cpp", "//chromeos/components/remote_apps/mojom:mojom", - "//chromeos/dbus:test_support", "//chromeos/dbus/dlp", "//chromeos/dbus/missive:test_support", "//chromeos/login/login_state:test_support",
diff --git a/chrome/test/data/webui/chrome_timeticks_browsertest.js b/chrome/test/data/webui/chrome_timeticks_browsertest.js index 375366cd..d56d9eb 100644 --- a/chrome/test/data/webui/chrome_timeticks_browsertest.js +++ b/chrome/test/data/webui/chrome_timeticks_browsertest.js
@@ -15,18 +15,18 @@ var ChromeTimeTicksBrowserTest = class extends testing.Test { /** @override */ get browsePreload() { - return 'chrome://dummyurl'; + return 'chrome://test/test_loader.html?module=chrome_timeticks_test.js'; + } + + /** @override */ + get isAsync() { + return true; } /** @override */ get webuiHost() { return 'dummyurl'; } - - /** @override */ - get browsePreload() { - return 'chrome://test/test_loader.html?module=chrome_timeticks_test.js'; - } }; TEST_F('ChromeTimeTicksBrowserTest', 'All', function() {
diff --git a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js index a4adfc57c..edf0c81 100644 --- a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js +++ b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.js
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; - import {fakeFirmwareUpdates} from 'chrome://accessory-update/fake_data.js'; import {FakeUpdateController} from 'chrome://accessory-update/fake_update_controller.js'; import {FakeUpdateProvider} from 'chrome://accessory-update/fake_update_provider.js'; @@ -12,6 +10,7 @@ import {getUpdateProvider, setUpdateControllerForTesting, setUpdateProviderForTesting} from 'chrome://accessory-update/mojo_interface_provider.js'; import {mojoString16ToString} from 'chrome://accessory-update/mojo_utils.js'; import {UpdateCardElement} from 'chrome://accessory-update/update_card.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js index a89612e..0b0acac5 100644 --- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js +++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test.js
@@ -850,7 +850,8 @@ // Simulate the ESC key by sending the `cancel` event to the native // dialog. - scanFailedDialog.$$('dialog').dispatchEvent(new Event('cancel')); + scanFailedDialog.shadowRoot.querySelector('#dialog').dispatchEvent( + new Event('cancel')); assertFalse(scanningApp.$$('#scanFailedDialog').open); assertFalse(scanButton.disabled); assertTrue(isVisible(/** @type {!CrButtonElement} */ (scanButton)));
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js index 5fd78f5a..9f2440589 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/hardware_error_page_test.js
@@ -82,10 +82,8 @@ await initializeHardwareErrorPage(); let callCount = 0; - let shutdownMethod; - service.endRma = (seenShutdownMethod) => { + service.shutDownAfterHardwareError = () => { callCount++; - shutdownMethod = seenShutdownMethod; return resolver.promise; }; await flushTasks(); @@ -94,6 +92,5 @@ await flushTasks(); assertEquals(1, callCount); - assertEquals(ShutdownMethod.kShutdown, shutdownMethod); }); }
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js index 8c3e4306..c1828bf 100644 --- a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js
@@ -261,7 +261,8 @@ const pinInput = enterPinDialog.querySelector('#enterPin'); pinInput.value = '1111111'; - pinInput.fire('enter', {path: [pinInput]}); + pinInput.dispatchEvent(new CustomEvent( + 'enter', {bubbles: true, composed: true, detail: {path: [pinInput]}})); await flushAsync(); deviceState = @@ -285,7 +286,8 @@ assertTrue(!!enterPinDialog); assertTrue(enterPinDialog.open); assertTrue(simLockDialog.isDialogOpen); - enterPinDialog.fire('cancel'); + enterPinDialog.dispatchEvent( + new CustomEvent('cancel', {bubbles: true, composed: true})); await flushAsync(); assertFalse(enterPinDialog.open); assertFalse(simLockDialog.isDialogOpen); @@ -307,7 +309,9 @@ const enterPin = async function(pin) { const pinInput = enterPinDialog.querySelector('#enterPin'); pinInput.value = pin; - pinInput.fire('enter', {path: [pinInput]}); + pinInput.dispatchEvent(new CustomEvent( + 'enter', + {bubbles: true, composed: true, detail: {path: [pinInput]}})); await flushAsync(); };
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn index eaccde7..d25f32b 100644 --- a/chrome/test/data/webui/cr_elements/BUILD.gn +++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -22,7 +22,6 @@ "cr_button_tests.ts", "cr_card_radio_button_test.ts", "cr_checkbox_test.ts", - "cr_container_shadow_behavior_test.ts", "cr_container_shadow_mixin_test.ts", "cr_dialog_test.ts", "cr_drawer_tests.ts", @@ -61,6 +60,7 @@ if (is_chromeos_ash) { in_files += [ + "cr_container_shadow_behavior_test.ts", "cr_searchable_drop_down_tests.ts", "find_shortcut_behavior_test.ts", ]
diff --git a/chrome/test/data/webui/cr_elements/cr_dialog_test.ts b/chrome/test/data/webui/cr_elements/cr_dialog_test.ts index c7f2180..3736a991 100644 --- a/chrome/test/data/webui/cr_elements/cr_dialog_test.ts +++ b/chrome/test/data/webui/cr_elements/cr_dialog_test.ts
@@ -339,11 +339,13 @@ const dialog = document.body.querySelector('cr-dialog')!; assertFalse(dialog.open); - const bodyContainer = dialog.$$('.body-container'); + const bodyContainer = dialog.shadowRoot!.querySelector('.body-container'); assertTrue(!!bodyContainer); - const topShadow = dialog.$$('#cr-container-shadow-top'); + const topShadow = + dialog.shadowRoot!.querySelector('#cr-container-shadow-top'); assertTrue(!!topShadow); - const bottomShadow = dialog.$$('#cr-container-shadow-bottom'); + const bottomShadow = + dialog.shadowRoot!.querySelector('#cr-container-shadow-bottom'); assertTrue(!!bottomShadow); return flushTasks().then(() => { @@ -365,9 +367,11 @@ const bodyContainer = dialog.shadowRoot!.querySelector<HTMLElement>('.body-container'); assertTrue(!!bodyContainer); - const topShadow = dialog.$$('#cr-container-shadow-top'); + const topShadow = + dialog.shadowRoot!.querySelector('#cr-container-shadow-top'); assertTrue(!!topShadow); - const bottomShadow = dialog.$$('#cr-container-shadow-bottom'); + const bottomShadow = + dialog.shadowRoot!.querySelector('#cr-container-shadow-bottom'); assertTrue(!!bottomShadow); dialog.showModal(); // Attach the dialog for the first time here.
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js index fec14e9..3af45057 100644 --- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js +++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -49,6 +49,7 @@ mocha.run(); }); +GEN('#if BUILDFLAG(IS_CHROMEOS_ASH)'); var CrElementsContainerShadowBehaviorTest = class extends CrElementsBrowserTest { /** @override */ @@ -60,6 +61,7 @@ TEST_F('CrElementsContainerShadowBehaviorTest', 'All', function() { mocha.run(); }); +GEN('#endif'); var CrElementsContainerShadowMixinTest = class extends CrElementsBrowserTest { /** @override */
diff --git a/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js b/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js deleted file mode 100644 index 4ffa6f5c..0000000 --- a/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js +++ /dev/null
@@ -1,377 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -import {AmbientModeBrowserProxyImpl, AmbientModeTemperatureUnit, AmbientModeTopicSource, CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; -import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; -import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {waitAfterNextRender} from 'chrome://test/test_util.js'; - -import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; -import {TestBrowserProxy} from '../../test_browser_proxy.js'; - -/** - * @implements {AmbientModeBrowserProxy} - */ -class TestAmbientModeBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'requestSettings', - 'requestAlbums', - 'setSelectedTemperatureUnit', - 'setSelectedAlbums', - ]); - } - - /** @override */ - requestSettings() { - this.methodCalled('requestSettings'); - } - - /** @override */ - requestAlbums(topicSource) { - this.methodCalled('requestAlbums', [topicSource]); - } - - /** @override */ - setSelectedTemperatureUnit(temperatureUnit) { - this.methodCalled('setSelectedTemperatureUnit', [temperatureUnit]); - } - - /** @override */ - setSelectedAlbums(settings) { - this.methodCalled('setSelectedAlbums', [settings]); - } -} - -suite('AmbientModeHandler', function() { - /** @type {SettingsAmbientModePageElement} */ - let ambientModePage = null; - - /** @type {?TestAmbientModeBrowserProxy} */ - let browserProxy = null; - - suiteSetup(function() {}); - - setup(function() { - browserProxy = new TestAmbientModeBrowserProxy(); - AmbientModeBrowserProxyImpl.setInstanceForTesting(browserProxy); - - PolymerTest.clearBody(); - - const prefElement = document.createElement('settings-prefs'); - document.body.appendChild(prefElement); - - return CrSettingsPrefs.initialized.then(function() { - ambientModePage = document.createElement('settings-ambient-mode-page'); - ambientModePage.prefs = prefElement.prefs; - - ambientModePage.prefs.settings.ambient_mode = { - enabled: {value: true}, - }; - - document.body.appendChild(ambientModePage); - flush(); - }); - }); - - teardown(function() { - ambientModePage.remove(); - Router.getInstance().resetRouteForTesting(); - }); - - test('toggleAmbientMode', () => { - const button = - ambientModePage.shadowRoot.querySelector('#ambientModeEnable'); - assertTrue(!!button); - assertFalse(button.disabled); - - // The button's state is set by the pref value. - const enabled = - ambientModePage.getPref('settings.ambient_mode.enabled.value'); - assertEquals(enabled, button.checked); - - // Click the button will toggle the pref value. - button.click(); - flush(); - const enabled_toggled = - ambientModePage.getPref('settings.ambient_mode.enabled.value'); - assertEquals(enabled_toggled, button.checked); - assertEquals(enabled, !enabled_toggled); - - // Click again will toggle the pref value. - button.click(); - flush(); - const enabled_toggled_twice = - ambientModePage.getPref('settings.ambient_mode.enabled.value'); - assertEquals(enabled_toggled_twice, button.checked); - assertEquals(enabled, enabled_toggled_twice); - }); - - test('hasNoTopicSourceItemsWhenLoading', () => { - const spinner = - ambientModePage.shadowRoot.querySelector('paper-spinner-lite'); - assertTrue(!!spinner); - assertTrue(spinner.active); - assertFalse(spinner.hidden); - - const topicSourceListDiv = - ambientModePage.shadowRoot.querySelector('#topicSourceListDiv'); - assertFalse(!!topicSourceListDiv); - }); - - test('hasTopicSourceItemsAfterLoad', function() { - const spinner = - ambientModePage.shadowRoot.querySelector('paper-spinner-lite'); - assertTrue(!!spinner); - assertTrue(spinner.active); - assertFalse(spinner.hidden); - - const topicSourceListDiv = - ambientModePage.shadowRoot.querySelector('#topicSourceListDiv'); - assertFalse(!!topicSourceListDiv); - - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - // Spinner is not active and not visible. - assertFalse(spinner.active); - assertTrue(spinner.hidden); - - const topicSourceList = - ambientModePage.shadowRoot.querySelector('topic-source-list'); - const ironList = topicSourceList.shadowRoot.querySelector('iron-list'); - const topicSourceItems = ironList.querySelectorAll('topic-source-item'); - - // Only have two topics source items: GOOGLE_PHOTOS and ART_GALLERY. - assertEquals(2, topicSourceItems.length); - }); - - test('topicSourceItemHasCorrectRowHeight', function() { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const topicSourceList = - ambientModePage.shadowRoot.querySelector('topic-source-list'); - const ironList = topicSourceList.shadowRoot.querySelector('iron-list'); - const topicSourceItems = ironList.querySelectorAll('topic-source-item'); - - topicSourceItems.forEach((row) => { - assertEquals(64, row.offsetHeight); - }); - }); - - test('doubleClickTopicSource', () => { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const topicSourceList = - ambientModePage.shadowRoot.querySelector('topic-source-list'); - const ironList = topicSourceList.shadowRoot.querySelector('iron-list'); - const topicSourceItem = - ironList.querySelector('topic-source-item[checked]'); - const clickableDiv = - topicSourceItem.shadowRoot.querySelector('#rowContainer'); - - // Verify that the show-albums event is sent when the google photos radio - // button is clicked again. - let showAlbumEventCalls = 0; - topicSourceList.addEventListener('show-albums', (event) => { - assertEquals(AmbientModeTopicSource.GOOGLE_PHOTOS, event.detail); - showAlbumEventCalls++; - }); - - clickableDiv.click(); - assertEquals(1, showAlbumEventCalls); - - // Should navigate to the ambient-mode/photos?topic-source=0 subpage. - const router = Router.getInstance(); - assertEquals('/ambientMode/photos', router.getCurrentRoute().path); - assertEquals('topicSource=0', router.getQueryParameters().toString()); - }); - - test('Deep link to topic sources', async () => { - const params = new URLSearchParams(); - params.append('settingId', '502'); - Router.getInstance().navigateTo(routes.AMBIENT_MODE, params); - - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const deepLinkElement = - ambientModePage.shadowRoot.querySelector('topic-source-list') - .shadowRoot.querySelector('topic-source-item'); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Topic sources row should be focused for settingId=502.'); - }); - - test('temperatureUnitRadioButtonsVisibility', () => { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - flush(); - - // When |selectedTemperatureUnit_| is invalid the radio buttons is not - // visible. This is the initial state. - let radioGroup = - ambientModePage.shadowRoot.querySelector('#weatherDiv cr-radio-group'); - assertFalse(!!radioGroup); - - // When |selectedTemperatureUnit_| is valid the radio buttons should be - // visible and enabled. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - radioGroup = - ambientModePage.shadowRoot.querySelector('#weatherDiv cr-radio-group'); - assertTrue(!!radioGroup); - assertFalse(radioGroup.disabled); - }); - - test('temperatureUnitRadioButtons', async () => { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const celsiusButton = ambientModePage.shadowRoot.querySelector( - 'cr-radio-button[name=celsius]'); - const fahrenheitButton = ambientModePage.shadowRoot.querySelector( - 'cr-radio-button[name=fahrenheit]'); - - assertTrue(celsiusButton.checked); - assertFalse(fahrenheitButton.checked); - - browserProxy.resetResolver('setSelectedTemperatureUnit'); - - // Click fahrenheit and expect the fahrenheit radio button to be checked and - // the browser proxy to be called with the correct argument. - fahrenheitButton.click(); - - assertFalse(celsiusButton.checked); - assertTrue(fahrenheitButton.checked); - - assertEquals(1, browserProxy.getCallCount('setSelectedTemperatureUnit')); - const fahrenheitArgs = - await browserProxy.whenCalled('setSelectedTemperatureUnit'); - assertDeepEquals(['fahrenheit'], fahrenheitArgs); - - browserProxy.resetResolver('setSelectedTemperatureUnit'); - - // Click celsius and expect the celsius radio button to be checked and the - // browser proxy to be called with the correct argument. - celsiusButton.click(); - - assertTrue(celsiusButton.checked); - assertFalse(fahrenheitButton.checked); - - assertEquals(1, browserProxy.getCallCount('setSelectedTemperatureUnit')); - const celsiusArgs = - await browserProxy.whenCalled('setSelectedTemperatureUnit'); - assertDeepEquals(['celsius'], celsiusArgs); - }); - - test('temperatureUnitRadioButtonsDoubleClick', async () => { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const celsiusButton = ambientModePage.shadowRoot.querySelector( - 'cr-radio-button[name=celsius]'); - - browserProxy.resetResolver('setSelectedTemperatureUnit'); - - // Nothing should happen. - celsiusButton.click(); - assertEquals(0, browserProxy.getCallCount('setSelectedTemperatureUnit')); - }); - - test('topicSourceAndWeatherDisabledWhenToggleOff', () => { - // Select the google photos topic source. - webUIListenerCallback('topic-source-changed', { - 'topicSource': AmbientModeTopicSource.GOOGLE_PHOTOS, - 'hasAlbums': true, - }); - // Select celsius as the initial temperature unit. - webUIListenerCallback( - 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); - flush(); - - const button = - ambientModePage.shadowRoot.querySelector('#ambientModeEnable'); - assertTrue(!!button); - assertFalse(button.disabled); - - // The button's state is set by the pref value. - let enabled = - ambientModePage.getPref('settings.ambient_mode.enabled.value'); - assertTrue(enabled); - assertEquals(enabled, button.checked); - - // Topic source list and weather radio group are enabled. - const topicSourceList = - ambientModePage.shadowRoot.querySelector('topic-source-list'); - assertFalse(topicSourceList.disabled); - const radioGroup = - ambientModePage.shadowRoot.querySelector('#weatherDiv cr-radio-group'); - assertFalse(radioGroup.disabled); - - // Click the button will toggle the pref value. - button.click(); - flush(); - enabled = ambientModePage.getPref('settings.ambient_mode.enabled.value'); - assertFalse(enabled); - assertEquals(enabled, button.checked); - - // Topic source list and weather radio group are disabled. - assertTrue(topicSourceList.disabled); - assertTrue(radioGroup.disabled); - }); - -});
diff --git a/chrome/test/data/webui/settings/chromeos/ambient_mode_photos_page_test.js b/chrome/test/data/webui/settings/chromeos/ambient_mode_photos_page_test.js deleted file mode 100644 index aa7a4fd..0000000 --- a/chrome/test/data/webui/settings/chromeos/ambient_mode_photos_page_test.js +++ /dev/null
@@ -1,919 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {AmbientModeBrowserProxyImpl, AmbientModeTopicSource} from 'chrome://os-settings/chromeos/os_settings.js'; -import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {waitAfterNextRender} from 'chrome://test/test_util.js'; - -import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; -import {TestBrowserProxy} from '../../test_browser_proxy.js'; - -/** - * @implements {AmbientModeBrowserProxy} - */ -class TestAmbientModeBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'requestTopicSource', - 'requestAlbums', - 'setSelectedAlbums', - ]); - } - - /** @override */ - requestTopicSource() { - this.methodCalled('requestTopicSource'); - } - - /** @override */ - requestAlbums(topicSource) { - this.methodCalled('requestAlbums', [topicSource]); - } - - setSelectedAlbums(settings) { - this.methodCalled('setSelectedAlbums', [settings]); - } -} - -suite('AmbientModeHandler', function() { - /** @type {SettingsAmbientModePhotosPageElement} */ - let ambientModePhotosPage = null; - - /** @type {?TestAmbientModeBrowserProxy} */ - let browserProxy = null; - - suiteSetup(function() {}); - - setup(function() { - browserProxy = new TestAmbientModeBrowserProxy(); - AmbientModeBrowserProxyImpl.setInstanceForTesting(browserProxy); - PolymerTest.clearBody(); - - ambientModePhotosPage = - document.createElement('settings-ambient-mode-photos-page'); - document.body.appendChild(ambientModePhotosPage); - flush(); - }); - - teardown(function() { - ambientModePhotosPage.remove(); - }); - - /** - * @param {!AmbientModeTopicSource} topicSource - * @private - */ - function assertCheckPosition(topicSource) { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0', url: 'url'}, - {albumId: 'id1', checked: true, title: 'album1', url: 'url'}, - ], - topicSource); - - getAlbumItems_().forEach((album) => { - const check = album.shadowRoot.querySelector('.check'); - const image = album.shadowRoot.querySelector('#image'); - const boundingWidth = image.getBoundingClientRect().width; - const scale = boundingWidth / image.offsetWidth; - - const checkTop = Math.round( - (image.offsetHeight * (1.0 - scale) - check.offsetHeight) / 2.0); - assertEquals(checkTop, check.offsetTop); - - const checkLeft = Math.round( - (image.offsetWidth * (1.0 - scale) - check.offsetWidth) / 2.0 + - boundingWidth); - assertEquals(checkLeft, check.offsetLeft); - }); - } - - /** - * Retrieve the title element for the albumItem at the position. - * @param {number} position - * @return {Element} - * @private - */ - function getTitleElement_(position) { - return getAlbumItems_()[position].shadowRoot.querySelector('#albumTitle'); - } - - /** - * Retrieve the description element for the albumItem at the position. - * @param {number} position - * @return {Element} - * @private - */ - function getDescriptionElement_(position) { - return getAlbumItems_()[position].shadowRoot.querySelector( - '#albumDescription'); - } - - /** - * Setup the photos page and flush the DOM. - * @param {Array<!AmbientModeAlbum>} albums - * @param {!AmbientModeTopicSource} topicSource - * @private - */ - function displayPhotosPage_(albums, topicSource) { - ambientModePhotosPage.albums = albums; - ambientModePhotosPage.topicSource = topicSource; - flush(); - } - - /** - * Get all displayed album item elements. - * @return {Array<Element>} - * @private - */ - function getAlbumItems_() { - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - return ironList.querySelectorAll('album-item:not([hidden])'); - } - - /** - * @param {Element} element - * @return {number} - * @private - */ - function getZIndex_(element) { - const zIndex = parseInt(getComputedStyle(element).zIndex); - return zIndex === NaN ? 0 : zIndex; - } - - /** - * Asserts the title and the description elements are limited to 1 and 2 lines - * respectively. - * @param {number} albumIndex - * @private - */ - function assertAllTextClamped_(albumIndex) { - assertTextClamped(getTitleElement_(albumIndex), 1); - assertTextClamped(getDescriptionElement_(albumIndex), 2); - } - - /** - * Asserts that the textWithTooltip element is limited to the specified number - * of lines. - * @param {Element} textWithTooltip - * @param {number} lineCount - * @private - */ - function assertTextClamped(textWithTooltip, lineCount) { - const element = textWithTooltip.shadowRoot.querySelector('#textDiv'); - const height = element.offsetHeight; - const lineHeight = parseInt(getComputedStyle(element).lineHeight); - assertTrue( - height / lineHeight <= lineCount, - 'Actual Height: ' + height.toString() + ' Line height: ' + - lineHeight.toString() + ' Content: ' + element.innerHTML); - } - - /** - * Generate a random UTF16 String of specified length. - * @param {number} length The length of the string - * @return {String} - * @private - */ - function createRandomString_(length) { - let randomString = ''; - for (let i = 0; i < length; i++) { - randomString = randomString.concat(getRandomUTF16Char_()); - } - return randomString; - } - - /** - * Generate a random UTF16 character. - * @return {String} The character - * @private - */ - function getRandomUTF16Char_() { - const utf16Max = 65535; - return String.fromCharCode(Math.floor(Math.random() * utf16Max)); - } - - /** - * Determines if a tooltip is visible for the parameter. - * @param {Element} parentElement The element containing the tooltip. - * @return {boolean} If a tooltip element is within an animate in delay or is - * already visible/animating. - */ - function isTooltipAvailable_(parentElement) { - const tooltip = parentElement.shadowRoot.querySelector('paper-tooltip'); - return tooltip !== null && getComputedStyle(tooltip).display !== 'none'; - } - - test('hasAlbumsWithoutPhotoPreview', function() { - // Disable photo preview feature and reload the |ambientModePhotosPage|. - loadTimeData.overrideValues({isAmbientModePhotoPreviewEnabled: false}); - assertFalse(loadTimeData.getBoolean('isAmbientModePhotoPreviewEnabled')); - - ambientModePhotosPage.remove(); - ambientModePhotosPage = - document.createElement('settings-ambient-mode-photos-page'); - document.body.appendChild(ambientModePhotosPage); - - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - {albumId: 'id1', checked: false, title: 'album1'}, - ], - null); - - const ironList = - ambientModePhotosPage.shadowRoot.querySelector('iron-list'); - const checkboxes = ironList.querySelectorAll('cr-checkbox'); - assertEquals(2, checkboxes.length); - - const checkbox0 = checkboxes[0]; - const checkbox1 = checkboxes[1]; - assertEquals('id0', checkbox0.dataset.id); - assertTrue(checkbox0.checked); - assertEquals('album0', checkbox0.label); - assertEquals('id1', checkbox1.dataset.id); - assertFalse(checkbox1.checked); - assertEquals('album1', checkbox1.label); - - // Reset/enable photo preview feature. - loadTimeData.overrideValues({isAmbientModePhotoPreviewEnabled: true}); - assertTrue(loadTimeData.getBoolean('isAmbientModePhotoPreviewEnabled')); - }); - - test('hasAlbumsWithPhotoPreview', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - {albumId: 'id1', checked: false, title: 'album1'}, - ], - null); - - const albumItems = getAlbumItems_(); - assertEquals(2, albumItems.length); - - const album0 = albumItems[0]; - const album1 = albumItems[1]; - assertEquals('id0', album0.album.albumId); - assertTrue(album0.album.checked); - assertEquals('album0', album0.album.title); - assertEquals('id1', album1.album.albumId); - assertFalse(album1.album.checked); - assertEquals('album1', album1.album.title); - }); - - test('spinnerVisibility', function() { - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const spinner = albumList.shadowRoot.querySelector('paper-spinner-lite'); - assertTrue(!!spinner); - assertTrue(spinner.active); - assertFalse(spinner.hidden); - - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - {albumId: 'id1', checked: false, title: 'album1'}, - ], - null); - - // Spinner is not active and not visible. - assertFalse(spinner.active); - assertTrue(spinner.hidden); - }); - - test('personalPhotosImageContainerHasCorrectSize', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - {albumId: 'id1', checked: false, title: 'album1'}, - {albumId: 'id2', checked: false, title: 'album2'}, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - assertTrue(ironList.grid); - - const albumItems = ironList.querySelectorAll('album-item:not([hidden])'); - assertEquals(3, albumItems.length); - albumItems.forEach((album) => { - const imageContainer = album.shadowRoot.querySelector('#imageContainer'); - assertEquals(160, imageContainer.clientHeight); - assertEquals(160, imageContainer.clientWidth); - }); - }); - - test('artImageContainerHasCorrectSize', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - {albumId: 'id1', checked: false, title: 'album1'}, - {albumId: 'id2', checked: false, title: 'album2'}, - ], - AmbientModeTopicSource.ART_GALLERY); - - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - assertTrue(ironList.grid); - - const albumItems = ironList.querySelectorAll('album-item:not([hidden])'); - assertEquals(3, albumItems.length); - albumItems.forEach((album) => { - const imageContainer = album.shadowRoot.querySelector('#imageContainer'); - assertEquals(160, imageContainer.clientHeight); - assertEquals(256, imageContainer.clientWidth); - }); - }); - - test('toggleAlbumSelectionByClick', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0', url: 'url'}, - {albumId: 'id1', checked: false, title: 'album1', url: 'url'}, - ], - null); - - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - const albumItems = ironList.querySelectorAll('album-item:not([hidden])'); - assertEquals(2, albumItems.length); - - const album0 = albumItems[0]; - const album1 = albumItems[1]; - assertTrue(album0.checked); - assertFalse(album1.checked); - - // Verify that the selected-albums-changed event is sent when the album - // image is clicked. - let selectedAlbumsChangedEventCalls = 0; - albumList.addEventListener('selected-albums-changed', (event) => { - selectedAlbumsChangedEventCalls++; - }); - - // Click album item image will toggle the check. - const image0 = album0.shadowRoot.querySelector('#image'); - image0.click(); - assertFalse(album0.checked); - assertEquals(1, selectedAlbumsChangedEventCalls); - - // Click album item image will toggle the check. - image0.click(); - assertTrue(album0.checked); - assertEquals(2, selectedAlbumsChangedEventCalls); - - // Click album item image will toggle the check. - const image1 = album1.shadowRoot.querySelector('#image'); - image1.click(); - assertTrue(album1.checked); - assertEquals(3, selectedAlbumsChangedEventCalls); - - // Click album item image will toggle the check. - image1.click(); - assertFalse(album1.checked); - assertEquals(4, selectedAlbumsChangedEventCalls); - }); - - test('notDeselectLastArtAlbum', async () => { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0', url: 'url'}, - {albumId: 'id1', checked: true, title: 'album1', url: 'url'}, - ], - AmbientModeTopicSource.ART_GALLERY); - - const albumItems = getAlbumItems_(); - assertEquals(2, albumItems.length); - - const album0 = albumItems[0]; - const album1 = albumItems[1]; - assertTrue(album0.checked); - assertTrue(album1.checked); - - // Click album item image will toggle the check. - const image0 = album0.shadowRoot.querySelector('#image'); - image0.click(); - assertFalse(album0.checked); - - // Click the last art album item image will not toggle the check and will - // show a dialog. - const image1 = album1.shadowRoot.querySelector('#image'); - image1.click(); - assertTrue(album1.checked); - flush(); - - const artAlbumDialog = - ambientModePhotosPage.shadowRoot.querySelector('art-album-dialog'); - await waitAfterNextRender(artAlbumDialog); - assertTrue(artAlbumDialog.shadowRoot.querySelector('#dialog').open); - }); - - test('showCheckIconOnSelectedAlbum', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0', url: 'url'}, - {albumId: 'id1', checked: false, title: 'album1', url: 'url'}, - ], - null); - - const album0 = getAlbumItems_()[0]; - const check0 = album0.shadowRoot.querySelector('.check'); - assertTrue(album0.checked); - assertFalse(check0.hidden); - - // Click album item image will toggle the check. - album0.shadowRoot.querySelector('#image').click(); - assertFalse(album0.checked); - assertTrue(check0.hidden); - - const album1 = getAlbumItems_()[1]; - const check1 = album1.shadowRoot.querySelector('.check'); - assertFalse(album1.checked); - assertTrue(check1.hidden); - - // Click album item image will toggle the check. - album1.shadowRoot.querySelector('#image').click(); - assertTrue(album1.checked); - assertFalse(check1.hidden); - // Click album1 will not affect album0. - assertFalse(album0.checked); - assertTrue(check0.hidden); - }); - - test('personalPhotosCheckIconHasCorrectPosition', function() { - assertCheckPosition(AmbientModeTopicSource.GOOGLE_PHOTOS); - }); - - test('artPhotosCheckIconHasCorrectPosition', function() { - assertCheckPosition(AmbientModeTopicSource.ART_GALLERY); - }); - - test('setSelectedAlbums', async () => { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0', url: 'url'}, - {albumId: 'id1', checked: false, title: 'album1', url: 'url'}, - ], - null); - - const albumItems = getAlbumItems_(); - assertEquals(2, albumItems.length); - - const album0 = albumItems[0]; - const album1 = albumItems[1]; - assertTrue(album0.checked); - assertFalse(album1.checked); - - browserProxy.resetResolver('setSelectedAlbums'); - - // Click album item image will toggle the check. - album1.shadowRoot.querySelector('#image').click(); - assertTrue(album1.checked); - - assertEquals(1, browserProxy.getCallCount('setSelectedAlbums')); - let albumsArgs = await browserProxy.whenCalled('setSelectedAlbums'); - assertDeepEquals( - [{albumId: 'id0'}, {albumId: 'id1'}], albumsArgs[0].albums); - - browserProxy.resetResolver('setSelectedAlbums'); - - // Click album item image will toggle the check. - album0.shadowRoot.querySelector('#image').click(); - assertFalse(album0.checked); - - assertEquals(1, browserProxy.getCallCount('setSelectedAlbums')); - albumsArgs = await browserProxy.whenCalled('setSelectedAlbums'); - assertDeepEquals([{albumId: 'id1'}], albumsArgs[0].albums); - }); - - test('notToggleAlbumSelection', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - null); - - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - const albumItems = ironList.querySelectorAll('album-item:not([hidden])'); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - assertTrue(album0.checked); - - // Verify that the selected-albums-changed event is sent when the album - // image is clicked. - let selectedAlbumsChangedEventCalls = 0; - albumList.addEventListener('selected-albums-changed', (event) => { - selectedAlbumsChangedEventCalls++; - }); - - // Click outside album item image will not toggle the check. - album0.$.albumInfo.click(); - assertTrue(album0.checked); - assertEquals(0, selectedAlbumsChangedEventCalls); - }); - - test('toggleAlbumSelectionByKeypress', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - null); - - const albumList = - ambientModePhotosPage.shadowRoot.querySelector('album-list'); - const ironList = albumList.shadowRoot.querySelector('iron-list'); - const albumItems = ironList.querySelectorAll('album-item:not([hidden])'); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - assertTrue(album0.checked); - - // Verify that the selected-albums-changed event is sent when the album - // image is clicked. - let selectedAlbumsChangedEventCalls = 0; - albumList.addEventListener('selected-albums-changed', (event) => { - selectedAlbumsChangedEventCalls++; - }); - - // Keydown with Enter key on album item will toggle the selection. - const enterEvent = new KeyboardEvent( - 'keydown', {cancelable: true, key: 'Enter', keyCode: 13}); - album0.dispatchEvent(enterEvent); - assertFalse(album0.checked); - assertEquals(1, selectedAlbumsChangedEventCalls); - - // Keydown with Enter key on album item will toggle the selection. - album0.dispatchEvent(enterEvent); - assertTrue(album0.checked); - assertEquals(2, selectedAlbumsChangedEventCalls); - }); - - test('updateAlbumURL', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - AmbientModeTopicSource.ART_GALLERY); - - const albumItems = getAlbumItems_(); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - - // Update album URL. - const url = 'url'; - webUIListenerCallback('album-preview-changed', { - topicSource: AmbientModeTopicSource.ART_GALLERY, - albumId: 'id0', - url: url, - }); - assertEquals(url, album0.album.url); - }); - - test('notUpdateAlbumURL', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - AmbientModeTopicSource.ART_GALLERY); - - const albumItems = getAlbumItems_(); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - - // Different topic source will no update album URL. - const url = 'chrome://ambient'; - webUIListenerCallback('album-preview-changed', { - topicSource: AmbientModeTopicSource.GOOGLE_PHOTOS, - albumId: 'id0', - url: url, - }); - assertFalse(!!album0.album.url); - }); - - test('updateImgVisibility', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - AmbientModeTopicSource.ART_GALLERY); - - const albumItems = getAlbumItems_(); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - - let img = album0.shadowRoot.querySelector('#image'); - assertFalse(!!img); - - // Update album URL. - const url = 'url'; - webUIListenerCallback('album-preview-changed', { - topicSource: AmbientModeTopicSource.ART_GALLERY, - albumId: 'id0', - url: url, - }); - assertEquals(url, album0.album.url); - - img = album0.shadowRoot.querySelector('#image'); - assertTrue(!!img); - assertFalse(img.hidden); - - const images = album0.shadowRoot.querySelector('#rhImages'); - assertFalse(!!images); - }); - - test('updateRecentHighlightsImagesVisibility', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - const albumItems = getAlbumItems_(); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - let images = album0.shadowRoot.querySelector('#rhImages'); - assertFalse(!!images); - - // Update Recent Highlights album URLs. - const url = 'url'; - webUIListenerCallback('album-preview-changed', { - topicSource: AmbientModeTopicSource.GOOGLE_PHOTOS, - albumId: 'id0', - recentHighlightsUrls: [url, url, url, url], - }); - assertEquals(url, album0.album.recentHighlightsUrls[0]); - assertEquals(url, album0.album.recentHighlightsUrls[1]); - assertEquals(url, album0.album.recentHighlightsUrls[2]); - assertEquals(url, album0.album.recentHighlightsUrls[3]); - images = album0.shadowRoot.querySelector('#rhImages'); - assertTrue(!!images); - assertFalse(images.hidden); - const image_top_left = - album0.shadowRoot.querySelector('.image-rh.top-left'); - const image_top_right = - album0.shadowRoot.querySelector('.image-rh.top-right'); - const image_bottom_left = - album0.shadowRoot.querySelector('.image-rh.bottom-left'); - const image_bottom_right = - album0.shadowRoot.querySelector('.image-rh.bottom-right'); - assertTrue(!!image_top_left); - assertFalse(image_top_left.hidden); - assertTrue(!!image_top_right); - assertFalse(image_top_right.hidden); - assertTrue(!!image_bottom_left); - assertFalse(image_bottom_left.hidden); - assertTrue(!!image_bottom_right); - assertFalse(image_bottom_right.hidden); - - const img = album0.shadowRoot.querySelector('#image'); - assertFalse(!!img); - }); - - test('updateRecentHighlightsImagesVisibilityWithThreeImages', function() { - displayPhotosPage_( - [ - {albumId: 'id0', checked: true, title: 'album0'}, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - const albumItems = getAlbumItems_(); - assertEquals(1, albumItems.length); - - const album0 = albumItems[0]; - let images = album0.shadowRoot.querySelector('#rhImages'); - assertFalse(!!images); - - // Only update 3 images. - const url = 'url'; - webUIListenerCallback('album-preview-changed', { - topicSource: AmbientModeTopicSource.GOOGLE_PHOTOS, - albumId: 'id0', - recentHighlightsUrls: [url, url, url], - }); - assertEquals(url, album0.album.recentHighlightsUrls[0]); - assertEquals(url, album0.album.recentHighlightsUrls[1]); - assertEquals(url, album0.album.recentHighlightsUrls[2]); - assertFalse(!!album0.album.recentHighlightsUrls[3]); - images = album0.shadowRoot.querySelector('#rhImages'); - assertTrue(!!images); - assertFalse(images.hidden); - const image_top_left = - album0.shadowRoot.querySelector('.image-rh.top-left'); - const image_top_right = - album0.shadowRoot.querySelector('.image-rh.top-right'); - const image_bottom_left = - album0.shadowRoot.querySelector('.image-rh.bottom-left'); - const image_bottom_right = - album0.shadowRoot.querySelector('.image-rh.bottom-right'); - assertTrue(!!image_top_left); - assertFalse(image_top_left.hidden); - assertTrue(!!image_top_right); - assertFalse(image_top_right.hidden); - assertTrue(!!image_bottom_left); - assertFalse(image_bottom_left.hidden); - assertTrue(!!image_bottom_right); - assertTrue(image_bottom_right.hidden); - - const img = album0.shadowRoot.querySelector('#image'); - assertFalse(!!img); - }); - - test('albumSizeIsConsistent', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(1), - description: createRandomString_(1), - url: 'url', - }, - { - albumId: 'id1', - checked: false, - title: createRandomString_(500), - description: createRandomString_(500), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - const album0 = getAlbumItems_()[0]; - const album1 = getAlbumItems_()[1]; - assertEquals( - album0.offsetHeight, album1.offsetHeight, - 'grids in iron-list require height to be consistent across items'); - }); - - test('linesAreClamped', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(1), - description: createRandomString_(1), - url: 'url', - }, - { - albumId: 'id1', - checked: false, - title: createRandomString_(500), - description: createRandomString_(500), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - assertAllTextClamped_(0); - assertAllTextClamped_(1); - }); - - test('tooltipVisibilityAdjustsZIndex', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(500), - description: createRandomString_(500), - url: 'url', - }, - { - albumId: 'id1', - checked: false, - title: createRandomString_(500), - description: createRandomString_(500), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - const album0 = getAlbumItems_()[0]; - const album1 = getAlbumItems_()[1]; - - album0.titleTooltipIsVisible = true; - assertTrue(getZIndex_(album0) > getZIndex_(album1)); - - album0.titleTooltipIsVisible = false; - album1.titleTooltipIsVisible = true; - assertTrue(getZIndex_(album0) < getZIndex_(album1)); - album1.titleTooltipIsVisible = false; - - album1.descriptionTooltipIsVisible = true; - assertTrue(getZIndex_(album0) < getZIndex_(album1)); - - album0.descriptionTooltipIsVisible = true; - album1.descriptionTooltipIsVisible = false; - assertTrue(getZIndex_(album0) > getZIndex_(album1)); - }); - - test('textWithTooltip_hasTooltipWhenTextOverflows', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(1), - description: createRandomString_(1), - url: 'url', - }, - { - albumId: 'id1', - checked: false, - title: createRandomString_(500), - description: createRandomString_(500), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - assertFalse( - isTooltipAvailable_(getTitleElement_(0)), - 'There shouldn\'t be a tooltip for non-overflowing text.'); - assertFalse( - isTooltipAvailable_(getDescriptionElement_(0)), - 'There shouldn\'t be a tooltip for non-overflowing text.'); - - assertTrue( - isTooltipAvailable_(getTitleElement_(1)), - 'There should be a tooltip for overflowing text.'); - assertTrue( - isTooltipAvailable_(getDescriptionElement_(1)), - 'There should be a tooltip for overflowing text.'); - }); - - test('textWithTooltip_tooltipVisibilityWhenTextChanges', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(1), - description: createRandomString_(1), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - - assertFalse( - isTooltipAvailable_(getTitleElement_(0)), - 'There shouldn\'t be a tooltip for non-overflowing text.'); - - getTitleElement_(0).text = createRandomString_(300); - flush(); - assertTrue( - isTooltipAvailable_(getTitleElement_(0)), - 'There should be a tooltip for overflowing text.'); - - getTitleElement_(0).text = createRandomString_(1); - flush(); - assertFalse( - isTooltipAvailable_(getTitleElement_(0)), - 'There shouldn\'t be a tooltip for non-overflowing text.'); - }); - - test('textWithTooltip_tooltipVisibilityCallbacks', function() { - displayPhotosPage_( - [ - { - albumId: 'id0', - checked: false, - title: createRandomString_(500), - description: createRandomString_(1), - url: 'url', - }, - ], - AmbientModeTopicSource.GOOGLE_PHOTOS); - getTitleElement_(0).dispatchEvent(new MouseEvent('mouseenter', null)); - assertFalse( - getTitleElement_(0).tooltipIsVisible, - 'Tooltip should have an animate in delay'); - // Delay animate in delay and animate out duration is currently 500. - setTimeout(() => { - assertTrue( - getTitleElement_(0).tooltipIsVisible, 'Tooltip should be visible'); - - getTitleElement_(0).dispatchEvent(new MouseEvent('mouseleave', null)); - assertTrue( - getTitleElement_(0).tooltipIsVisible, - 'Tooltip should have an animate out duration'); - setTimeout(() => { - assertFalse( - getTitleElement_(0).tooltipIsVisible, - 'Tooltip shouldn\'t be visible after it\'s finished animating out'); - }, 1000); - }, 1000); - }); -});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index bf64d5e..e7ef248e 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -289,16 +289,6 @@ [['AccessibilityPage', 'os_a11y_page_tests.js'], ['AboutPage', 'os_about_page_tests.js'], ['AccountsPage', 'add_users_tests.js'], - [ - 'AmbientModePage', - 'ambient_mode_page_test.js', - {disabled: ['ash::features::kPersonalizationHub']}, - ], - [ - 'AmbientModePhotosPage', - 'ambient_mode_photos_page_test.js', - {disabled: ['ash::features::kPersonalizationHub']}, - ], ['AppsPage', 'apps_page_test.js'], ['AppNotificationsSubpage', 'app_notifications_subpage_tests.js'], ['AppManagementAppDetailsItem', 'app_management/app_details_item_test.js'], @@ -463,7 +453,9 @@ ['SwitchAccessSetupGuideDialog', 'switch_access_setup_guide_dialog_test.js'], ['SwitchAccessSubpage', 'switch_access_subpage_tests.js'], ['TetherConnectionDialog', 'tether_connection_dialog_test.js'], - ['TextToSpeechPage', 'text_to_speech_page_tests.js', + [ + 'TextToSpeechPage', + 'text_to_speech_page_tests.js', {enabled: ['features::kAccessibilityOSSettingsVisibility']}, ], ['TextToSpeechSubpage', 'text_to_speech_subpage_tests.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/personalization_page_test.js b/chrome/test/data/webui/settings/chromeos/personalization_page_test.js index 06e255f..ddd59dc 100644 --- a/chrome/test/data/webui/settings/chromeos/personalization_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/personalization_page_test.js
@@ -118,19 +118,6 @@ assertEquals(routes.CHANGE_PICTURE, Router.getInstance().getCurrentRoute()); }); - test('ambientMode', function() { - const isGuest = loadTimeData.getBoolean('isGuest'); - const isAmbientModeEnabled = loadTimeData.getBoolean('isAmbientModeEnabled'); - - if(!isGuest && isAmbientModeEnabled){ - const row = - personalizationPage.shadowRoot.querySelector('#ambientModeRow'); - assertTrue(!!row); - row.click(); - assertEquals(routes.AMBIENT_MODE, Router.getInstance().getCurrentRoute()); - } - }); - test('Deep link to change account picture', async () => { const params = new URLSearchParams(); params.append('settingId', '503');
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 8b394e2a..0655b57 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -134,6 +134,10 @@ } }; +TEST_F('CrSettingsTranslatePageTest', 'TargetLanguageSelect', function() { + mocha.grep(translate_page_tests.TestNames.TargetLanguageSelect).run(); +}); + TEST_F('CrSettingsTranslatePageTest', 'AlwaysTranslateDialog', function() { mocha.grep(translate_page_tests.TestNames.AlwaysTranslateDialog).run(); });
diff --git a/chrome/test/data/webui/settings/fake_language_settings_private.ts b/chrome/test/data/webui/settings/fake_language_settings_private.ts index 1c93a48..1080eb4c 100644 --- a/chrome/test/data/webui/settings/fake_language_settings_private.ts +++ b/chrome/test/data/webui/settings/fake_language_settings_private.ts
@@ -356,7 +356,7 @@ * Sets the translate target language. */ setTranslateTargetLanguage(languageCode: string) { - this.settingsPrefs_!.push( + this.settingsPrefs_!.set( 'prefs.translate_recent_target.value', languageCode); } @@ -468,7 +468,7 @@ { key: 'translate_recent_target', type: chrome.settingsPrivate.PrefType.STRING, - value: 'en-US', + value: 'en', }, ]; }
diff --git a/chrome/test/data/webui/settings/translate_page_tests.ts b/chrome/test/data/webui/settings/translate_page_tests.ts index ffabde9..2aa3ef38 100644 --- a/chrome/test/data/webui/settings/translate_page_tests.ts +++ b/chrome/test/data/webui/settings/translate_page_tests.ts
@@ -18,6 +18,7 @@ const translate_page_tests = { TestNames: { + TargetLanguageSelect: 'target language select', AlwaysTranslateDialog: 'always translate dialog', NeverTranslateDialog: 'never translate dialog', TranslateToggle: 'offer to translate toggle', @@ -31,6 +32,7 @@ let translatePage: SettingsTranslatePageElement; let browserProxy: TestLanguagesBrowserProxy; + const translateTarget = 'translate_recent_target'; // Always Translate language pref name for the platform. const alwaysTranslatePref = 'translate_allowlists'; const neverTranslatePref = 'translate_blocked_languages'; @@ -88,6 +90,22 @@ document.body.innerHTML = ''; }); + suite(translate_page_tests.TestNames.TargetLanguageSelect, function() { + test('change target language', function() { + const targetLanguageSelector = translatePage.shadowRoot!.querySelector + <HTMLSelectElement>('#targetLanguage'); + assertTrue(!!targetLanguageSelector); + + assertEquals(targetLanguageSelector.value, + translatePage.getPref(translateTarget).value); + + targetLanguageSelector.value = 'sw'; + targetLanguageSelector.dispatchEvent(new CustomEvent('change')); + + assertEquals(translatePage.getPref(translateTarget).value, 'sw'); + }); + }); + suite(translate_page_tests.TestNames.TranslateToggle, function() { test('test translate.enable toggle', function() { const settingsToggle =
diff --git a/chrome/updater/app/server/win/com_classes.cc b/chrome/updater/app/server/win/com_classes.cc index a4515a50..15514ad 100644 --- a/chrome/updater/app/server/win/com_classes.cc +++ b/chrome/updater/app/server/win/com_classes.cc
@@ -111,6 +111,23 @@ return S_OK; } +STDMETHODIMP UpdateStateImpl::get_installerText(BSTR* installer_text) { + DCHECK(installer_text); + *installer_text = + base::win::ScopedBstr(base::UTF8ToWide(update_state_.installer_text)) + .Release(); + return S_OK; +} + +STDMETHODIMP UpdateStateImpl::get_installerCommandLine( + BSTR* installer_cmd_line) { + DCHECK(installer_cmd_line); + *installer_cmd_line = + base::win::ScopedBstr(base::UTF8ToWide(update_state_.installer_cmd_line)) + .Release(); + return S_OK; +} + STDMETHODIMP CompleteStatusImpl::get_statusCode(LONG* code) { DCHECK(code); *code = code_; @@ -590,9 +607,6 @@ [](scoped_refptr<base::SequencedTaskRunner> task_runner, IUpdaterObserverPtr observer, const UpdateService::Result result) { - // TODO(crbug.com/1286574): Once `result` is expanded - // with more detailed installation result, convert and - // forward the details to `CompleteStatusImpl`. task_runner->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(
diff --git a/chrome/updater/app/server/win/com_classes.h b/chrome/updater/app/server/win/com_classes.h index 8b1ca8f..dd29538 100644 --- a/chrome/updater/app/server/win/com_classes.h +++ b/chrome/updater/app/server/win/com_classes.h
@@ -47,6 +47,8 @@ IFACEMETHODIMP get_errorCategory(LONG* error_category) override; IFACEMETHODIMP get_errorCode(LONG* error_code) override; IFACEMETHODIMP get_extraCode1(LONG* extra_code1) override; + IFACEMETHODIMP get_installerText(BSTR* installer_text) override; + IFACEMETHODIMP get_installerCommandLine(BSTR* installer_cmd_line) override; private: ~UpdateStateImpl() override = default;
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc index deefd66..52edae5 100644 --- a/chrome/updater/app/server/win/com_classes_legacy.cc +++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -701,7 +701,8 @@ } PolicyStatusImpl::PolicyStatusImpl() - : policy_service_(PolicyService::Create(CreateExternalConstants())) {} + : policy_service_( + AppServerSingletonInstance()->config()->GetPolicyService()) {} PolicyStatusImpl::~PolicyStatusImpl() = default; HRESULT PolicyStatusImpl::RuntimeClassInitialize() {
diff --git a/chrome/updater/app/server/win/updater_idl.template b/chrome/updater/app/server/win/updater_idl.template index d676fc3..55543c3 100644 --- a/chrome/updater/app/server/win/updater_idl.template +++ b/chrome/updater/app/server/win/updater_idl.template
@@ -26,6 +26,8 @@ [propget] HRESULT errorCategory([out, retval] LONG*); [propget] HRESULT errorCode([out, retval] LONG*); [propget] HRESULT extraCode1([out, retval] LONG*); + [propget] HRESULT installerText([out, retval] BSTR*); + [propget] HRESULT installerCommandLine([out, retval] BSTR*); }; [
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc index e6576bc5..a33b9f2 100644 --- a/chrome/updater/test/integration_tests_win.cc +++ b/chrome/updater/test/integration_tests_win.cc
@@ -1244,60 +1244,75 @@ } void RunOfflineInstall(UpdaterScope scope) { - constexpr wchar_t kTestRegKey[] = L"software\\updater\\test"; - constexpr wchar_t kTestRegValue[] = L"install_result"; + constexpr wchar_t kTestAppID[] = L"{CDABE316-39CD-43BA-8440-6D1E0547AEE6}"; constexpr char kManifestFormat[] = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<response protocol=\"3.0\">" - " <app appid=\"{CDABE316-39CD-43BA-8440-6D1E0547AEE6}\" status=\"ok\">" - " <updatecheck status=\"ok\">" - " <manifest version=\"1.2.3.4\">" - " <packages>" - " <package hash_sha256=\"sha256hash_foobar\"" - " name=\"reg.exe\" required=\"true\" size=\"%lld\"/>" - " </packages>" - " <actions>" - " <action event=\"install\" needsadmin=\"false\"" - " run=\"reg.exe\"" - " arguments=\"ADD %s\\%ls /t REG_DWORD /v %ls /d 123 /f\"/>" - " </actions>" - " </manifest>" - " </updatecheck>" - " <data index=\"verboselogging\" name=\"install\" status=\"ok\">" - " {\"distribution\": { \"verbose_logging\": true}}" - " </data>" - " </app>" - "</response>"; + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<response protocol=\"3.0\">\n" + " <app appid=\"%ls\" status=\"ok\">\n" + " <updatecheck status=\"ok\">\n" + " <manifest version=\"1.2.3.4\">\n" + " <packages>\n" + " <package hash_sha256=\"sha256hash_foobar\"\n" + " name=\"reg.exe\" required=\"true\" size=\"%lld\"/>\n" + " </packages>\n" + " <actions>\n" + " <action event=\"install\"\n" + " run=\"reg.exe\"\n" + " arguments=\"IMPORT %s /REG:32\"/>\n" + " </actions>\n" + " </manifest>\n" + " </updatecheck>\n" + " <data index=\"verboselogging\" name=\"install\" status=\"ok\">\n" + " {\"distribution\": { \"verbose_logging\": true}}\n" + " </data>\n" + " </app>\n" + "</response>\n"; - HKEY key_hive = - scope == UpdaterScope::kSystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + const HKEY root = UpdaterScopeToHKeyRoot(scope); + const std::wstring app_client_state_key = GetAppClientStateKey(kTestAppID); - DeleteRegKey(key_hive, kTestRegKey); + EXPECT_TRUE(DeleteRegKey(root, app_client_state_key)); - wchar_t reg_exe_path[MAX_PATH] = {0}; - DWORD size = ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\reg.exe", - reg_exe_path, std::size(reg_exe_path)); - ASSERT_TRUE(size > 0 && size < MAX_PATH); - const base::FilePath exe_path(reg_exe_path); - ASSERT_TRUE(base::PathExists(exe_path)); + base::FilePath reg_exe_path; + ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, ®_exe_path)); + reg_exe_path = reg_exe_path.Append(L"reg.exe"); + ASSERT_TRUE(base::PathExists(reg_exe_path)); base::ScopedTempDir temp_dir; EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); const base::FilePath& offline_dir = temp_dir.GetPath(); + // Create installer result reg file. These are 32-bit registry values and + // must be imported with flag `/REG:32`. + constexpr char kRegFileName[] = "InstallerResult.reg"; + constexpr char kInstallerResultRegFileFormat[] = + "Windows Registry Editor Version 5.00\n" + "\n" + "[%s\\%ls]\n" + "\"InstallerResult\"=dword:00000000\n" + "\"InstallerError\"=dword:00000000\n" + "\"InstallerExtraCode1\"=dword:00000000\n" + "\"InstallerResultUIString\"=\"CoolApp\"\n" + "\"InstallerSuccessLaunchCmdLine\"=\"notepad.exe\"\n"; + base::FilePath installer_result_path = offline_dir.AppendASCII(kRegFileName); + EXPECT_TRUE(base::WriteFile( + installer_result_path, + base::StringPrintf(kInstallerResultRegFileFormat, + scope == UpdaterScope::kSystem ? "HKEY_LOCAL_MACHINE" + : "HKEY_CURRENT_USER", + app_client_state_key.c_str()))); + // Create manifest file. base::FilePath manifest_path = offline_dir.Append(FILE_PATH_LITERAL("OfflineManifest.gup")); int64_t exe_size = 0; - EXPECT_TRUE(base::GetFileSize(exe_path, &exe_size)); + EXPECT_TRUE(base::GetFileSize(reg_exe_path, &exe_size)); const std::string manifest = - base::StringPrintf(kManifestFormat, exe_size, - scope == UpdaterScope::kSystem ? "HKLM" : "HKCU", - kTestRegKey, kTestRegValue); + base::StringPrintf(kManifestFormat, kTestAppID, exe_size, kRegFileName); EXPECT_TRUE(base::WriteFile(manifest_path, manifest)); // Copy app installer. - ASSERT_TRUE(base::CopyFile(exe_path, + ASSERT_TRUE(base::CopyFile(reg_exe_path, offline_dir.Append(FILE_PATH_LITERAL("reg.exe")))); // Trigger offline install. @@ -1312,9 +1327,9 @@ if (scope == UpdaterScope::kSystem) offline_install_cmd.AppendSwitch(kSystemSwitch); - offline_install_cmd.AppendSwitchASCII( + offline_install_cmd.AppendSwitchNative( updater::kHandoffSwitch, - "appguid={CDABE316-39CD-43BA-8440-6D1E0547AEE6}&lang=en"); + base::StrCat({L"appguid=", kTestAppID, L"&lang=en"})); offline_install_cmd.AppendSwitchASCII( updater::kSessionIdSwitch, "{E85204C6-6F2F-40BF-9E6C-4952208BB977}"); offline_install_cmd.AppendSwitchNative(updater::kOfflineDirSwitch, @@ -1325,7 +1340,7 @@ // Dismiss the installation completion dialog, then wait for the process exit. EXPECT_TRUE(WaitFor(base::BindRepeating( - [](HKEY key_hive, const wchar_t* test_key_name, + [](HKEY root, const wchar_t* test_key_name, const wchar_t* test_value_name) { // Enumerate the top-level dialogs to find the setup dialog. WindowEnumerator( @@ -1357,17 +1372,21 @@ if (IsUpdaterRunning()) return false; - // Wait for the app installer writes the expected reg value. + // Wait for the app installer to write the expected reg value. base::win::RegKey key; - DWORD value = 0; - return (ERROR_SUCCESS == - key.Open(key_hive, test_key_name, KEY_QUERY_VALUE) && - ERROR_SUCCESS == key.ReadValueDW(test_value_name, &value) && - value == 123); + std::wstring value; + return ERROR_SUCCESS == + key.Open(root, test_key_name, Wow6432(KEY_QUERY_VALUE)) && + ERROR_SUCCESS == key.ReadValue(test_value_name, &value) && + value == L"CoolApp"; }, - key_hive, kTestRegKey, kTestRegValue))); + root, app_client_state_key.c_str(), kRegValueInstallerResultUIString))); - DeleteRegKey(key_hive, kTestRegKey); + // notepad.exe was run as a post-install command via the installer result API. + // The process will be present until test completes. + EXPECT_TRUE(test::IsProcessRunning(L"notepad.exe")); + + EXPECT_TRUE(DeleteRegKey(root, app_client_state_key)); } } // namespace updater::test
diff --git a/chrome/updater/update_service.h b/chrome/updater/update_service.h index 1866343..2d47d9f6 100644 --- a/chrome/updater/update_service.h +++ b/chrome/updater/update_service.h
@@ -166,6 +166,11 @@ ErrorCategory error_category = ErrorCategory::kNone; int error_code = 0; int extra_code1 = 0; + + // Results collected from installer result API. See the definition of + // `update_client::CrxInstaller::Result` for the meaning of the members. + std::string installer_text; + std::string installer_cmd_line; }; // Urgency of the update service invocation.
diff --git a/chrome/updater/update_service_impl.cc b/chrome/updater/update_service_impl.cc index bb91821..993d771 100644 --- a/chrome/updater/update_service_impl.cc +++ b/chrome/updater/update_service_impl.cc
@@ -145,6 +145,9 @@ update_state.error_code = crx_update_item.error_code; update_state.extra_code1 = crx_update_item.extra_code1; + // TODO(crbug.com/1352307): Investigate if it is desirable to read the + // result from the installer result API here when update completes. + // Commit the prefs values written by |update_client| when the // update has completed, such as `pv` and `fingerprint`. if (update_state.state == UpdateService::UpdateState::State::kUpdated) { @@ -558,19 +561,21 @@ base::BindOnce( [](StateChangeCallback state_update, const std::string& app_id, Callback callback, const InstallerResult& result) { + // Final state update after installation completes. UpdateState state; state.app_id = app_id; state.state = result.error == 0 ? UpdateState::State::kUpdated : UpdateState::State::kUpdateError; + state.error_code = result.error; + state.extra_code1 = result.extended_error; + state.installer_text = result.installer_text; + state.installer_cmd_line = result.installer_cmd_line; state_update.Run(state); - VLOG(1) << app_id << " installation completed: " << result.error; // TODO(crbug.com/1286574): Perform post-install actions, such as // send pings (if `enterprise` is not set in install_settings). - // TODO(crbug.com/1286574): Expand arguments in `Callback` to take - // more installation result details. std::move(callback).Run(result.error == 0 ? Result::kSuccess : Result::kInstallFailed); },
diff --git a/chrome/updater/win/app_install_controller.cc b/chrome/updater/win/app_install_controller.cc index 531f52f..92aa3e0 100644 --- a/chrome/updater/win/app_install_controller.cc +++ b/chrome/updater/win/app_install_controller.cc
@@ -809,9 +809,36 @@ base::StringPrintf("%s?product=%s&error=%d", HELP_CENTER_URL, base::EscapeUrlEncodedData(app_id_, false).c_str(), update_state.error_code); - // TODO(sorin): implement the installer API and provide the - // application info in the observer info. https://crbug.com/1014630 - observer_info.apps_info.push_back({}); + + AppCompletionInfo app_info; + if (update_state.state != UpdateService::UpdateState::State::kNoUpdate) { + app_info.app_id = base::ASCIIToUTF16(update_state.app_id); + app_info.completion_message = + base::ASCIIToUTF16(update_state.installer_text); + app_info.error_code = update_state.error_code; + app_info.extra_code1 = update_state.extra_code1; + app_info.post_install_launch_command_line = + base::SysUTF8ToWide(update_state.installer_cmd_line); + VLOG(1) << app_info.app_id << " installation completed: error_code[" + << app_info.error_code << "], extra_code1[" << app_info.extra_code1 + << "], completion_message[" << app_info.completion_message + << "], post_install_launch_command_line[" + << app_info.post_install_launch_command_line << "]"; + + // TODO(crbug.com/1352307): Figure out how to populate members like + // `completion_code` and `post_install_url`. For now, set the completion + // for the basic cases and ignore the post install URL. + if (app_info.error_code == 0) { + app_info.completion_code = + app_info.post_install_launch_command_line.empty() + ? CompletionCodes::COMPLETION_CODE_SUCCESS + : CompletionCodes::COMPLETION_CODE_LAUNCH_COMMAND; + } else { + app_info.completion_code = CompletionCodes::COMPLETION_CODE_ERROR; + } + } + observer_info.apps_info.push_back(app_info); + install_progress_observer_ipc_->OnComplete(observer_info); }
diff --git a/chrome/updater/win/ui/progress_wnd.cc b/chrome/updater/win/ui/progress_wnd.cc index 7e6d56f0b..27be415 100644 --- a/chrome/updater/win/ui/progress_wnd.cc +++ b/chrome/updater/win/ui/progress_wnd.cc
@@ -518,6 +518,9 @@ bool launch_commands_succeeded = LaunchCmdLines(observer_info); + // TODO(crbug.com/1353148): Figure out how to display app-specific + // installation result in addition to `observer_info.completion_text`. + CompletionCodes overall_completion_code = GetBundleOverallCompletionCode(observer_info); switch (overall_completion_code) {
diff --git a/chrome/updater/win/update_service_proxy.cc b/chrome/updater/win/update_service_proxy.cc index ca2a2658..00a89b4 100644 --- a/chrome/updater/win/update_service_proxy.cc +++ b/chrome/updater/win/update_service_proxy.cc
@@ -204,6 +204,23 @@ if (SUCCEEDED(hr)) update_service_state.extra_code1 = extra_code1; } + { + base::win::ScopedBstr installer_text; + HRESULT hr = update_state->get_installerText(installer_text.Receive()); + if (SUCCEEDED(hr)) { + update_service_state.installer_text = + base::WideToUTF8(installer_text.Get()); + } + } + { + base::win::ScopedBstr installer_cmd_line; + HRESULT hr = + update_state->get_installerCommandLine(installer_cmd_line.Receive()); + if (SUCCEEDED(hr)) { + update_service_state.installer_cmd_line = + base::WideToUTF8(installer_cmd_line.Get()); + } + } VLOG(4) << update_service_state; return update_service_state;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index ce53d1d..7c851806 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -76,8 +76,8 @@ ] if (is_chromeos_ash) { deps += [ + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/network:test_support", - "//chromeos/dbus:test_support", "//chromeos/login/login_state:test_support", "//google_apis", "//net:test_support", @@ -115,11 +115,11 @@ deps += [ ":test_support", "//chromeos/ash/components:unit_tests", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/network:test_support", "//chromeos/ash/services:unit_tests", "//chromeos/crosapi/cpp:unit_tests", "//chromeos/crosapi/mojom:unit_tests", - "//chromeos/dbus:test_support", "//chromeos/dbus:unit_tests", "//chromeos/language/language_packs:unit_tests", "//chromeos/login/login_state:unit_tests",
diff --git a/chromeos/ash/components/assistant/OWNERS b/chromeos/ash/components/assistant/OWNERS index e69808e..2a43895 100644 --- a/chromeos/ash/components/assistant/OWNERS +++ b/chromeos/ash/components/assistant/OWNERS
@@ -1,3 +1,4 @@ updowndota@chromium.org wutao@chromium.org xiaohuic@chromium.org +yawano@google.com
diff --git a/chromeos/ash/components/attestation/BUILD.gn b/chromeos/ash/components/attestation/BUILD.gn index 7097827e..9853acc 100644 --- a/chromeos/ash/components/attestation/BUILD.gn +++ b/chromeos/ash/components/attestation/BUILD.gn
@@ -63,9 +63,9 @@ ":test_support", "//ash/components/cryptohome", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/attestation", "//chromeos/ash/components/dbus/attestation:attestation_proto", - "//chromeos/dbus:test_support", "//components/account_id", "//testing/gmock", "//testing/gtest",
diff --git a/chromeos/ash/components/dbus/BUILD.gn b/chromeos/ash/components/dbus/BUILD.gn index 6ad48ea..4b44420 100644 --- a/chromeos/ash/components/dbus/BUILD.gn +++ b/chromeos/ash/components/dbus/BUILD.gn
@@ -8,10 +8,27 @@ assert(is_chromeos_ash, "Non ChromeOS builds must not depend on //chromeos/ash") +source_set("test_support") { + testonly = true + configs += [ "//build/config/linux/dbus" ] + public_deps = [ + "//chromeos/dbus", + "//chromeos/dbus/constants", + "//dbus", + "//dbus:test_support", + ] + deps = [ + "//base", + "//testing/gmock", + "//testing/gtest", + ] +} + source_set("unit_tests") { configs += [ "//build/config/linux/dbus" ] testonly = true deps = [ + ":test_support", "//base", "//base/test:test_support", "//chromeos/ash/components/dbus/audio", @@ -40,7 +57,6 @@ "//chromeos/ash/components/dbus/userdataauth", "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", "//chromeos/ash/components/install_attributes:test_support", - "//chromeos/dbus:test_support", "//components/account_id", "//dbus", ]
diff --git a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc index 211c570..4b6259ec 100644 --- a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc +++ b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.cc
@@ -35,7 +35,7 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/cros_system_api/dbus/service_constants.h" -namespace chromeos { +namespace ash { namespace { constexpr char kReadOnlyOption[] = "ro"; @@ -630,9 +630,6 @@ }; } // namespace -} // namespace chromeos - -namespace ash { std::ostream& operator<<(std::ostream& out, const MountType type) { switch (type) { @@ -698,10 +695,6 @@ return out << std::underlying_type_t<MountError>(error); } -} // namespace ash - -namespace chromeos { - std::ostream& operator<<(std::ostream& out, const MountEntry& entry) { return out << "error_code = " << entry.error_code << ", source_path = '" << entry.source_path << "', mount_type = " << entry.mount_type @@ -917,7 +910,7 @@ void CrosDisksClient::Initialize(dbus::Bus* bus) { // See ArcDataSnapshotdManager for code that sets this flag. if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kCrosDisksFake)) { + chromeos::switches::kCrosDisksFake)) { InitializeFake(); return; } @@ -989,4 +982,4 @@ return mount_options; } -} // namespace chromeos +} // namespace ash
diff --git a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h index aafde276..62b791c 100644 --- a/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h +++ b/chromeos/ash/components/dbus/cros_disks/cros_disks_client.h
@@ -165,20 +165,6 @@ // MountError::kPathNotMounted error code. kRemountExistingDevice, }; -} // namespace ash - -namespace chromeos { - -// TODO(https://crbug.com/1164001): remove when the migration is finished. -using ::ash::DeviceType; -using ::ash::FormatError; -using ::ash::MountAccessMode; -using ::ash::MountError; -using ::ash::MountEventType; -using ::ash::MountType; -using ::ash::PartitionError; -using ::ash::RemountOption; -using ::ash::RenameError; // A class to represent information about a disk sent from cros-disks. class COMPONENT_EXPORT(ASH_DBUS_CROS_DISKS) DiskInfo { @@ -450,13 +436,6 @@ ~CrosDisksClient() override; }; -} // namespace chromeos - -// TODO(https://crbug.com/1164001): remove when //chromeos/dbus moved to ash. -namespace ash { -using ::chromeos::CrosDisksClient; -using ::chromeos::DiskInfo; -using ::chromeos::MountEntry; } // namespace ash #endif // CHROMEOS_ASH_COMPONENTS_DBUS_CROS_DISKS_CROS_DISKS_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/cros_disks/cros_disks_client_unittest.cc b/chromeos/ash/components/dbus/cros_disks/cros_disks_client_unittest.cc index 3fe6c18..9bc5ae9 100644 --- a/chromeos/ash/components/dbus/cros_disks/cros_disks_client_unittest.cc +++ b/chromeos/ash/components/dbus/cros_disks/cros_disks_client_unittest.cc
@@ -12,7 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" -namespace chromeos { +namespace ash { namespace { @@ -199,4 +199,4 @@ EXPECT_EQ(kExpectedMountLabelOption, custom_mount_options[3]); } -} // namespace chromeos +} // namespace ash
diff --git a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc index d744809..21ed3df 100644 --- a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc +++ b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.cc
@@ -15,7 +15,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "url/gurl.h" -namespace chromeos { +namespace ash { namespace { @@ -260,4 +260,4 @@ custom_mount_point_callbacks_.emplace_back(custom_mount_point_callback); } -} // namespace chromeos +} // namespace ash
diff --git a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h index 32420c0..a92cea0d4 100644 --- a/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h +++ b/chromeos/ash/components/dbus/cros_disks/fake_cros_disks_client.h
@@ -15,7 +15,7 @@ #include "base/observer_list.h" #include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h" -namespace chromeos { +namespace ash { // A fake implementation of CrosDiskeClient. This class provides a fake behavior // and the user of this class can raise a fake mouse events. @@ -200,11 +200,6 @@ base::WeakPtrFactory<FakeCrosDisksClient> weak_ptr_factory_{this}; }; -} // namespace chromeos - -// TODO(https://crbug.com/1164001): remove when //chromeos/dbus moved to ash. -namespace ash { -using ::chromeos::FakeCrosDisksClient; } // namespace ash #endif // CHROMEOS_ASH_COMPONENTS_DBUS_CROS_DISKS_FAKE_CROS_DISKS_CLIENT_H_
diff --git a/chromeos/ash/components/local_search_service/linear_map_search.cc b/chromeos/ash/components/local_search_service/linear_map_search.cc index bb409ee..6d84b4b 100644 --- a/chromeos/ash/components/local_search_service/linear_map_search.cc +++ b/chromeos/ash/components/local_search_service/linear_map_search.cc
@@ -53,8 +53,7 @@ FuzzyTokenizedStringMatch match; const double relevance = match.Relevance(query, *(tag.second), true /* use_weighted_ratio */, - false /* use_edit_distance */, - 0.9 /* partial_match_penalty_rate */, 0.1); + false /* use_edit_distance */, 0.1); if (relevance >= relevance_threshold) { *relevance_score = relevance; Position position;
diff --git a/chromeos/ash/components/network/BUILD.gn b/chromeos/ash/components/network/BUILD.gn index 970e315..ffc6b17 100644 --- a/chromeos/ash/components/network/BUILD.gn +++ b/chromeos/ash/components/network/BUILD.gn
@@ -244,6 +244,7 @@ "//base", "//base:i18n", "//base/test:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/shill", "//chromeos/ash/components/feature_usage", "//chromeos/ash/components/network/metrics:unit_tests", @@ -251,7 +252,6 @@ "//chromeos/ash/components/network/proxy:unit_tests", "//chromeos/components/onc", "//chromeos/components/onc:test_support", - "//chromeos/dbus:test_support", "//chromeos/dbus/permission_broker", "//chromeos/login/login_state", "//chromeos/services/hotspot_config/public/mojom",
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/BUILD.gn b/chromeos/ash/components/oobe_quick_start/connectivity/BUILD.gn index c3330d4..ba80505b 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/BUILD.gn +++ b/chromeos/ash/components/oobe_quick_start/connectivity/BUILD.gn
@@ -17,6 +17,8 @@ sources = [ "fast_pair_advertiser.cc", "fast_pair_advertiser.h", + "random_session_id.cc", + "random_session_id.h", "target_device_connection_broker.cc", "target_device_connection_broker.h", "target_device_connection_broker_factory.cc",
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.cc b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.cc index f957c4f..a0a7360 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.cc +++ b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.cc
@@ -9,7 +9,7 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" -#include "base/unguessable_token.h" +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" namespace ash::quick_start { @@ -112,7 +112,7 @@ void FastPairAdvertiser::StartAdvertising( base::OnceCallback<void()> callback, base::OnceCallback<void()> error_callback, - const base::UnguessableToken& random_session_id) { + const RandomSessionId& random_session_id) { DCHECK(adapter_->IsPresent() && adapter_->IsPowered()); DCHECK(!advertisement_); RegisterAdvertisement(std::move(callback), std::move(error_callback), @@ -132,7 +132,7 @@ void FastPairAdvertiser::RegisterAdvertisement( base::OnceClosure callback, base::OnceClosure error_callback, - const base::UnguessableToken& random_session_id) { + const RandomSessionId& random_session_id) { auto advertisement_data = std::make_unique<device::BluetoothAdvertisement::Data>( device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST); @@ -213,8 +213,9 @@ } std::vector<uint8_t> FastPairAdvertiser::GenerateManufacturerMetadata( - const base::UnguessableToken& random_session_id) { - base::span<const uint8_t, 16> id = random_session_id.AsBytes(); + const RandomSessionId& random_session_id) { + base::span<const uint8_t, RandomSessionId::kLength> id = + random_session_id.AsBytes(); std::vector<uint8_t> metadata(std::begin(id), std::end(id)); return metadata; }
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h index 5d00006..e05a9177 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h +++ b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h
@@ -10,12 +10,13 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" -#include "base/unguessable_token.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_advertisement.h" namespace ash::quick_start { +class RandomSessionId; + // FastPairAdvertiser broadcasts advertisements with the service UUID // 0xFE2C and model ID 0x41C0D9. When the remote device detects this // advertisement it will trigger a prompt to begin Quick Start. @@ -47,10 +48,9 @@ FastPairAdvertiser& operator=(const FastPairAdvertiser&) = delete; // Begin broadcasting Fast Pair advertisement. - virtual void StartAdvertising( - base::OnceClosure callback, - base::OnceClosure error_callback, - const base::UnguessableToken& random_session_id); + virtual void StartAdvertising(base::OnceClosure callback, + base::OnceClosure error_callback, + const RandomSessionId& random_session_id); // Stop broadcasting Fast Pair advertisement. virtual void StopAdvertising(base::OnceClosure callback); @@ -64,7 +64,7 @@ void RegisterAdvertisement(base::OnceClosure callback, base::OnceClosure error_callback, - const base::UnguessableToken& random_session_id); + const RandomSessionId& random_session_id); void OnRegisterAdvertisement( base::OnceClosure callback, scoped_refptr<device::BluetoothAdvertisement> advertisement); @@ -78,7 +78,7 @@ // Returns metadata in format [ random_session_id (16 bytes) ]. std::vector<uint8_t> GenerateManufacturerMetadata( - const base::UnguessableToken& random_session_id); + const RandomSessionId& random_session_id); scoped_refptr<device::BluetoothAdapter> adapter_; scoped_refptr<device::BluetoothAdvertisement> advertisement_; @@ -88,4 +88,4 @@ } // namespace ash::quick_start -#endif // CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_FAST_PAIR_ADVERTISER_H_ \ No newline at end of file +#endif // CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_FAST_PAIR_ADVERTISER_H_
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc index d2639b7..c8f1138 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc +++ b/chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc
@@ -14,7 +14,7 @@ #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" -#include "base/unguessable_token.h" +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/bluetooth/test/mock_bluetooth_advertisement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -171,7 +171,7 @@ base::Unretained(this)), base::BindOnce(&FastPairAdvertiserTest::OnStartAdvertisingError, base::Unretained(this)), - base::UnguessableToken::Create()); + RandomSessionId()); auto service_uuid_list = std::make_unique<device::BluetoothAdvertisement::UUIDList>(); service_uuid_list->push_back(kFastPairServiceUuid); @@ -201,7 +201,7 @@ bool called_on_stop_advertising() { return called_on_stop_advertising_; } std::vector<uint8_t> GetManufacturerMetadata( - const base::UnguessableToken& random_id) { + const RandomSessionId& random_id) { return fast_pair_advertiser_->GenerateManufacturerMetadata(random_id); } @@ -245,7 +245,7 @@ fast_pair_advertiser_->StartAdvertising( base::DoNothing(), base::BindLambdaForTesting([&]() { fast_pair_advertiser_.reset(); }), - base::UnguessableToken::Create()); + RandomSessionId()); std::move(register_args_->error_callback) .Run(device::BluetoothAdvertisement::ErrorCode:: @@ -301,15 +301,16 @@ } TEST_F(FastPairAdvertiserTest, TestGenerateManufacturerMetadata) { - auto random_id = base::UnguessableToken::Create(); - base::span<const uint8_t, 16> random_id_bytes = random_id.AsBytes(); + RandomSessionId random_id; + base::span<const uint8_t, RandomSessionId::kLength> random_id_bytes = + random_id.AsBytes(); std::vector<uint8_t> manufacturer_metadata = GetManufacturerMetadata(random_id); EXPECT_EQ(random_id_bytes.size(), manufacturer_metadata.size()); - for (int i = 0; i < 16; i++) { + for (size_t i = 0; i < random_id_bytes.size(); i++) { EXPECT_EQ(random_id_bytes[i], manufacturer_metadata[i]); } } -} // namespace ash::quick_start \ No newline at end of file +} // namespace ash::quick_start
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.cc b/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.cc new file mode 100644 index 0000000..7c20277 --- /dev/null +++ b/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.cc
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" + +#include <algorithm> + +#include "base/strings/string_number_conversions.h" +#include "crypto/random.h" + +namespace ash::quick_start { + +RandomSessionId::RandomSessionId() { + crypto::RandBytes(bytes_); +} + +std::string RandomSessionId::ToString() const { + return base::HexEncode(bytes_); +} + +std::ostream& operator<<(std::ostream& stream, + const RandomSessionId& random_session_id) { + return stream << random_session_id.ToString(); +} + +} // namespace ash::quick_start
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h b/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h new file mode 100644 index 0000000..fc3e3de --- /dev/null +++ b/chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_RANDOM_SESSION_ID_H_ +#define CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_RANDOM_SESSION_ID_H_ + +#include <array> +#include <ostream> + +#include "base/containers/span.h" + +namespace ash::quick_start { + +// An immutable, copyable type representing ten random bytes. +class RandomSessionId { + public: + // This length is chosen to be 10 bytes in order to match the format used by + // SmartSetup on Android for interoperability. + static constexpr size_t kLength = 10; + + RandomSessionId(); + RandomSessionId(RandomSessionId&) = default; + RandomSessionId& operator=(RandomSessionId&) = default; + ~RandomSessionId() = default; + + base::span<const uint8_t, kLength> AsBytes() const { return bytes_; }; + + // Convert to hexadecimal. + std::string ToString() const; + + private: + std::array<uint8_t, kLength> bytes_; +}; + +// Write the RandomSessionId to the ostream in hexadecimal for logging. +std::ostream& operator<<(std::ostream& stream, + const RandomSessionId& random_session_id); + +} // namespace ash::quick_start + +#endif // CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_RANDOM_SESSION_ID_H_
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc index 888b0a9..980696c 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc +++ b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc
@@ -5,17 +5,59 @@ #include "chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.h" #include <memory> +#include <vector> #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h" +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" namespace ash::quick_start { +namespace { + +// Endpoint Info version number, currently version 1. +constexpr uint8_t kEndpointInfoVersion = 1; + +// Smart Setup verification style, e.g. shapes, pin, etc. +// 0 = "Default", since there isn't yet a QR code option. +// Values come from this enum: +// http://google3/logs/proto/wireless/android/smartsetup/smart_setup_extension.proto;l=876;rcl=458110957 +constexpr uint8_t kEndpointInfoVerificationStyle = 0; + +// Device Type for Smart Setup, e.g. phone, tablet. +// 0 = "Unknown", since there isn't yet a Chromebook option. +// Values come from this enum: +// http://google3/logs/proto/wireless/android/smartsetup/smart_setup_extension.proto;l=961;rcl=458110957 +constexpr uint8_t kEndpointInfoDeviceType = 0; + +// Boolean field indicating to Smart Setup whether the client is Quick Start. +constexpr uint8_t kEndpointInfoIsQuickStart = 1; + +constexpr char kEndpointInfoDefaultDisplayName[] = "Chromebook"; + +// The display name must: +// - Be a variable-length string of utf-8 bytes +// - Be at most 18 bytes +// - If less than 18 bytes, must be null-terminated +std::vector<uint8_t> GetEndpointInfoDisplayNameBytes( + RandomSessionId session_id) { + // TODO(b/234655072): Append session id to display name, vary name based on + // device type, e.g. Chromebook, Chromebox, Chromebase, Chromebit, etc. + std::string display_name = kEndpointInfoDefaultDisplayName; + std::vector<uint8_t> display_name_bytes(display_name.begin(), + display_name.end()); + display_name_bytes.push_back(0); + + return display_name_bytes; +} + +} // namespace + void TargetDeviceConnectionBrokerImpl::BluetoothAdapterFactoryWrapper:: GetAdapter(device::BluetoothAdapterFactory::AdapterCallback callback) { if (bluetooth_adapter_factory_wrapper_for_testing_) { @@ -107,9 +149,7 @@ return; } - if (!random_session_id_) { - random_session_id_ = base::UnguessableToken::Create(); - } + VLOG(1) << "Starting advertising with session id " << random_session_id_; fast_pair_advertiser_ = FastPairAdvertiser::Factory::Create(bluetooth_adapter_); @@ -153,4 +193,33 @@ std::move(callback).Run(); } +// The EndpointInfo consists of the following fields: +// - EndpointInfo version number, 1 byte +// - Display name, max 18 bytes (see GetEndpointInfoDisplayNameBytes()) +// - Advertisement data, 13 bytes: +// - Verification Style, byte[0] +// - Device Type, byte[1] +// - Advertising Id, byte[2-11], 10 bytes. (See RandomSessionId) +// - isQuickStart, byte[12], =1 for Quick Start. +std::vector<uint8_t> TargetDeviceConnectionBrokerImpl::GenerateEndpointInfo() { + base::span<const uint8_t, RandomSessionId::kLength> session_id_bytes = + random_session_id_.AsBytes(); + std::vector<uint8_t> display_name_bytes = + GetEndpointInfoDisplayNameBytes(random_session_id_); + + std::vector<uint8_t> endpoint_info; + endpoint_info.reserve(32); + + endpoint_info.push_back(kEndpointInfoVersion); + endpoint_info.insert(endpoint_info.end(), display_name_bytes.begin(), + display_name_bytes.end()); + endpoint_info.push_back(kEndpointInfoVerificationStyle); + endpoint_info.push_back(kEndpointInfoDeviceType); + endpoint_info.insert(endpoint_info.end(), session_id_bytes.begin(), + session_id_bytes.end()); + endpoint_info.push_back(kEndpointInfoIsQuickStart); + + return endpoint_info; +} + } // namespace ash::quick_start
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.h b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.h index cc0aa83..bf869182 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.h +++ b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl.h
@@ -6,7 +6,7 @@ #define CHROMEOS_ASH_COMPONENTS_OOBE_QUICK_START_CONNECTIVITY_TARGET_DEVICE_CONNECTION_BROKER_IMPL_H_ #include "base/memory/weak_ptr.h" -#include "base/unguessable_token.h" +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" #include "chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -53,16 +53,22 @@ void StopAdvertising(base::OnceClosure on_stop_advertising_callback) override; private: + friend class TargetDeviceConnectionBrokerImplTest; + void GetBluetoothAdapter(); void OnGetBluetoothAdapter(scoped_refptr<device::BluetoothAdapter> adapter); void OnStartFastPairAdvertisingError(ResultCallback callback); void OnStopFastPairAdvertising(base::OnceClosure callback); + // The EndpointInfo is the set of bytes that SmartSetup on Android expects to + // be in the Nearby Connections advertisement. + std::vector<uint8_t> GenerateEndpointInfo(); + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; base::OnceClosure deferred_start_advertising_callback_; std::unique_ptr<FastPairAdvertiser> fast_pair_advertiser_; - base::UnguessableToken random_session_id_; + RandomSessionId random_session_id_; base::WeakPtrFactory<TargetDeviceConnectionBrokerImpl> weak_ptr_factory_{ this};
diff --git a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc index 474f6c37..b1b3116 100644 --- a/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc +++ b/chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc
@@ -7,21 +7,20 @@ #include "base/bind.h" #include "base/test/task_environment.h" #include "chromeos/ash/components/oobe_quick_start/connectivity/fast_pair_advertiser.h" +#include "chromeos/ash/components/oobe_quick_start/connectivity/random_session_id.h" #include "chromeos/ash/components/oobe_quick_start/connectivity/target_device_connection_broker_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +namespace ash::quick_start { + namespace { -using testing::NiceMock; +constexpr size_t kMaxEndpointInfoDisplayNameLength = 18; -using TargetDeviceConnectionBroker = - ash::quick_start::TargetDeviceConnectionBroker; -using TargetDeviceConnectionBrokerImpl = - ash::quick_start::TargetDeviceConnectionBrokerImpl; -using FastPairAdvertiser = ash::quick_start::FastPairAdvertiser; +using testing::NiceMock; // Allows us to delay returning a Bluetooth adapter until after ReturnAdapter() // is called. Used for testing how the connection broker behaves before the @@ -63,10 +62,9 @@ std::move(on_destroy_callback_).Run(); } - void StartAdvertising( - base::OnceCallback<void()> callback, - base::OnceCallback<void()> error_callback, - const base::UnguessableToken& random_session_id) override { + void StartAdvertising(base::OnceCallback<void()> callback, + base::OnceCallback<void()> error_callback, + const RandomSessionId& random_session_id) override { ++start_advertising_call_count_; if (should_succeed_on_start_) std::move(callback).Run(); @@ -201,6 +199,18 @@ void StopAdvertisingCallback() { stop_advertising_callback_called_ = true; } + std::vector<uint8_t> GenerateEndpointInfo() { + return static_cast<TargetDeviceConnectionBrokerImpl*>( + connection_broker_.get()) + ->GenerateEndpointInfo(); + } + + const RandomSessionId& GetRandomSessionId() { + return static_cast<TargetDeviceConnectionBrokerImpl*>( + connection_broker_.get()) + ->random_session_id_; + } + protected: bool is_bluetooth_powered_ = true; bool is_bluetooth_present_ = true; @@ -368,3 +378,68 @@ EXPECT_TRUE(fast_pair_advertiser_factory_->AdvertiserDestroyed()); EXPECT_TRUE(stop_advertising_callback_called_); } + +TEST_F(TargetDeviceConnectionBrokerImplTest, GenerateEndpointInfo) { + std::vector<uint8_t> endpoint_info = GenerateEndpointInfo(); + + // Points to the field being parsed. + size_t i = 0; + + ASSERT_GT(endpoint_info.size(), i); + uint8_t version = endpoint_info[i]; + EXPECT_EQ(1u, version); + i++; + + // Parse the display name. The field is variable-length, so we have to look + // out for either a null byte or for the display name to reach the maximum + // length. + ASSERT_GT(endpoint_info.size(), i); + size_t j = 0; + std::vector<uint8_t> display_name_bytes; + while (i + j < endpoint_info.size() && endpoint_info[i + j] != 0u && + j < kMaxEndpointInfoDisplayNameLength) { + display_name_bytes.push_back(endpoint_info[i + j]); + j++; + } + // Assert that we didn't break out of the while loop because we ran out of + // bytes. + ASSERT_LT(i + j, endpoint_info.size()); + if (j < kMaxEndpointInfoDisplayNameLength) { + // Move past the null-terminator if the display name length is less than the + // max. + ASSERT_EQ(0u, endpoint_info[i + j]); + j++; + } + std::string display_name = + std::string(display_name_bytes.begin(), display_name_bytes.end()); + EXPECT_EQ("Chromebook", display_name); + i += j; + + ASSERT_GT(endpoint_info.size(), i); + uint8_t verification_style = endpoint_info[i]; + EXPECT_EQ(0u, verification_style); + i++; + + ASSERT_GT(endpoint_info.size(), i); + uint8_t device_type = endpoint_info[i]; + EXPECT_EQ(0u, device_type); + i++; + + // Parse the fixed-length RandomSessionId. + ASSERT_GE(endpoint_info.size(), i + RandomSessionId::kLength); + base::span<const uint8_t, RandomSessionId::kLength> session_id_bytes = + GetRandomSessionId().AsBytes(); + for (size_t k = i; k < i + RandomSessionId::kLength; k++) { + EXPECT_EQ(session_id_bytes[k - i], endpoint_info[k]); + } + i += RandomSessionId::kLength; + + ASSERT_GT(endpoint_info.size(), i); + uint8_t is_quick_start = endpoint_info[i]; + EXPECT_EQ(1u, is_quick_start); + + // There should be no more endpoint info after the isQuickStart field. + EXPECT_EQ(endpoint_info.size(), i + 1); +} + +} // namespace ash::quick_start
diff --git a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc index 5dbb3af..e331cf7 100644 --- a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc +++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc
@@ -23,6 +23,8 @@ namespace { +constexpr double kPartialMatchPenaltyRate = 0.9; + constexpr double kMinScore = 0.0; constexpr double kMaxScore = 1.0; @@ -45,7 +47,6 @@ const TokenizedString& query, const TokenizedString& text, bool partial, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty) { std::set<std::u16string> query_token(query.tokens().begin(), @@ -82,15 +83,13 @@ base::JoinString(text_diff_query, u" ")}); if (partial) { - return std::max({PartialRatio(intersection_string, query_rewritten, - partial_match_penalty_rate, use_edit_distance, - num_matching_blocks_penalty), - PartialRatio(intersection_string, text_rewritten, - partial_match_penalty_rate, use_edit_distance, - num_matching_blocks_penalty), - PartialRatio(query_rewritten, text_rewritten, - partial_match_penalty_rate, use_edit_distance, - num_matching_blocks_penalty)}); + return std::max( + {PartialRatio(intersection_string, query_rewritten, use_edit_distance, + num_matching_blocks_penalty), + PartialRatio(intersection_string, text_rewritten, use_edit_distance, + num_matching_blocks_penalty), + PartialRatio(query_rewritten, text_rewritten, use_edit_distance, + num_matching_blocks_penalty)}); } return std::max( @@ -109,7 +108,6 @@ const TokenizedString& query, const TokenizedString& text, bool partial, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty) { const std::u16string query_sorted = @@ -118,8 +116,8 @@ base::JoinString(ProcessAndSort(text), u" "); if (partial) { - return PartialRatio(query_sorted, text_sorted, partial_match_penalty_rate, - use_edit_distance, num_matching_blocks_penalty); + return PartialRatio(query_sorted, text_sorted, use_edit_distance, + num_matching_blocks_penalty); } return SequenceMatcher(query_sorted, text_sorted, use_edit_distance, num_matching_blocks_penalty) @@ -129,7 +127,6 @@ double FuzzyTokenizedStringMatch::PartialRatio( const std::u16string& query, const std::u16string& text, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty) { if (query.empty() || text.empty()) { @@ -162,7 +159,7 @@ current--; } const double penalty = - std::pow(partial_match_penalty_rate, long_start - current - 1); + std::pow(kPartialMatchPenaltyRate, long_start - current - 1); // TODO(crbug/990684): currently this part re-calculate the ratio for every // pair. Improve this to reduce latency. partial_ratio = std::max( @@ -182,7 +179,6 @@ double FuzzyTokenizedStringMatch::WeightedRatio( const TokenizedString& query, const TokenizedString& text, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty) { // All token based comparisons are scaled by 0.95 (on top of any partial @@ -223,24 +219,23 @@ weighted_ratio = std::max(weighted_ratio, PartialRatio(query_normalized, text_normalized, - partial_match_penalty_rate, use_edit_distance, - num_matching_blocks_penalty) * + use_edit_distance, num_matching_blocks_penalty) * partial_scale); } - weighted_ratio = std::max( - weighted_ratio, - TokenSortRatio(query, text, use_partial, partial_match_penalty_rate, - use_edit_distance, num_matching_blocks_penalty) * - unbase_scale * partial_scale); + weighted_ratio = + std::max(weighted_ratio, + TokenSortRatio(query, text, use_partial, use_edit_distance, + num_matching_blocks_penalty) * + unbase_scale * partial_scale); // Do not use partial match for token set because the match between the // intersection string and query/text rewrites will always return an extremely // high value. - weighted_ratio = std::max( - weighted_ratio, - TokenSetRatio(query, text, false /*partial*/, partial_match_penalty_rate, - use_edit_distance, num_matching_blocks_penalty) * - unbase_scale * partial_scale); + weighted_ratio = + std::max(weighted_ratio, + TokenSetRatio(query, text, false /*partial*/, use_edit_distance, + num_matching_blocks_penalty) * + unbase_scale * partial_scale); return weighted_ratio; } @@ -256,7 +251,6 @@ const TokenizedString& text, bool use_weighted_ratio, bool use_edit_distance, - double partial_match_penalty_rate, double num_matching_blocks_penalty) { // If there is an exact match, relevance will be 1.0 and there is only 1 hit // that is the entire text/query. @@ -292,11 +286,10 @@ if (use_weighted_ratio) { // If WeightedRatio is used, |relevance_| is the average of WeightedRatio // and PrefixMatcher scores. - relevance_ = - (WeightedRatio(query, text, partial_match_penalty_rate, - use_edit_distance, num_matching_blocks_penalty) + - prefix_score) / - 2; + relevance_ = (WeightedRatio(query, text, use_edit_distance, + num_matching_blocks_penalty) + + prefix_score) / + 2; } else { // Use simple algorithm to calculate match ratio. relevance_ =
diff --git a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h index 298cfaa..345cb09 100644 --- a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h +++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h
@@ -50,7 +50,6 @@ static double TokenSetRatio(const TokenizedString& query, const TokenizedString& text, bool partial, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty); @@ -61,7 +60,6 @@ static double TokenSortRatio(const TokenizedString& query, const TokenizedString& text, bool partial, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty); @@ -70,7 +68,6 @@ // to lower case). The return score is in range of [0, 1]. static double PartialRatio(const std::u16string& query, const std::u16string& text, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty); @@ -79,7 +76,6 @@ // The return score is in range of [0, 1]. static double WeightedRatio(const TokenizedString& query, const TokenizedString& text, - double partial_match_penalty_rate, bool use_edit_distance, double num_matching_blocks_penalty); // TODO(crbug.com/1336160): Should prefix match always be favored over other @@ -98,7 +94,6 @@ const TokenizedString& text, bool use_weighted_ratio, bool use_edit_distance, - double partial_match_penalty_rate, double num_matching_blocks_penalty = 0.0); const Hits& hits() const { return hits_; }
diff --git a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc index 6aa8475..60d4ef2 100644 --- a/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc +++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
@@ -27,7 +27,6 @@ // Default parameters. constexpr bool kUseWeightedRatio = false; constexpr bool kUseEditDistance = false; -constexpr double kPartialMatchPenaltyRate = 0.9; void ExpectAllNearlyEqualTo(const std::vector<double>& scores, double target_score, @@ -85,8 +84,7 @@ const std::u16string& text) { FuzzyTokenizedStringMatch match; return match.Relevance(TokenizedString(query), TokenizedString(text), - kUseWeightedRatio, kUseEditDistance, - kPartialMatchPenaltyRate); + kUseWeightedRatio, kUseEditDistance); } // Return a string formatted for displaying query-text relevance score details. @@ -858,9 +856,9 @@ FuzzyTokenizedStringMatch match; std::u16string text = u"xyzabc abcdef"; std::u16string query = u"abc"; - const double relevance = match.Relevance( - TokenizedString(query), TokenizedString(text), kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate); + const double relevance = + match.Relevance(TokenizedString(query), TokenizedString(text), + kUseWeightedRatio, kUseEditDistance); VLOG(1) << FormatRelevanceResult(query, text, relevance, /*query_first*/ false); @@ -904,9 +902,9 @@ std::u16string text = u"abcde abfgh abijk"; std::u16string query = u"ab"; - const double relevance = match.Relevance( - TokenizedString(query), TokenizedString(text), kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate); + const double relevance = + match.Relevance(TokenizedString(query), TokenizedString(text), + kUseWeightedRatio, kUseEditDistance); VLOG(1) << FormatRelevanceResult(query, text, relevance, /*query_first*/ false); @@ -923,9 +921,9 @@ std::u16string text = u"abxyz abcwv abcdt"; std::u16string query = u"abcde"; - const double relevance = match.Relevance( - TokenizedString(query), TokenizedString(text), kUseWeightedRatio, - kUseEditDistance, kPartialMatchPenaltyRate); + const double relevance = + match.Relevance(TokenizedString(query), TokenizedString(text), + kUseWeightedRatio, kUseEditDistance); VLOG(1) << FormatRelevanceResult(query, text, relevance, /*query_first*/ false); @@ -1236,17 +1234,14 @@ // TODO(crbug.com/1336160): update the tests once params are consolidated. TEST_F(FuzzyTokenizedStringMatchTest, PartialRatioTest) { FuzzyTokenizedStringMatch match; - EXPECT_NEAR(match.PartialRatio(u"abcde", u"ababcXXXbcdeY", - kPartialMatchPenaltyRate, false, 0.0), - 0.6, 0.01); - EXPECT_NEAR(match.PartialRatio(u"big string", u"strength", - kPartialMatchPenaltyRate, false, 0.0), - 0.71, 0.01); - EXPECT_EQ( - match.PartialRatio(u"abc", u"", kPartialMatchPenaltyRate, false, 0.0), 0); - EXPECT_NEAR(match.PartialRatio(u"different in order", u"order text", - kPartialMatchPenaltyRate, false, 0.0), - 0.67, 0.01); + EXPECT_NEAR(match.PartialRatio(u"abcde", u"ababcXXXbcdeY", false, 0.0), 0.6, + 0.01); + EXPECT_NEAR(match.PartialRatio(u"big string", u"strength", false, 0.0), 0.71, + 0.01); + EXPECT_EQ(match.PartialRatio(u"abc", u"", false, 0.0), 0); + EXPECT_NEAR( + match.PartialRatio(u"different in order", u"order text", false, 0.0), + 0.67, 0.01); } TEST_F(FuzzyTokenizedStringMatchTest, TokenSetRatioTest) { @@ -1255,46 +1250,41 @@ std::u16string query(u"order different in"); std::u16string text(u"text order"); EXPECT_EQ(match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), + true, false, 0.0), 1); - EXPECT_NEAR( - match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.67, 0.01); + EXPECT_NEAR(match.TokenSetRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.67, 0.01); } { std::u16string query(u"short text"); std::u16string text(u"this text is really really really long"); EXPECT_EQ(match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), + true, false, 0.0), 1); - EXPECT_NEAR( - match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.57, 0.01); + EXPECT_NEAR(match.TokenSetRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.57, 0.01); } { std::u16string query(u"common string"); std::u16string text(u"nothing is shared"); - EXPECT_NEAR( - match.TokenSetRatio(TokenizedString(query), TokenizedString(text), true, - kPartialMatchPenaltyRate, false, 0.0), - 0.38, 0.01); - EXPECT_NEAR( - match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.33, 0.01); + EXPECT_NEAR(match.TokenSetRatio(TokenizedString(query), + TokenizedString(text), true, false, 0.0), + 0.38, 0.01); + EXPECT_NEAR(match.TokenSetRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.33, 0.01); } { std::u16string query(u"token shared token same shared same"); std::u16string text(u"token shared token text text long"); EXPECT_EQ(match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), + true, false, 0.0), 1); - EXPECT_NEAR( - match.TokenSetRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.83, 0.01); + EXPECT_NEAR(match.TokenSetRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.83, 0.01); } } @@ -1303,38 +1293,32 @@ { std::u16string query(u"order different in"); std::u16string text(u"text order"); - EXPECT_NEAR( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), - 0.67, 0.01); - EXPECT_NEAR( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.36, 0.01); + EXPECT_NEAR(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), true, false, 0.0), + 0.67, 0.01); + EXPECT_NEAR(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.36, 0.01); } { std::u16string query(u"short text"); std::u16string text(u"this text is really really really long"); - EXPECT_EQ( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), - 0.5 * std::pow(0.9, 1)); - EXPECT_NEAR( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.33, 0.01); + EXPECT_EQ(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), true, false, 0.0), + 0.5 * std::pow(0.9, 1)); + EXPECT_NEAR(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.33, 0.01); } { std::u16string query(u"common string"); std::u16string text(u"nothing is shared"); - EXPECT_NEAR( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - true, kPartialMatchPenaltyRate, false, 0.0), - 0.38, 0.01); - EXPECT_NEAR( - match.TokenSortRatio(TokenizedString(query), TokenizedString(text), - false, kPartialMatchPenaltyRate, false, 0.0), - 0.33, 0.01); + EXPECT_NEAR(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), true, false, 0.0), + 0.38, 0.01); + EXPECT_NEAR(match.TokenSortRatio(TokenizedString(query), + TokenizedString(text), false, false, 0.0), + 0.33, 0.01); } } @@ -1343,36 +1327,32 @@ { std::u16string query(u"anonymous"); std::u16string text(u"famous"); - EXPECT_NEAR( - match.WeightedRatio(TokenizedString(query), TokenizedString(text), - kPartialMatchPenaltyRate, false, 0.0), - 0.67, 0.01); + EXPECT_NEAR(match.WeightedRatio(TokenizedString(query), + TokenizedString(text), false, 0.0), + 0.67, 0.01); } { std::u16string query(u"Clash.of.clan"); std::u16string text(u"ClashOfTitan"); - EXPECT_NEAR( - match.WeightedRatio(TokenizedString(query), TokenizedString(text), - kPartialMatchPenaltyRate, false, 0.0), - 0.81, 0.01); + EXPECT_NEAR(match.WeightedRatio(TokenizedString(query), + TokenizedString(text), false, 0.0), + 0.81, 0.01); } { std::u16string query(u"final fantasy"); std::u16string text(u"finalfantasy"); - EXPECT_NEAR( - match.WeightedRatio(TokenizedString(query), TokenizedString(text), - kPartialMatchPenaltyRate, false, 0.0), - 0.96, 0.01); + EXPECT_NEAR(match.WeightedRatio(TokenizedString(query), + TokenizedString(text), false, 0.0), + 0.96, 0.01); } { std::u16string query(u"short text!!!"); std::u16string text( u"this sentence is much much much much much longer " u"than the text before"); - EXPECT_NEAR( - match.WeightedRatio(TokenizedString(query), TokenizedString(text), - kPartialMatchPenaltyRate, false, 0.0), - 0.49, 0.01); + EXPECT_NEAR(match.WeightedRatio(TokenizedString(query), + TokenizedString(text), false, 0.0), + 0.49, 0.01); } } @@ -1441,21 +1421,21 @@ std::u16string query(u"anonymous"); std::u16string text(u"famous"); EXPECT_LT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate, 0.0), + true, false, 0.0), 0.4); } { std::u16string query(u"CC"); std::u16string text(u"Clash Of Clan"); EXPECT_LT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate, 0.0), + true, false, 0.0), 0.25); } { std::u16string query(u"Clash.of.clan"); std::u16string text(u"ClashOfTitan"); EXPECT_GT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate, 0.0), + true, false, 0.0), 0.4); } } @@ -1466,21 +1446,21 @@ std::u16string query(u"anonymous"); std::u16string text(u"famous"); EXPECT_LT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate, 0.0), + true, false, 0.0), 0.5); } { std::u16string query(u"CC"); std::u16string text(u"Clash Of Clan"); EXPECT_LT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate), + true, false), 0.25); } { std::u16string query(u"Clash.of.clan"); std::u16string text(u"ClashOfTitan"); EXPECT_LT(match.Relevance(TokenizedString(query), TokenizedString(text), - true, false, kPartialMatchPenaltyRate, 0.0), + true, false, 0.0), 0.5); } } @@ -1489,9 +1469,8 @@ FuzzyTokenizedStringMatch match; std::u16string query(u"anonymous"); std::u16string text(u"famous"); - const double relevance = - match.Relevance(TokenizedString(query), TokenizedString(text), false, - true, kPartialMatchPenaltyRate, 0.0); + const double relevance = match.Relevance( + TokenizedString(query), TokenizedString(text), false, true, 0.0); EXPECT_LT(relevance, 0.35); EXPECT_NEAR(relevance, 0.33 / 2, 0.01); @@ -1501,9 +1480,8 @@ FuzzyTokenizedStringMatch match; std::u16string query(u"yat"); std::u16string text(u"YaT"); - const double relevance = - match.Relevance(TokenizedString(query), TokenizedString(text), false, - true, kPartialMatchPenaltyRate, 0.0); + const double relevance = match.Relevance( + TokenizedString(query), TokenizedString(text), false, true, 0.0); EXPECT_GT(relevance, 0.35); EXPECT_DOUBLE_EQ(relevance, 1.0); EXPECT_EQ(match.hits().size(), 1u);
diff --git a/chromeos/ash/services/assistant/BUILD.gn b/chromeos/ash/services/assistant/BUILD.gn index 0b92ba0..943135f 100644 --- a/chromeos/ash/services/assistant/BUILD.gn +++ b/chromeos/ash/services/assistant/BUILD.gn
@@ -106,10 +106,10 @@ "//base/test:test_support", "//chromeos/ash/components/assistant:buildflags", "//chromeos/ash/components/assistant/test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/assistant/public/mojom", - "//chromeos/dbus:test_support", "//chromeos/dbus/power", "//chromeos/services/libassistant/public/mojom", "//components/prefs:test_support",
diff --git a/chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.cc b/chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.cc index d3b852a2..d00b286c 100644 --- a/chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.cc +++ b/chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.cc
@@ -32,7 +32,8 @@ void ScopedAssistantBrowserDelegate::OpenUrl(GURL url) { NewWindowDelegate::GetPrimary()->OpenUrl( - url, NewWindowDelegate::OpenUrlFrom::kUserInteraction); + url, NewWindowDelegate::OpenUrlFrom::kUserInteraction, + NewWindowDelegate::Disposition::kNewForegroundTab); } } // namespace ash::assistant
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index b7508cf..80ed4bd 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -2782,7 +2782,7 @@ <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> repair </message> <message name="IDS_SHIMLESS_RMA_AUTHORIZED_TECH_ONLY_WARNING" translateable="false" desc="Warning that RMA is only for qualified technicians."> - This repair process is intended for a trained repair technician. Start only after replacing the malfunctioning components. + This repair process is intended for a trained repair technician. Start after you’ve fixed any device issues such as broken or missing parts. </message> <message name="IDS_SHIMLESS_RMA_VALIDATING_COMPONENTS" translateable="false" desc="Checking that device components are approved for this device."> Validating components... @@ -2804,7 +2804,7 @@ Get connected </message> <message name="IDS_SHIMLESS_RMA_CONNECT_PAGE_DESCRIPTION" translateable="false" desc="Description for the connect to wifi page."> - Connecting to Wi-Fi is recommended to make the repair process easier. Your network will be saved. + Connecting to the internet is recommended to make the repair process easier </message> <message name="IDS_SHIMLESS_RMA_CONNECT_DIALOG_CONFIG_NAME" translateable="false" desc="Title for the network configuration dialog for an existing network."> Configure <ph name="NAME">$1<ex>My WiFi network</ex></ph> @@ -2829,7 +2829,7 @@ This component couldn't be detected. </message> <message name="IDS_SHIMLESS_RMA_REWORK_FLOW_LINK" translateable="false" desc="The text with a link that will redirect the user to the reworking flow. The reworking flow is only used when the user wants to repurpose the mainboard for another device."> - If you are reworking a mainboard to use in another device, go to the <ph name="LINK_BEGIN"><a id="reworkFlowLink"></ph>rework flow<ph name="LINK_END"></a></ph>. + If you replaced or reworked the mainboard, go to this <ph name="LINK_BEGIN"><a id="reworkFlowLink"></ph>rework flow<ph name="LINK_END"></a></ph>. </message> <!-- Choose destination page --> <message name="IDS_SHIMLESS_RMA_CHOOSE_DESTINATION" translateable="false" desc="Title for the page shown when choosing the return destination of the device after repair."> @@ -2940,13 +2940,13 @@ </message> <!-- Repair complete page --> <message name="IDS_SHIMLESS_RMA_REPAIR_COMPLETED" translateable="false" desc="Title for the page shown when the RMA process repair process is completed."> - Repair is complete + Almost done! </message> <message name="IDS_SHIMLESS_RMA_REPAIR_COMPLETED_DESCRIPTION" translateable="false" desc="Notice for the user that repair is complete and they can shutdown when ready or run diagnostics/view logs."> - Your repair was successful. You can shut down the device or take some additional actions. + Shut down or reboot the device to complete the repair process. You can also take some additional actions. </message> <message name="IDS_SHIMLESS_RMA_REPAIR_COMPLETED_DIAGNOSTICS_BUTTON" translateable="false" desc="Label of the button that launches the post-boot diagnostics SWA."> - Run Diagnostics + Run diagnostics </message> <message name="IDS_SHIMLESS_RMA_REPAIR_COMPLETED_DIAGNOSTICS_DESCRIPTION" translateable="false" desc="Description of what the diagnostics SWA is for"> Confirm everything's in the right place and view the diagnostic report
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index 68c4d8cf..af6200bf 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -1344,7 +1344,7 @@ // should not use this value. [Default] kLegacyAutoDetection = 0, - // Opens a new tab and navigate to the given URL. + // Opens the given URL in a new tab. kNewForegroundTab = 1, // If there's an existing tab showing the given URL, activate it. @@ -1352,6 +1352,9 @@ // to the given URL. Otherwise, opens a new tab and navigate it to // the given URL. kSwitchToTab = 2, + + // Opens the given URL in a new window. + [MinVersion=1] kNewWindow = 3, }; WindowOpenDisposition disposition@0;
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index ab68a1a2..bba8704 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -22,28 +22,11 @@ ] } -source_set("test_support") { - testonly = true - configs += [ "//build/config/linux/dbus" ] - public_deps = [ - ":dbus", - "//chromeos/dbus/constants", - "//dbus", - "//dbus:test_support", - ] - deps = [ - "//base", - "//testing/gmock", - "//testing/gtest", - ] -} - source_set("unit_tests") { configs += [ "//build/config/linux/dbus" ] testonly = true deps = [ ":dbus", - ":test_support", "//base", "//base/test:test_support", "//chromeos/dbus/dlcservice:unit_tests",
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index 53c114c..439f13a 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -301,4 +301,13 @@ tast_disabled_tests_from_lacros_all = [ # https://crbug.com/1329764 "policy.HistoryClustersVisible", + + # https://crbug.com/1352476 + "lacros.ShelfLaunch", + + # https://crbug.com/1352478 + "mlservice.WebHandwritingRecognition.lacros", + + # https://crbug.com/1352477 + "platform.PerfettoChromeConsumer.lacros", ]
diff --git a/chromeos/ui/frame/frame_header.cc b/chromeos/ui/frame/frame_header.cc index eef25df..d0b14ec 100644 --- a/chromeos/ui/frame/frame_header.cc +++ b/chromeos/ui/frame/frame_header.cc
@@ -457,13 +457,13 @@ if (center_button_) { constexpr int kCenterButtonSpacing = 5; - int full_width = center_button_->GetPreferredSize().width(); - const gfx::Range range( - std::max((view_->width() - full_width) / 2, - origin + kCenterButtonSpacing), - std::min((view_->width() + full_width) / 2, - caption_button_container_->x() - kCenterButtonSpacing)); - center_button_->SetBounds(range.start(), 0, range.end() - range.start(), + const int full_width = center_button_->GetPreferredSize().width(); + const int begin = std::max((view_->width() - full_width) / 2, + origin + kCenterButtonSpacing); + const int end = std::max( + begin, std::min((view_->width() + full_width) / 2, + caption_button_container_->x() - kCenterButtonSpacing)); + center_button_->SetBounds(begin, 0, end - begin, caption_button_container_size.height()); } }
diff --git a/chromeos/ui/frame/highlight_border_overlay.cc b/chromeos/ui/frame/highlight_border_overlay.cc index 2a692a8..ce33782 100644 --- a/chromeos/ui/frame/highlight_border_overlay.cc +++ b/chromeos/ui/frame/highlight_border_overlay.cc
@@ -16,6 +16,26 @@ namespace { +// A highlight border overlay is featured by its highlight color, border color, +// and rounded corner radius. +using HighlightBorderFeatureKey = std::tuple<SkColor, SkColor, int>; +// Currently, each dark and light mode has only one set of highlight and border +// colors. The windows that are using HighlightBorderOverlay have three +// different rounded corner radius. There should be 6 different types of image +// sources for highlight border. +constexpr size_t kMaxImageSourceNum = 6; + +constexpr views::HighlightBorder::Type kBorderType = + views::HighlightBorder::Type::kHighlightBorder3; + +int GetRoundedCornerRadius(chromeos::WindowStateType type) { + if (type == chromeos::WindowStateType::kPip) + return chromeos::kPipRoundedCornerRadius; + + return IsNormalWindowStateType(type) ? chromeos::kTopCornerRadiusWhenRestored + : 0; +} + // `ImageSource` generates an image painted with a highlight border. class ImageSource : public gfx::CanvasImageSource { public: @@ -36,14 +56,6 @@ base::raw_ptr<HighlightBorderOverlay> highlight_border_layer_; }; -int GetRoundedCornerRadius(chromeos::WindowStateType type) { - if (type == chromeos::WindowStateType::kPip) - return chromeos::kPipRoundedCornerRadius; - - return IsNormalWindowStateType(type) ? chromeos::kTopCornerRadiusWhenRestored - : 0; -} - } // namespace HighlightBorderOverlay::HighlightBorderOverlay(views::Widget* widget) @@ -72,8 +84,7 @@ views::HighlightBorder::PaintBorderToCanvas( canvas, *(widget_->GetContentsView()), gfx::Rect(CalculateImageSourceSize()), - gfx::RoundedCornersF(rounded_corner_radius_), - views::HighlightBorder::Type::kHighlightBorder3, + gfx::RoundedCornersF(rounded_corner_radius_), kBorderType, /*use_light_colors=*/false); } @@ -167,11 +178,34 @@ } void HighlightBorderOverlay::UpdateNinePatchLayer() { - // Configure the nine patch layer. - auto* border_image_source = new ImageSource(this); - gfx::Size image_source_size = border_image_source->size(); - layer_.UpdateNinePatchLayerImage( - gfx::ImageSkia(base::WrapUnique(border_image_source), image_source_size)); + // Get the highlight border features. + const views::View& view = *(widget_->GetContentsView()); + SkColor highlight_color = views::HighlightBorder::GetHighlightColor( + view, kBorderType, /*use_light_colors=*/false); + SkColor border_color = views::HighlightBorder::GetBorderColor( + view, kBorderType, /*use_light_colors=*/false); + HighlightBorderFeatureKey key(highlight_color, border_color, + rounded_corner_radius_); + + gfx::Size image_source_size = CalculateImageSourceSize(); + + static base::NoDestructor<std::map<HighlightBorderFeatureKey, gfx::ImageSkia>> + image_source_map; + auto iter = image_source_map->find(key); + if (iter == image_source_map->end()) { + // Create a new image. + auto insertion = image_source_map->emplace( + key, + gfx::ImageSkia(std::make_unique<ImageSource>(this), image_source_size)); + DCHECK(insertion.second); + // When dynamic color feature launches or HighlightBorderOverlay applies to + // more window types, the cache size may increase. Add a dcheck here to + // notice the cache size change. + DCHECK_LE(image_source_map->size(), kMaxImageSourceNum); + iter = insertion.first; + } + + layer_.UpdateNinePatchLayerImage(iter->second); gfx::Rect aperture(image_source_size); gfx::Insets border_region = CalculateBorderRegion();
diff --git a/components/account_id/account_id.cc b/components/account_id/account_id.cc index 16da864..0bbe0028 100644 --- a/components/account_id/account_id.cc +++ b/components/account_id/account_id.cc
@@ -188,13 +188,6 @@ } // static -AccountId AccountId::AdFromObjGuid(const std::string& obj_guid) { - DCHECK(!obj_guid.empty()); - return AccountId(obj_guid, std::string() /* email */, - AccountType::ACTIVE_DIRECTORY); -} - -// static AccountType AccountId::StringToAccountType( const std::string& account_type_string) { if (account_type_string == kGoogle)
diff --git a/components/account_id/account_id.h b/components/account_id/account_id.h index 0ead8677..0a76b68 100644 --- a/components/account_id/account_id.h +++ b/components/account_id/account_id.h
@@ -80,8 +80,6 @@ // AccountId with ACTIVE_DIRECTORY AccountType; static AccountId AdFromUserEmailObjGuid(const std::string& email, const std::string& obj_guid); - // AccountId with ACTIVE_DIRECTORY AccountType; - static AccountId AdFromObjGuid(const std::string& obj_guid); // Translation functions between AccountType and std::string. Used for // serialization.
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 812ab54..69c8b097 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -104,9 +104,6 @@ "autofill_profile_sync_util.h", "autofill_profile_update_strike_database.cc", "autofill_profile_update_strike_database.h", - "autofill_regex_constants.h", - "autofill_regexes.cc", - "autofill_regexes.h", "autofill_subject.cc", "autofill_subject.h", "autofill_suggestion_generator.cc", @@ -203,8 +200,6 @@ "form_parsing/search_field.h", "form_parsing/travel_field.cc", "form_parsing/travel_field.h", - "form_processing/autocomplete_attribute_processing_util.cc", - "form_processing/autocomplete_attribute_processing_util.h", "form_processing/label_processing_util.cc", "form_processing/label_processing_util.h", "form_processing/name_processing_util.cc", @@ -791,7 +786,6 @@ "autofill_profile_save_strike_database_unittest.cc", "autofill_profile_sync_util_unittest.cc", "autofill_profile_update_strike_database_unittest.cc", - "autofill_regexes_unittest.cc", "autofill_subject_unittest.cc", "autofill_suggestion_generator_unittest.cc", "autofill_type_unittest.cc", @@ -830,7 +824,6 @@ "form_parsing/price_field_unittest.cc", "form_parsing/regex_patterns_unittest.cc", "form_parsing/search_field_unittest.cc", - "form_processing/autocomplete_attribute_processing_util_unittest.cc", "form_processing/label_processing_util_unittest.cc", "form_processing/name_processing_util_unittest.cc", "form_structure_unittest.cc",
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc index cb97c23..4217ccc 100644 --- a/components/autofill/core/browser/autocomplete_history_manager.cc +++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -14,7 +14,6 @@ #include "base/memory/weak_ptr.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_experiments.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/metrics/autofill_metrics.h" #include "components/autofill/core/browser/suggestions_context.h" #include "components/autofill/core/browser/ui/suggestion.h" @@ -23,6 +22,7 @@ #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_prefs.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_data.h" #include "components/prefs/pref_service.h" #include "components/version_info/version_info.h"
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index 59b3766d6..33d9fd9 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -52,7 +52,6 @@ #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/autofill_external_delegate.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_suggestion_generator.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/browser_autofill_manager_test_delegate.h" @@ -63,7 +62,6 @@ #include "components/autofill/core/browser/data_model/phone_number.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_data_importer.h" -#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/geo/country_names.h" #include "components/autofill/core/browser/geo/phone_number_i18n.h" @@ -78,6 +76,7 @@ #include "components/autofill/core/browser/suggestions_context.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/validation.h" +#include "components/autofill/core/common/autocomplete_parsing_util.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_data_validation.h" @@ -86,6 +85,7 @@ #include "components/autofill/core/common/autofill_internals/logging_scope.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/autofill/core/common/autofill_prefs.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_tick_clock.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_predictions.h"
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc index 47b7bcb..988c42c 100644 --- a/components/autofill/core/browser/data_model/contact_info.cc +++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -13,12 +13,12 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_l10n_util.h" +#include "components/autofill/core/common/autofill_regexes.h" namespace autofill {
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc index 94d167f7..a357783 100644 --- a/components/autofill/core/browser/data_model/credit_card.cc +++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -24,7 +24,6 @@ #include "build/build_config.h" #include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/data_model/autofill_metadata.h" #include "components/autofill/core/browser/data_model/data_model_utils.h" @@ -34,6 +33,7 @@ #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_payments_features.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_field_data.h" #include "components/grit/components_scaled_resources.h" #include "components/strings/grit/components_strings.h"
diff --git a/components/autofill/core/browser/data_model/data_model_utils.cc b/components/autofill/core/browser/data_model/data_model_utils.cc index aa49d229..2eb0ae1a 100644 --- a/components/autofill/core/browser/data_model/data_model_utils.cc +++ b/components/autofill/core/browser/data_model/data_model_utils.cc
@@ -9,9 +9,9 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "third_party/icu/source/common/unicode/uloc.h" #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
diff --git a/components/autofill/core/browser/field_filler.cc b/components/autofill/core/browser/field_filler.cc index 72e15f56..f4ae5b2 100644 --- a/components/autofill/core/browser/field_filler.cc +++ b/components/autofill/core/browser/field_filler.cc
@@ -18,7 +18,6 @@ #include "components/autofill/core/browser/address_normalizer.h" #include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/data_model/autofill_data_model.h" #include "components/autofill/core/browser/data_model/credit_card.h" @@ -32,6 +31,7 @@ #include "components/autofill/core/browser/proto/states.pb.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_l10n_util.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_util.h" #include "components/strings/grit/components_strings.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
diff --git a/components/autofill/core/browser/form_parsing/address_field.cc b/components/autofill/core/browser/form_parsing/address_field.cc index 33e983a1..01bf673 100644 --- a/components/autofill/core/browser/form_parsing/address_field.cc +++ b/components/autofill/core/browser/form_parsing/address_field.cc
@@ -13,11 +13,11 @@ #include "base/check.h" #include "base/strings/string_util.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/birthdate_field.cc b/components/autofill/core/browser/form_parsing/birthdate_field.cc index b2435d0..005a4b8 100644 --- a/components/autofill/core/browser/form_parsing/birthdate_field.cc +++ b/components/autofill/core/browser/form_parsing/birthdate_field.cc
@@ -8,10 +8,10 @@ #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" #include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/credit_card_field.cc b/components/autofill/core/browser/form_parsing/credit_card_field.cc index de426c5c..d025e90 100644 --- a/components/autofill/core/browser/form_parsing/credit_card_field.cc +++ b/components/autofill/core/browser/form_parsing/credit_card_field.cc
@@ -15,8 +15,6 @@ #include "base/strings/string_util.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/field_filler.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" @@ -24,6 +22,8 @@ #include "components/autofill/core/browser/form_parsing/regex_patterns.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/components/autofill/core/browser/form_parsing/email_field.cc b/components/autofill/core/browser/form_parsing/email_field.cc index 4b386ed..85d78a6 100644 --- a/components/autofill/core/browser/form_parsing/email_field.cc +++ b/components/autofill/core/browser/form_parsing/email_field.cc
@@ -4,9 +4,9 @@ #include "components/autofill/core/browser/form_parsing/email_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc index 2eecf3ac..d185d20 100644 --- a/components/autofill/core/browser/form_parsing/form_field.cc +++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -17,7 +17,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/address_field.h" @@ -34,7 +33,7 @@ #include "components/autofill/core/browser/form_parsing/search_field.h" #include "components/autofill/core/browser/form_parsing/standalone_cvc_field.h" #include "components/autofill/core/browser/form_parsing/travel_field.h" -#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h" +#include "components/autofill/core/common/autocomplete_parsing_util.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/common/autofill_constants.h" @@ -42,6 +41,7 @@ #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/autofill_internals/logging_scope.h" #include "components/autofill/core/common/autofill_payments_features.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_util.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/iban_field.cc b/components/autofill/core/browser/form_parsing/iban_field.cc index 4526a33..deff528 100644 --- a/components/autofill/core/browser/form_parsing/iban_field.cc +++ b/components/autofill/core/browser/form_parsing/iban_field.cc
@@ -5,7 +5,7 @@ #include "components/autofill/core/browser/form_parsing/iban_field.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/common/autofill_payments_features.h"
diff --git a/components/autofill/core/browser/form_parsing/merchant_promo_code_field.cc b/components/autofill/core/browser/form_parsing/merchant_promo_code_field.cc index 98966ca4..14d755d 100644 --- a/components/autofill/core/browser/form_parsing/merchant_promo_code_field.cc +++ b/components/autofill/core/browser/form_parsing/merchant_promo_code_field.cc
@@ -5,9 +5,9 @@ #include "components/autofill/core/browser/form_parsing/merchant_promo_code_field.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/common/autofill_payments_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/name_field.cc b/components/autofill/core/browser/form_parsing/name_field.cc index c0739a22..3aeb720 100644 --- a/components/autofill/core/browser/form_parsing/name_field.cc +++ b/components/autofill/core/browser/form_parsing/name_field.cc
@@ -10,11 +10,11 @@ #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_util.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill { namespace {
diff --git a/components/autofill/core/browser/form_parsing/name_field_unittest.cc b/components/autofill/core/browser/form_parsing/name_field_unittest.cc index 95cd0861..0885590 100644 --- a/components/autofill/core/browser/form_parsing/name_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/name_field_unittest.cc
@@ -8,10 +8,10 @@ #include <vector> #include "base/test/scoped_feature_list.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_parsing/parsing_test_utils.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_field_data.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/phone_field.cc b/components/autofill/core/browser/form_parsing/phone_field.cc index 5928ab29..0c6cabf 100644 --- a/components/autofill/core/browser/form_parsing/phone_field.cc +++ b/components/autofill/core/browser/form_parsing/phone_field.cc
@@ -16,12 +16,12 @@ #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" #include "components/autofill/core/browser/metrics/autofill_metrics.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" namespace autofill { namespace {
diff --git a/components/autofill/core/browser/form_parsing/price_field.cc b/components/autofill/core/browser/form_parsing/price_field.cc index 7c09531..7fcf9df 100644 --- a/components/autofill/core/browser/form_parsing/price_field.cc +++ b/components/autofill/core/browser/form_parsing/price_field.cc
@@ -5,9 +5,9 @@ #include "components/autofill/core/browser/form_parsing/price_field.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc b/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc index 37e1c6cd5..d51d5fc 100644 --- a/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc +++ b/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc
@@ -16,10 +16,10 @@ #include "base/logging.h" #include "base/ranges/ranges.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_parsing/buildflags.h" #include "components/autofill/core/browser/form_parsing/regex_patterns_inl.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/autofill/core/browser/form_parsing/search_field.cc b/components/autofill/core/browser/form_parsing/search_field.cc index 475ba1a..fdce2b87 100644 --- a/components/autofill/core/browser/form_parsing/search_field.cc +++ b/components/autofill/core/browser/form_parsing/search_field.cc
@@ -5,9 +5,9 @@ #include "components/autofill/core/browser/form_parsing/search_field.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_parsing/travel_field.cc b/components/autofill/core/browser/form_parsing/travel_field.cc index 636f406..0d1618ea 100644 --- a/components/autofill/core/browser/form_parsing/travel_field.cc +++ b/components/autofill/core/browser/form_parsing/travel_field.cc
@@ -7,8 +7,8 @@ #include <memory> #include <utility> -#include "components/autofill/core/browser/autofill_regex_constants.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/common/autofill_regex_constants.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_processing/name_processing_util.cc b/components/autofill/core/browser/form_processing/name_processing_util.cc index 48a456f..ce3786b 100644 --- a/components/autofill/core/browser/form_processing/name_processing_util.cc +++ b/components/autofill/core/browser/form_processing/name_processing_util.cc
@@ -6,9 +6,9 @@ #include "base/feature_list.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regexes.h" namespace autofill {
diff --git a/components/autofill/core/browser/form_processing/name_processing_util.h b/components/autofill/core/browser/form_processing/name_processing_util.h index 6c644d5..2bbb77e 100644 --- a/components/autofill/core/browser/form_processing/name_processing_util.h +++ b/components/autofill/core/browser/form_processing/name_processing_util.h
@@ -9,7 +9,6 @@ #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_structure.h" #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 255988a..5491f1b 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -34,13 +34,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/buildflags.h" #include "components/autofill/core/browser/form_parsing/form_field.h" -#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h" #include "components/autofill/core/browser/form_processing/label_processing_util.h" #include "components/autofill/core/browser/form_processing/name_processing_util.h" #include "components/autofill/core/browser/logging/log_manager.h" @@ -49,11 +46,14 @@ #include "components/autofill/core/browser/randomized_encoder.h" #include "components/autofill/core/browser/rationalization_util.h" #include "components/autofill/core/browser/validation.h" +#include "components/autofill/core/common/autocomplete_parsing_util.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/autofill_internals/logging_scope.h" #include "components/autofill/core/common/autofill_payments_features.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_tick_clock.h" #include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/dense_set.h"
diff --git a/components/autofill/core/browser/validation.cc b/components/autofill/core/browser/validation.cc index d81a9b46..afe2c98 100644 --- a/components/autofill/core/browser/validation.cc +++ b/components/autofill/core/browser/validation.cc
@@ -17,12 +17,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/geo/phone_number_i18n.h" #include "components/autofill/core/browser/geo/state_names.h" #include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn index 32c9af5..530d6b5 100644 --- a/components/autofill/core/common/BUILD.gn +++ b/components/autofill/core/common/BUILD.gn
@@ -5,6 +5,8 @@ static_library("common") { sources = [ "aliases.h", + "autocomplete_parsing_util.cc", + "autocomplete_parsing_util.h", "autofill_clock.cc", "autofill_clock.h", "autofill_constants.cc", @@ -21,6 +23,9 @@ "autofill_payments_features.h", "autofill_prefs.cc", "autofill_prefs.h", + "autofill_regex_constants.h", + "autofill_regexes.cc", + "autofill_regexes.h", "autofill_switches.cc", "autofill_switches.h", "autofill_tick_clock.cc", @@ -99,10 +104,12 @@ source_set("unit_tests") { testonly = true sources = [ + "autocomplete_parsing_util_unittest.cc", "autofill_internals/log_message_unittest.cc", "autofill_internals/logging_scope_unittest.cc", "autofill_l10n_util_unittest.cc", "autofill_prefs_unittest.cc", + "autofill_regexes_unittest.cc", "autofill_util_unittest.cc", "dense_set_unittest.cc", "field_data_manager_unittest.cc",
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc b/components/autofill/core/common/autocomplete_parsing_util.cc similarity index 96% rename from components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc rename to components/autofill/core/common/autocomplete_parsing_util.cc index 7773dfb..dda2292 100644 --- a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc +++ b/components/autofill/core/common/autocomplete_parsing_util.cc
@@ -1,15 +1,15 @@ // Copyright 2022 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h" +#include "components/autofill/core/common/autocomplete_parsing_util.h" #include <vector> #include "base/containers/fixed_flat_map.h" #include "base/notreached.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_util.h" namespace autofill { @@ -53,7 +53,7 @@ // might indicate a 4 digit year. // In case no rationalization rule applies, the original type is returned. HtmlFieldType RationalizeAutocompleteType(HtmlFieldType type, - const AutofillField& field) { + const FormFieldData& field) { // (original-type, max-length) -> new-type static constexpr auto rules = base::MakeFixedFlatMap<std::pair<HtmlFieldType, uint64_t>, HtmlFieldType>( @@ -188,7 +188,7 @@ HtmlFieldType FieldTypeFromAutocompleteAttributeValue( std::string value, - const AutofillField& field) { + const FormFieldData& field) { if (value.empty()) return HTML_TYPE_UNSPECIFIED; @@ -222,7 +222,7 @@ } absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( - const AutofillField& field) { + const FormFieldData& field) { std::vector<std::string> tokens = LowercaseAndTokenizeAttributeString(field.autocomplete_attribute);
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h b/components/autofill/core/common/autocomplete_parsing_util.h similarity index 80% rename from components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h rename to components/autofill/core/common/autocomplete_parsing_util.h index 352bbc97..7fd6da8 100644 --- a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h +++ b/components/autofill/core/common/autocomplete_parsing_util.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_ +#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOCOMPLETE_PARSING_UTIL_H_ +#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOCOMPLETE_PARSING_UTIL_H_ #include <string> #include "base/strings/string_piece.h" -#include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/html_field_types.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -34,7 +34,7 @@ // webauthn is parsed, but otherwise unused. }; absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( - const AutofillField& field); + const FormFieldData& field); // Checks if `autocomplete` is one of "on", "off" or "false". These values are // currently ignored by Autofill. @@ -48,8 +48,8 @@ // Otherwise HTML_TYPE_UNRECOGNIZED is returned. HtmlFieldType FieldTypeFromAutocompleteAttributeValue( std::string value, - const AutofillField& field); + const FormFieldData& field); } // namespace autofill -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_AUTOCOMPLETE_ATTRIBUTE_PROCESSING_UTIL_H_ +#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOCOMPLETE_PARSING_UTIL_H_
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util_unittest.cc b/components/autofill/core/common/autocomplete_parsing_util_unittest.cc similarity index 94% rename from components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util_unittest.cc rename to components/autofill/core/common/autocomplete_parsing_util_unittest.cc index f596dcb..41f1670 100644 --- a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util_unittest.cc +++ b/components/autofill/core/common/autocomplete_parsing_util_unittest.cc
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.h" +#include "components/autofill/core/common/autocomplete_parsing_util.h" #include <string> #include "base/strings/string_piece.h" -#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/common/form_field_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -92,7 +91,7 @@ if (test.max_length) field.max_length = test.max_length; - auto result = ParseAutocompleteAttribute(AutofillField(field)); + auto result = ParseAutocompleteAttribute(field); ASSERT_EQ(result.has_value(), test.expected_result.has_value()); if (result.has_value()) { EXPECT_EQ(result->section, test.expected_result->section);
diff --git a/components/autofill/core/browser/autofill_regex_constants.h b/components/autofill/core/common/autofill_regex_constants.h similarity index 99% rename from components/autofill/core/browser/autofill_regex_constants.h rename to components/autofill/core/common/autofill_regex_constants.h index 73a92dc9..91466aa 100644 --- a/components/autofill/core/browser/autofill_regex_constants.h +++ b/components/autofill/core/common/autofill_regex_constants.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_ +#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEX_CONSTANTS_H_ +#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEX_CONSTANTS_H_ namespace autofill {
diff --git a/components/autofill/core/browser/autofill_regexes.cc b/components/autofill/core/common/autofill_regexes.cc similarity index 97% rename from components/autofill/core/browser/autofill_regexes.cc rename to components/autofill/core/common/autofill_regexes.cc index 759fe9df..b62c57a 100644 --- a/components/autofill/core/browser/autofill_regexes.cc +++ b/components/autofill/core/common/autofill_regexes.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_regexes.h" +#include "components/autofill/core/common/autofill_regexes.h" #include <map> #include <memory>
diff --git a/components/autofill/core/browser/autofill_regexes.h b/components/autofill/core/common/autofill_regexes.h similarity index 95% rename from components/autofill/core/browser/autofill_regexes.h rename to components/autofill/core/common/autofill_regexes.h index d8a5fb7e..d378abb 100644 --- a/components/autofill/core/browser/autofill_regexes.h +++ b/components/autofill/core/common/autofill_regexes.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEXES_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEXES_H_ +#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEXES_H_ +#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEXES_H_ #include <map> #include <memory>
diff --git a/components/autofill/core/browser/autofill_regexes_unittest.cc b/components/autofill/core/common/autofill_regexes_unittest.cc similarity index 98% rename from components/autofill/core/browser/autofill_regexes_unittest.cc rename to components/autofill/core/common/autofill_regexes_unittest.cc index e0c3e5ec..dffad89 100644 --- a/components/autofill/core/browser/autofill_regexes_unittest.cc +++ b/components/autofill/core/common/autofill_regexes_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_regexes.h" +#include "components/autofill/core/common/autofill_regexes.h" // Keep these tests in sync with // components/autofill/core/browser/pattern_provider/default_regex_patterns_unittest.cc @@ -13,7 +13,7 @@ #include <string> #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regex_constants.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/commerce/core/DEPS b/components/commerce/core/DEPS index cd894101..a82b9ed 100644 --- a/components/commerce/core/DEPS +++ b/components/commerce/core/DEPS
@@ -18,4 +18,5 @@ "+services/network/public/cpp", "+services/network/test", "+ui/base", + "+mojo/public/cpp/bindings", ]
diff --git a/components/commerce/core/mojom/BUILD.gn b/components/commerce/core/mojom/BUILD.gn new file mode 100644 index 0000000..a5ae9f9 --- /dev/null +++ b/components/commerce/core/mojom/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojo_bindings") { + sources = [ "shopping_list.mojom" ] + webui_module_path = "/" + public_deps = [ + "//mojo/public/mojom/base", + "//url/mojom:url_mojom_gurl", + ] +}
diff --git a/components/commerce/core/mojom/OWNERS b/components/commerce/core/mojom/OWNERS new file mode 100644 index 0000000..61b5e28 --- /dev/null +++ b/components/commerce/core/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/components/commerce/core/mojom/shopping_list.mojom b/components/commerce/core/mojom/shopping_list.mojom new file mode 100644 index 0000000..8c64f31 --- /dev/null +++ b/components/commerce/core/mojom/shopping_list.mojom
@@ -0,0 +1,57 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +module shopping_list.mojom; + +import "url/mojom/url.mojom"; + +// This is a specialized version of shopping_specifics proto. The +// struct here has most of the same information with the proto but +// focuses more on UI needs. +struct ProductInfo { + // The title of the product. + string title; + + // The eTLD+1 domain of the merchant website where the + // product was originally tracked on. This should only be used + // for showing this information directly on the UI. + string domain; + + // Direct link to the product image. + url.mojom.Url image_url; + + // Direct link to the product page. Right now this is + // only used to fetch site favicon in case image_url + // is not available. + url.mojom.Url product_url; + + // Price as shown in the page. This should include + // both the amount and the currency symbol. + string current_price; + + // Previous price if there has been a price drop. + // This should include both the amount and the currency + // symbol. + string previous_price; +}; + +struct BookmarkProductInfo { + // The ID of the bookmark that owns this product info. + int64 bookmark_id; + + // The product information associated with 'bookmark_id'. + ProductInfo info; +}; + +// Used by the price tracking section in side panel to bootstrap +// bidirectional communication. +interface ShoppingListHandlerFactory { + // The WebUI calls this method when the page is first initialized. + CreateShoppingListHandler(pending_receiver<ShoppingListHandler> handler); +}; + +// Browser-side handler for requests from WebUI page. +interface ShoppingListHandler { + // Returns all the tracked product info from bookmarks. + GetAllBookmarkProductInfo() => (array<BookmarkProductInfo> productInfos); +}; \ No newline at end of file
diff --git a/components/commerce/core/webui/BUILD.gn b/components/commerce/core/webui/BUILD.gn new file mode 100644 index 0000000..169b44c --- /dev/null +++ b/components/commerce/core/webui/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("webui") { + sources = [ + "shopping_list_handler.cc", + "shopping_list_handler.h", + ] + + deps = [ + "../mojom:mojo_bindings", + "//base", + "//mojo/public/cpp/bindings", + ] +}
diff --git a/components/commerce/core/webui/DEPS b/components/commerce/core/webui/DEPS new file mode 100644 index 0000000..16764a92 --- /dev/null +++ b/components/commerce/core/webui/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/public/cpp/bindings", +]
diff --git a/components/commerce/core/webui/shopping_list_handler.cc b/components/commerce/core/webui/shopping_list_handler.cc new file mode 100644 index 0000000..a30fafad --- /dev/null +++ b/components/commerce/core/webui/shopping_list_handler.cc
@@ -0,0 +1,25 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/commerce/core/webui/shopping_list_handler.h" + +#include <vector> + +namespace commerce { + +ShoppingListHandler::ShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> receiver) + : receiver_(this, std::move(receiver)) {} + +ShoppingListHandler::~ShoppingListHandler() = default; + +void ShoppingListHandler::GetAllBookmarkProductInfo( + GetAllBookmarkProductInfoCallback callback) { + std::vector<shopping_list::mojom::BookmarkProductInfoPtr> info_list; + + // TODO(crbug.com/1346620): Call actual implementation from ShoppingService to + // get data. + std::move(callback).Run(std::move(info_list)); +} +} // namespace commerce
diff --git a/components/commerce/core/webui/shopping_list_handler.h b/components/commerce/core/webui/shopping_list_handler.h new file mode 100644 index 0000000..f9728ca --- /dev/null +++ b/components/commerce/core/webui/shopping_list_handler.h
@@ -0,0 +1,33 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_COMMERCE_CORE_WEBUI_SHOPPING_LIST_HANDLER_H_ +#define COMPONENTS_COMMERCE_CORE_WEBUI_SHOPPING_LIST_HANDLER_H_ + +#include "components/commerce/core/mojom/shopping_list.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" + +namespace commerce { + +class ShoppingListHandler : public shopping_list::mojom::ShoppingListHandler { + public: + explicit ShoppingListHandler( + mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandler> + receiver); + ShoppingListHandler(const ShoppingListHandler&) = delete; + ShoppingListHandler& operator=(const ShoppingListHandler&) = delete; + ~ShoppingListHandler() override; + + // shopping_list::mojom::ShoppingListHandler: + void GetAllBookmarkProductInfo( + GetAllBookmarkProductInfoCallback callback) override; + + private: + mojo::Receiver<shopping_list::mojom::ShoppingListHandler> receiver_; +}; + +} // namespace commerce + +#endif // COMPONENTS_COMMERCE_CORE_WEBUI_SHOPPING_LIST_HANDLER_H_
diff --git a/components/contextual_search/core/browser/contextual_search_context.h b/components/contextual_search/core/browser/contextual_search_context.h index ef9fead8..d0c85db1 100644 --- a/components/contextual_search/core/browser/contextual_search_context.h +++ b/components/contextual_search/core/browser/contextual_search_context.h
@@ -7,11 +7,13 @@ #include <string> +#include "base/memory/weak_ptr.h" #include "url/gurl.h" // Encapsulates key parts of a Contextual Search Context, including surrounding // text. -struct ContextualSearchContext { +struct ContextualSearchContext + : public base::SupportsWeakPtr<ContextualSearchContext> { public: // Languages used for translation. struct TranslationLanguages { @@ -38,12 +40,6 @@ void SetResolveProperties(const std::string& home_country, bool may_send_base_page_url); - // Sets the surrounding text to the given string and the selection to the - // given start/end range. - void SetSurroundingsAndSelection(const std::string& surrounding_text, - int selection_start, - int selection_end); - // Adjust the current selection offsets by the given signed amounts. void AdjustSelection(int start_adjust, int end_adjust);
diff --git a/components/contextual_search/core/browser/contextual_search_delegate_unittest.cc b/components/contextual_search/core/browser/contextual_search_delegate_unittest.cc index 476fc86..39daba11 100644 --- a/components/contextual_search/core/browser/contextual_search_delegate_unittest.cc +++ b/components/contextual_search/core/browser/contextual_search_delegate_unittest.cc
@@ -37,24 +37,17 @@ } // namespace -class WeakContextualSearchContext : public ContextualSearchContext { - public: - WeakContextualSearchContext(const std::string& home_country, - const GURL& page_url, - const std::string& encoding) { - SetResolveProperties(home_country, /*may_send_base_page_url=*/true); - SetBasePageUrl(page_url); - SetBasePageEncoding(encoding); - } - ~WeakContextualSearchContext() = default; - - base::WeakPtr<WeakContextualSearchContext> GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - - private: - base::WeakPtrFactory<WeakContextualSearchContext> weak_factory_{this}; -}; +std::unique_ptr<ContextualSearchContext> MakeTestContext( + const std::string& home_country, + const GURL& page_url, + const std::string& encoding) { + std::unique_ptr<ContextualSearchContext> context = + std::make_unique<ContextualSearchContext>(); + context->SetResolveProperties(home_country, /*may_send_base_page_url=*/true); + context->SetBasePageUrl(page_url); + context->SetBasePageEncoding(encoding); + return context; +} // Unit tests for the native |ContextualSearchDelegate|. class ContextualSearchDelegateTest : public testing::Test { @@ -112,12 +105,12 @@ const std::u16string& surrounding_text, int start_offset, int end_offset) { - test_context_ = std::make_unique<WeakContextualSearchContext>( - std::string(), GURL(kSomeSpecificBasePage), "utf-8"); + test_context_ = + MakeTestContext(std::string(), GURL(kSomeSpecificBasePage), "utf-8"); test_context_->SetSelectionSurroundings(start_offset, end_offset, surrounding_text); delegate_->ResolveSearchTermFromContext( - test_context_->GetWeakPtr(), + test_context_->AsWeakPtr(), base::BindRepeating( &ContextualSearchDelegateTest::recordSearchTermResolutionResponse, base::Unretained(this))); @@ -150,8 +143,8 @@ // from tests, but can be called here because this is a friend class. //------------------------------------------------------------------- void CreateTestContext() { - test_context_ = std::make_unique<WeakContextualSearchContext>( - std::string(), GURL(kSomeSpecificBasePage), "utf-8"); + test_context_ = + MakeTestContext(std::string(), GURL(kSomeSpecificBasePage), "utf-8"); } void DestroyTestContext() { test_context_.reset(); } @@ -202,8 +195,8 @@ void SetSurroundingContext(const std::u16string& surrounding_text, int start_offset, int end_offset) { - test_context_ = std::make_unique<WeakContextualSearchContext>( - std::string(), GURL(kSomeSpecificBasePage), "utf-8"); + test_context_ = + MakeTestContext(std::string(), GURL(kSomeSpecificBasePage), "utf-8"); test_context_->SetSelectionSurroundings(start_offset, end_offset, surrounding_text); } @@ -271,7 +264,7 @@ // The delegate under test. std::unique_ptr<ContextualSearchDelegate> delegate_; - std::unique_ptr<WeakContextualSearchContext> test_context_; + std::unique_ptr<ContextualSearchContext> test_context_; network::TestURLLoaderFactory test_url_loader_factory_; @@ -691,7 +684,7 @@ // Test that we can destroy the context while resolving without a crash. TEST_F(ContextualSearchDelegateTest, DestroyContextDuringResolve) { CreateTestContext(); - CallResolveSearchTermFromContext(test_context_->GetWeakPtr()); + CallResolveSearchTermFromContext(test_context_->AsWeakPtr()); DestroyTestContext(); std::string response("Any response as it does not matter here."); @@ -704,7 +697,7 @@ TEST_F(ContextualSearchDelegateTest, DestroyContextDuringGatherSurroundings) { CreateTestContext(); base::WeakPtr<ContextualSearchContext> weak_context = - test_context_->GetWeakPtr(); + test_context_->AsWeakPtr(); DestroyTestContext(); CallOnTextSurroundingSelectionAvailable(weak_context); }
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc index f2dccff..91d409d3 100644 --- a/components/exo/text_input.cc +++ b/components/exo/text_input.cc
@@ -215,6 +215,16 @@ } void TextInput::InsertChar(const ui::KeyEvent& event) { + // TODO(b/240618514): Short term workaround to accept temporary fix in IME + // for urgent production breakage. + // We should come up with the proper solution of what to be done. + if (event.key_code() == ui::VKEY_UNKNOWN) { + // On some specific cases, IME use InsertChar, even if there's no clear + // key mapping from key_code. Then, use InsertText(). + InsertText(std::u16string(1u, event.GetCharacter()), + InsertTextCursorBehavior::kMoveCursorAfterText); + return; + } // TextInput is currently used only for Lacros, and this is the // short term workaround not to duplicate KeyEvent there. // This is what we do for ARC, which is being removed in the near
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java index 9216b6da..b12ebca 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -25,6 +25,7 @@ FeatureConstants.CHROME_HOME_EXPAND_FEATURE, FeatureConstants.CHROME_HOME_PULL_TO_REFRESH_FEATURE, FeatureConstants.CROW_FEATURE, FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING, + FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING_ACTION_CHIP, FeatureConstants.DATA_SAVER_PREVIEW_FEATURE, FeatureConstants.DATA_SAVER_DETAIL_FEATURE, FeatureConstants.DATA_SAVER_MILESTONE_PROMO_FEATURE, FeatureConstants.EPHEMERAL_TAB_FEATURE, FeatureConstants.EXPLORE_SITES_TILE_FEATURE, FeatureConstants.PREVIEWS_OMNIBOX_UI_FEATURE, @@ -90,6 +91,8 @@ String AUTO_DARK_USER_EDUCATION_MESSAGE_OPT_IN_FEATURE = "IPH_AutoDarkUserEducationMessageOptIn"; String CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING = "IPH_ContextualPageActions_PriceTracking"; + String CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING_ACTION_CHIP = + "IPH_ContextualPageActions_PriceTrackingActionChip"; String CROW_FEATURE = "IPH_Crow"; String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage"; String DOWNLOAD_PAGE_SCREENSHOT_FEATURE = "IPH_DownloadPageScreenshot";
diff --git a/components/feature_engagement/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc index 94bc2873..8b4fd48 100644 --- a/components/feature_engagement/public/event_constants.cc +++ b/components/feature_engagement/public/event_constants.cc
@@ -59,6 +59,8 @@ const char kDefaultSiteViewShown[] = "default_site_view_shown"; const char kPasswordSuggestionsShown[] = "password_suggestions_shown"; const char kPasswordSuggestionSelected[] = "password_suggestion_selected"; +const char kOverflowMenuNoHorizontalScrollOrAction[] = + "overflow_menu_no_horizontal_scroll_or_action"; #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_ANDROID)
diff --git a/components/feature_engagement/public/event_constants.h b/components/feature_engagement/public/event_constants.h index c7a23e8..71a5a249 100644 --- a/components/feature_engagement/public/event_constants.h +++ b/components/feature_engagement/public/event_constants.h
@@ -109,6 +109,10 @@ // The user has selected an Autofill password suggestion. extern const char kPasswordSuggestionSelected[]; +// The user has exited the overflow menu without scrolling horizontally and +// without taking an action. +extern const char kOverflowMenuNoHorizontalScrollOrAction[]; + #endif // BUILDFLAG(IS_IOS) // Android.
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc index 781d9b3..1769f91 100644 --- a/components/feature_engagement/public/feature_configurations.cc +++ b/components/feature_engagement/public/feature_configurations.cc
@@ -231,6 +231,24 @@ Comparator(LESS_THAN, 3), 90, 360)); return config; } + if (kIPHContextualPageActionsPriceTrackingActionChipFeature.name == + feature->name) { + // A config that allows the Price Tracking Action Chip to be shown: + // * 3 times per session. + // * 5 times per day. + // * 10 times per week. + absl::optional<FeatureConfig> config = FeatureConfig(); + config->valid = true; + config->availability = Comparator(ANY, 0); + config->session_rate = Comparator(LESS_THAN, 3); + config->trigger = EventConfig( + "contextual_page_actions_price_tracking_action_chip_iph_trigger", + Comparator(LESS_THAN, 5), 1, 360); + config->event_configs.insert(EventConfig( + "contextual_page_actions_price_tracking_action_chip_iph_trigger", + Comparator(LESS_THAN, 10), 7, 360)); + return config; + } if (kIPHAddToHomescreenMessageFeature.name == feature->name) { // A config that allows the Add to homescreen message IPH to be shown: // * Once per 15 days @@ -500,6 +518,11 @@ return config; } if (kIPHShoppingListMenuItemFeature.name == feature->name) { + // Allows a shopping list menu item IPH to be displayed at most: + // * Once per week. + // * Up to 3 times per year. + // * And only as long as the user has never initiated price tracking from + // the menu. absl::optional<FeatureConfig> config = FeatureConfig(); config->valid = true; config->availability = Comparator(ANY, 0);
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc index d6940c6..b29f060 100644 --- a/components/feature_engagement/public/feature_constants.cc +++ b/components/feature_engagement/public/feature_constants.cc
@@ -89,6 +89,9 @@ const base::Feature kIPHContextualPageActionsPriceTrackingFeature{ "IPH_ContextualPageActions_PriceTracking", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kIPHContextualPageActionsPriceTrackingActionChipFeature{ + "IPH_ContextualPageActions_PriceTrackingActionChip", + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kIPHCrowFeature{"IPH_Crow", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHDataSaverDetailFeature{ @@ -283,6 +286,8 @@ "IPH_PasswordSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHFollowWhileBrowsingFeature{ "IPH_FollowWhileBrowsing", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kIPHOverflowMenuTipFeature{ + "IPH_OverflowMenuTip", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index 3671eb1f..f28ae3e 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -70,6 +70,8 @@ extern const base::Feature kIPHAutoDarkUserEducationMessageFeature; extern const base::Feature kIPHAutoDarkUserEducationMessageOptInFeature; extern const base::Feature kIPHContextualPageActionsPriceTrackingFeature; +extern const base::Feature + kIPHContextualPageActionsPriceTrackingActionChipFeature; extern const base::Feature kIPHCrowFeature; extern const base::Feature kIPHDataSaverDetailFeature; extern const base::Feature kIPHDataSaverMilestonePromoFeature; @@ -171,6 +173,7 @@ extern const base::Feature kIPHDefaultSiteViewFeature; extern const base::Feature kIPHPasswordSuggestionsFeature; extern const base::Feature kIPHFollowWhileBrowsingFeature; +extern const base::Feature kIPHOverflowMenuTipFeature; #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc index 75a2e5b..93175638 100644 --- a/components/feature_engagement/public/feature_list.cc +++ b/components/feature_engagement/public/feature_list.cc
@@ -36,6 +36,7 @@ &kIPHChromeReengagementNotification2Feature, &kIPHChromeReengagementNotification3Feature, &kIPHContextualPageActionsPriceTrackingFeature, + &kIPHContextualPageActionsPriceTrackingActionChipFeature, &kIPHCrowFeature, &kIPHDownloadSettingsFeature, &kIPHDownloadInfoBarDownloadContinuingFeature, @@ -113,6 +114,7 @@ &kIPHDefaultSiteViewFeature, &kIPHPasswordSuggestionsFeature, &kIPHFollowWhileBrowsingFeature, + &kIPHOverflowMenuTipFeature, #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index 76a38886..adca44b 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -61,6 +61,8 @@ "IPH_AutoDarkUserEducationMessageOptIn"); DEFINE_VARIATION_PARAM(kIPHContextualPageActionsPriceTrackingFeature, "IPH_ContextualPageActions_PriceTracking"); +DEFINE_VARIATION_PARAM(kIPHContextualPageActionsPriceTrackingActionChipFeature, + "IPH_ContextualPageActions_PriceTrackingActionChip"); DEFINE_VARIATION_PARAM(kIPHCrowFeature, "IPH_Crow"); DEFINE_VARIATION_PARAM(kIPHDataSaverDetailFeature, "IPH_DataSaverDetail"); DEFINE_VARIATION_PARAM(kIPHDataSaverMilestonePromoFeature, @@ -208,6 +210,7 @@ "IPH_PasswordSuggestions"); DEFINE_VARIATION_PARAM(kIPHFollowWhileBrowsingFeature, "IPH_FollowWhileBrowsing"); +DEFINE_VARIATION_PARAM(kIPHOverflowMenuTipFeature, "IPH_OverflowMenuTip"); #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \ @@ -341,6 +344,7 @@ VARIATION_ENTRY(kIPHDefaultSiteViewFeature), VARIATION_ENTRY(kIPHPasswordSuggestionsFeature), VARIATION_ENTRY(kIPHFollowWhileBrowsingFeature), + VARIATION_ENTRY(kIPHOverflowMenuTipFeature), #elif BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) VARIATION_ENTRY(kIPHDesktopTabGroupsNewGroupFeature),
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 7f174df..e3836ed 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1775,7 +1775,7 @@ if (!db_) return base::Time::Min(); const auto clusters = - GetMostRecentClusters(base::Time::Min(), base::Time::Max(), 1); + GetMostRecentClusters(base::Time::Min(), base::Time::Max(), 1, false); return clusters.empty() ? base::Time::Min() : clusters[0] .GetMostRecentVisit() @@ -1796,26 +1796,30 @@ std::vector<Cluster> HistoryBackend::GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time, - int max_clusters) { + int max_clusters, + bool include_keywords) { TRACE_EVENT0("browser", "HistoryBackend::GetMostRecentClusters"); if (!db_) return {}; const auto cluster_ids = db_->GetMostRecentClusterIds( inclusive_min_time, exclusive_max_time, max_clusters); std::vector<Cluster> clusters; - base::ranges::transform( - cluster_ids, std::back_inserter(clusters), - [&](const auto& cluster_id) { return GetCluster(cluster_id); }); + base::ranges::transform(cluster_ids, std::back_inserter(clusters), + [&](const auto& cluster_id) { + return GetCluster(cluster_id, include_keywords); + }); return clusters; } -Cluster HistoryBackend::GetCluster(int64_t cluster_id) { +Cluster HistoryBackend::GetCluster(int64_t cluster_id, bool include_keywords) { TRACE_EVENT0("browser", "HistoryBackend::GetCluster"); if (!db_) return {}; Cluster cluster = db_->GetCluster(cluster_id); cluster.visits = ToClusterVisits(db_->GetVisitIdsInCluster(cluster_id)); + if (include_keywords) + cluster.keyword_to_data_map = db_->GetClusterKeywords(cluster_id); return cluster; }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index e4fcbd3..dce097e 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -483,10 +483,12 @@ std::vector<Cluster> GetMostRecentClusters(base::Time inclusive_min_time, base::Time exclusive_max_time, - int max_clusters); + int max_clusters, + bool include_keywords = true); - // Get a `Cluster`. - Cluster GetCluster(int64_t cluster_id); + // Get a `Cluster`. `keyword_to_data_map` isn't always useful, and it requires + // an extra SQL execution. It's only populated If `include_keywords` is true. + Cluster GetCluster(int64_t cluster_id, bool include_keywords = true); // Finds the 1st visit in the redirect chain containing `visit`. // Unlike `GetRedirectsToSpecificVisit()`, this only considers actual
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index b2c4af1ab..dc7f819 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -3908,17 +3908,50 @@ // returned. ClusterVisit visit_3; visit_3.annotated_visit.visit_row.visit_id = 3; - backend_->db_->AddClusters( - {{0, {visit_1, visit_2, visit_3}, {}, false, u"label"}}); - const auto cluster = backend_->GetCluster(1); + ClusterKeywordData keyword_data_1 = { + ClusterKeywordData::ClusterKeywordType::kEntityAlias, + .4, + {"entity1", "entity2"}}; + ClusterKeywordData keyword_data_2 = { + ClusterKeywordData::ClusterKeywordType::kEntityCategory, .6, {}}; + + backend_->db_->AddClusters( + {{0, + {visit_1, visit_2, visit_3}, + {{u"keyword1", keyword_data_1}, {u"keyword2", keyword_data_2}}, + false, + u"label"}}); + + auto cluster = backend_->GetCluster(1, true); VerifyCluster(cluster, {1, {2, 1}}); EXPECT_EQ(cluster.cluster_id, 1); EXPECT_EQ(cluster.label, u"label"); EXPECT_EQ(cluster.visits[1].url_for_display, u"url_for_display"); + EXPECT_EQ(cluster.keyword_to_data_map.size(), 2u); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword1"].type, + ClusterKeywordData::ClusterKeywordType::kEntityAlias); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword1"].score, .4f); + // Only the 1st keyword entity should be preserved. + EXPECT_THAT(cluster.keyword_to_data_map[u"keyword1"].entity_collections, + UnorderedElementsAre("entity1")); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword2"].type, + ClusterKeywordData::ClusterKeywordType::kEntityCategory); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword2"].score, .6f); + EXPECT_TRUE( + cluster.keyword_to_data_map[u"keyword2"].entity_collections.empty()); + + // Verify keywords are not returned, but other info is, when the + // `include_keywords` param is false. + cluster = backend_->GetCluster(1, false); + VerifyCluster(cluster, {1, {2, 1}}); + EXPECT_EQ(cluster.cluster_id, 1); + EXPECT_EQ(cluster.label, u"label"); + EXPECT_EQ(cluster.visits[1].url_for_display, u"url_for_display"); + EXPECT_TRUE(cluster.keyword_to_data_map.empty()); // Verify non-existent clusters aren't returned. - VerifyCluster(backend_->GetCluster(2), {0}); + VerifyCluster(backend_->GetCluster(2, true), {0}); } TEST_F(HistoryBackendTest, GetRedirectChainStart) {
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 8515f10d..d167d18 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -315,7 +315,8 @@ return tracker->PostTaskAndReplyWithResult( backend_task_runner_.get(), FROM_HERE, base::BindOnce(&HistoryBackend::GetMostRecentClusters, history_backend_, - inclusive_min_time, exclusive_max_time, max_clusters), + inclusive_min_time, exclusive_max_time, max_clusters, + /*include_keywords=*/true), std::move(callback)); }
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 567cb04..1931e766 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -956,11 +956,11 @@ // crbug.com/1335975: Remove this method when we remove the histograms. std::string GetKeywordTypeLabel() const; - ClusterKeywordType type; + ClusterKeywordType type = ClusterKeywordData::kUnknown; - // A floating point score describing how important this - // keyword is to the containing cluster. - float score; + // A floating point score describing how important this keyword is to the + // containing cluster. + float score = 0; // Entity collections associated with the keyword this is attached to. std::vector<std::string> entity_collections; @@ -994,7 +994,6 @@ std::vector<ClusterVisit> visits; // A map of keywords to additional data. - // TODO(manukh): Persist to db. base::flat_map<std::u16string, ClusterKeywordData> keyword_to_data_map; // Whether the cluster should be shown prominently on UI surfaces.
diff --git a/components/history/core/browser/visit_annotations_database.cc b/components/history/core/browser/visit_annotations_database.cc index 16afd81..4314906f 100644 --- a/components/history/core/browser/visit_annotations_database.cc +++ b/components/history/core/browser/visit_annotations_database.cc
@@ -221,6 +221,17 @@ if (!CreateClustersAndVisitsTableAndIndex()) return false; + // Represents the one-to-many relationship of `Cluster`s and + // `ClusterKeywordData`s. + if (!GetDB().Execute("CREATE TABLE IF NOT EXISTS cluster_keywords(" + "cluster_id INTEGER NOT NULL," + "keyword VARCHAR NOT NULL," + "type INTEGER NOT NULL," + "score NUMERIC NOT NULL," + "collections VARCHAR NOT NULL)")) { + return false; + } + return true; } @@ -229,7 +240,8 @@ return GetDB().Execute("DROP TABLE content_annotations") && GetDB().Execute("DROP TABLE context_annotations") && GetDB().Execute("DROP TABLE clusters") && - GetDB().Execute("DROP TABLE clusters_and_visits"); + GetDB().Execute("DROP TABLE clusters_and_visits") && + GetDB().Execute("DROP TABLE cluster_keywords"); } void VisitAnnotationsDatabase::AddContentAnnotationsForVisit( @@ -503,6 +515,11 @@ "(cluster_id,visit_id,score,engagement_score,url_for_deduping," "normalized_url,url_for_display)" "VALUES(?,?,?,?,?,?,?)")); + sql::Statement cluster_keywords_statement( + GetDB().GetCachedStatement(SQL_FROM_HERE, + "INSERT INTO cluster_keywords" + "(cluster_id,keyword,type,score,collections)" + "VALUES(?,?,?,?,?)")); for (const auto& cluster : clusters) { if (cluster.visits.empty()) @@ -542,6 +559,23 @@ << "cluster_id = " << cluster_id << ", visit_id = " << visit_id; } }); + + // Insert each keyword into 'cluster_keywords'. + for (const auto& [keyword, keyword_data] : cluster.keyword_to_data_map) { + cluster_keywords_statement.Reset(true); + cluster_keywords_statement.BindInt64(0, cluster_id); + cluster_keywords_statement.BindString16(1, keyword); + cluster_keywords_statement.BindInt(2, keyword_data.type); + cluster_keywords_statement.BindDouble(3, keyword_data.score); + cluster_keywords_statement.BindString( + 4, keyword_data.entity_collections.empty() + ? "" + : keyword_data.entity_collections[0]); + if (!cluster_keywords_statement.Run()) { + DVLOG(0) << "Failed to execute 'cluster_keywords' insert statement: " + << "cluster_id = " << cluster_id << ", keyword = " << keyword; + } + } } } @@ -659,6 +693,27 @@ return 0; } +base::flat_map<std::u16string, ClusterKeywordData> +VisitAnnotationsDatabase::GetClusterKeywords(int64_t cluster_id) { + DCHECK_GT(cluster_id, 0); + sql::Statement statement( + GetDB().GetCachedStatement(SQL_FROM_HERE, + "SELECT keyword,type,score,collections " + "FROM cluster_keywords " + "WHERE cluster_id=?")); + statement.BindInt64(0, cluster_id); + + base::flat_map<std::u16string, ClusterKeywordData> keyword_data; + while (statement.Step()) { + keyword_data[statement.ColumnString16(0)] = { + static_cast<ClusterKeywordData::ClusterKeywordType>( + statement.ColumnInt(1)), + static_cast<float>(statement.ColumnDouble(2)), + DeserializeFromStringColumn(statement.ColumnString(3))}; + } + return keyword_data; +} + void VisitAnnotationsDatabase::DeleteClusters( const std::vector<int64_t>& cluster_ids) { if (cluster_ids.empty()) @@ -670,6 +725,9 @@ sql::Statement clusters_and_visits_statement(GetDB().GetCachedStatement( SQL_FROM_HERE, "DELETE FROM clusters_and_visits WHERE cluster_id=?")); + sql::Statement cluster_keywords_statement(GetDB().GetCachedStatement( + SQL_FROM_HERE, "DELETE FROM cluster_keywords WHERE cluster_id=?")); + for (auto cluster_id : cluster_ids) { clusters_statement.Reset(true); clusters_statement.BindInt64(0, cluster_id); @@ -684,6 +742,13 @@ DVLOG(0) << "Failed to execute clusters_and_visits delete statement: " << "cluster_id = " << cluster_id; } + + cluster_keywords_statement.Reset(true); + cluster_keywords_statement.BindInt64(0, cluster_id); + if (!cluster_keywords_statement.Run()) { + DVLOG(0) << "Failed to execute cluster_keywords delete statement: " + << "cluster_id = " << cluster_id; + } } }
diff --git a/components/history/core/browser/visit_annotations_database.h b/components/history/core/browser/visit_annotations_database.h index 2611086..acd10927 100644 --- a/components/history/core/browser/visit_annotations_database.h +++ b/components/history/core/browser/visit_annotations_database.h
@@ -83,7 +83,8 @@ // entries for any `Cluster` that it failed to add. void AddClusters(const std::vector<Cluster>& clusters); - // Get a `Cluster`. + // Get a `Cluster`. Does not include the cluster's `visits` or + // `keyword_to_data_map`. Cluster GetCluster(int64_t cluster_id); // Get the most recent clusters within the constraints. The most recent visit @@ -102,6 +103,10 @@ // is not in a cluster.` int64_t GetClusterIdContainingVisit(VisitID visit_id); + // Return the keyword data associated with `cluster_id`. + base::flat_map<std::u16string, ClusterKeywordData> GetClusterKeywords( + int64_t cluster_id); + // Delete `Cluster`s from the table. void DeleteClusters(const std::vector<int64_t>& cluster_ids);
diff --git a/components/history/core/browser/visit_annotations_database_unittest.cc b/components/history/core/browser/visit_annotations_database_unittest.cc index a594ad0a..282d024 100644 --- a/components/history/core/browser/visit_annotations_database_unittest.cc +++ b/components/history/core/browser/visit_annotations_database_unittest.cc
@@ -254,7 +254,8 @@ EXPECT_EQ(final.alternative_title, "New alternative title"); } -TEST_F(VisitAnnotationsDatabaseTest, AddClusters_GetCluster_GetClusterVisit) { +TEST_F(VisitAnnotationsDatabaseTest, + AddClusters_GetCluster_GetClusterVisit_GetClusterKeywords) { // Test `AddClusters()`. // Cluster without visits shouldn't be added. @@ -391,7 +392,10 @@ AddContextAnnotationsForVisit(1, {}); AddContentAnnotationsForVisit(2, {}); AddContextAnnotationsForVisit(2, {}); - AddCluster({1, 2}); + auto cluster = CreateCluster({1, 2}); + cluster.keyword_to_data_map[u"keyword1"]; + cluster.keyword_to_data_map[u"keyword2"]; + AddClusters({cluster}); VisitContentAnnotations got_content_annotations; VisitContextAnnotations got_context_annotations; @@ -400,10 +404,11 @@ EXPECT_TRUE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_TRUE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_TRUE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 1); EXPECT_THAT(GetVisitIdsInCluster(1), UnorderedElementsAre(1, 2)); EXPECT_EQ(GetClusterIdContainingVisit(1), 1); EXPECT_EQ(GetClusterIdContainingVisit(2), 1); - EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetClusterKeywords(1).size(), 2u); // Delete 1 visit. Make sure the tables are updated, but the cluster remains. DeleteAnnotationsForVisit(1); @@ -411,10 +416,11 @@ EXPECT_FALSE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_TRUE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_TRUE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 1); EXPECT_THAT(GetVisitIdsInCluster(1), UnorderedElementsAre(2)); EXPECT_EQ(GetClusterIdContainingVisit(1), 0); EXPECT_EQ(GetClusterIdContainingVisit(2), 1); - EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetClusterKeywords(1).size(), 2u); // Delete the 2nd visit. Make sure the cluster is removed. DeleteAnnotationsForVisit(2); @@ -422,31 +428,56 @@ EXPECT_FALSE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_FALSE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_FALSE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 0); EXPECT_TRUE(GetVisitIdsInCluster(1).empty()); EXPECT_EQ(GetClusterIdContainingVisit(1), 0); EXPECT_EQ(GetClusterIdContainingVisit(2), 0); - EXPECT_EQ(GetCluster(1).cluster_id, 0); + EXPECT_EQ(GetClusterKeywords(1).size(), 0u); } TEST_F(VisitAnnotationsDatabaseTest, AddClusters_DeleteClusters) { AddClusters(CreateClusters({{3, 2, 5}, {3, 2, 5}, {6}})); + auto cluster_with_keyword_data = CreateCluster({10}); + cluster_with_keyword_data.keyword_to_data_map[u"keyword1"]; + cluster_with_keyword_data.keyword_to_data_map[u"keyword2"]; + AddClusters({cluster_with_keyword_data}); + + EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 3); + EXPECT_EQ(GetCluster(4).cluster_id, 4); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre(6)); + EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre(10)); + EXPECT_EQ(GetClusterKeywords(4).size(), 2u); DeleteClusters({}); + EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 3); + EXPECT_EQ(GetCluster(4).cluster_id, 4); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre(6)); + EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre(10)); + EXPECT_EQ(GetClusterKeywords(4).size(), 2u); - DeleteClusters({1, 3, 4}); + DeleteClusters({1, 3, 4, 5}); + EXPECT_EQ(GetCluster(1).cluster_id, 0); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 0); + EXPECT_EQ(GetCluster(4).cluster_id, 0); + EXPECT_EQ(GetCluster(5).cluster_id, 0); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre()); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre()); EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre()); + EXPECT_THAT(GetVisitIdsInCluster(5), ElementsAre()); + EXPECT_TRUE(GetClusterKeywords(4).empty()); } } // namespace history
diff --git a/components/history_clusters_strings.grdp b/components/history_clusters_strings.grdp index fe94d0a..2906d7c 100644 --- a/components/history_clusters_strings.grdp +++ b/components/history_clusters_strings.grdp
@@ -30,6 +30,9 @@ <message name="IDS_HISTORY_CLUSTERS_LOAD_MORE_BUTTON_LABEL" desc="A label for the button that loads more history clusters at the bottom of the history clusters list."> Load more </message> + <message name="IDS_HISTORY_CLUSTERS_NO_SEARCH_RESULTS" desc="Text used to denote that there are no search results for a search term in history clusters."> + No search results + </message> <message name="IDS_HISTORY_CLUSTERS_OPEN_ALL_IN_TABGROUP" desc="Label of the item in drop-down menu that allows the user to open a group of urls in a tab group." formatter_data="android_java"> Open all in new tab group
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_NO_SEARCH_RESULTS.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_NO_SEARCH_RESULTS.png.sha1 new file mode 100644 index 0000000..1c02e09 --- /dev/null +++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_NO_SEARCH_RESULTS.png.sha1
@@ -0,0 +1 @@ +1485dbfbf2fc5da5826c5fb6a99a2e3ac4f749be \ No newline at end of file
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 7aa82b5..2006302e 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -538,8 +538,8 @@ if (is_chromeos_ash) { deps += [ + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/network:test_support", - "//chromeos/dbus:test_support", ] } @@ -561,9 +561,7 @@ } if (is_win || is_linux) { - sources += [ - "motherboard_metrics_provider_unittest.cc", - ] + sources += [ "motherboard_metrics_provider_unittest.cc" ] } }
diff --git a/components/metrics/generate_expired_histograms_array.gni b/components/metrics/generate_expired_histograms_array.gni index e649e4ca..8815d1a 100644 --- a/components/metrics/generate_expired_histograms_array.gni +++ b/components/metrics/generate_expired_histograms_array.gni
@@ -39,6 +39,7 @@ "//tools/metrics/histograms/metadata/apps/histograms.xml", "//tools/metrics/histograms/metadata/arc/histograms.xml", "//tools/metrics/histograms/metadata/ash/histograms.xml", + "//tools/metrics/histograms/metadata/ash_clipboard/histograms.xml", "//tools/metrics/histograms/metadata/assistant/histograms.xml", "//tools/metrics/histograms/metadata/auth/histograms.xml", "//tools/metrics/histograms/metadata/auto/histograms.xml",
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc index b76d01ca..1d49ff5 100644 --- a/components/omnibox/browser/base_search_provider.cc +++ b/components/omnibox/browser/base_search_provider.cc
@@ -246,9 +246,15 @@ } // static +bool BaseSearchProvider::IsOtherWebPage( + metrics::OmniboxEventProto::PageClassification classification) { + return (classification == OEP::OTHER) || + (classification == OEP::OTHER_ZPS_PREFETCH); +} + +// static bool BaseSearchProvider::CanSendPageURLInRequest(const GURL& page_url) { - return page_url.is_valid() && (page_url.scheme() == url::kHttpScheme || - page_url.scheme() == url::kHttpsScheme); + return page_url.is_valid() && page_url.SchemeIsHTTPOrHTTPS(); } // static
diff --git a/components/omnibox/browser/base_search_provider.h b/components/omnibox/browser/base_search_provider.h index 6156e71..31e15a3 100644 --- a/components/omnibox/browser/base_search_provider.h +++ b/components/omnibox/browser/base_search_provider.h
@@ -109,6 +109,10 @@ // Returns whether the provided classification indicates Search Results Page. static bool IsSearchResultsPage( metrics::OmniboxEventProto::PageClassification classification); + // Returns whether the provided classification indicates a non-NTP/non-SRP Web + // Page. + static bool IsOtherWebPage( + metrics::OmniboxEventProto::PageClassification classification); // Returns whether a suggest request can be made. It requires that all the // following to hold: // * The suggest request is sent over HTTPS. This avoids leaking the current
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index e5fed181..6d3c13d 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -53,6 +53,7 @@ #include "components/omnibox/common/omnibox_features.h" #include "components/prefs/pref_service.h" #include "components/search_engines/omnibox_focus_type.h" +#include "components/search_engines/search_engine_type.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_prepopulate_data.h" #include "components/search_engines/template_url_service.h" @@ -103,6 +104,11 @@ // enum XML file. const char kEnteredKeywordModeHistogram[] = "Omnibox.EnteredKeywordMode2"; +// Histogram name which counts the number of times the user completes a search +// in keyword mode, enumerated by the type of search engine. +const char kEnteredKeywordModeByEngineTypeHistogram[] = + "Omnibox.EnteredKeywordModeByEngineType"; + // Histogram name which counts the number of milliseconds a user takes // between focusing and editing the omnibox. const char kFocusToEditTimeHistogram[] = "Omnibox.FocusToEditTime"; @@ -116,11 +122,19 @@ // in keyword mode, enumerated by how they enter keyword mode. const char kAcceptedKeywordSuggestion[] = "Omnibox.AcceptedKeywordSuggestion"; -void EmitKeywordHistogram( - OmniboxEventProto::KeywordModeEntryMethod entry_method) { +void EmitEnteredKeywordModeHistogram( + OmniboxEventProto::KeywordModeEntryMethod entry_method, + const TemplateURL* turl) { UMA_HISTOGRAM_ENUMERATION( kEnteredKeywordModeHistogram, static_cast<int>(entry_method), static_cast<int>(OmniboxEventProto::KeywordModeEntryMethod_MAX + 1)); + + if (turl != nullptr) { + UMA_HISTOGRAM_ENUMERATION( + kEnteredKeywordModeByEngineTypeHistogram, + static_cast<int>(turl->GetBuiltinEngineType()), + static_cast<int>(BuiltinEngineType::KEYWORD_MODE_ENGINE_TYPE_MAX)); + } } // `executed_position` should be set to the position of the executed @@ -755,8 +769,9 @@ autocomplete_controller()->Stop(false); - keyword_ = - client_->GetTemplateURLService()->GetDefaultSearchProvider()->keyword(); + const TemplateURL* default_search_provider = + client_->GetTemplateURLService()->GetDefaultSearchProvider(); + keyword_ = default_search_provider->keyword(); is_keyword_hint_ = false; keyword_mode_entry_method_ = entry_method; @@ -773,7 +788,7 @@ if (entry_method == OmniboxEventProto::KEYBOARD_SHORTCUT) view_->SelectAll(false); - EmitKeywordHistogram(entry_method); + EmitEnteredKeywordModeHistogram(entry_method, default_search_provider); } void OmniboxEditModel::ExecuteAction(const AutocompleteMatch& match, @@ -1077,7 +1092,9 @@ } base::RecordAction(base::UserMetricsAction("AcceptedKeywordHint")); - EmitKeywordHistogram(entry_method); + const TemplateURL* turl = + client_->GetTemplateURLService()->GetTemplateURLForKeyword(keyword_); + EmitEnteredKeywordModeHistogram(entry_method, turl); return true; } @@ -1615,7 +1632,9 @@ view_->UpdatePopup(); if (allow_exact_keyword_match_) { keyword_mode_entry_method_ = OmniboxEventProto::SPACE_IN_MIDDLE; - EmitKeywordHistogram(OmniboxEventProto::SPACE_IN_MIDDLE); + const TemplateURL* turl = + client_->GetTemplateURLService()->GetTemplateURLForKeyword(keyword_); + EmitEnteredKeywordModeHistogram(OmniboxEventProto::SPACE_IN_MIDDLE, turl); allow_exact_keyword_match_ = false; }
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index ce514aa9..218f6fc 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -786,7 +786,8 @@ bool IsZeroSuggestPrefetchingEnabled() { return base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetching) || - base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP); + base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) || + base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnWeb); } const base::FeatureParam<bool> kZeroSuggestIgnoreDuplicateVisits(
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index 413b547..6b69b11 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -219,12 +219,13 @@ client->GetPrefs()->SetString(omnibox::kZeroSuggestCachedResults, response_json); LogEvent(Event::kRemoteResponseCached, result_type, is_prefetch); - } else if (base::FeatureList::IsEnabled( - omnibox::kZeroSuggestPrefetchingOnSRP) && - result_type == ZeroSuggestProvider::ResultType::kRemoteSendURL) { - omnibox::SetUserPreferenceForZeroSuggestCachedResponse( - client->GetPrefs(), input.current_url().spec(), response_json); - LogEvent(Event::kRemoteResponseCached, result_type, is_prefetch); + } else if (result_type == ZeroSuggestProvider::ResultType::kRemoteSendURL) { + if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) || + base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnWeb)) { + omnibox::SetUserPreferenceForZeroSuggestCachedResponse( + client->GetPrefs(), input.current_url().spec(), response_json); + LogEvent(Event::kRemoteResponseCached, result_type, is_prefetch); + } } return true; @@ -247,11 +248,12 @@ if (result_type == ZeroSuggestProvider::ResultType::kRemoteNoURL) { response_json = client->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); - } else if (base::FeatureList::IsEnabled( - omnibox::kZeroSuggestPrefetchingOnSRP) && - result_type == ZeroSuggestProvider::ResultType::kRemoteSendURL) { - response_json = omnibox::GetUserPreferenceForZeroSuggestCachedResponse( - client->GetPrefs(), input.current_url().spec()); + } else if (result_type == ZeroSuggestProvider::ResultType::kRemoteSendURL) { + if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnSRP) || + base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchingOnWeb)) { + response_json = omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + client->GetPrefs(), input.current_url().spec()); + } } if (response_json.empty()) { @@ -306,7 +308,7 @@ } // Open Web - does NOT include Search Results Page. - if (page_class == OEP::OTHER) { + if (BaseSearchProvider::IsOtherWebPage(page_class)) { if (focus_type_input_type == std::make_pair(OFT::ON_FOCUS, OIT::URL) && base::FeatureList::IsEnabled( omnibox::kFocusTriggersContextualWebZeroSuggest)) {
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc index 75ae7e6..3ac54da 100644 --- a/components/omnibox/browser/zero_suggest_provider_unittest.cc +++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -160,11 +160,18 @@ return input; } + AutocompleteInput PrefetchingInputForWeb() { + AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER_ZPS_PREFETCH, + TestSchemeClassifier()); + input.set_current_url(GURL("https://example.com/")); + input.set_focus_type(OmniboxFocusType::DELETED_PERMANENT_TEXT); + return input; + } + AutocompleteInput PrefixInputForWeb() { - std::string input_url = "https://example.com/"; AutocompleteInput input(u"foobar", metrics::OmniboxEventProto::OTHER, TestSchemeClassifier()); - input.set_current_url(GURL(input_url)); + input.set_current_url(GURL("https://example.com/")); input.set_focus_type(OmniboxFocusType::DEFAULT); return input; } @@ -191,21 +198,19 @@ } AutocompleteInput PrefetchingInputForSRP() { - std::string input_url = "https://google.com/search?q=omnibox"; AutocompleteInput input(u"", metrics::OmniboxEventProto::SRP_ZPS_PREFETCH, TestSchemeClassifier()); - input.set_current_url(GURL(input_url)); + input.set_current_url(GURL("https://google.com/search?q=omnibox")); input.set_focus_type(OmniboxFocusType::DELETED_PERMANENT_TEXT); return input; } AutocompleteInput PrefixInputForSRP() { - std::string input_url = "https://google.com/search?q=omnibox"; AutocompleteInput input(u"foobar", metrics::OmniboxEventProto:: SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT, TestSchemeClassifier()); - input.set_current_url(GURL(input_url)); + input.set_current_url(GURL("https://google.com/search?q=omnibox")); input.set_focus_type(OmniboxFocusType::DEFAULT); return input; } @@ -242,7 +247,8 @@ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>(); scoped_feature_list_->InitWithFeatures( /*enabled_features=*/{omnibox::kZeroSuggestPrefetching, - omnibox::kZeroSuggestPrefetchingOnSRP}, + omnibox::kZeroSuggestPrefetchingOnSRP, + omnibox::kZeroSuggestPrefetchingOnWeb}, /*disabled_features=*/{}); } @@ -700,6 +706,72 @@ EXPECT_FALSE(provider_did_notify_); } +TEST_F(ZeroSuggestProviderTest, StartStopWeb) { + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + // Set up the pref to cache the response from the previous run. + std::string json_response( + R"(["",["search1", "search2", "search3"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + PrefService* prefs = client_->GetPrefs(); + AutocompleteInput input = OnClobberInputForWeb(); + omnibox::SetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec(), json_response); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + + // Make sure valid input starts the provider. + provider_->Start(input, false); + EXPECT_FALSE(provider_->done()); + // Expect that matches got populated out of cache. + EXPECT_FALSE(provider_->matches().empty()); + // Expect that network request was sent. + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + // Expect the provider to not have notified the provider listener yet. + EXPECT_FALSE(provider_did_notify_); + + // Make sure valid input restarts the provider. + provider_->Start(input, false); + EXPECT_FALSE(provider_->done()); + // Expect that matches got populated out of cache. + EXPECT_FALSE(provider_->matches().empty()); + // Expect that network request was sent. + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + // Expect the provider to not have notified the provider listener yet. + EXPECT_FALSE(provider_did_notify_); + + // Make sure invalid input stops the provider. + AutocompleteInput prefix_input = PrefixInputForWeb(); + provider_->Start(prefix_input, false); + EXPECT_TRUE(provider_->done()); + // Expect that matches did not get populated out of cache. + EXPECT_TRUE(provider_->matches().empty()); + // Expect that network request was not sent. + EXPECT_FALSE(test_loader_factory()->IsPending(suggest_url.spec())); + // Expect the provider to not have notified the provider listener since the + // request was invalidated. + EXPECT_FALSE(provider_did_notify_); + + // Make sure valid input restarts the provider. + provider_->Start(input, false); + EXPECT_FALSE(provider_->done()); + // Expect that matches got populated out of cache. + EXPECT_FALSE(provider_->matches().empty()); + // Expect that network request was sent. + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + // Expect the provider to not have notified the provider listener yet. + EXPECT_FALSE(provider_did_notify_); +} + TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestCachingFirstRunNTP) { base::HistogramTester histogram_tester; @@ -819,6 +891,70 @@ prefs, input.current_url().spec())); } +TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestCachingFirstRunWeb) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + AutocompleteInput input = OnClobberInputForWeb(); + provider_->Start(input, false); + ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, + provider_->GetResultTypeRunningForTesting()); + + EXPECT_TRUE(provider_->matches().empty()); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + + std::string json_response( + R"(["",["search1", "search2", "search3"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + test_loader_factory()->AddResponse(suggest_url.spec(), json_response); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(provider_->done()); + + // Expect correct histograms to have been logged. + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 4); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 1 /*REQUEST_SENT*/, + 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 3 /*REMOTE_RESPONSE_RECEIVED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 4 /*REMOTE_RESPONSE_CACHED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 5 /*REMOTE_RESPONSE_CONVERTED_TO_MATCHES*/, 1); + + // Expect the provider to have notified the provider listener. + EXPECT_TRUE(provider_did_notify_); + + EXPECT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + PrefService* prefs = client_->GetPrefs(); + EXPECT_EQ(json_response, + omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec())); +} + TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestOmitAsynchronousMatchesTrueNTP) { EXPECT_CALL(*client_, IsAuthenticated()) @@ -888,6 +1024,44 @@ EXPECT_FALSE(provider_did_notify_); } +TEST_F(ZeroSuggestProviderTest, + TestPsuggestZeroSuggestOmitAsynchronousMatchesTrueWeb) { + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + AutocompleteInput input = OnClobberInputForWeb(); + input.set_omit_asynchronous_matches(true); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + + // Ensure the cache is empty. + PrefService* prefs = client_->GetPrefs(); + prefs->SetString(omnibox::kZeroSuggestCachedResults, ""); + prefs->SetDict(omnibox::kZeroSuggestCachedResultsWithURL, + base::Value::Dict()); + + provider_->Start(input, false); + ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, + provider_->GetResultTypeRunningForTesting()); + EXPECT_TRUE(provider_->done()); + EXPECT_TRUE(provider_->matches().empty()); + + // There should be no pending network requests, given that asynchronous logic + // has been explicitly disabled (`omit_asynchronous_matches_ == true`). + ASSERT_FALSE(test_loader_factory()->IsPending(suggest_url.spec())); + + // Expect the provider to not have notified the provider listener since the + // request was not sent. + EXPECT_FALSE(provider_did_notify_); +} + TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestHasCachedResultsNTP) { base::HistogramTester histogram_tester; @@ -1042,6 +1216,88 @@ prefs, input.current_url().spec())); } +TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestHasCachedResultsWeb) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + // Set up the pref to cache the response from the previous run. + std::string json_response( + R"(["",["search1", "search2", "search3"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + PrefService* prefs = client_->GetPrefs(); + AutocompleteInput input = OnClobberInputForWeb(); + omnibox::SetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec(), json_response); + + provider_->Start(input, false); + ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, + provider_->GetResultTypeRunningForTesting()); + + // Expect that matches get populated synchronously out of the cache. + ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + EXPECT_EQ(u"search1", provider_->matches()[0].contents); + EXPECT_EQ(u"search2", provider_->matches()[1].contents); + EXPECT_EQ(u"search3", provider_->matches()[2].contents); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + std::string json_response2( + R"(["",["search4", "search5", "search6"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + test_loader_factory()->AddResponse(suggest_url.spec(), json_response2); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(provider_->done()); + + // Expect the provider to not have notified the provider listener when using + // the cached response. + EXPECT_FALSE(provider_did_notify_); + + // Expect correct histograms to have been logged. + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 4); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 1 /*REQUEST_SENT*/, + 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 3 /*REMOTE_RESPONSE_RECEIVED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 4 /*REMOTE_RESPONSE_CACHED*/, 1); + + // Expect the same results after the response has been handled. + ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + EXPECT_EQ(u"search1", provider_->matches()[0].contents); + EXPECT_EQ(u"search2", provider_->matches()[1].contents); + EXPECT_EQ(u"search3", provider_->matches()[2].contents); + + // Expect the new results to have been stored. + EXPECT_EQ(json_response2, + omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec())); +} + TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestReceivedEmptyResultsNTP) { base::HistogramTester histogram_tester; @@ -1190,6 +1446,85 @@ prefs, input.current_url().spec())); } +TEST_F(ZeroSuggestProviderTest, + TestPsuggestZeroSuggestReceivedEmptyResultsWeb) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + // Set up the pref to cache the response from the previous run. + std::string json_response( + R"(["",["search1", "search2", "search3"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + PrefService* prefs = client_->GetPrefs(); + AutocompleteInput input = OnClobberInputForWeb(); + omnibox::SetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec(), json_response); + + provider_->Start(input, false); + ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, + provider_->GetResultTypeRunningForTesting()); + + // Expect that matches get populated synchronously out of the cache. + ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + EXPECT_EQ(u"search1", provider_->matches()[0].contents); + EXPECT_EQ(u"search2", provider_->matches()[1].contents); + EXPECT_EQ(u"search3", provider_->matches()[2].contents); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + std::string empty_response(R"(["",[],[],[],{}])"); + test_loader_factory()->AddResponse(suggest_url.spec(), empty_response); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(provider_->done()); + + // Expect correct histograms to have been logged. + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 5); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 1 /*REQUEST_SENT*/, + 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 3 /*REMOTE_RESPONSE_RECEIVED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 4 /*REMOTE_RESPONSE_CACHED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 5 /*REMOTE_RESPONSE_CONVERTED_TO_MATCHES*/, 1); + + // Expect the provider to have notified the provider listener. + EXPECT_TRUE(provider_did_notify_); + + // Expect that the matches have been cleared. + ASSERT_TRUE(provider_->matches().empty()); + + // Expect the new results to have been stored. + EXPECT_EQ(empty_response, + omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec())); +} + TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestPrefetchThenNTPOnFocus) { EXPECT_CALL(*client_, IsAuthenticated()) .WillRepeatedly(testing::Return(true)); @@ -1460,3 +1795,144 @@ prefs, input.current_url().spec())); } } + +TEST_F(ZeroSuggestProviderTest, + TestPsuggestZeroSuggestPrefetchThenWebOnClobber) { + EXPECT_CALL(*client_, IsAuthenticated()) + .WillRepeatedly(testing::Return(true)); + + // Enable on-clobber ZPS. + base::test::ScopedFeatureList features; + features.InitAndEnableFeature( + omnibox::kClobberTriggersContextualWebZeroSuggest); + + // Set up the pref to cache the response from the previous run. + std::string json_response( + R"(["",["search1", "search2", "search3"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + PrefService* prefs = client_->GetPrefs(); + AutocompleteInput input = PrefetchingInputForWeb(); + omnibox::SetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec(), json_response); + + { + base::HistogramTester histogram_tester; + + // Start a prefetch request. + provider_->StartPrefetch(input); + EXPECT_TRUE(provider_->done()); + + // Expect the results to be empty. + ASSERT_EQ(0U, provider_->matches().size()); + + GURL suggest_url = GetSuggestURL( + metrics::OmniboxEventProto::OTHER_ZPS_PREFETCH, + OmniboxFocusType::DELETED_PERMANENT_TEXT, input.current_url().spec()); + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + std::string json_response2( + R"(["",["search4", "search5", "search6"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + test_loader_factory()->AddResponse(suggest_url.spec(), json_response2); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(provider_->done()); + + // Expect correct histograms to have been logged. + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 3); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 0); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 1 /*REQUEST_SENT*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", + 3 /*REMOTE_RESPONSE_RECEIVED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", + 4 /*REMOTE_RESPONSE_CACHED*/, 1); + + // Expect the provider to not have notified the provider listener since the + // matches were not updated. + EXPECT_FALSE(provider_did_notify_); + + // Expect the same empty results after the response has been handled. + ASSERT_EQ(0U, provider_->matches().size()); + + // Expect the new response to have been stored in the pref. + EXPECT_EQ(json_response2, + omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec())); + } + { + base::HistogramTester histogram_tester; + + // Start a non-prefetch request. + AutocompleteInput input = OnClobberInputForWeb(); + provider_->Start(input, false); + EXPECT_FALSE(provider_->done()); + ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, + provider_->GetResultTypeRunningForTesting()); + + // Expect the results from the cached response. + ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + EXPECT_EQ(u"search4", provider_->matches()[0].contents); + EXPECT_EQ(u"search5", provider_->matches()[1].contents); + EXPECT_EQ(u"search6", provider_->matches()[2].contents); + + GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER, + OmniboxFocusType::DELETED_PERMANENT_TEXT, + input.current_url().spec()); + EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec())); + std::string json_response3( + R"(["",["search7", "search8", "search9"],)" + R"([],[],{"google:suggestrelevance":[602, 601, 600],)" + R"("google:verbatimrelevance":1300}])"); + test_loader_factory()->AddResponse(suggest_url.spec(), json_response3); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(provider_->done()); + + // Expect correct histograms to have been logged. + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.NoURL.NonPrefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.Prefetch", 0); + histogram_tester.ExpectTotalCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 4); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 0 /*CACHED_RESPONSE_CONVERTED_TO_MATCHES*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", 1 /*REQUEST_SENT*/, + 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 3 /*REMOTE_RESPONSE_RECEIVED*/, 1); + histogram_tester.ExpectBucketCount( + "Omnibox.ZeroSuggestProvider.URLBased.NonPrefetch", + 4 /*REMOTE_RESPONSE_CACHED*/, 1); + + // Expect the provider to not have notified the provider listener since the + // matches were not updated. + EXPECT_FALSE(provider_did_notify_); + + // Expect the same results after the response has been handled. + ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match + EXPECT_EQ(u"search4", provider_->matches()[0].contents); + EXPECT_EQ(u"search5", provider_->matches()[1].contents); + EXPECT_EQ(u"search6", provider_->matches()[2].contents); + + // Expect the new response to have been stored in the pref. + EXPECT_EQ(json_response3, + omnibox::GetUserPreferenceForZeroSuggestCachedResponse( + prefs, input.current_url().spec())); + } +}
diff --git a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc index dbb94e2..b3edfbe 100644 --- a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
@@ -121,6 +121,15 @@ } page_load_metrics::PageLoadMetricsObserver::ObservePolicy +BackForwardCachePageLoadMetricsObserver::OnPrerenderStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) { + // This class mainly interested in the behavior after entreing Back/Forward + // Cache. Works as same as non prerendering case. + return CONTINUE_OBSERVING; +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy BackForwardCachePageLoadMetricsObserver::OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) { if (!in_back_forward_cache_) { @@ -173,6 +182,13 @@ PageLoadMetricsObserver::ObservePolicy policy = PageLoadMetricsObserver::ShouldObserveMimeType(mime_type); if (policy == STOP_OBSERVING && has_ever_entered_back_forward_cache_) { + // We should not record UKMs while prerendering. But the page in + // prerendering is not eligible for Back/Forward Cache and + // `has_ever_entered_back_forward_cache_` implies the page is not in + // prerendering. So, we can record UKM safely. + DCHECK_NE(GetDelegate().GetPrerenderingState(), + page_load_metrics::PrerenderingState::kInPrerendering); + ukm::builders::UserPerceivedPageVisit( GetLastUkmSourceIdForBackForwardCacheRestore()) .SetNotCountedForCoreWebVitals(true)
diff --git a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h index 5db58c0..a474fff4 100644 --- a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h +++ b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h
@@ -68,6 +68,9 @@ page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnFencedFramesStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) override; + page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnPrerenderStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) override; page_load_metrics::PageLoadMetricsObserver::ObservePolicy OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) override; page_load_metrics::PageLoadMetricsObserver::ObservePolicy
diff --git a/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc index a3cd0c0..b51f097 100644 --- a/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc
@@ -38,13 +38,29 @@ return STOP_OBSERVING; } +page_load_metrics::PageLoadMetricsObserver::ObservePolicy +LayoutPageLoadMetricsObserver::OnPrerenderStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) { + // This class works as same as non prerendering case. + return CONTINUE_OBSERVING; +} + void LayoutPageLoadMetricsObserver::OnComplete(const mojom::PageLoadTiming&) { + if (GetDelegate().IsInPrerenderingBeforeActivationStart()) { + return; + } + Record(GetDelegate().GetPageRenderData()); } PageLoadMetricsObserver::ObservePolicy LayoutPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground( const mojom::PageLoadTiming&) { + if (GetDelegate().IsInPrerenderingBeforeActivationStart()) { + return STOP_OBSERVING; + } + Record(GetDelegate().GetPageRenderData()); // Record() should be called once per page. return STOP_OBSERVING;
diff --git a/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.h index 31c952f..fcbf1a91 100644 --- a/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.h +++ b/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.h
@@ -19,6 +19,8 @@ ObservePolicy OnFencedFramesStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) override; + ObservePolicy OnPrerenderStart(content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url) override; void OnComplete(const mojom::PageLoadTiming& timing) override; ObservePolicy FlushMetricsOnAppEnterBackground( const mojom::PageLoadTiming& timing) override;
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc index 6bdd0e0..955c24b 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -21,10 +21,10 @@ #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/unique_ids.h" #include "components/password_manager/core/browser/password_form.h"
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index 4ce0109..d5602c27 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -18,10 +18,10 @@ #include "build/build_config.h" #include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/randomized_encoder.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/signatures.h"
diff --git a/components/performance_manager/features.cc b/components/performance_manager/features.cc index 1d7a7932..41e2fcc 100644 --- a/components/performance_manager/features.cc +++ b/components/performance_manager/features.cc
@@ -28,7 +28,10 @@ "BatterySaverModeAvailable", base::FEATURE_DISABLED_BY_DEFAULT}; const base::FeatureParam<base::TimeDelta> kHighEfficiencyModeTimeBeforeDiscard{ - &kHighEfficiencyModeAvailable, "time_before_discard", base::Minutes(5)}; + &kHighEfficiencyModeAvailable, "time_before_discard", base::Hours(2)}; + +extern const base::FeatureParam<bool> kHighEfficiencyModeDefaultState{ + &kHighEfficiencyModeAvailable, "default_state", false}; #endif const base::Feature kBFCachePerformanceManagerPolicy{
diff --git a/components/performance_manager/public/features.h b/components/performance_manager/public/features.h index ea991d03..122bcd1e 100644 --- a/components/performance_manager/public/features.h +++ b/components/performance_manager/public/features.h
@@ -40,6 +40,9 @@ // High-Efficiency Mode. extern const base::FeatureParam<base::TimeDelta> kHighEfficiencyModeTimeBeforeDiscard; + +// The default state of the high-efficiency mode pref +extern const base::FeatureParam<bool> kHighEfficiencyModeDefaultState; #endif // Policy that evicts the BFCache of pages that become non visible or the
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc index 5f1e5ad..65de1e6 100644 --- a/components/permissions/permission_util.cc +++ b/components/permissions/permission_util.cc
@@ -156,7 +156,8 @@ case ContentSettingsType::BACKGROUND_SYNC: *out = PermissionType::BACKGROUND_SYNC; break; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \ + BUILDFLAG(IS_FUCHSIA) case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER: *out = PermissionType::PROTECTED_MEDIA_IDENTIFIER; break; @@ -228,7 +229,8 @@ case ContentSettingsType::MEDIASTREAM_CAMERA: case ContentSettingsType::MEDIASTREAM_MIC: case ContentSettingsType::BACKGROUND_SYNC: -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \ + BUILDFLAG(IS_FUCHSIA) case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER: #endif case ContentSettingsType::SENSORS: @@ -313,7 +315,8 @@ case PermissionType::GEOLOCATION: return ContentSettingsType::GEOLOCATION; case PermissionType::PROTECTED_MEDIA_IDENTIFIER: -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \ + BUILDFLAG(IS_FUCHSIA) return ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER; #else break; @@ -398,7 +401,8 @@ return PermissionType::AUDIO_CAPTURE; case ContentSettingsType::BACKGROUND_SYNC: return PermissionType::BACKGROUND_SYNC; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \ + BUILDFLAG(IS_FUCHSIA) case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER: return PermissionType::PROTECTED_MEDIA_IDENTIFIER; #endif
diff --git a/components/policy/core/browser/configuration_policy_pref_store.cc b/components/policy/core/browser/configuration_policy_pref_store.cc index 88648aa0..bfee2f4 100644 --- a/components/policy/core/browser/configuration_policy_pref_store.cc +++ b/components/policy/core/browser/configuration_policy_pref_store.cc
@@ -88,11 +88,10 @@ return true; } -std::unique_ptr<base::DictionaryValue> ConfigurationPolicyPrefStore::GetValues() - const { +base::Value::Dict ConfigurationPolicyPrefStore::GetValues() const { if (!prefs_) - return std::make_unique<base::DictionaryValue>(); - return prefs_->AsDictionaryValue(); + return base::Value::Dict(); + return prefs_->AsDict(); } void ConfigurationPolicyPrefStore::OnPolicyUpdated(const PolicyNamespace& ns,
diff --git a/components/policy/core/browser/configuration_policy_pref_store.h b/components/policy/core/browser/configuration_policy_pref_store.h index b5c12e0..e1ce4f5 100644 --- a/components/policy/core/browser/configuration_policy_pref_store.h +++ b/components/policy/core/browser/configuration_policy_pref_store.h
@@ -49,7 +49,7 @@ bool IsInitializationComplete() const override; bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; // PolicyService::Observer methods: void OnPolicyUpdated(const PolicyNamespace& ns,
diff --git a/components/prefs/default_pref_store.cc b/components/prefs/default_pref_store.cc index 2c86687..c2570e372 100644 --- a/components/prefs/default_pref_store.cc +++ b/components/prefs/default_pref_store.cc
@@ -18,8 +18,8 @@ return prefs_.GetValue(key, result); } -std::unique_ptr<base::DictionaryValue> DefaultPrefStore::GetValues() const { - return prefs_.AsDictionaryValue(); +base::Value::Dict DefaultPrefStore::GetValues() const { + return prefs_.AsDict(); } void DefaultPrefStore::AddObserver(PrefStore::Observer* observer) {
diff --git a/components/prefs/default_pref_store.h b/components/prefs/default_pref_store.h index d6b691b6..60abda81 100644 --- a/components/prefs/default_pref_store.h +++ b/components/prefs/default_pref_store.h
@@ -27,7 +27,7 @@ // PrefStore implementation: bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/components/prefs/in_memory_pref_store.cc b/components/prefs/in_memory_pref_store.cc index 1eb5e9f..13d169a9 100644 --- a/components/prefs/in_memory_pref_store.cc +++ b/components/prefs/in_memory_pref_store.cc
@@ -19,8 +19,8 @@ return prefs_.GetValue(key, value); } -std::unique_ptr<base::DictionaryValue> InMemoryPrefStore::GetValues() const { - return prefs_.AsDictionaryValue(); +base::Value::Dict InMemoryPrefStore::GetValues() const { + return prefs_.AsDict(); } bool InMemoryPrefStore::GetMutableValue(const std::string& key,
diff --git a/components/prefs/in_memory_pref_store.h b/components/prefs/in_memory_pref_store.h index ed21f7e0..0e7dc6bd 100644 --- a/components/prefs/in_memory_pref_store.h +++ b/components/prefs/in_memory_pref_store.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/observer_list.h" +#include "base/values.h" #include "components/prefs/persistent_pref_store.h" #include "components/prefs/pref_value_map.h" @@ -28,7 +29,7 @@ // PrefStore implementation. bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/components/prefs/json_pref_store.cc b/components/prefs/json_pref_store.cc index 40115a0..e8718a0 100644 --- a/components/prefs/json_pref_store.cc +++ b/components/prefs/json_pref_store.cc
@@ -179,8 +179,8 @@ return true; } -std::unique_ptr<base::DictionaryValue> JsonPrefStore::GetValues() const { - return prefs_->CreateDeepCopy(); +base::Value::Dict JsonPrefStore::GetValues() const { + return prefs_->GetDict().Clone(); } void JsonPrefStore::AddObserver(PrefStore::Observer* observer) {
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h index c9a132a..8322bc2 100644 --- a/components/prefs/json_pref_store.h +++ b/components/prefs/json_pref_store.h
@@ -20,6 +20,7 @@ #include "base/observer_list.h" #include "base/sequence_checker.h" #include "base/task/thread_pool.h" +#include "base/values.h" #include "components/prefs/persistent_pref_store.h" #include "components/prefs/pref_filter.h" #include "components/prefs/prefs_export.h" @@ -27,14 +28,12 @@ class PrefFilter; namespace base { -class DictionaryValue; class FilePath; class JsonPrefStoreCallbackTest; class JsonPrefStoreLossyWriteTest; class SequencedTaskRunner; class WriteCallbacksObserver; -class Value; -} +} // namespace base // A writable PrefStore implementation that is used for user preferences. class COMPONENTS_PREFS_EXPORT JsonPrefStore @@ -77,7 +76,7 @@ // PrefStore overrides: bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/components/prefs/overlay_user_pref_store.cc b/components/prefs/overlay_user_pref_store.cc index 1b0299bf..2ecbb657 100644 --- a/components/prefs/overlay_user_pref_store.cc +++ b/components/prefs/overlay_user_pref_store.cc
@@ -86,7 +86,7 @@ return persistent_user_pref_store_->GetValue(key, result); } -std::unique_ptr<base::DictionaryValue> OverlayUserPrefStore::GetValues() const { +base::Value::Dict OverlayUserPrefStore::GetValues() const { auto values = ephemeral_user_pref_store_->GetValues(); auto persistent_values = persistent_user_pref_store_->GetValues(); @@ -95,9 +95,10 @@ // overwritten by the content of |persistent_user_pref_store_| (the persistent // store). for (const auto& key : persistent_names_set_) { - absl::optional<base::Value> out_value = persistent_values->ExtractPath(key); + absl::optional<base::Value> out_value = + persistent_values.ExtractByDottedPath(key); if (out_value.has_value()) { - values->SetPath(key, std::move(*out_value)); + values.SetByDottedPath(key, std::move(*out_value)); } } return values;
diff --git a/components/prefs/overlay_user_pref_store.h b/components/prefs/overlay_user_pref_store.h index d4f676c..bcee6577 100644 --- a/components/prefs/overlay_user_pref_store.h +++ b/components/prefs/overlay_user_pref_store.h
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" +#include "base/values.h" #include "components/prefs/persistent_pref_store.h" #include "components/prefs/pref_value_map.h" #include "components/prefs/prefs_export.h" @@ -44,7 +45,7 @@ bool IsInitializationComplete() const override; bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; // Methods of PersistentPrefStore. bool GetMutableValue(const std::string& key, base::Value** result) override;
diff --git a/components/prefs/overlay_user_pref_store_unittest.cc b/components/prefs/overlay_user_pref_store_unittest.cc index 067188d9..c1b701d 100644 --- a/components/prefs/overlay_user_pref_store_unittest.cc +++ b/components/prefs/overlay_user_pref_store_unittest.cc
@@ -261,17 +261,19 @@ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); auto values = overlay_->GetValues(); - const Value* value = nullptr; // Check that an overlay preference is returned. - ASSERT_TRUE(values->Get(persistent_key, &value)); + const Value* value = values.FindByDottedPath(persistent_key); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(42), *value); // Check that an underlay preference is returned. - ASSERT_TRUE(values->Get(regular_key, &value)); + value = values.FindByDottedPath(regular_key); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(43), *value); // Check that the overlay is preferred. - ASSERT_TRUE(values->Get(shared_key, &value)); + value = values.FindByDottedPath(shared_key); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(43), *value); }
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc index 2a0810a9..5d736f9f 100644 --- a/components/prefs/pref_service.cc +++ b/components/prefs/pref_service.cc
@@ -62,7 +62,7 @@ if (!pref_store) return; auto values = pref_store->GetValues(); - for (auto item : values->DictItems()) { + for (auto item : values) { // If the key already presents, skip it as a store with higher precedence // already sets the entry. if (pref_changed_map->find(item.first) != pref_changed_map->end())
diff --git a/components/prefs/pref_store.h b/components/prefs/pref_store.h index 4c0a4bd0..4ffde0a 100644 --- a/components/prefs/pref_store.h +++ b/components/prefs/pref_store.h
@@ -9,13 +9,9 @@ #include <string> #include "base/memory/ref_counted.h" +#include "base/values.h" #include "components/prefs/prefs_export.h" -namespace base { -class DictionaryValue; -class Value; -} - // This is an abstract interface for reading and writing from/to a persistent // preference store, used by PrefService. An implementation using a JSON file // can be found in JsonPrefStore, while an implementation without any backing @@ -56,8 +52,8 @@ virtual bool GetValue(const std::string& key, const base::Value** result) const = 0; - // Get all the values. Never returns a null pointer. - virtual std::unique_ptr<base::DictionaryValue> GetValues() const = 0; + // Get all the values. + virtual base::Value::Dict GetValues() const = 0; protected: friend class base::RefCounted<PrefStore>;
diff --git a/components/prefs/pref_value_map.cc b/components/prefs/pref_value_map.cc index 168638d2..6f88ede 100644 --- a/components/prefs/pref_value_map.cc +++ b/components/prefs/pref_value_map.cc
@@ -169,10 +169,10 @@ differing_keys->push_back(other_pref->first); } -std::unique_ptr<base::DictionaryValue> PrefValueMap::AsDictionaryValue() const { - auto dictionary = std::make_unique<base::DictionaryValue>(); +base::Value::Dict PrefValueMap::AsDict() const { + base::Value::Dict dictionary; for (const auto& value : prefs_) - dictionary->SetPath(value.first, value.second.Clone()); + dictionary.SetByDottedPath(value.first, value.second.Clone()); return dictionary; }
diff --git a/components/prefs/pref_value_map.h b/components/prefs/pref_value_map.h index 94f26b2..794acb1 100644 --- a/components/prefs/pref_value_map.h +++ b/components/prefs/pref_value_map.h
@@ -6,17 +6,12 @@ #define COMPONENTS_PREFS_PREF_VALUE_MAP_H_ #include <map> -#include <memory> #include <string> #include <vector> +#include "base/values.h" #include "components/prefs/prefs_export.h" -namespace base { -class DictionaryValue; -class Value; -} - // A generic string to value map used by the PrefStore implementations. class COMPONENTS_PREFS_EXPORT PrefValueMap { public: @@ -89,8 +84,8 @@ void GetDifferingKeys(const PrefValueMap* other, std::vector<std::string>* differing_keys) const; - // Copies the map into a dictionary value. - std::unique_ptr<base::DictionaryValue> AsDictionaryValue() const; + // Copies the map into a Value::Dict. + base::Value::Dict AsDict() const; private: Map prefs_;
diff --git a/components/prefs/segregated_pref_store.cc b/components/prefs/segregated_pref_store.cc index 0f1ab05e..82fef703 100644 --- a/components/prefs/segregated_pref_store.cc +++ b/components/prefs/segregated_pref_store.cc
@@ -89,14 +89,15 @@ return StoreForKey(key)->GetValue(key, result); } -std::unique_ptr<base::DictionaryValue> SegregatedPrefStore::GetValues() const { - auto values = default_pref_store_->GetValues(); - auto selected_pref_store_values = selected_pref_store_->GetValues(); +base::Value::Dict SegregatedPrefStore::GetValues() const { + base::Value::Dict values = default_pref_store_->GetValues(); + base::Value::Dict selected_pref_store_values = + selected_pref_store_->GetValues(); for (const auto& key : selected_preference_names_) { - if (const base::Value* value = selected_pref_store_values->FindPath(key)) { - values->SetPath(key, value->Clone()); + if (base::Value* value = selected_pref_store_values.FindByDottedPath(key)) { + values.SetByDottedPath(key, std::move(*value)); } else { - values->RemoveKey(key); + values.Remove(key); } } return values;
diff --git a/components/prefs/segregated_pref_store.h b/components/prefs/segregated_pref_store.h index 2c172050..61aa3ad 100644 --- a/components/prefs/segregated_pref_store.h +++ b/components/prefs/segregated_pref_store.h
@@ -54,7 +54,7 @@ bool IsInitializationComplete() const override; bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; // WriteablePrefStore implementation void SetValue(const std::string& key,
diff --git a/components/prefs/segregated_pref_store_unittest.cc b/components/prefs/segregated_pref_store_unittest.cc index 4014acd..3a1ef88 100644 --- a/components/prefs/segregated_pref_store_unittest.cc +++ b/components/prefs/segregated_pref_store_unittest.cc
@@ -378,17 +378,19 @@ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); auto values = segregated_store_->GetValues(); - const base::Value* value = nullptr; // Check that a selected preference is returned. - ASSERT_TRUE(values->Get(kSelectedPref, &value)); + const base::Value* value = values.Find(kSelectedPref); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(kValue1), *value); // Check that a a default preference is returned. - ASSERT_TRUE(values->Get(kUnselectedPref, &value)); + value = values.Find(kUnselectedPref); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(kValue2), *value); // Check that the selected preference is preferred. - ASSERT_TRUE(values->Get(kSharedPref, &value)); + value = values.Find(kSharedPref); + ASSERT_TRUE(value); EXPECT_EQ(base::Value(kValue1), *value); }
diff --git a/components/prefs/testing_pref_store.cc b/components/prefs/testing_pref_store.cc index 5d3d1ec..27f61f5b 100644 --- a/components/prefs/testing_pref_store.cc +++ b/components/prefs/testing_pref_store.cc
@@ -26,8 +26,8 @@ return prefs_.GetValue(key, value); } -std::unique_ptr<base::DictionaryValue> TestingPrefStore::GetValues() const { - return prefs_.AsDictionaryValue(); +base::Value::Dict TestingPrefStore::GetValues() const { + return prefs_.AsDict(); } bool TestingPrefStore::GetMutableValue(const std::string& key,
diff --git a/components/prefs/testing_pref_store.h b/components/prefs/testing_pref_store.h index a4b5d000..8e0e0b3 100644 --- a/components/prefs/testing_pref_store.h +++ b/components/prefs/testing_pref_store.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/observer_list.h" +#include "base/values.h" #include "components/prefs/persistent_pref_store.h" #include "components/prefs/pref_value_map.h" @@ -27,7 +28,7 @@ // Overriden from PrefStore. bool GetValue(const std::string& key, const base::Value** result) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/components/prefs/value_map_pref_store.cc b/components/prefs/value_map_pref_store.cc index 14fa1ee..a4c0d022 100644 --- a/components/prefs/value_map_pref_store.cc +++ b/components/prefs/value_map_pref_store.cc
@@ -17,8 +17,8 @@ return prefs_.GetValue(key, value); } -std::unique_ptr<base::DictionaryValue> ValueMapPrefStore::GetValues() const { - return prefs_.AsDictionaryValue(); +base::Value::Dict ValueMapPrefStore::GetValues() const { + return prefs_.AsDict(); } void ValueMapPrefStore::AddObserver(PrefStore::Observer* observer) {
diff --git a/components/prefs/value_map_pref_store.h b/components/prefs/value_map_pref_store.h index 68c0b0e..d1083c11 100644 --- a/components/prefs/value_map_pref_store.h +++ b/components/prefs/value_map_pref_store.h
@@ -11,6 +11,7 @@ #include <string> #include "base/observer_list.h" +#include "base/values.h" #include "components/prefs/pref_value_map.h" #include "components/prefs/prefs_export.h" #include "components/prefs/writeable_pref_store.h" @@ -27,7 +28,7 @@ // PrefStore overrides: bool GetValue(const std::string& key, const base::Value** value) const override; - std::unique_ptr<base::DictionaryValue> GetValues() const override; + base::Value::Dict GetValues() const override; void AddObserver(PrefStore::Observer* observer) override; void RemoveObserver(PrefStore::Observer* observer) override; bool HasObservers() const override;
diff --git a/components/search_engines/search_engine_type.h b/components/search_engines/search_engine_type.h index 2d99e020..3b1dc0c 100644 --- a/components/search_engines/search_engine_type.h +++ b/components/search_engines/search_engine_type.h
@@ -82,4 +82,18 @@ SEARCH_ENGINE_MAX // Bounding value needed for UMA histogram macro. }; +// Enum to record the type of search engine a user used in keyword mode. This +// should be kept aligned with the `OmniboxBuiltinEngineType` enum in enums.xml. +// Entries should not be renumbered and numeric values should never be reused. +enum BuiltinEngineType { + KEYWORD_MODE_NON_BUILT_IN = 0, + KEYWORD_MODE_PREPOPULATED_ENGINE = 1, + KEYWORD_MODE_STARTER_PACK_BOOKMARKS = 2, + KEYWORD_MODE_STARTER_PACK_HISTORY = 3, + KEYWORD_MODE_STARTER_PACK_TABS = 4, + + KEYWORD_MODE_ENGINE_TYPE_MAX // Bounding value needed for UMA histogram + // macro. +}; + #endif // COMPONENTS_SEARCH_ENGINES_SEARCH_ENGINE_TYPE_H_
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc index 3f57613..72f9652 100644 --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc
@@ -40,6 +40,7 @@ #include "google_apis/google_api_keys.h" #include "net/base/mime_util.h" #include "net/base/url_util.h" +#include "template_url_starter_pack_data.h" #include "third_party/metrics_proto/omnibox_input_type.pb.h" #include "ui/base/device_form_factor.h" #include "url/gurl.h" @@ -1577,6 +1578,26 @@ return engine_type_; } +BuiltinEngineType TemplateURL::GetBuiltinEngineType() const { + if (data_.prepopulate_id != 0) { + return KEYWORD_MODE_PREPOPULATED_ENGINE; + } else if (data_.starter_pack_id != 0) { + switch (data_.starter_pack_id) { + case TemplateURLStarterPackData::kBookmarks: + return KEYWORD_MODE_STARTER_PACK_BOOKMARKS; + case TemplateURLStarterPackData::kHistory: + return KEYWORD_MODE_STARTER_PACK_HISTORY; + case TemplateURLStarterPackData::kTabs: + return KEYWORD_MODE_STARTER_PACK_TABS; + default: + NOTREACHED(); + return KEYWORD_MODE_NON_BUILT_IN; + } + } else { + return KEYWORD_MODE_NON_BUILT_IN; + } +} + bool TemplateURL::ExtractSearchTermsFromURL( const GURL& url, const SearchTermsData& search_terms_data,
diff --git a/components/search_engines/template_url.h b/components/search_engines/template_url.h index b858d9c..baff8c6 100644 --- a/components/search_engines/template_url.h +++ b/components/search_engines/template_url.h
@@ -802,6 +802,10 @@ SearchEngineType GetEngineType( const SearchTermsData& search_terms_data) const; + // Returns the type of this search engine, i.e. whether the engine is a + // prepopulated engine, starter pack engine, or not built-in. + BuiltinEngineType GetBuiltinEngineType() const; + // Use the alternate URLs and the search URL to match the provided |url| // and extract |search_terms| from it. Returns false and an empty // |search_terms| if no search terms can be matched. The URLs are matched in
diff --git a/components/services/app_service/public/cpp/features.cc b/components/services/app_service/public/cpp/features.cc index cc1c6b20..b68b645 100644 --- a/components/services/app_service/public/cpp/features.cc +++ b/components/services/app_service/public/cpp/features.cc
@@ -18,4 +18,7 @@ const base::Feature kAppServiceUninstallWithoutMojom{ "AppServiceUninstallWithoutMojom", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kAppServiceWithoutMojom{"AppServiceWithoutMojom", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace apps
diff --git a/components/services/app_service/public/cpp/features.h b/components/services/app_service/public/cpp/features.h index a5faf22..99dc36a 100644 --- a/components/services/app_service/public/cpp/features.h +++ b/components/services/app_service/public/cpp/features.h
@@ -18,6 +18,8 @@ extern const base::Feature kAppServiceSetPermissionWithoutMojom; COMPONENT_EXPORT(APP_TYPES) extern const base::Feature kAppServiceUninstallWithoutMojom; +COMPONENT_EXPORT(APP_TYPES) +extern const base::Feature kAppServiceWithoutMojom; } // namespace apps
diff --git a/components/services/screen_ai/BUILD.gn b/components/services/screen_ai/BUILD.gn index ee9b48c..c946535b 100644 --- a/components/services/screen_ai/BUILD.gn +++ b/components/services/screen_ai/BUILD.gn
@@ -40,34 +40,40 @@ } } -group("unit_tests_data") { - visibility = [ ":unit_tests" ] +group("test_support_data") { + visibility = [ ":test_support" ] testonly = true - data = [ - "$root_gen_dir/components/services/screen_ai/proto/view_hierarchy.descriptor", - "//components/test/data/screen_ai/sample_01_ax_tree.json", - "//components/test/data/screen_ai/sample_01_expected_proto.pbtxt", - ] + data = [ "$root_gen_dir/components/services/screen_ai/proto/view_hierarchy.descriptor" ] deps = [ "//components/services/screen_ai/proto:view_hierarchy_proto_descriptor", ] } -source_set("unit_tests") { +source_set("test_support") { testonly = true sources = [ - "proto/proto_convertor_unittest.cc", "proto/test_proto_loader.cc", "proto/test_proto_loader.h", ] - data_deps = [ ":unit_tests_data" ] + data_deps = [ ":test_support_data" ] deps = [ + "//base", + "//third_party/protobuf:protobuf_full", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "proto/proto_convertor_unittest.cc" ] + + data = [ "//components/test/data/screen_ai/" ] + deps = [ + ":test_support", "//components/services/screen_ai/proto", "//components/services/screen_ai/proto:proto_convertors", "//testing/gtest", - "//third_party/protobuf:protobuf_full", "//ui/accessibility:test_support", ] }
diff --git a/components/services/screen_ai/proto/proto_convertor_unittest.cc b/components/services/screen_ai/proto/proto_convertor_unittest.cc index 5b36dbf..48045dcd 100644 --- a/components/services/screen_ai/proto/proto_convertor_unittest.cc +++ b/components/services/screen_ai/proto/proto_convertor_unittest.cc
@@ -229,23 +229,6 @@ } } -void LoadViewHierarchyTextProto(const base::FilePath& file_path, - screenai::ViewHierarchy& proto) { - std::string file_content; - ASSERT_TRUE(base::ReadFileToString(file_path, &file_content)) - << "Failed to read expected proto from " << file_path; - - base::FilePath descriptor_path; - EXPECT_TRUE( - base::PathService::Get(base::DIR_GEN_TEST_DATA_ROOT, &descriptor_path)); - descriptor_path = descriptor_path.AppendASCII( - "gen/components/services/screen_ai/proto/view_hierarchy.descriptor"); - - test_proto_loader::TestProtoLoader loader; - ASSERT_TRUE(loader.ParseFromText(descriptor_path, file_content, proto)) - << "Failed to parse expected proto."; -} - } // namespace namespace screen_ai { @@ -465,8 +448,10 @@ // Load expected Proto. screenai::ViewHierarchy expected_view_hierarchy; - ASSERT_NO_FATAL_FAILURE( - LoadViewHierarchyTextProto(kExpectedProtoPath, expected_view_hierarchy)); + ASSERT_TRUE(test_proto_loader::TestProtoLoader::LoadTextProto( + kExpectedProtoPath, + "gen/components/services/screen_ai/proto/view_hierarchy.descriptor", + expected_view_hierarchy)); // Compare protos. ASSERT_NO_FATAL_FAILURE(ExpectViewHierarchyProtos(generated_view_hierarchy,
diff --git a/components/services/screen_ai/proto/test_proto_loader.cc b/components/services/screen_ai/proto/test_proto_loader.cc index 1b8c939..dabe4b2 100644 --- a/components/services/screen_ai/proto/test_proto_loader.cc +++ b/components/services/screen_ai/proto/test_proto_loader.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/logging.h" +#include "base/path_service.h" #include "base/strings/string_split.h" #include "google/protobuf/text_format.h" @@ -75,4 +76,28 @@ return true; } +// static +bool TestProtoLoader::LoadTextProto( + const base::FilePath& proto_file_path, + const char* proto_descriptor_relative_file_path, + google::protobuf::MessageLite& proto) { + std::string file_content; + if (!base::ReadFileToString(proto_file_path, &file_content)) { + LOG(ERROR) << "Failed to read expected proto from: " << proto_file_path; + return false; + } + + base::FilePath descriptor_full_path; + if (!base::PathService::Get(base::DIR_GEN_TEST_DATA_ROOT, + &descriptor_full_path)) { + LOG(ERROR) << "Generated test data root not found!"; + return false; + } + descriptor_full_path = + descriptor_full_path.AppendASCII(proto_descriptor_relative_file_path); + + test_proto_loader::TestProtoLoader loader; + return loader.ParseFromText(descriptor_full_path, file_content, proto); +} + } // namespace test_proto_loader
diff --git a/components/services/screen_ai/proto/test_proto_loader.h b/components/services/screen_ai/proto/test_proto_loader.h index b314f96..4621ad9 100644 --- a/components/services/screen_ai/proto/test_proto_loader.h +++ b/components/services/screen_ai/proto/test_proto_loader.h
@@ -36,6 +36,13 @@ const std::string& proto_text, google::protobuf::MessageLite& destination); + // Loads a text proto file from |proto_file_path| into |proto|, where the + // descriptor of the proto exists in |proto_descriptor_relative_file_path|, + // relative to DIR_GEN_TEST_DATA_ROOT. + static bool LoadTextProto(const base::FilePath& proto_file_path, + const char* proto_descriptor_relative_file_path, + google::protobuf::MessageLite& proto); + private: const google::protobuf::Message* GetPrototype(base::FilePath descriptor_path, std::string package,
diff --git a/components/translate/content/android/translate_message.cc b/components/translate/content/android/translate_message.cc index dce4333..bdf4f39 100644 --- a/components/translate/content/android/translate_message.cc +++ b/components/translate/content/android/translate_message.cc
@@ -102,6 +102,16 @@ return kDismissalDuration.Get(); } +base::android::ScopedJavaLocalRef<jstring> GetDefaultMessageDescription( + JNIEnv* env, + const std::u16string& source_language_display_name, + const std::u16string& target_language_display_name) { + return base::android::ConvertUTF16ToJavaString( + env, l10n_util::GetStringFUTF16(IDS_TRANSLATE_MESSAGE_DESCRIPTION, + source_language_display_name, + target_language_display_name)); +} + } // namespace const base::Feature kTranslateMessageUI("TranslateMessageUI", @@ -112,7 +122,7 @@ TranslateMessage::TranslateMessage( content::WebContents* web_contents, const base::WeakPtr<TranslateManager>& translate_manager, - base::OnceCallback<void()> on_dismiss_callback, + base::RepeatingCallback<void()> on_dismiss_callback, std::unique_ptr<Bridge> bridge) : web_contents_(web_contents), translate_manager_(translate_manager), @@ -124,7 +134,7 @@ TranslateMessage::TranslateMessage( content::WebContents* web_contents, const base::WeakPtr<TranslateManager>& translate_manager, - base::OnceCallback<void()> on_dismiss_callback) + base::RepeatingCallback<void()> on_dismiss_callback) : TranslateMessage(web_contents, translate_manager, std::move(on_dismiss_callback), @@ -135,15 +145,16 @@ // destruction. This prevents a possible use-after-free if the callback points // to a method on the owner of |this|. on_dismiss_callback_.Reset(); - if (bridge_) - bridge_->Dismiss(base::android::AttachCurrentThread()); + if (bridge_) { + JNIEnv* env = base::android::AttachCurrentThread(); + bridge_->Dismiss(env); + bridge_->ClearNativePointer(env); + } } void TranslateMessage::ShowTranslateStep(TranslateStep step, const std::string& source_language, const std::string& target_language) { - // Once the TranslateMessage has been dismissed, ShowTranslateStep() should - // not be called again on it. DCHECK(!on_dismiss_callback_.is_null()); JNIEnv* env = base::android::AttachCurrentThread(); @@ -165,6 +176,20 @@ ui_delegate_->UpdateTargetLanguage(target_language); if (step == TRANSLATE_STEP_TRANSLATE_ERROR) { + // Prevent auto-always-translate from triggering if an error occurs. + is_translation_eligible_for_auto_always_translate_ = false; + + // Count an error as an interaction so that the translation ignored/denied + // counts don't rise in response to errors. For example, suppose a user + // wants to translate a webpage that's in Hindi, and has "Always translate + // pages in Hindi" turned on, but for some reason repeatedly gets + // translation errors and repeatedly swipes away the message and refreshes + // the page trying to make translation work. If these are counted as + // translations being denied, then this could affect decisions made by the + // translate ranker or cause auto-never-translate-language to trigger + // inadvertently. + has_been_interacted_with_ = true; + bridge_->ShowTranslateError(env, web_contents_); // Since an error occurred, show the UI in the last good state. @@ -174,25 +199,39 @@ else step = TRANSLATE_STEP_BEFORE_TRANSLATE; } - translate_step_ = step; + + const std::u16string& source_language_display_name = + ui_delegate_->GetLanguageNameAt(ui_delegate_->GetSourceLanguageIndex()); + const std::u16string& target_language_display_name = + ui_delegate_->GetLanguageNameAt(ui_delegate_->GetTargetLanguageIndex()); base::android::ScopedJavaLocalRef<jstring> title; + base::android::ScopedJavaLocalRef<jstring> description; base::android::ScopedJavaLocalRef<jstring> primary_button_text; - switch (translate_step_) { + switch (step) { case TRANSLATE_STEP_BEFORE_TRANSLATE: title = base::android::ConvertUTF16ToJavaString( env, l10n_util::GetStringUTF16( IDS_TRANSLATE_MESSAGE_BEFORE_TRANSLATE_TITLE)); + description = GetDefaultMessageDescription( + env, source_language_display_name, target_language_display_name); primary_button_text = base::android::ConvertUTF16ToJavaString( env, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUTTON)); + + state_ = State::kBeforeTranslate; + is_translation_eligible_for_auto_always_translate_ = false; break; case TRANSLATE_STEP_TRANSLATING: title = base::android::ConvertUTF16ToJavaString( env, l10n_util::GetStringUTF16( IDS_TRANSLATE_MESSAGE_BEFORE_TRANSLATE_TITLE)); + description = GetDefaultMessageDescription( + env, source_language_display_name, target_language_display_name); primary_button_text = nullptr; + + state_ = State::kTranslating; break; case TRANSLATE_STEP_AFTER_TRANSLATE: @@ -201,6 +240,25 @@ IDS_TRANSLATE_MESSAGE_AFTER_TRANSLATE_TITLE)); primary_button_text = base::android::ConvertUTF16ToJavaString( env, l10n_util::GetStringUTF16(IDS_TRANSLATE_MESSAGE_UNDO_BUTTON)); + + if (is_translation_eligible_for_auto_always_translate_ && + ui_delegate_->ShouldAutoAlwaysTranslate()) { + ui_delegate_->SetAlwaysTranslate(true); + + description = base::android::ConvertUTF16ToJavaString( + env, + l10n_util::GetStringFUTF16( + IDS_TRANSLATE_MESSAGE_AUTO_ALWAYS_TRANSLATE_LANGUAGE_DESCRIPTION, + source_language_display_name, target_language_display_name)); + + state_ = State::kAfterTranslateWithAutoAlwaysConfirmation; + } else { + description = GetDefaultMessageDescription( + env, source_language_display_name, target_language_display_name); + state_ = State::kAfterTranslate; + } + + is_translation_eligible_for_auto_always_translate_ = false; break; default: @@ -208,40 +266,32 @@ break; } - const std::u16string& source_language_display_name = - ui_delegate_->GetLanguageNameAt(ui_delegate_->GetSourceLanguageIndex()); - const std::u16string& target_language_display_name = - ui_delegate_->GetLanguageNameAt(ui_delegate_->GetTargetLanguageIndex()); - base::android::ScopedJavaLocalRef<jstring> description = - base::android::ConvertUTF16ToJavaString( - env, l10n_util::GetStringFUTF16(IDS_TRANSLATE_MESSAGE_DESCRIPTION, - source_language_display_name, - target_language_display_name)); - bridge_->ShowMessage(env, std::move(title), std::move(description), std::move(primary_button_text)); } void TranslateMessage::HandlePrimaryAction(JNIEnv* env) { - switch (translate_step_) { - case TRANSLATE_STEP_BEFORE_TRANSLATE: + has_been_interacted_with_ = true; + is_translation_eligible_for_auto_always_translate_ = false; + + switch (state_) { + case State::kBeforeTranslate: + is_translation_eligible_for_auto_always_translate_ = true; ui_delegate_->ReportUIInteraction(UIInteraction::kTranslate); ui_delegate_->Translate(); break; - case TRANSLATE_STEP_AFTER_TRANSLATE: + case State::kAfterTranslateWithAutoAlwaysConfirmation: + // The user clicked "Undo" on a translated page when the + // auto-always-translate confirmation message was showing, so turn off + // "always translate language" before reverting the translation. + ui_delegate_->SetAlwaysTranslate(false); + [[fallthrough]]; + case State::kAfterTranslate: ui_delegate_->ReportUIInteraction(UIInteraction::kRevert); RevertTranslationAndUpdateMessage(); break; - case TRANSLATE_STEP_TRANSLATING: - // TODO(crbug.com/1304118): Once the TRANSLATE_STEP_TRANSLATING state - // replaces the primary action button with a spinning progress indicator - // (and thus there is no longer a clickable primary button), fall through - // to the |default| NOTREACHED handler below. Until then, do nothing in - // this case. - break; - default: NOTREACHED(); break; @@ -250,11 +300,9 @@ void TranslateMessage::HandleDismiss(JNIEnv* env, jint dismiss_reason) { switch (static_cast<messages::DismissReason>(dismiss_reason)) { - case messages::DismissReason::PRIMARY_ACTION: - case messages::DismissReason::SECONDARY_ACTION: case messages::DismissReason::GESTURE: - ui_delegate_->ReportUIInteraction(UIInteraction::kCloseUIExplicitly); ui_delegate_->OnUIClosedByUser(); + ui_delegate_->ReportUIInteraction(UIInteraction::kCloseUIExplicitly); break; case messages::DismissReason::TAB_SWITCHED: @@ -268,24 +316,46 @@ ui_delegate_->ReportUIInteraction(UIInteraction::kCloseUITimerRanOut); break; + case messages::DismissReason::PRIMARY_ACTION: + case messages::DismissReason::SECONDARY_ACTION: + // These dismiss reasons should not be possible for a TranslateMessage, + // since clicking the primary or secondary buttons doesn't dismiss the + // message. + NOTREACHED(); + break; + default: break; } - bridge_->ClearNativePointer(env); - bridge_.reset(); + if (!has_been_interacted_with_ && state_ == State::kBeforeTranslate) { + ui_delegate_->TranslationDeclined( + static_cast<messages::DismissReason>(dismiss_reason) == + messages::DismissReason::GESTURE); + } + + state_ = State::kDismissed; // The only time |on_dismiss_callback_| will be null is during the destruction // of |this|. if (!on_dismiss_callback_.is_null()) { // Note that this callback can destroy |this|, so this method shouldn't do // anything afterwards. - std::move(on_dismiss_callback_).Run(); + on_dismiss_callback_.Run(); } } base::android::ScopedJavaLocalRef<jobjectArray> TranslateMessage::BuildOverflowMenu(JNIEnv* env) { + has_been_interacted_with_ = true; + + // If the overflow menu is open when auto-always-translate triggers, then the + // "Always translate language" option in the menu would remain unchecked even + // if auto-always-translate triggers and changes that setting. To avoid this + // inconsistency, don't try to turn on auto-always-translate if the user + // opened the overflow menu mid-translation. + is_translation_eligible_for_auto_always_translate_ = false; + // |titles| must have the capacity to fit the maximum number of menu items in // the overflow menu, including dividers. std::u16string titles[1U + // Change target language. @@ -379,6 +449,13 @@ jint overflow_menu_item_id, const base::android::JavaRef<jstring>& language_code, jboolean had_checkmark) { + has_been_interacted_with_ = true; + + // Interacting with the secondary menu can cause the page to be translated or + // an existing translation to be reverted, so to avoid these edge cases, don't + // try to turn on auto-always-translate. + is_translation_eligible_for_auto_always_translate_ = false; + std::string language_code_utf8 = ConvertJavaStringToUTF8(env, language_code); if (!language_code_utf8.empty()) { switch (static_cast<OverflowMenuItemId>(overflow_menu_item_id)) { @@ -429,10 +506,8 @@ if (ui_delegate_->ShouldAlwaysTranslate() != desired_toggle_value) ui_delegate_->SetAlwaysTranslate(desired_toggle_value); - if (desired_toggle_value && - translate_step_ == TRANSLATE_STEP_BEFORE_TRANSLATE) { + if (desired_toggle_value && state_ == State::kBeforeTranslate) ui_delegate_->Translate(); - } break; case OverflowMenuItemId::kToggleNeverTranslateLanguage: @@ -441,8 +516,8 @@ ui_delegate_->SetLanguageBlocked(desired_toggle_value); if (desired_toggle_value && - (translate_step_ == TRANSLATE_STEP_TRANSLATING || - translate_step_ == TRANSLATE_STEP_AFTER_TRANSLATE)) { + (state_ == State::kTranslating || state_ == State::kAfterTranslate || + state_ == State::kAfterTranslateWithAutoAlwaysConfirmation)) { RevertTranslationAndUpdateMessage(); } break; @@ -453,8 +528,8 @@ ui_delegate_->SetNeverPromptSite(desired_toggle_value); if (desired_toggle_value && - (translate_step_ == TRANSLATE_STEP_TRANSLATING || - translate_step_ == TRANSLATE_STEP_AFTER_TRANSLATE)) { + (state_ == State::kTranslating || state_ == State::kAfterTranslate || + state_ == State::kAfterTranslateWithAutoAlwaysConfirmation)) { RevertTranslationAndUpdateMessage(); } break;
diff --git a/components/translate/content/android/translate_message.h b/components/translate/content/android/translate_message.h index e4499fb..d589f41 100644 --- a/components/translate/content/android/translate_message.h +++ b/components/translate/content/android/translate_message.h
@@ -33,15 +33,17 @@ public: TranslateMessage(content::WebContents* web_contents, const base::WeakPtr<TranslateManager>& translate_manager, - base::OnceCallback<void()> on_dismiss_callback); + base::RepeatingCallback<void()> on_dismiss_callback); + + TranslateMessage(const TranslateMessage&) = delete; + TranslateMessage& operator=(const TranslateMessage&) = delete; // Dismiss message on destruction if it is shown. ~TranslateMessage(); // Show the Translate message UI in the specified state, or update an // existing visible message to have the specified state if one is already - // visible. Note that once a TranslateMessage has been dismissed, it must not - // be shown again - construct a new TranslateMessage instead. + // visible. void ShowTranslateStep(TranslateStep step, const std::string& source_language, const std::string& target_language); @@ -116,7 +118,7 @@ // Test-only constructor with a custom JavaMethodCaller. TranslateMessage(content::WebContents* web_contents, const base::WeakPtr<TranslateManager>& translate_manager, - base::OnceCallback<void()> on_dismiss_callback, + base::RepeatingCallback<void()> on_dismiss_callback, std::unique_ptr<Bridge> bridge); // This enum is only visible for testing purposes - the Java TranslateMessage @@ -131,6 +133,16 @@ }; private: + enum class State { + kDismissed, + + kBeforeTranslate, + kTranslating, + kAfterTranslate, + + kAfterTranslateWithAutoAlwaysConfirmation, + }; + void RevertTranslationAndUpdateMessage(); base::android::ScopedJavaLocalRef<jobjectArray> ConstructLanguagePickerMenu( @@ -141,13 +153,21 @@ raw_ptr<content::WebContents> web_contents_; base::WeakPtr<TranslateManager> translate_manager_; - base::OnceCallback<void()> on_dismiss_callback_; + base::RepeatingCallback<void()> on_dismiss_callback_; std::unique_ptr<Bridge> bridge_; // Constructed the first time ShowTranslateStep is called. std::unique_ptr<TranslateUIDelegate> ui_delegate_; - TranslateStep translate_step_ = TRANSLATE_STEP_TRANSLATE_ERROR; + State state_ = State::kDismissed; + + // Keeps track of whether or not this TranslateMessage has ever been + // interacted with in any way aside from dismissing it. + bool has_been_interacted_with_ = false; + + // Keeps track of whether or not a translation is in progress that could + // trigger automatically setting "always translate language". + bool is_translation_eligible_for_auto_always_translate_ = false; }; } // namespace translate
diff --git a/components/translate/content/android/translate_message_unittest.cc b/components/translate/content/android/translate_message_unittest.cc index 30ec0f0..d3e97c57 100644 --- a/components/translate/content/android/translate_message_unittest.cc +++ b/components/translate/content/android/translate_message_unittest.cc
@@ -27,6 +27,7 @@ #include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/browser/translate_ui_delegate.h" #include "components/translate/core/common/translate_constants.h" +#include "components/translate/core/common/translate_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -142,13 +143,6 @@ return base::android::ToJavaArrayOfStrings(env, test_strings); } -void OnDismissTranslateMessage( - std::unique_ptr<TranslateMessage>* translate_message, - bool* was_on_dismiss_callback_called) { - *was_on_dismiss_callback_called = true; - translate_message->reset(); -} - constexpr int kDefaultDismissalDurationSeconds = 10; struct SecondaryMenuItem { @@ -165,14 +159,9 @@ driver_.SetLastCommittedURL(GURL("http://www.example.com/")); } - void CreateAndShowBeforeTranslationMessage( - JNIEnv* env, - const std::string& source_language_code, - const std::string& target_language_code) { - EXPECT_CALL(*bridge_, CreateTranslateMessage( - env, _, _, kDefaultDismissalDurationSeconds)) - .WillOnce(Return(true)); - + void ShowBeforeTranslationMessage(JNIEnv* env, + const std::string& source_language_code, + const std::string& target_language_code) { EXPECT_CALL( *bridge_, ShowMessage(env, @@ -183,8 +172,6 @@ translate_message_->ShowTranslateStep(TRANSLATE_STEP_BEFORE_TRANSLATE, source_language_code, target_language_code); - - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } void ExpectTranslationInProgress(JNIEnv* env, @@ -233,8 +220,6 @@ manager_->PageTranslated(source_language_code, target_language_code, TranslateErrors::NONE); - - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } void ExpectTranslationReverts(JNIEnv* env, @@ -253,28 +238,27 @@ void TranslateThenRevertThenDismiss(JNIEnv* env, const std::string& source_language_code, const std::string& target_language_code) { - CreateAndShowBeforeTranslationMessage(env, source_language_code, - target_language_code); + ShowBeforeTranslationMessage(env, source_language_code, + target_language_code); ExpectTranslationInProgress(env, source_language_code, target_language_code); translate_message_->HandlePrimaryAction(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, source_language_code, target_language_code); ExpectTranslationReverts(env, source_language_code, target_language_code); translate_message_->HandlePrimaryAction(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); // Simulate a dismissal triggered from the Java side. - EXPECT_CALL(*bridge_, ClearNativePointer(env)); + int prev_on_dismiss_callback_called_count = + on_dismiss_callback_called_count_; translate_message_->HandleDismiss( env, static_cast<jint>(messages::DismissReason::TIMER)); // The on-dismiss callback should have been called. - EXPECT_FALSE(translate_message_); - EXPECT_TRUE(was_on_dismiss_callback_called_); + EXPECT_EQ(prev_on_dismiss_callback_called_count + 1, + on_dismiss_callback_called_count_); } void ExpectConstructMenuItemArray( @@ -353,10 +337,14 @@ auto owned_bridge = std::make_unique<TestBridge>(); bridge_ = owned_bridge->GetWeakPtr(); + translate_message_ = std::make_unique<TranslateMessage>( /*web_contents=*/nullptr, manager_->GetWeakPtr(), - base::BindOnce(&OnDismissTranslateMessage, &translate_message_, - &was_on_dismiss_callback_called_), + base::BindRepeating( + [](int* on_dismiss_callback_called_count) { + ++(*on_dismiss_callback_called_count); + }, + &on_dismiss_callback_called_count_), std::move(owned_bridge)); } @@ -370,21 +358,34 @@ base::WeakPtr<TestBridge> bridge_; std::unique_ptr<TranslateMessage> translate_message_; - bool was_on_dismiss_callback_called_ = false; + int on_dismiss_callback_called_count_ = 0; }; TEST_F(TranslateMessageTest, TranslateAndRevert) { JNIEnv* env = base::android::AttachCurrentThread(); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + TranslateThenRevertThenDismiss(env, "fr", "en"); } +TEST_F(TranslateMessageTest, TranslateAndRevertMultipleTimes) { + JNIEnv* env = base::android::AttachCurrentThread(); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + + TranslateThenRevertThenDismiss(env, "fr", "en"); + TranslateThenRevertThenDismiss(env, "de", "es"); +} + TEST_F(TranslateMessageTest, ShowErrorBeforeTranslation) { JNIEnv* env = base::android::AttachCurrentThread(); ON_CALL(*client_, ShowTranslateUI(_, _, _, _, _)).WillByDefault(Return(true)); manager_->GetLanguageState()->SetSourceLanguage("fr"); manager_->GetLanguageState()->SetCurrentLanguage("fr"); - ASSERT_TRUE(Mock::VerifyAndClear(client_.get())); EXPECT_CALL(*bridge_, CreateTranslateMessage( env, _, _, kDefaultDismissalDurationSeconds)) @@ -406,7 +407,6 @@ ON_CALL(*client_, ShowTranslateUI(_, _, _, _, _)).WillByDefault(Return(true)); manager_->GetLanguageState()->SetSourceLanguage("fr"); manager_->GetLanguageState()->SetCurrentLanguage("en"); - ASSERT_TRUE(Mock::VerifyAndClear(client_.get())); EXPECT_CALL(*bridge_, CreateTranslateMessage( env, _, _, kDefaultDismissalDurationSeconds)) @@ -424,8 +424,11 @@ TEST_F(TranslateMessageTest, DismissMessageOnDestruction) { JNIEnv* env = base::android::AttachCurrentThread(); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + ShowBeforeTranslationMessage(env, "fr", "en"); EXPECT_CALL(*bridge_, Dismiss(env)) .WillOnce(InvokeWithoutArgs([env, message = translate_message_.get()]() { @@ -441,13 +444,16 @@ // By design, the on_dismiss_callback_ will not be called, since it's cleared // in the TranslateMessage destructor before dismissing the message, in order // to prevent a use-after-free bug. - EXPECT_FALSE(was_on_dismiss_callback_called_); + EXPECT_EQ(0, on_dismiss_callback_called_count_); } TEST_F(TranslateMessageTest, OverflowMenuToggleAlwaysTranslateLanguage) { JNIEnv* env = base::android::AttachCurrentThread(); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectConstructMenuItemArray( env, @@ -467,7 +473,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE( translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); @@ -478,7 +483,6 @@ TranslateMessage::OverflowMenuItemId::kToggleAlwaysTranslateLanguage), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_TRUE( translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); @@ -502,7 +506,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE(translate_message_->HandleSecondaryMenuItemClicked( env, @@ -519,10 +522,12 @@ JNIEnv* env = base::android::AttachCurrentThread(); // Begin from a translated page. - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectTranslationInProgress(env, "fr", "en"); translate_message_->HandlePrimaryAction(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, "fr", "en"); ExpectConstructMenuItemArray( @@ -543,7 +548,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE(translate_prefs_->IsBlockedLanguage("fr")); ExpectTranslationReverts(env, "fr", "en"); @@ -553,7 +557,6 @@ TranslateMessage::OverflowMenuItemId::kToggleNeverTranslateLanguage), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_TRUE(translate_prefs_->IsBlockedLanguage("fr")); ExpectConstructMenuItemArray( @@ -574,7 +577,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE(translate_message_->HandleSecondaryMenuItemClicked( env, @@ -589,10 +591,12 @@ JNIEnv* env = base::android::AttachCurrentThread(); // Begin from a translated page. - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectTranslationInProgress(env, "fr", "en"); translate_message_->HandlePrimaryAction(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, "fr", "en"); ExpectConstructMenuItemArray( @@ -613,7 +617,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE(translate_prefs_->IsSiteOnNeverPromptList( driver_.GetLastCommittedURL().HostNoBracketsPiece())); @@ -624,7 +627,6 @@ TranslateMessage::OverflowMenuItemId::kToggleNeverTranslateSite), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_TRUE(translate_prefs_->IsSiteOnNeverPromptList( driver_.GetLastCommittedURL().HostNoBracketsPiece())); @@ -646,7 +648,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); EXPECT_FALSE(translate_message_->HandleSecondaryMenuItemClicked( env, @@ -665,7 +666,10 @@ translate_prefs_->AddToLanguageList("es", true); translate_prefs_->AddToLanguageList("de", true); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectConstructMenuItemArray( env, @@ -686,7 +690,6 @@ CreateTestJobjectArray(env)); EXPECT_TRUE(translate_message_->BuildOverflowMenu(env)); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); std::vector<SecondaryMenuItem> menu_items; TranslateUIDelegate ui_delegate(manager_->GetWeakPtr(), "fr", "en"); @@ -708,7 +711,6 @@ TranslateMessage::OverflowMenuItemId::kChangeSourceLanguage), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); // Clicking a language should kick off a translation. ExpectTranslationInProgress(env, "de", "en"); @@ -718,7 +720,6 @@ TranslateMessage::OverflowMenuItemId::kChangeSourceLanguage), base::android::ConvertUTF8ToJavaString(env, "de"), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, "de", "en"); } @@ -735,7 +736,10 @@ translate_prefs_->AddToLanguageList("es", true); translate_prefs_->AddToLanguageList("de", true); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectConstructMenuItemArray( env, @@ -756,7 +760,6 @@ CreateTestJobjectArray(env)); EXPECT_TRUE(translate_message_->BuildOverflowMenu(env)); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); std::vector<SecondaryMenuItem> menu_items; TranslateUIDelegate ui_delegate(manager_->GetWeakPtr(), "fr", "en"); @@ -778,7 +781,6 @@ TranslateMessage::OverflowMenuItemId::kChangeTargetLanguage), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); // Clicking a language should kick off a translation. ExpectTranslationInProgress(env, "fr", "de"); @@ -788,7 +790,6 @@ TranslateMessage::OverflowMenuItemId::kChangeTargetLanguage), base::android::ConvertUTF8ToJavaString(env, "de"), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, "fr", "de"); } @@ -805,7 +806,10 @@ translate_prefs_->AddToLanguageList("es", true); translate_prefs_->AddToLanguageList("de", true); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); ExpectConstructMenuItemArray( env, @@ -826,7 +830,6 @@ CreateTestJobjectArray(env)); EXPECT_TRUE(translate_message_->BuildOverflowMenu(env)); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); std::vector<SecondaryMenuItem> menu_items = { {TranslateMessage::OverflowMenuItemId::kChangeTargetLanguage, false, @@ -856,7 +859,6 @@ TranslateMessage::OverflowMenuItemId::kChangeTargetLanguage), base::android::ConvertUTF8ToJavaString(env, std::string()), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); // Clicking a language should kick off a translation. ExpectTranslationInProgress(env, "fr", "de"); @@ -866,7 +868,6 @@ TranslateMessage::OverflowMenuItemId::kChangeTargetLanguage), base::android::ConvertUTF8ToJavaString(env, "de"), static_cast<jboolean>(false))); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); FinishTranslation(env, "fr", "de"); } @@ -875,7 +876,10 @@ JNIEnv* env = base::android::AttachCurrentThread(); ON_CALL(driver_, IsIncognito()).WillByDefault(Return(true)); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); // Doesn't include the kToggleAlwaysTranslateLanguage option. ExpectConstructMenuItemArray( @@ -893,14 +897,16 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } TEST_F(TranslateMessageTest, OverflowMenuEmptyUrl) { JNIEnv* env = base::android::AttachCurrentThread(); driver_.SetLastCommittedURL(GURL()); - CreateAndShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); // Doesn't include the kToggleNeverTranslateSite option. ExpectConstructMenuItemArray( @@ -919,13 +925,15 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } TEST_F(TranslateMessageTest, OverflowMenuUnknownSourceLanguage) { JNIEnv* env = base::android::AttachCurrentThread(); - CreateAndShowBeforeTranslationMessage(env, kUnknownLanguageCode, "en"); + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, kUnknownLanguageCode, "en"); // Doesn't include the kToggleAlwaysTranslateLanguage option or the // kToggleNeverTranslateLanguage option. @@ -942,7 +950,6 @@ std::string()}})); translate_message_->BuildOverflowMenu(env); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } TEST_F(TranslateMessageTest, CreateTranslateMessageFails) { @@ -957,8 +964,6 @@ translate_message_->ShowTranslateStep(TRANSLATE_STEP_BEFORE_TRANSLATE, "fr", "en"); - - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); } TEST_F(TranslateMessageTest, CreateTranslateMessageFailsThenSucceeds) { @@ -975,13 +980,487 @@ translate_message_->ShowTranslateStep(TRANSLATE_STEP_BEFORE_TRANSLATE, "fr", "en"); - ASSERT_TRUE(Mock::VerifyAndClearExpectations(bridge_.get())); - // The second call to CreateTranslateMessage will succeed, and test that the // whole process of translating, reverting, and dismissing works properly // afterwards. + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); TranslateThenRevertThenDismiss(env, "fr", "en"); } +TEST_F(TranslateMessageTest, TranslationDismissedInProgressByTimer) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateDeniedCount) + ->GetDict() + .Set("fr", 100); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateIgnoredCount) + ->GetDict() + .Set("fr", 100); + + // Show the translate message and click "Translate". + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + EXPECT_EQ(1, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); + + // Dismiss the translate message while translation is still in-progress. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::TIMER)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(1, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationDismissedInProgressByGesture) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateDeniedCount) + ->GetDict() + .Set("fr", 100); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateIgnoredCount) + ->GetDict() + .Set("fr", 100); + + // Show the translate message and click "Translate". + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + EXPECT_EQ(1, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); + + // Dismiss the translate message while translation is still in-progress. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(1, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationIgnored) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", 100); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateDeniedCount) + ->GetDict() + .Set("fr", 100); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::TIMER)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(100, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(100, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(1, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationNotIgnoredBecauseOverflowMenuOpened) { + JNIEnv* env = base::android::AttachCurrentThread(); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + + // Show the translate message and simulate the overflow menu being opened. + ShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, ConstructMenuItemArray(env, _, _, _, _, _)) + .WillOnce(Return(nullptr)); + translate_message_->BuildOverflowMenu(env); + + // Dismiss the translate message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::TIMER)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + // The dismissal isn't counted as an ignore because opening the overflow menu + // counts as interacting with the UI. + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); + + // Show the translate message again, this time without interacting with it. + ShowBeforeTranslationMessage(env, "fr", "en"); + + // Dismiss the translate message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::TIMER)); + EXPECT_EQ(2, on_dismiss_callback_called_count_); + + // The dismissal still isn't counted as an ignore because the translate + // message was previously interacted with on this page. + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationNotIgnoredBecauseErrorOccurred) { + JNIEnv* env = base::android::AttachCurrentThread(); + + ON_CALL(*client_, ShowTranslateUI(_, _, _, _, _)).WillByDefault(Return(true)); + manager_->GetLanguageState()->SetSourceLanguage("fr"); + manager_->GetLanguageState()->SetCurrentLanguage("fr"); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + EXPECT_CALL(*bridge_, ShowTranslateError(env, _)); + EXPECT_CALL(*bridge_, + ShowMessage(env, + /*title=*/Truly(IsJavaStringNonNull), + /*description=*/Truly(IsJavaStringNonNull), + /*primary_button_text=*/Truly(IsJavaStringNonNull))); + + translate_message_->ShowTranslateStep(TRANSLATE_STEP_TRANSLATE_ERROR, "fr", + "en"); + + // Dismiss the message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::TIMER)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(0, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationDenied) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", 100); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateIgnoredCount) + ->GetDict() + .Set("fr", 100); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(0, translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(1, translate_prefs_->GetTranslationDeniedCount("fr")); + EXPECT_EQ(100, translate_prefs_->GetTranslationIgnoredCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationNotDeniedBecauseOverflowMenuOpened) { + JNIEnv* env = base::android::AttachCurrentThread(); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + + // Show the translate message and simulate the overflow menu being opened. + ShowBeforeTranslationMessage(env, "fr", "en"); + EXPECT_CALL(*bridge_, ConstructMenuItemArray(env, _, _, _, _, _)) + .WillOnce(Return(nullptr)); + translate_message_->BuildOverflowMenu(env); + + // Dismiss the translate message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + // The dismissal isn't counted as an denial because opening the overflow menu + // counts as interacting with the UI. + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); + + // Show the translate message again, this time without interacting with it. + ShowBeforeTranslationMessage(env, "fr", "en"); + + // Dismiss the translate message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(2, on_dismiss_callback_called_count_); + + // The dismissal still isn't counted as an denial because the translate + // message was previously interacted with on this page. + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); +} + +TEST_F(TranslateMessageTest, TranslationNotDeniedBecauseErrorOccurred) { + JNIEnv* env = base::android::AttachCurrentThread(); + + ON_CALL(*client_, ShowTranslateUI(_, _, _, _, _)).WillByDefault(Return(true)); + manager_->GetLanguageState()->SetSourceLanguage("fr"); + manager_->GetLanguageState()->SetCurrentLanguage("fr"); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + EXPECT_CALL(*bridge_, ShowTranslateError(env, _)); + EXPECT_CALL(*bridge_, + ShowMessage(env, + /*title=*/Truly(IsJavaStringNonNull), + /*description=*/Truly(IsJavaStringNonNull), + /*primary_button_text=*/Truly(IsJavaStringNonNull))); + + translate_message_->ShowTranslateStep(TRANSLATE_STEP_TRANSLATE_ERROR, "fr", + "en"); + + // Dismiss the message. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + + EXPECT_EQ(0, translate_prefs_->GetTranslationDeniedCount("fr")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslate) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold() - 1); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways() - 1); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + FinishTranslation(env, "fr", "en"); + + EXPECT_TRUE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways(), + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationAcceptedCount("fr")); + + // Simulate clicking "Undo", which should disable "Always translate language." + ExpectTranslationReverts(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslatePastAcceptedThreshold) { + JNIEnv* env = base::android::AttachCurrentThread(); + + // Once the translation happens, this count will be 1 larger than the + // threshold. This test is to make sure that the comparison is + // greater-than-or-equal, not just equality. + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold()); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways() - 1); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + FinishTranslation(env, "fr", "en"); + + EXPECT_TRUE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways(), + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationAcceptedCount("fr")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslateDismissedInProgress) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold() - 1); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways() - 1); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + // Start the translation. + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + // Simulate the message being dismissed from Java. + translate_message_->HandleDismiss( + env, static_cast<jint>(messages::DismissReason::GESTURE)); + EXPECT_EQ(1, on_dismiss_callback_called_count_); + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + // Finish the translation, causing the Message to pop up again. + FinishTranslation(env, "fr", "en"); + + EXPECT_TRUE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways(), + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); + EXPECT_EQ(0, translate_prefs_->GetTranslationAcceptedCount("fr")); + + // Simulate clicking "Undo", which should disable "Always translate language." + ExpectTranslationReverts(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslateThresholdNotReached) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold() - 2); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways() - 1); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + // Start the translation. + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + FinishTranslation(env, "fr", "en"); + + // Auto-always-translate should not have triggered, since the threshold of + // accepted translations has not been reached. + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetAutoAlwaysThreshold() - 1, + translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways() - 1, + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslatePastMaximumTimes) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold() - 1); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways()); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + // Start the translation. + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + FinishTranslation(env, "fr", "en"); + + // Auto-always-translate should not have triggered, since + // auto-always-translate has already triggered the maximum number of allowed + // times. + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetAutoAlwaysThreshold(), + translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways(), + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); +} + +TEST_F(TranslateMessageTest, AutoAlwaysTranslateInterruptedByOverflowMenu) { + JNIEnv* env = base::android::AttachCurrentThread(); + + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAcceptedCount) + ->GetDict() + .Set("fr", GetAutoAlwaysThreshold() - 1); + DictionaryPrefUpdate(pref_service_.get(), + TranslatePrefs::kPrefTranslateAutoAlwaysCount) + ->GetDict() + .Set("fr", GetMaximumNumberOfAutoAlways() - 1); + + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + + // Start the translation. + EXPECT_CALL(*bridge_, CreateTranslateMessage( + env, _, _, kDefaultDismissalDurationSeconds)) + .WillOnce(Return(true)); + ShowBeforeTranslationMessage(env, "fr", "en"); + ExpectTranslationInProgress(env, "fr", "en"); + translate_message_->HandlePrimaryAction(env); + + // While the translation is in progress, simulate the overflow menu being + // opened. + EXPECT_CALL(*bridge_, ConstructMenuItemArray(env, _, _, _, _, _)) + .WillOnce(Return(nullptr)); + translate_message_->BuildOverflowMenu(env); + + FinishTranslation(env, "fr", "en"); + + // Auto-always-translate should not have triggered, since opening the overflow + // menu mid-translation should have prevented it from triggering. + EXPECT_FALSE( + translate_prefs_->IsLanguagePairOnAlwaysTranslateList("fr", "en")); + EXPECT_EQ(GetAutoAlwaysThreshold(), + translate_prefs_->GetTranslationAcceptedCount("fr")); + EXPECT_EQ(GetMaximumNumberOfAutoAlways() - 1, + translate_prefs_->GetTranslationAutoAlwaysCount("fr")); +} + } // namespace } // namespace translate
diff --git a/components/translate_strings.grdp b/components/translate_strings.grdp index 178462c..e1d2dde 100644 --- a/components/translate_strings.grdp +++ b/components/translate_strings.grdp
@@ -113,6 +113,9 @@ <message name="IDS_TRANSLATE_MESSAGE_NEVER_TRANSLATE_LANGUAGE" desc="Option in the overflow menu. User can click the 'Never Translate' option to indicate that they never want the app to translate pages in this language. Imperative."> Never translate pages in <ph name="SOURCE_LANGUAGE">$1<ex>French</ex></ph> </message> + <message name="IDS_TRANSLATE_MESSAGE_AUTO_ALWAYS_TRANSLATE_LANGUAGE_DESCRIPTION" desc="A text label on the translate message popup that lets the user know that pages in the source language will be automatically translated to the target language from now on."> + Pages in <ph name="source_language">$1<ex>French</ex></ph> will be translated to <ph name="target_language">$2<ex>English</ex></ph> from now on + </message> </if> <!-- Translate Notifications -->
diff --git a/components/translate_strings_grdp/IDS_TRANSLATE_MESSAGE_AUTO_ALWAYS_TRANSLATE_LANGUAGE_DESCRIPTION.png.sha1 b/components/translate_strings_grdp/IDS_TRANSLATE_MESSAGE_AUTO_ALWAYS_TRANSLATE_LANGUAGE_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..7ab4987 --- /dev/null +++ b/components/translate_strings_grdp/IDS_TRANSLATE_MESSAGE_AUTO_ALWAYS_TRANSLATE_LANGUAGE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +cd78536d6399f0405d842b5bdfff5d0dc612503d \ No newline at end of file
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc index 3324139..f8ccbc42 100644 --- a/components/user_manager/known_user.cc +++ b/components/user_manager/known_user.cc
@@ -431,10 +431,6 @@ } return AccountId::FromUserEmailGaiaId(sanitized_email, id); case AccountType::ACTIVE_DIRECTORY: - if (const std::string* stored_email = - FindStringPath(AccountId::AdFromObjGuid(id), kCanonicalEmail)) { - return AccountId::AdFromUserEmailObjGuid(*stored_email, id); - } return AccountId::AdFromUserEmailObjGuid(sanitized_email, id); case AccountType::UNKNOWN: return AccountId::FromUserEmail(sanitized_email);
diff --git a/components/user_manager/known_user_unittest.cc b/components/user_manager/known_user_unittest.cc index fe375e7..16b86cad 100644 --- a/components/user_manager/known_user_unittest.cc +++ b/components/user_manager/known_user_unittest.cc
@@ -173,9 +173,6 @@ EXPECT_TRUE(FindPrefs(AccountId::AdFromUserEmailObjGuid(kEmailB, "a"))); // Finding by e-mail should also work even if the guid doesn't match. EXPECT_TRUE(FindPrefs(AccountId::AdFromUserEmailObjGuid(kEmailA, "b"))); - // Finding by just AD guid without any e-mail doesn't work (because the - // resulting AccountId is not considered valid). - EXPECT_FALSE(FindPrefs(AccountId::AdFromObjGuid("a"))); // An unrelated AD AccountId with the same Account Type doesn't find // anything.
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index c5a6e8b..85ef156d 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -70,9 +70,9 @@ // This reads integer value from kUserType Local State preference and // interprets it as UserType. It is used in initial users load. -UserType GetStoredUserType(const base::Value* prefs_user_types, +UserType GetStoredUserType(const base::Value::Dict& prefs_user_types, const AccountId& account_id) { - const base::Value* stored_user_type = prefs_user_types->FindKey( + const base::Value* stored_user_type = prefs_user_types.Find( account_id.HasAccountIdKey() ? account_id.GetAccountIdKey() : account_id.GetUserEmail()); if (!stored_user_type || !stored_user_type->is_int()) @@ -506,8 +506,8 @@ } UserType UserManagerBase::GetUserType(const AccountId& account_id) { - const base::Value* prefs_user_types = - GetLocalState()->GetDictionary(kUserType); + const base::Value::Dict& prefs_user_types = + GetLocalState()->GetValueDict(kUserType); return GetStoredUserType(prefs_user_types, account_id); } @@ -845,13 +845,14 @@ const base::Value::List& prefs_regular_users = local_state->GetValueList(kRegularUsersPref); - const base::Value* prefs_display_names = - local_state->GetDictionary(kUserDisplayName); - const base::Value* prefs_given_names = - local_state->GetDictionary(kUserGivenName); - const base::Value* prefs_display_emails = - local_state->GetDictionary(kUserDisplayEmail); - const base::Value* prefs_user_types = local_state->GetDictionary(kUserType); + const base::Value::Dict& prefs_display_names = + local_state->GetValueDict(kUserDisplayName); + const base::Value::Dict& prefs_given_names = + local_state->GetValueDict(kUserGivenName); + const base::Value::Dict& prefs_display_emails = + local_state->GetValueDict(kUserDisplayEmail); + const base::Value::Dict& prefs_user_types = + local_state->GetValueDict(kUserType); // Load public sessions first. std::set<AccountId> device_local_accounts_set; @@ -884,19 +885,19 @@ for (auto* user : users_) { auto& account_id = user->GetAccountId(); const std::string* display_name = - prefs_display_names->FindStringKey(account_id.GetUserEmail()); + prefs_display_names.FindString(account_id.GetUserEmail()); if (display_name) { user->set_display_name(base::UTF8ToUTF16(*display_name)); } const std::string* given_name = - prefs_given_names->FindStringKey(account_id.GetUserEmail()); + prefs_given_names.FindString(account_id.GetUserEmail()); if (given_name) { user->set_given_name(base::UTF8ToUTF16(*given_name)); } const std::string* display_email = - prefs_display_emails->FindStringKey(account_id.GetUserEmail()); + prefs_display_emails.FindString(account_id.GetUserEmail()); if (display_email) { user->set_display_email(*display_email); } @@ -1017,13 +1018,11 @@ const AccountId& account_id) const { DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence()); - const base::Value* prefs_oauth_status = - GetLocalState()->GetDictionary(kUserOAuthTokenStatus); - if (!prefs_oauth_status) - return User::OAUTH_TOKEN_STATUS_UNKNOWN; + const base::Value::Dict& prefs_oauth_status = + GetLocalState()->GetValueDict(kUserOAuthTokenStatus); absl::optional<int> oauth_token_status = - prefs_oauth_status->FindIntKey(account_id.GetUserEmail()); + prefs_oauth_status.FindInt(account_id.GetUserEmail()); if (!oauth_token_status.has_value()) return User::OAUTH_TOKEN_STATUS_UNKNOWN; @@ -1033,13 +1032,10 @@ bool UserManagerBase::LoadForceOnlineSignin(const AccountId& account_id) const { DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence()); - const base::Value* prefs_force_online = - GetLocalState()->GetDictionary(kUserForceOnlineSignin); - if (prefs_force_online) { - return prefs_force_online->FindBoolKey(account_id.GetUserEmail()) - .value_or(false); - } - return false; + const base::Value::Dict& prefs_force_online = + GetLocalState()->GetValueDict(kUserForceOnlineSignin); + + return prefs_force_online.FindBool(account_id.GetUserEmail()).value_or(false); } void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) {
diff --git a/components/variations/processed_study_unittest.cc b/components/variations/processed_study_unittest.cc index 3364343..93d7f9d 100644 --- a/components/variations/processed_study_unittest.cc +++ b/components/variations/processed_study_unittest.cc
@@ -18,10 +18,10 @@ std::numeric_limits<base::FieldTrial::Probability>::max(); // Adds an experiment with the given name and probability to a study. -Study::Experiment* AddExperiment(Study& study, - const std::string& name, - uint32_t probability) { - Study::Experiment* experiment = study.add_experiment(); +Study::Experiment* AddExperiment(const std::string& name, + uint32_t probability, + Study* study) { + Study::Experiment* experiment = study->add_experiment(); experiment->set_name(name); experiment->set_probability_weight(probability); return experiment; @@ -47,12 +47,13 @@ filter->set_min_os_version("1"); filter->set_max_os_version("2.*"); - Study::Experiment* default_experiment = AddExperiment(study, "Default", 0); + Study::Experiment* default_experiment = AddExperiment("Default", 0, &study); - Study::Experiment* enabled_experiment = AddExperiment(study, "Enabled", 50); + Study::Experiment* enabled_experiment = AddExperiment("Enabled", 50, &study); enabled_experiment->set_google_web_experiment_id(1); - Study::Experiment* disabled_experiment = AddExperiment(study, "Disabled", 50); + Study::Experiment* disabled_experiment = + AddExperiment("Disabled", 50, &study); disabled_experiment->set_google_web_experiment_id(2); study.set_default_experiment_name(default_experiment->name()); @@ -145,7 +146,7 @@ Study study = CreateValidStudy(); - AddExperiment(study, "", 0); + AddExperiment("", 0, &study); ProcessedStudy processed_study; EXPECT_FALSE(processed_study.Init(&study, false)); @@ -161,8 +162,8 @@ Study study = CreateValidStudy(); - AddExperiment(study, "Group", 0); - AddExperiment(study, "Group", 0); + AddExperiment("Group", 0, &study); + AddExperiment("Group", 0, &study); ProcessedStudy processed_study; EXPECT_FALSE(processed_study.Init(&study, false)); @@ -178,7 +179,7 @@ Study study = CreateValidStudy(); - Study::Experiment* experiment = AddExperiment(study, "Group", 0); + Study::Experiment* experiment = AddExperiment("Group", 0, &study); experiment->set_google_web_experiment_id(123); experiment->set_google_web_trigger_experiment_id(123); @@ -196,7 +197,7 @@ Study study = CreateStudy("Study"); - AddExperiment(study, "Group", kMaxProbabilityValue + 1); + AddExperiment("Group", kMaxProbabilityValue + 1, &study); ProcessedStudy processed_study; EXPECT_FALSE(processed_study.Init(&study, false)); @@ -212,8 +213,8 @@ Study study = CreateStudy("Study"); - AddExperiment(study, "Group1", kMaxProbabilityValue); - AddExperiment(study, "Group2", 1); + AddExperiment("Group1", kMaxProbabilityValue, &study); + AddExperiment("Group2", 1, &study); ProcessedStudy processed_study; EXPECT_FALSE(processed_study.Init(&study, false)); @@ -238,4 +239,138 @@ InvalidStudyReason::kMissingDefaultExperimentInList, 1); } +TEST(ProcessedStudyTest, ValidateStudy) { + Study study; + study.set_name("study"); + study.set_default_experiment_name("def"); + AddExperiment("abc", 100, &study); + Study::Experiment* default_group = AddExperiment("def", 200, &study); + + ProcessedStudy processed_study; + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_EQ(300, processed_study.total_probability()); + EXPECT_FALSE(processed_study.all_assignments_to_one_group()); + + // Min version checks. + study.mutable_filter()->set_min_version("1.2.3.*"); + EXPECT_TRUE(processed_study.Init(&study, false)); + study.mutable_filter()->set_min_version("1.*.3"); + EXPECT_FALSE(processed_study.Init(&study, false)); + study.mutable_filter()->set_min_version("1.2.3"); + EXPECT_TRUE(processed_study.Init(&study, false)); + + // Max version checks. + study.mutable_filter()->set_max_version("2.3.4.*"); + EXPECT_TRUE(processed_study.Init(&study, false)); + study.mutable_filter()->set_max_version("*.3"); + EXPECT_FALSE(processed_study.Init(&study, false)); + study.mutable_filter()->set_max_version("2.3.4"); + EXPECT_TRUE(processed_study.Init(&study, false)); + + // A blank default study is allowed. + study.clear_default_experiment_name(); + EXPECT_TRUE(processed_study.Init(&study, false)); + + study.set_default_experiment_name("xyz"); + EXPECT_FALSE(processed_study.Init(&study, false)); + + study.set_default_experiment_name("def"); + default_group->clear_name(); + EXPECT_FALSE(processed_study.Init(&study, false)); + + default_group->set_name("def"); + EXPECT_TRUE(processed_study.Init(&study, false)); + Study::Experiment* repeated_group = study.add_experiment(); + repeated_group->set_name("abc"); + repeated_group->set_probability_weight(1); + EXPECT_FALSE(processed_study.Init(&study, false)); +} + +TEST(ProcessedStudyTest, ValidateStudyWithAssociatedFeatures) { + Study study; + study.set_name("study"); + study.set_default_experiment_name("def"); + Study::Experiment* exp1 = AddExperiment("exp1", 100, &study); + Study::Experiment* exp2 = AddExperiment("exp2", 100, &study); + Study::Experiment* exp3 = AddExperiment("exp3", 100, &study); + AddExperiment("def", 100, &study); + + ProcessedStudy processed_study; + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_EQ(400, processed_study.total_probability()); + + EXPECT_THAT(processed_study.associated_features(), ::testing::IsEmpty()); + + const char kFeature1Name[] = "Feature1"; + const char kFeature2Name[] = "Feature2"; + + exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_THAT(processed_study.associated_features(), + ::testing::ElementsAre(kFeature1Name)); + + exp1->clear_feature_association(); + exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); + exp1->mutable_feature_association()->add_enable_feature(kFeature2Name); + EXPECT_TRUE(processed_study.Init(&study, false)); + // Since there's multiple different features, |associated_features| should now + // contain them all. + EXPECT_THAT(processed_study.associated_features(), + ::testing::ElementsAre(kFeature1Name, kFeature2Name)); + + exp1->clear_feature_association(); + exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); + exp2->mutable_feature_association()->add_enable_feature(kFeature1Name); + exp3->mutable_feature_association()->add_disable_feature(kFeature1Name); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_THAT(processed_study.associated_features(), + ::testing::ElementsAre(kFeature1Name)); + + // Setting a different feature name on exp2 should cause |associated_features| + // to contain both feature names. + exp2->mutable_feature_association()->set_enable_feature(0, kFeature2Name); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_THAT(processed_study.associated_features(), + ::testing::ElementsAre(kFeature1Name, kFeature2Name)); + + // Setting a different activation type should result in empty + // |associated_features|. + study.set_activation_type(Study::ACTIVATE_ON_STARTUP); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_THAT(processed_study.associated_features(), ::testing::IsEmpty()); +} + +TEST(ProcessedStudyTest, ProcessedStudyAllAssignmentsToOneGroup) { + Study study; + study.set_name("study1"); + study.set_default_experiment_name("def"); + AddExperiment("def", 100, &study); + + ProcessedStudy processed_study; + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_TRUE(processed_study.all_assignments_to_one_group()); + + AddExperiment("abc", 0, &study); + + AddExperiment("flag", 0, &study)->set_forcing_flag("flag_test1"); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_TRUE(processed_study.all_assignments_to_one_group()); + + AddExperiment("xyz", 1, &study); + EXPECT_TRUE(processed_study.Init(&study, false)); + EXPECT_FALSE(processed_study.all_assignments_to_one_group()); + + // Try with default group and first group being at 0. + Study study2; + study2.set_name("study2"); + study2.set_default_experiment_name("def"); + AddExperiment("def", 0, &study2); + AddExperiment("xyz", 34, &study2); + EXPECT_TRUE(processed_study.Init(&study2, false)); + EXPECT_TRUE(processed_study.all_assignments_to_one_group()); + AddExperiment("abc", 12, &study2); + EXPECT_TRUE(processed_study.Init(&study2, false)); + EXPECT_FALSE(processed_study.all_assignments_to_one_group()); +} + } // namespace variations \ No newline at end of file
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc index 4157ebf..a6ae5f7 100644 --- a/components/variations/variations_seed_processor_unittest.cc +++ b/components/variations/variations_seed_processor_unittest.cc
@@ -412,139 +412,6 @@ EXPECT_EQ(u"test", it->second); } -TEST_F(VariationsSeedProcessorTest, ValidateStudy) { - Study study; - study.set_name("study"); - study.set_default_experiment_name("def"); - AddExperiment("abc", 100, &study); - Study::Experiment* default_group = AddExperiment("def", 200, &study); - - ProcessedStudy processed_study; - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_EQ(300, processed_study.total_probability()); - EXPECT_FALSE(processed_study.all_assignments_to_one_group()); - - // Min version checks. - study.mutable_filter()->set_min_version("1.2.3.*"); - EXPECT_TRUE(processed_study.Init(&study, false)); - study.mutable_filter()->set_min_version("1.*.3"); - EXPECT_FALSE(processed_study.Init(&study, false)); - study.mutable_filter()->set_min_version("1.2.3"); - EXPECT_TRUE(processed_study.Init(&study, false)); - - // Max version checks. - study.mutable_filter()->set_max_version("2.3.4.*"); - EXPECT_TRUE(processed_study.Init(&study, false)); - study.mutable_filter()->set_max_version("*.3"); - EXPECT_FALSE(processed_study.Init(&study, false)); - study.mutable_filter()->set_max_version("2.3.4"); - EXPECT_TRUE(processed_study.Init(&study, false)); - - // A blank default study is allowed. - study.clear_default_experiment_name(); - EXPECT_TRUE(processed_study.Init(&study, false)); - - study.set_default_experiment_name("xyz"); - EXPECT_FALSE(processed_study.Init(&study, false)); - - study.set_default_experiment_name("def"); - default_group->clear_name(); - EXPECT_FALSE(processed_study.Init(&study, false)); - - default_group->set_name("def"); - EXPECT_TRUE(processed_study.Init(&study, false)); - Study::Experiment* repeated_group = study.add_experiment(); - repeated_group->set_name("abc"); - repeated_group->set_probability_weight(1); - EXPECT_FALSE(processed_study.Init(&study, false)); -} - -TEST_F(VariationsSeedProcessorTest, ValidateStudyWithAssociatedFeatures) { - Study study; - study.set_name("study"); - study.set_default_experiment_name("def"); - Study::Experiment* exp1 = AddExperiment("exp1", 100, &study); - Study::Experiment* exp2 = AddExperiment("exp2", 100, &study); - Study::Experiment* exp3 = AddExperiment("exp3", 100, &study); - AddExperiment("def", 100, &study); - - ProcessedStudy processed_study; - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_EQ(400, processed_study.total_probability()); - - EXPECT_THAT(processed_study.associated_features(), IsEmpty()); - - const char kFeature1Name[] = "Feature1"; - const char kFeature2Name[] = "Feature2"; - - exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_THAT(processed_study.associated_features(), - ElementsAre(kFeature1Name)); - - exp1->clear_feature_association(); - exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); - exp1->mutable_feature_association()->add_enable_feature(kFeature2Name); - EXPECT_TRUE(processed_study.Init(&study, false)); - // Since there's multiple different features, |associated_features| should now - // contain them all. - EXPECT_THAT(processed_study.associated_features(), - ElementsAre(kFeature1Name, kFeature2Name)); - - exp1->clear_feature_association(); - exp1->mutable_feature_association()->add_enable_feature(kFeature1Name); - exp2->mutable_feature_association()->add_enable_feature(kFeature1Name); - exp3->mutable_feature_association()->add_disable_feature(kFeature1Name); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_THAT(processed_study.associated_features(), - ElementsAre(kFeature1Name)); - - // Setting a different feature name on exp2 should cause |associated_features| - // to contain both feature names. - exp2->mutable_feature_association()->set_enable_feature(0, kFeature2Name); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_THAT(processed_study.associated_features(), - ElementsAre(kFeature1Name, kFeature2Name)); - - // Setting a different activation type should result in empty - // |associated_features|. - study.set_activation_type(Study::ACTIVATE_ON_STARTUP); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_THAT(processed_study.associated_features(), IsEmpty()); -} - -TEST_F(VariationsSeedProcessorTest, ProcessedStudyAllAssignmentsToOneGroup) { - Study study; - study.set_name("study1"); - study.set_default_experiment_name("def"); - AddExperiment("def", 100, &study); - - ProcessedStudy processed_study; - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_TRUE(processed_study.all_assignments_to_one_group()); - - AddExperiment("abc", 0, &study); - AddExperiment("flag", 0, &study)->set_forcing_flag(kForcingFlag1); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_TRUE(processed_study.all_assignments_to_one_group()); - - AddExperiment("xyz", 1, &study); - EXPECT_TRUE(processed_study.Init(&study, false)); - EXPECT_FALSE(processed_study.all_assignments_to_one_group()); - - // Try with default group and first group being at 0. - Study study2; - study2.set_name("study2"); - study2.set_default_experiment_name("def"); - AddExperiment("def", 0, &study2); - AddExperiment("xyz", 34, &study2); - EXPECT_TRUE(processed_study.Init(&study2, false)); - EXPECT_TRUE(processed_study.all_assignments_to_one_group()); - AddExperiment("abc", 12, &study2); - EXPECT_TRUE(processed_study.Init(&study2, false)); - EXPECT_FALSE(processed_study.all_assignments_to_one_group()); -} - TEST_F(VariationsSeedProcessorTest, VariationParams) { Study study; study.set_name("Study1");
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn index 11db086..cce8408 100644 --- a/components/vector_icons/BUILD.gn +++ b/components/vector_icons/BUILD.gn
@@ -91,6 +91,7 @@ "notifications_off.icon", "open_in_new.icon", "page_info_content_paste.icon", + "palette.icon", "pause.icon", "photo.icon", "play_arrow.icon",
diff --git a/components/vector_icons/palette.icon b/components/vector_icons/palette.icon new file mode 100644 index 0000000..245a1904 --- /dev/null +++ b/components/vector_icons/palette.icon
@@ -0,0 +1,51 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 1.67f, 10, +CUBIC_TO, 1.67f, 14.59f, 5.41f, 18.33f, 10, 18.33f, +CUBIC_TO, 11.15f, 18.33f, 12.08f, 17.4f, 12.08f, 16.25f, +CUBIC_TO, 12.08f, 15.74f, 11.89f, 15.25f, 11.55f, 14.86f, +CUBIC_TO, 11.48f, 14.77f, 11.44f, 14.68f, 11.44f, 14.58f, +CUBIC_TO, 11.44f, 14.35f, 11.62f, 14.17f, 11.86f, 14.17f, +H_LINE_TO, 13.33f, +CUBIC_TO, 16.09f, 14.17f, 18.33f, 11.92f, 18.33f, 9.17f, +CUBIC_TO, 18.33f, 5.03f, 14.59f, 1.67f, 10, 1.67f, +CUBIC_TO, 5.41f, 1.67f, 1.67f, 5.41f, 1.67f, 10, +CLOSE, +MOVE_TO, 3.33f, 10, +CUBIC_TO, 3.33f, 6.32f, 6.32f, 3.33f, 10, 3.33f, +CUBIC_TO, 13.67f, 3.33f, 16.67f, 5.95f, 16.67f, 9.17f, +CUBIC_TO, 16.67f, 11.01f, 15.17f, 12.5f, 13.33f, 12.5f, +H_LINE_TO, 11.86f, +CUBIC_TO, 10.71f, 12.5f, 9.77f, 13.43f, 9.77f, 14.58f, +CUBIC_TO, 9.77f, 15.08f, 9.96f, 15.57f, 10.3f, 15.96f, +CUBIC_TO, 10.35f, 16.02f, 10.42f, 16.12f, 10.42f, 16.25f, +CUBIC_TO, 10.42f, 16.48f, 10.23f, 16.67f, 10, 16.67f, +CUBIC_TO, 6.32f, 16.67f, 3.33f, 13.67f, 3.33f, 10, +CLOSE, +MOVE_TO, 5.42f, 10.83f, +CUBIC_TO, 6.11f, 10.83f, 6.67f, 10.27f, 6.67f, 9.58f, +CUBIC_TO, 6.67f, 8.89f, 6.11f, 8.33f, 5.42f, 8.33f, +CUBIC_TO, 4.73f, 8.33f, 4.17f, 8.89f, 4.17f, 9.58f, +CUBIC_TO, 4.17f, 10.27f, 4.73f, 10.83f, 5.42f, 10.83f, +CLOSE, +MOVE_TO, 9.17f, 6.25f, +CUBIC_TO, 9.17f, 6.94f, 8.61f, 7.5f, 7.92f, 7.5f, +CUBIC_TO, 7.23f, 7.5f, 6.67f, 6.94f, 6.67f, 6.25f, +CUBIC_TO, 6.67f, 5.56f, 7.23f, 5, 7.92f, 5, +CUBIC_TO, 8.61f, 5, 9.17f, 5.56f, 9.17f, 6.25f, +CLOSE, +MOVE_TO, 12.08f, 7.5f, +CUBIC_TO, 12.77f, 7.5f, 13.33f, 6.94f, 13.33f, 6.25f, +CUBIC_TO, 13.33f, 5.56f, 12.77f, 5, 12.08f, 5, +CUBIC_TO, 11.39f, 5, 10.83f, 5.56f, 10.83f, 6.25f, +CUBIC_TO, 10.83f, 6.94f, 11.39f, 7.5f, 12.08f, 7.5f, +CLOSE, +MOVE_TO, 15.83f, 9.58f, +CUBIC_TO, 15.83f, 10.27f, 15.27f, 10.83f, 14.58f, 10.83f, +CUBIC_TO, 13.89f, 10.83f, 13.33f, 10.27f, 13.33f, 9.58f, +CUBIC_TO, 13.33f, 8.89f, 13.89f, 8.33f, 14.58f, 8.33f, +CUBIC_TO, 15.27f, 8.33f, 15.83f, 8.89f, 15.83f, 9.58f, +CLOSE
diff --git a/components/viz/host/gpu_client.cc b/components/viz/host/gpu_client.cc index 62ae74ac..7203287 100644 --- a/components/viz/host/gpu_client.cc +++ b/components/viz/host/gpu_client.cc
@@ -89,6 +89,30 @@ gpu_host->SetChannelClientPid(client_id_, client_pid); } +void GpuClient::SetDiskCacheHandle(const gpu::GpuDiskCacheHandle& handle) { + if (!task_runner_->RunsTasksInCurrentSequence()) { + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&GpuClient::SetDiskCacheHandle, + weak_factory_.GetWeakPtr(), handle)); + return; + } + + if (GpuHostImpl* gpu_host = delegate_->EnsureGpuHost()) + gpu_host->SetChannelDiskCacheHandle(client_id_, handle); +} + +void GpuClient::RemoveDiskCacheHandles() { + if (!task_runner_->RunsTasksInCurrentSequence()) { + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&GpuClient::RemoveDiskCacheHandles, + weak_factory_.GetWeakPtr())); + return; + } + + if (GpuHostImpl* gpu_host = delegate_->EnsureGpuHost()) + gpu_host->RemoveChannelDiskCacheHandles(client_id_); +} + void GpuClient::SetConnectionErrorHandler( ConnectionErrorHandlerClosure connection_error_handler) { connection_error_handler_ = std::move(connection_error_handler);
diff --git a/components/viz/host/gpu_client.h b/components/viz/host/gpu_client.h index f62a185..cb019da 100644 --- a/components/viz/host/gpu_client.h +++ b/components/viz/host/gpu_client.h
@@ -15,6 +15,7 @@ #include "components/viz/host/gpu_client_delegate.h" #include "components/viz/host/gpu_host_impl.h" #include "components/viz/host/viz_host_export.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "services/viz/public/mojom/gpu.mojom.h" @@ -47,6 +48,10 @@ // known. void SetClientPid(base::ProcessId client_pid); + // Sets/removes disk cache handle(s) that can be used by this channel. + void SetDiskCacheHandle(const gpu::GpuDiskCacheHandle& handle); + void RemoveDiskCacheHandles(); + void SetConnectionErrorHandler( ConnectionErrorHandlerClosure connection_error_handler);
diff --git a/components/viz/host/gpu_host_impl.cc b/components/viz/host/gpu_host_impl.cc index d6d1fe8..036e80a 100644 --- a/components/viz/host/gpu_host_impl.cc +++ b/components/viz/host/gpu_host_impl.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/process/process_handle.h" +#include "base/strings/strcat.h" #include "base/threading/thread_checker.h" #include "base/trace_event/trace_event.h" #include "base/values.h" @@ -177,13 +178,13 @@ if (activity_flags_.IsFlagSet( gpu::ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY)) { auto* gpu_disk_cache_factory = delegate_->GetGpuDiskCacheFactory(); - for (auto& [client_id, _] : client_id_to_shader_cache_) { + for (auto& [_, cache] : client_id_to_caches_) { // This call will temporarily extend the lifetime of the cache (kept // alive in the factory), and may drop loads of cached shader binaries if // it takes a while to complete. As we are intentionally dropping all // binaries, this behavior is fine. - gpu_disk_cache_factory->ClearByClientId( - client_id, base::Time(), base::Time::Max(), base::DoNothing()); + gpu_disk_cache_factory->ClearByCache( + cache, base::Time(), base::Time::Max(), base::DoNothing()); } } } @@ -248,9 +249,6 @@ return; } - bool cache_shaders_on_disk = - delegate_->GetGpuDiskCacheFactory()->Get(client_id) != nullptr; - channel_requests_[client_id] = std::move(callback); if (sync) { mojo::ScopedMessagePipeHandle channel_handle; @@ -258,21 +256,24 @@ gpu::GpuFeatureInfo gpu_feature_info; { mojo::SyncCallRestrictions::ScopedAllowSyncCall scoped_allow; - gpu_service_remote_->EstablishGpuChannel( - client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk, - &channel_handle, &gpu_info, &gpu_feature_info); + gpu_service_remote_->EstablishGpuChannel(client_id, client_tracing_id, + is_gpu_host, &channel_handle, + &gpu_info, &gpu_feature_info); } OnChannelEstablished(client_id, true, std::move(channel_handle), gpu_info, gpu_feature_info); } else { gpu_service_remote_->EstablishGpuChannel( - client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk, + client_id, client_tracing_id, is_gpu_host, base::BindOnce(&GpuHostImpl::OnChannelEstablished, weak_ptr_factory_.GetWeakPtr(), client_id, false)); } - if (!params_.disable_gpu_shader_disk_cache) - CreateChannelCache(client_id); + // The gpu host channel uses the same cache as the compositor client. + if (is_gpu_host) { + SetChannelDiskCacheHandle(client_id, + gpu::kDisplayCompositorGpuDiskCacheHandle); + } } void GpuHostImpl::SetChannelClientPid(int client_id, @@ -280,6 +281,33 @@ gpu_service_remote_->SetChannelClientPid(client_id, client_pid); } +void GpuHostImpl::SetChannelDiskCacheHandle( + int client_id, + const gpu::GpuDiskCacheHandle& handle) { + if (!params_.disable_gpu_shader_disk_cache) { + return; + } + + scoped_refptr<gpu::GpuDiskCache> cache = + delegate_->GetGpuDiskCacheFactory()->Get(handle); + if (!cache) { + // Create the cache if necessary and save a reference. + cache = delegate_->GetGpuDiskCacheFactory()->Create( + handle, base::BindRepeating(&GpuHostImpl::LoadedBlob, + weak_ptr_factory_.GetWeakPtr())); + if (!cache) { + return; + } + } + + client_id_to_caches_.emplace(client_id, cache); + gpu_service_remote_->SetChannelDiskCacheHandle(client_id, handle); +} + +void GpuHostImpl::RemoveChannelDiskCacheHandles(int client_id) { + client_id_to_caches_.erase(client_id); +} + void GpuHostImpl::CloseChannel(int client_id) { gpu_service_remote_->CloseChannel(client_id); @@ -384,36 +412,30 @@ return shader_prefix_key_; } -void GpuHostImpl::LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data) { +void GpuHostImpl::LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::string prefix = GetShaderPrefixKey(); - bool prefix_ok = !key.compare(0, prefix.length(), prefix); - UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok); - if (prefix_ok) { - // Remove the prefix from the key before load. - std::string key_no_prefix = key.substr(prefix.length() + 1); - gpu_service_remote_->LoadedShader(client_id, key_no_prefix, data); + switch (gpu::GetHandleType(handle)) { + case gpu::GpuDiskCacheType::kGlShaders: { + std::string prefix = GetShaderPrefixKey(); + bool prefix_ok = !key.compare(0, prefix.length(), prefix); + UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok); + if (prefix_ok) { + // Remove the prefix from the key before load. + std::string key_no_prefix = key.substr(prefix.length() + 1); + gpu_service_remote_->LoadedBlob(handle, key_no_prefix, data); + } + break; + } + case gpu::GpuDiskCacheType::kDawnWebGPU: { + gpu_service_remote_->LoadedBlob(handle, key, data); + break; + } } } -void GpuHostImpl::CreateChannelCache(int32_t client_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("gpu", "GpuHostImpl::CreateChannelCache"); - - scoped_refptr<gpu::GpuDiskCache> cache = - delegate_->GetGpuDiskCacheFactory()->Get(client_id); - if (!cache) - return; - - cache->SetBlobLoadedCallback(base::BindRepeating( - &GpuHostImpl::LoadedShader, weak_ptr_factory_.GetWeakPtr(), client_id)); - - client_id_to_shader_cache_[client_id] = cache; -} - void GpuHostImpl::OnChannelEstablished( int client_id, bool sync, @@ -471,8 +493,10 @@ gpu_feature_info_for_hardware_gpu, gpu_extra_info); if (!params_.disable_gpu_shader_disk_cache) { - CreateChannelCache(gpu::kDisplayCompositorClientId); - CreateChannelCache(gpu::kGrShaderCacheClientId); + SetChannelDiskCacheHandle(gpu::kDisplayCompositorClientId, + gpu::kDisplayCompositorGpuDiskCacheHandle); + SetChannelDiskCacheHandle(gpu::kGrShaderCacheClientId, + gpu::kGrShaderGpuDiskCacheHandle); } } @@ -499,7 +523,7 @@ void GpuHostImpl::DidDestroyChannel(int32_t client_id) { TRACE_EVENT0("gpu", "GpuHostImpl::DidDestroyChannel"); - client_id_to_shader_cache_.erase(client_id); + client_id_to_caches_.erase(client_id); } void GpuHostImpl::DidDestroyAllChannels() { @@ -579,16 +603,27 @@ } #endif // BUILDFLAG(IS_WIN) -void GpuHostImpl::StoreShaderToDisk(int32_t client_id, - const std::string& key, - const std::string& shader) { - TRACE_EVENT0("gpu", "GpuHostImpl::StoreShaderToDisk"); - auto iter = client_id_to_shader_cache_.find(client_id); - // If the cache doesn't exist then this is an off the record profile. - if (iter == client_id_to_shader_cache_.end()) +void GpuHostImpl::StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& blob) { + TRACE_EVENT0("gpu", "GpuHostImpl::StoreBlobToDisk"); + scoped_refptr<gpu::GpuDiskCache> cache = + delegate_->GetGpuDiskCacheFactory()->Get(handle); + if (!cache) { return; - std::string prefix = GetShaderPrefixKey(); - iter->second->Cache(prefix + ":" + key, shader); + } + + switch (GetHandleType(handle)) { + case gpu::GpuDiskCacheType::kGlShaders: { + std::string prefix = GetShaderPrefixKey(); + cache->Cache(base::StrCat({prefix, ":", key}), blob); + break; + } + case gpu::GpuDiskCacheType::kDawnWebGPU: { + cache->Cache(key, blob); + break; + } + } } void GpuHostImpl::RecordLogMessage(int32_t severity,
diff --git a/components/viz/host/gpu_host_impl.h b/components/viz/host/gpu_host_impl.h index 3b62a4a..21c91786 100644 --- a/components/viz/host/gpu_host_impl.h +++ b/components/viz/host/gpu_host_impl.h
@@ -26,6 +26,7 @@ #include "components/viz/host/viz_host_export.h" #include "gpu/command_buffer/common/activity_flags.h" #include "gpu/config/gpu_domain_guilt.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -181,6 +182,9 @@ bool sync, EstablishChannelCallback callback); void SetChannelClientPid(int client_id, base::ProcessId client_pid); + void SetChannelDiskCacheHandle(int client_id, + const gpu::GpuDiskCacheHandle& handle); + void RemoveChannelDiskCacheHandles(int client_id); void CloseChannel(int client_id); #if BUILDFLAG(USE_VIZ_DEBUGGER) @@ -217,11 +221,9 @@ std::string GetShaderPrefixKey(); - void LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data); - - void CreateChannelCache(int32_t client_id); + void LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data); void OnChannelEstablished(int client_id, bool sync, @@ -255,9 +257,9 @@ void SetChildSurface(gpu::SurfaceHandle parent, gpu::SurfaceHandle child) override; #endif - void StoreShaderToDisk(int32_t client_id, - const std::string& key, - const std::string& shader) override; + void StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& blob) override; void RecordLogMessage(int32_t severity, const std::string& header, const std::string& message) override; @@ -295,8 +297,7 @@ // are guilty, and block automatic execution of 3D content from those domains. std::multiset<GURL> urls_with_live_offscreen_contexts_; - std::map<int32_t, scoped_refptr<gpu::GpuDiskCache>> - client_id_to_shader_cache_; + std::multimap<int32_t, scoped_refptr<gpu::GpuDiskCache>> client_id_to_caches_; std::string shader_prefix_key_; // These are the channel requests that we have already sent to the GPU
diff --git a/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc b/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc index 79c20529..6a21045d 100644 --- a/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc +++ b/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
@@ -107,10 +107,12 @@ void EstablishGpuChannel(int32_t client_id, uint64_t client_tracing_id, bool is_gpu_host, - bool cache_shaders_on_disk, EstablishGpuChannelCallback callback) override {} void SetChannelClientPid(int32_t client_id, base::ProcessId client_pid) override {} + void SetChannelDiskCacheHandle( + int32_t client_id, + const gpu::GpuDiskCacheHandle& handle) override {} void CloseChannel(int32_t client_id) override {} #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -190,9 +192,9 @@ void RequestDXGIInfo(RequestDXGIInfoCallback callback) override {} #endif - void LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data) override {} + void LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) override {} void WakeUpGpu() override {}
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index 6301d3df..a8282560 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -16,6 +16,7 @@ #include "base/no_destructor.h" #include "base/observer_list.h" #include "base/synchronization/waitable_event.h" +#include "base/task/bind_post_task.h" #include "base/task/task_runner_util.h" #include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" @@ -953,10 +954,10 @@ gpu_host_->DidLoseContext(offscreen, reason, active_url); } -void GpuServiceImpl::StoreShaderToDisk(int client_id, - const std::string& key, - const std::string& shader) { - gpu_host_->StoreShaderToDisk(client_id, key, shader); +void GpuServiceImpl::StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& shader) { + gpu_host_->StoreBlobToDisk(handle, key, shader); } void GpuServiceImpl::MaybeExitOnContextLost() { @@ -990,7 +991,6 @@ void GpuServiceImpl::EstablishGpuChannel(int32_t client_id, uint64_t client_tracing_id, bool is_gpu_host, - bool cache_shaders_on_disk, EstablishGpuChannelCallback callback) { // This should always be called on the IO thread first. if (io_runner_->BelongsToCurrentThread()) { @@ -1009,28 +1009,18 @@ return; } - EstablishGpuChannelCallback wrap_callback = base::BindOnce( - [](scoped_refptr<base::SingleThreadTaskRunner> runner, - EstablishGpuChannelCallback cb, mojo::ScopedMessagePipeHandle handle, - const gpu::GPUInfo& gpu_info, - const gpu::GpuFeatureInfo& gpu_feature_info) { - runner->PostTask(FROM_HERE, - base::BindOnce(std::move(cb), std::move(handle), - gpu_info, gpu_feature_info)); - }, - io_runner_, std::move(callback)); + EstablishGpuChannelCallback wrap_callback = + base::BindPostTask(io_runner_, std::move(callback)); main_runner_->PostTask( - FROM_HERE, - base::BindOnce(&GpuServiceImpl::EstablishGpuChannel, weak_ptr_, - client_id, client_tracing_id, is_gpu_host, - cache_shaders_on_disk, std::move(wrap_callback))); + FROM_HERE, base::BindOnce(&GpuServiceImpl::EstablishGpuChannel, + weak_ptr_, client_id, client_tracing_id, + is_gpu_host, std::move(wrap_callback))); return; } auto channel_token = base::UnguessableToken::Create(); gpu::GpuChannel* gpu_channel = gpu_channel_manager_->EstablishChannel( - channel_token, client_id, client_tracing_id, is_gpu_host, - cache_shaders_on_disk); + channel_token, client_id, client_tracing_id, is_gpu_host); if (!gpu_channel) { // This returns a null handle, which is treated by the client as a failure @@ -1063,6 +1053,18 @@ gpu_channel_manager_->SetChannelClientPid(client_id, client_pid); } +void GpuServiceImpl::SetChannelDiskCacheHandle( + int32_t client_id, + const gpu::GpuDiskCacheHandle& handle) { + if (io_runner_->BelongsToCurrentThread()) { + main_runner_->PostTask( + FROM_HERE, base::BindOnce(&GpuServiceImpl::SetChannelDiskCacheHandle, + weak_ptr_, client_id, handle)); + return; + } + gpu_channel_manager_->SetChannelDiskCacheHandle(client_id, handle); +} + void GpuServiceImpl::CloseChannel(int32_t client_id) { if (!main_runner_->BelongsToCurrentThread()) { main_runner_->PostTask( @@ -1073,16 +1075,16 @@ gpu_channel_manager_->RemoveChannel(client_id); } -void GpuServiceImpl::LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data) { +void GpuServiceImpl::LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) { if (!main_runner_->BelongsToCurrentThread()) { main_runner_->PostTask( - FROM_HERE, base::BindOnce(&GpuServiceImpl::LoadedShader, weak_ptr_, - client_id, key, data)); + FROM_HERE, base::BindOnce(&GpuServiceImpl::LoadedBlob, weak_ptr_, + handle, key, data)); return; } - gpu_channel_manager_->PopulateShaderCache(client_id, key, data); + gpu_channel_manager_->PopulateCache(handle, key, data); } void GpuServiceImpl::SetWakeUpGpuClosure(base::RepeatingClosure closure) {
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h index 185334c..b36c537 100644 --- a/components/viz/service/gl/gpu_service_impl.h +++ b/components/viz/service/gl/gpu_service_impl.h
@@ -30,6 +30,7 @@ #include "gpu/command_buffer/service/sequence_id.h" #include "gpu/config/gpu_info.h" #include "gpu/config/gpu_preferences.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" @@ -140,10 +141,12 @@ void EstablishGpuChannel(int32_t client_id, uint64_t client_tracing_id, bool is_gpu_host, - bool cache_shaders_on_disk, EstablishGpuChannelCallback callback) override; void SetChannelClientPid(int32_t client_id, base::ProcessId client_pid) override; + void SetChannelDiskCacheHandle( + int32_t client_id, + const gpu::GpuDiskCacheHandle& handle) override; void CloseChannel(int32_t client_id) override; #if BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) @@ -202,9 +205,9 @@ #if BUILDFLAG(IS_WIN) void RequestDXGIInfo(RequestDXGIInfoCallback callback) override; #endif - void LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data) override; + void LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) override; void WakeUpGpu() override; void GpuSwitched(gl::GpuPreference active_gpu_heuristic) override; void DisplayAdded() override; @@ -244,9 +247,9 @@ const GURL& active_url) override; void GetDawnInfo(GetDawnInfoCallback callback) override; - void StoreShaderToDisk(int client_id, - const std::string& key, - const std::string& shader) override; + void StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& shader) override; // Attempts to atomically shut down the process but only if not running in // host process. An error message will be logged. void MaybeExitOnContextLost() override;
diff --git a/components/web_package/web_bundle_parser.cc b/components/web_package/web_bundle_parser.cc index de70aeeb..d8983fa 100644 --- a/components/web_package/web_bundle_parser.cc +++ b/components/web_package/web_bundle_parser.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "components/cbor/reader.h" #include "components/web_package/input_reader.h" #include "components/web_package/signed_web_bundles/integrity_block_parser.h" @@ -42,6 +43,11 @@ // The initial buffer size for reading an item from the response section. constexpr uint64_t kInitialBufferSizeForResponse = 4096; +// The first byte of WebBundle format >=b2 (Array of length 5). +constexpr uint8_t kBundleHeadByte = 0x85; +// The first byte of WebBundle format b1 (Array of length 6). +constexpr uint8_t kBundleB1HeadByte = 0x86; + // CBOR of the magic string "🌐📦". // MetadataParser::ParseMagicBytes() checks the first byte (0x85) and this. // @@ -59,6 +65,12 @@ const uint8_t kVersionB2MagicBytes[] = { 0x44, 0x62, 0x32, 0x00, 0x00, }; +// CBOR of the version string "b1\0\0". +// 44 -- Byte string of length 4 +// 62 31 00 00 -- "b1\0\0" +const uint8_t kVersionB1MagicBytes[] = { + 0x44, 0x62, 0x31, 0x00, 0x00, +}; // Section names. constexpr char kCriticalSection[] = "critical"; @@ -294,9 +306,10 @@ return; } - if (*array_size != 0x85) { - RunErrorCallbackAndDestroy( - "Wrong CBOR array size of the top-level structure"); + // Let kBundleB1HeadByte pass this check, to report custom error message for + // b1 bundles. + if (*array_size != kBundleHeadByte && *array_size != kBundleB1HeadByte) { + RunErrorCallbackAndDestroy("Wrong magic bytes."); return; } @@ -318,10 +331,25 @@ if (!std::equal(version->begin(), version->end(), std::begin(kVersionB2MagicBytes), std::end(kVersionB2MagicBytes))) { + const char* message; + if (std::equal(version->begin(), version->end(), + std::begin(kVersionB1MagicBytes), + std::end(kVersionB1MagicBytes))) { + message = + "Bundle format version is 'b1' which is no longer supported." + " Currently supported version is: 'b2'"; + } else { + message = + "Version error: bundle format does not correspond to the specifed " + "version. Currently supported version is: 'b2'"; + } + RunErrorCallbackAndDestroy(message, + mojom::BundleParseErrorType::kVersionError); + return; + } + if (*array_size != kBundleHeadByte) { RunErrorCallbackAndDestroy( - "Version error: bundle format does not correspond to the specifed " - "version. Currently supported version is: 'b2'", - mojom::BundleParseErrorType::kVersionError); + "Wrong CBOR array size of the top-level structure"); return; } @@ -551,7 +579,11 @@ GURL parsed_url = ParseExchangeURL(url, base_url_); if (!parsed_url.is_valid()) { - RunErrorCallbackAndDestroy("Index section: exchange URL is not valid."); + std::string message = base::StringPrintf( + "Index section: exchange URL \"%s\" is not valid.", url.c_str()); + if (base_url_.is_empty()) + message += " (Relative URLs are not allowed in this context.)"; + RunErrorCallbackAndDestroy(message); return false; }
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index a705de9..2e692f4b 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -1700,23 +1700,6 @@ return GetPlatformNodeFromTree(node.id()); } -ui::AXTreeID BrowserAccessibilityManager::GetTreeID() const { - return ax_tree_id_; -} - -ui::AXTreeID BrowserAccessibilityManager::GetParentTreeID() const { - return GetTreeData().parent_tree_id; -} - -ui::AXNode* BrowserAccessibilityManager::GetRootAsAXNode() const { - // ax_tree_ is nullptr after destruction. - if (!ax_tree()) - return nullptr; - - // ax_tree_->root() can be null during AXTreeObserver callbacks. - return ax_tree()->root(); -} - ui::AXNode* BrowserAccessibilityManager::GetParentNodeFromParentTreeAsAXNode() const { BrowserAccessibilityManager* parent_manager = GetParentManager(); @@ -1749,13 +1732,6 @@ return parent_node; } -void BrowserAccessibilityManager::WillBeRemovedFromMap() { - if (!ax_tree()) - return; - - ax_tree()->NotifyTreeManagerWillBeRemoved(ax_tree_id_); -} - BrowserAccessibilityManager* BrowserAccessibilityManager::GetRootManager() const { if (IsRootTree())
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index aa49a3c..4fea19ac 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -489,11 +489,7 @@ ui::AXPlatformNode* GetPlatformNodeFromTree( const ui::AXNodeID node_id) const override; ui::AXPlatformNode* GetPlatformNodeFromTree(const ui::AXNode&) const override; - ui::AXTreeID GetTreeID() const override; - ui::AXTreeID GetParentTreeID() const override; - ui::AXNode* GetRootAsAXNode() const override; ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override; - void WillBeRemovedFromMap() override; BrowserAccessibilityDelegate* delegate() const { return delegate_; }
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc index 4a381cd..601a053 100644 --- a/content/browser/cache_storage/cache_storage.cc +++ b/content/browser/cache_storage/cache_storage.cc
@@ -35,6 +35,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/cache_storage/cache_storage.pb.h" #include "content/browser/cache_storage/cache_storage_cache.h" #include "content/browser/cache_storage/cache_storage_cache_handle.h" @@ -77,7 +78,6 @@ } // namespace const char CacheStorage::kIndexFileName[] = "index.txt"; -const char CacheStorage::kCacheStorage[] = "CacheStorage"; struct CacheStorage::CacheMatchResponse { CacheMatchResponse() = default; @@ -102,16 +102,16 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorage* cache_storage, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) : cache_task_runner_(cache_task_runner), scheduler_task_runner_(std::move(scheduler_task_runner)), quota_manager_proxy_(std::move(quota_manager_proxy)), blob_storage_context_(std::move(blob_storage_context)), cache_storage_(cache_storage), - storage_key_(storage_key), + bucket_locator_(bucket_locator), owner_(owner) { - DCHECK(!storage_key_.origin().opaque()); + DCHECK(!bucket_locator_.storage_key.origin().opaque()); } virtual ~CacheLoader() = default; @@ -160,8 +160,8 @@ // Raw pointer is safe because this object is owned by cache_storage_. raw_ptr<CacheStorage> cache_storage_; - blink::StorageKey storage_key_; - storage::mojom::CacheStorageOwner owner_; + const storage::BucketLocator bucket_locator_; + const storage::mojom::CacheStorageOwner owner_; }; // Creates memory-only ServiceWorkerCaches. Because these caches have no @@ -175,14 +175,14 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorage* cache_storage, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) : CacheLoader(cache_task_runner, std::move(scheduler_task_runner), std::move(quota_manager_proxy), std::move(blob_storage_context), cache_storage, - storage_key, + bucket_locator, owner) {} std::unique_ptr<CacheStorageCache> CreateCache( @@ -190,7 +190,7 @@ int64_t cache_size, int64_t cache_padding) override { return CacheStorageCache::CreateMemoryCache( - storage_key_, owner_, cache_name, cache_storage_, + bucket_locator_, owner_, cache_name, cache_storage_, scheduler_task_runner_, quota_manager_proxy_, blob_storage_context_); } @@ -243,14 +243,14 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorage* cache_storage, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) : CacheLoader(cache_task_runner, std::move(scheduler_task_runner), std::move(quota_manager_proxy), std::move(blob_storage_context), cache_storage, - storage_key, + bucket_locator, owner), directory_path_(directory_path) {} @@ -264,7 +264,7 @@ std::string cache_dir = cache_name_to_cache_dir_[cache_name]; base::FilePath cache_path = directory_path_.AppendASCII(cache_dir); return CacheStorageCache::CreatePersistentCache( - storage_key_, owner_, cache_name, cache_storage_, cache_path, + bucket_locator_, owner_, cache_name, cache_storage_, cache_path, scheduler_task_runner_, quota_manager_proxy_, blob_storage_context_, cache_size, cache_padding); } @@ -284,12 +284,12 @@ // Runs on the cache_task_runner_. static std::tuple<CacheStorageError, std::string> - PrepareNewCacheDirectoryInPool(const base::FilePath& origin_path) { + PrepareNewCacheDirectoryInPool(const base::FilePath& directory_path) { std::string cache_dir; base::FilePath cache_path; do { cache_dir = base::GenerateGUID(); - cache_path = origin_path.AppendASCII(cache_dir); + cache_path = directory_path.AppendASCII(cache_dir); } while (base::PathExists(cache_path)); base::File::Error error = base::File::FILE_OK; @@ -356,9 +356,12 @@ // `CacheStorageManager` no longer uses the origin as a fallback for // getting the storage key associated with each cache (for more info, see // `GetStorageKeysAndLastModifiedOnTaskRunner`). - protobuf_index.set_origin(storage_key_.origin().GetURL().spec()); + protobuf_index.set_origin( + bucket_locator_.storage_key.origin().GetURL().spec()); - protobuf_index.set_storage_key(storage_key_.Serialize()); + protobuf_index.set_storage_key(bucket_locator_.storage_key.Serialize()); + protobuf_index.set_bucket_id(bucket_locator_.id.value()); + protobuf_index.set_bucket_is_default(bucket_locator_.is_default); for (const auto& cache_metadata : index.ordered_cache_metadata()) { DCHECK(base::Contains(cache_name_to_cache_dir_, cache_metadata.name)); @@ -387,7 +390,7 @@ cache_task_runner_.get(), FROM_HERE, base::BindOnce(&SimpleCacheLoader::WriteIndexWriteToFileInPool, tmp_path, index_path, serialized, quota_manager_proxy_, - storage_key_), + bucket_locator_), std::move(callback)); } @@ -396,11 +399,11 @@ const base::FilePath& index_path, const std::string& data, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - const blink::StorageKey& storage_key) { + const storage::BucketLocator& bucket_locator) { int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size()); if (bytes_written != base::checked_cast<int>(data.size())) { base::DeleteFile(tmp_path); - quota_manager_proxy->NotifyWriteFailed(storage_key); + quota_manager_proxy->NotifyWriteFailed(bucket_locator.storage_key); return false; } @@ -414,7 +417,7 @@ PostTaskAndReplyWithResult( cache_task_runner_.get(), FROM_HERE, base::BindOnce(&SimpleCacheLoader::ReadAndMigrateIndexInPool, - directory_path_, quota_manager_proxy_, storage_key_), + directory_path_, quota_manager_proxy_, bucket_locator_), base::BindOnce(&SimpleCacheLoader::LoadIndexDidReadIndex, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } @@ -493,11 +496,11 @@ // Runs on cache_task_runner_ static proto::CacheStorageIndex ReadAndMigrateIndexInPool( - const base::FilePath& origin_path, + const base::FilePath& directory_path, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - const blink::StorageKey& storage_key) { + const storage::BucketLocator& bucket_locator) { const base::FilePath index_path = - origin_path.AppendASCII(CacheStorage::kIndexFileName); + directory_path.AppendASCII(CacheStorage::kIndexFileName); proto::CacheStorageIndex index; std::string body; @@ -515,12 +518,17 @@ // Look for caches that have no cache_dir. Give any such caches a directory // with a random name and move them there. Then, rewrite the index file. // Additionally invalidate the size of any index entries where the cache was - // modified after the index (making it out-of-date). + // modified after the index (making it out-of-date). We'll assume that any + // unmigrated index files predate the buckets integration and leave them in + // the directory for first-party Cache Storage instances in the default + // bucket. + for (int i = 0, max = index.cache_size(); i < max; ++i) { const proto::CacheStorageIndex::Cache& cache = index.cache(i); if (cache.has_cache_dir()) { if (cache.has_size()) { - base::FilePath cache_dir = origin_path.AppendASCII(cache.cache_dir()); + base::FilePath cache_dir = + directory_path.AppendASCII(cache.cache_dir()); if (!GetFileInfo(cache_dir, &file_info) || index_last_modified <= file_info.last_modified) { // Index is older than this cache, so invalidate index entries that @@ -531,12 +539,12 @@ } else { // Find a new home for the cache. base::FilePath legacy_cache_path = - origin_path.AppendASCII(HexedHash(cache.name())); + directory_path.AppendASCII(HexedHash(cache.name())); std::string cache_dir; base::FilePath cache_path; do { cache_dir = base::GenerateGUID(); - cache_path = origin_path.AppendASCII(cache_dir); + cache_path = directory_path.AppendASCII(cache_dir); } while (base::PathExists(cache_path)); if (!base::Move(legacy_cache_path, cache_path)) { @@ -553,17 +561,24 @@ } if (!index.has_storage_key()) { - DCHECK(storage_key.origin().GetURL().spec() == index.origin()); - index.set_storage_key(storage_key.Serialize()); + DCHECK(bucket_locator.storage_key.origin().GetURL().spec() == + index.origin()); + index.set_storage_key(bucket_locator.storage_key.Serialize()); + index_modified = true; + } + + if (!index.has_bucket_id()) { + index.set_bucket_id(bucket_locator.id.value()); + index.set_bucket_is_default(bucket_locator.is_default); index_modified = true; } if (index_modified) { - base::FilePath tmp_path = origin_path.AppendASCII("index.txt.tmp"); + base::FilePath tmp_path = directory_path.AppendASCII("index.txt.tmp"); if (!index.SerializeToString(&body) || !WriteIndexWriteToFileInPool(tmp_path, index_path, body, std::move(quota_manager_proxy), - storage_key)) { + bucket_locator)) { return proto::CacheStorageIndex(); } } @@ -587,9 +602,9 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorageManager* cache_storage_manager, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) - : storage_key_(storage_key), + : bucket_locator_(bucket_locator), memory_only_(memory_only), scheduler_( new CacheStorageScheduler(CacheStorageSchedulerClient::kStorage, @@ -601,16 +616,17 @@ owner_(owner), cache_storage_manager_(cache_storage_manager) { if (memory_only) { - cache_loader_ = base::WrapUnique<CacheLoader>(new MemoryLoader( - cache_task_runner_.get(), std::move(scheduler_task_runner), - quota_manager_proxy, blob_storage_context_, this, storage_key, owner)); + cache_loader_ = base::WrapUnique<CacheLoader>( + new MemoryLoader(cache_task_runner_.get(), + std::move(scheduler_task_runner), quota_manager_proxy, + blob_storage_context_, this, bucket_locator_, owner)); return; } cache_loader_ = base::WrapUnique<CacheLoader>(new SimpleCacheLoader( directory_path_, cache_task_runner_.get(), std::move(scheduler_task_runner), quota_manager_proxy, - blob_storage_context_, this, storage_key, owner)); + blob_storage_context_, this, bucket_locator_, owner)); #if BUILDFLAG(IS_ANDROID) app_status_listener_ = @@ -638,7 +654,7 @@ handle_ref_count_ -= 1; if (!handle_ref_count_ && cache_storage_manager_) { ReleaseUnreferencedCaches(); - cache_storage_manager_->CacheStorageUnreferenced(this, storage_key_, + cache_storage_manager_->CacheStorageUnreferenced(this, bucket_locator_, owner_); } } @@ -656,8 +672,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); // TODO: Hold a handle to this CacheStorage instance while executing // operations to better support use by internal code that may @@ -681,8 +697,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); auto id = scheduler_->CreateId(); scheduler_->ScheduleOperation( @@ -702,8 +718,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); auto id = scheduler_->CreateId(); scheduler_->ScheduleOperation( @@ -722,8 +738,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); auto id = scheduler_->CreateId(); scheduler_->ScheduleOperation( @@ -746,8 +762,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); auto id = scheduler_->CreateId(); scheduler_->ScheduleOperation( @@ -770,8 +786,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); auto id = scheduler_->CreateId(); scheduler_->ScheduleOperation( @@ -794,8 +810,8 @@ if (!initialized_) LazyInit(); - quota_manager_proxy_->NotifyStorageAccessed( - storage_key_, StorageType::kTemporary, base::Time::Now()); + quota_manager_proxy_->NotifyBucketAccessed(bucket_locator_.id, + base::Time::Now()); // Note, this is a shared operation since it only reads CacheStorage data. // The CacheStorageCache is responsible for making its put operation @@ -851,7 +867,8 @@ void CacheStorage::NotifyCacheContentChanged(const std::string& cache_name) { if (cache_storage_manager_) - cache_storage_manager_->NotifyCacheContentChanged(storage_key_, cache_name); + cache_storage_manager_->NotifyCacheContentChanged(bucket_locator_, + cache_name); } void CacheStorage::ScheduleWriteIndex() { @@ -1068,7 +1085,7 @@ cache_loader_->NotifyCacheCreated(cache_name, std::move(handle)); if (cache_storage_manager_) - cache_storage_manager_->NotifyCacheListChanged(storage_key_); + cache_storage_manager_->NotifyCacheListChanged(bucket_locator_); } void CacheStorage::CreateCacheDidWriteIndex( @@ -1159,7 +1176,7 @@ cache_loader_->NotifyCacheDoomed(std::move(cache_handle)); if (cache_storage_manager_) - cache_storage_manager_->NotifyCacheListChanged(storage_key_); + cache_storage_manager_->NotifyCacheListChanged(bucket_locator_); std::move(callback).Run(CacheStorageError::kSuccess); } @@ -1174,9 +1191,9 @@ void CacheStorage::DeleteCacheDidGetSize(CacheStorageCache* doomed_cache, int64_t cache_size) { - quota_manager_proxy_->NotifyStorageModified( - CacheStorageQuotaClient::GetClientTypeFromOwner(owner_), storage_key_, - StorageType::kTemporary, -cache_size, base::Time::Now(), + quota_manager_proxy_->NotifyBucketModified( + CacheStorageQuotaClient::GetClientTypeFromOwner(owner_), + bucket_locator_.id, -cache_size, base::Time::Now(), base::SequencedTaskRunnerHandle::Get(), base::DoNothing()); cache_loader_->CleanUpDeletedCache(doomed_cache);
diff --git a/content/browser/cache_storage/cache_storage.h b/content/browser/cache_storage/cache_storage.h index 8dd3692..65ccacb6 100644 --- a/content/browser/cache_storage/cache_storage.h +++ b/content/browser/cache_storage/cache_storage.h
@@ -31,7 +31,6 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/remote.h" #include "storage/browser/quota/quota_manager.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h" #if BUILDFLAG(IS_ANDROID) @@ -56,7 +55,7 @@ // TODO(jkarlin): Constrain the total bytes used per storage key. -// CacheStorage holds the set of caches for a given StorageKey. It is +// CacheStorage holds the set of caches for a given BucketLocator. It is // owned by the CacheStorageManager. This class expects to be run // on the IO thread. The asynchronous methods are executed serially. class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver { @@ -76,7 +75,6 @@ base::OnceCallback<void(std::vector<std::string> cache_names)>; static const char kIndexFileName[]; - static const char kCacheStorage[]; CacheStorage(const base::FilePath& origin_path, bool memory_only, @@ -85,7 +83,7 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorageManager* cache_storage_manager, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner); CacheStorage(const CacheStorage&) = delete; @@ -195,9 +193,6 @@ return static_cast<CacheStorage*>(handle.value()); } - // The immutable StorageKey of the CacheStorage. - const blink::StorageKey storage_key() const { return storage_key_; } - protected: // Virtual for testing virtual void CacheUnreferenced(CacheStorageCache* cache); @@ -330,15 +325,15 @@ void OnApplicationStateChange(base::android::ApplicationState state); #endif - // The StorageKey that this CacheStorage is associated with. - const blink::StorageKey storage_key_; + // The `BucketLocator` that this CacheStorage is associated with. + const storage::BucketLocator bucket_locator_; // Whether or not we've loaded the list of cache names into memory. bool initialized_ = false; bool initializing_ = false; // True if the backend is supposed to reside in memory only. - bool memory_only_; + const bool memory_only_; // The pending operation scheduler. std::unique_ptr<CacheStorageScheduler> scheduler_; @@ -370,7 +365,7 @@ scoped_refptr<BlobStorageContextWrapper> blob_storage_context_; // The owner that this CacheStorage is associated with. - storage::mojom::CacheStorageOwner owner_; + const storage::mojom::CacheStorageOwner owner_; CacheStorageSchedulerId init_id_ = -1;
diff --git a/content/browser/cache_storage/cache_storage.proto b/content/browser/cache_storage/cache_storage.proto index 3a4ea30..036be6e9 100644 --- a/content/browser/cache_storage/cache_storage.proto +++ b/content/browser/cache_storage/cache_storage.proto
@@ -20,6 +20,8 @@ repeated Cache cache = 1; optional string origin = 2 [deprecated = true]; optional string storage_key = 3; + optional int64 bucket_id = 4; + optional bool bucket_is_default = 5; } message CacheHeaderMap {
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index 367c7f2..3b8961c 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -493,7 +493,7 @@ } int64_t CalculateSideDataPadding( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, const ::content::proto::CacheResponse* response, int side_data_size) { DCHECK(ShouldPadResourceSize(response)); @@ -512,8 +512,8 @@ base::Time::FromInternalValue(response->response_time()); return storage::ComputeStableResponsePadding( - storage_key.origin(), url, response_time, response->request_method(), - side_data_size); + bucket_locator.storage_key.origin(), url, response_time, + response->request_method(), side_data_size); } net::RequestPriority GetDiskCachePriority( @@ -579,7 +579,7 @@ // static std::unique_ptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, CacheStorage* cache_storage, @@ -587,7 +587,7 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context) { CacheStorageCache* cache = new CacheStorageCache( - storage_key, owner, cache_name, base::FilePath(), cache_storage, + bucket_locator, owner, cache_name, base::FilePath(), cache_storage, std::move(scheduler_task_runner), std::move(quota_manager_proxy), std::move(blob_storage_context), /*cache_size=*/0, /*cache_padding=*/0); @@ -598,7 +598,7 @@ // static std::unique_ptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, CacheStorage* cache_storage, @@ -609,7 +609,7 @@ int64_t cache_size, int64_t cache_padding) { CacheStorageCache* cache = new CacheStorageCache( - storage_key, owner, cache_name, path, cache_storage, + bucket_locator, owner, cache_name, path, cache_storage, std::move(scheduler_task_runner), std::move(quota_manager_proxy), std::move(blob_storage_context), cache_size, cache_padding); cache->SetObserver(cache_storage); @@ -716,7 +716,7 @@ // GetUsageAndQuota is called before entering a scheduled operation since it // can call Size, another scheduled operation. quota_manager_proxy_->GetUsageAndQuota( - storage_key_, blink::mojom::StorageType::kTemporary, + bucket_locator_.storage_key, blink::mojom::StorageType::kTemporary, scheduler_task_runner_, base::BindOnce(&CacheStorageCache::WriteSideDataDidGetQuota, weak_ptr_factory_.GetWeakPtr(), std::move(callback), url, @@ -804,7 +804,7 @@ // Put runs, the cache might already be full and the usage will be larger // than it's supposed to be. quota_manager_proxy_->GetUsageAndQuota( - storage_key_, blink::mojom::StorageType::kTemporary, + bucket_locator_.storage_key, blink::mojom::StorageType::kTemporary, scheduler_task_runner_, base::BindOnce(&CacheStorageCache::BatchDidGetUsageAndQuota, weak_ptr_factory_.GetWeakPtr(), std::move(operations), @@ -1028,7 +1028,7 @@ } CacheStorageCache::CacheStorageCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, const base::FilePath& path, @@ -1038,7 +1038,7 @@ scoped_refptr<BlobStorageContextWrapper> blob_storage_context, int64_t cache_size, int64_t cache_padding) - : storage_key_(storage_key), + : bucket_locator_(bucket_locator), owner_(owner), cache_name_(cache_name), path_(path), @@ -1056,7 +1056,7 @@ owner, std::move(blob_storage_context))), memory_only_(path.empty()) { - DCHECK(!storage_key_.origin().opaque()); + DCHECK(!bucket_locator_.storage_key.origin().opaque()); DCHECK(quota_manager_proxy_.get()); if (cache_size_ != CacheStorage::kSizeUnknown && @@ -1354,7 +1354,7 @@ auto* response = metadata->mutable_response(); response->set_padding(storage::ComputeRandomResponsePadding()); response->set_side_data_padding(CalculateSideDataPadding( - storage_key_, response, entry->GetDataSize(INDEX_SIDE_DATA))); + bucket_locator_, response, entry->GetDataSize(INDEX_SIDE_DATA))); // Get a temporary copy of the entry and metadata pointers before moving them // into base::BindOnce. @@ -1693,7 +1693,7 @@ cache_padding_ -= response->side_data_padding(); response->set_side_data_padding( - CalculateSideDataPadding(storage_key_, response, rv)); + CalculateSideDataPadding(bucket_locator_, response, rv)); cache_padding_ += response->side_data_padding(); // Get a temporary copy of the entry pointer before passing it in @@ -1877,7 +1877,7 @@ put_context->cache_entry.reset(result.ReleaseEntry()); if (rv != net::OK) { - quota_manager_proxy_->NotifyWriteFailed(storage_key_); + quota_manager_proxy_->NotifyWriteFailed(bucket_locator_.storage_key); PutComplete(std::move(put_context), CacheStorageError::kErrorExists); return; } @@ -1942,7 +1942,7 @@ if (ShouldPadResourceSize(*put_context->response) && put_context->side_data_blob) { side_data_padding = CalculateSideDataPadding( - storage_key_, response_metadata, put_context->side_data_blob_size); + bucket_locator_, response_metadata, put_context->side_data_blob_size); } response_metadata->set_side_data_padding(side_data_padding); response_metadata->set_request_include_credentials( @@ -1971,7 +1971,7 @@ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); if (rv != expected_bytes) { - quota_manager_proxy_->NotifyWriteFailed(storage_key_); + quota_manager_proxy_->NotifyWriteFailed(bucket_locator_.storage_key); PutComplete( std::move(put_context), MakeErrorStorage(ErrorStorageType::kPutDidWriteHeadersWrongBytes)); @@ -2053,7 +2053,7 @@ // We have real data, so stream it into the entry. This will overwrite // any existing data. auto blob_to_cache = std::make_unique<CacheStorageBlobToDiskCache>( - quota_manager_proxy_, storage_key_); + quota_manager_proxy_, bucket_locator_.storage_key); CacheStorageBlobToDiskCache* blob_to_cache_raw = blob_to_cache.get(); BlobToDiskCacheIDMap::KeyType blob_to_cache_key = active_blob_to_disk_cache_writers_.Add(std::move(blob_to_cache)); @@ -2204,10 +2204,9 @@ int64_t size_delta = PaddedCacheSize() - last_reported_size_; last_reported_size_ = PaddedCacheSize(); - quota_manager_proxy_->NotifyStorageModified( - CacheStorageQuotaClient::GetClientTypeFromOwner(owner_), storage_key_, - blink::mojom::StorageType::kTemporary, size_delta, base::Time::Now(), - scheduler_task_runner_, + quota_manager_proxy_->NotifyBucketModified( + CacheStorageQuotaClient::GetClientTypeFromOwner(owner_), + bucket_locator_.id, size_delta, base::Time::Now(), scheduler_task_runner_, base::BindOnce(&CacheStorageCache::UpdateCacheSizeNotifiedStorageModified, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h index f44da0fa..161f9e8 100644 --- a/content/browser/cache_storage/cache_storage_cache.h +++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -17,6 +17,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "components/services/storage/public/mojom/cache_storage_control.mojom.h" #include "content/browser/cache_storage/blob_storage_context_wrapper.h" #include "content/browser/cache_storage/cache_storage_cache_handle.h" @@ -28,7 +29,6 @@ #include "net/base/io_buffer.h" #include "net/disk_cache/disk_cache.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" @@ -97,7 +97,7 @@ }; static std::unique_ptr<CacheStorageCache> CreateMemoryCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, CacheStorage* cache_storage, @@ -105,7 +105,7 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context); static std::unique_ptr<CacheStorageCache> CreatePersistentCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, CacheStorage* cache_storage, @@ -300,7 +300,7 @@ base::IDMap<std::unique_ptr<CacheStorageBlobToDiskCache>>; CacheStorageCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, const base::FilePath& path, @@ -590,21 +590,21 @@ // Be sure to check |backend_state_| before use. std::unique_ptr<disk_cache::Backend> backend_; - blink::StorageKey storage_key_; - storage::mojom::CacheStorageOwner owner_; + const storage::BucketLocator bucket_locator_; + const storage::mojom::CacheStorageOwner owner_; const std::string cache_name_; - base::FilePath path_; + const base::FilePath path_; // Raw pointer is safe because the CacheStorage instance owns this // CacheStorageCache object. - raw_ptr<CacheStorage> cache_storage_; + const raw_ptr<CacheStorage> cache_storage_; // A handle that is used to keep the owning CacheStorage instance referenced // as long this cache object is also referenced. CacheStorageHandle cache_storage_handle_; const scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner_; - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; + const scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; BackendState backend_state_ = BACKEND_UNINITIALIZED; std::unique_ptr<CacheStorageScheduler> scheduler_; bool initializing_ = false; @@ -622,7 +622,7 @@ BlobToDiskCacheIDMap active_blob_to_disk_cache_writers_; // Whether or not to store data in disk or memory. - bool memory_only_; + const bool memory_only_; // Active while waiting for the backend to finish its closing up, and contains // the callback passed to CloseImpl.
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc index 2657948..de8f2764f6 100644 --- a/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -24,9 +24,11 @@ #include "base/strings/string_split.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/test_future.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/buckets/constants.h" #include "components/services/storage/public/mojom/cache_storage_control.mojom.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/cache_storage/cache_storage.h" @@ -420,13 +422,13 @@ class TestCacheStorageCache : public CacheStorageCache { public: TestCacheStorageCache( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, const std::string& cache_name, const base::FilePath& path, CacheStorage* cache_storage, const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context) - : CacheStorageCache(storage_key, + : CacheStorageCache(bucket_locator, storage::mojom::CacheStorageOwner::kCacheAPI, cache_name, path, @@ -502,7 +504,7 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<BlobStorageContextWrapper> blob_storage_context, CacheStorageManager* cache_storage_manager, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) : CacheStorage(origin_path, memory_only, @@ -511,7 +513,7 @@ std::move(quota_manager_proxy), std::move(blob_storage_context), cache_storage_manager, - storage_key, + bucket_locator, owner) {} void CacheUnreferenced(CacheStorageCache* cache) override { @@ -564,6 +566,7 @@ std::vector<uint8_t>(expected_blob_data_.begin(), expected_blob_data_.end())); + auto bucket_locator = GetOrCreateBucket(kTestUrl); // Use a mock CacheStorage object so we can use real // CacheStorageCacheHandle reference counting. A CacheStorage // must be present to be notified when a cache becomes unreferenced. @@ -571,10 +574,9 @@ temp_dir_path_, MemoryOnly(), base::ThreadTaskRunnerHandle::Get().get(), base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_, blob_storage_context_, /* cache_storage_manager = */ nullptr, - blink::StorageKey(url::Origin::Create(kTestUrl)), - storage::mojom::CacheStorageOwner::kCacheAPI); + bucket_locator, storage::mojom::CacheStorageOwner::kCacheAPI); - InitCache(mock_cache_storage_.get()); + InitCache(mock_cache_storage_.get(), bucket_locator); } void TearDown() override { @@ -582,6 +584,17 @@ content::RunAllTasksUntilIdle(); } + storage::BucketLocator GetOrCreateBucket(const GURL& url) { + auto storage_key = blink::StorageKey(url::Origin::Create(url)); + base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future; + quota_manager_proxy_->UpdateOrCreateBucket( + storage::BucketInitParams(storage_key, storage::kDefaultBucketName), + base::ThreadTaskRunnerHandle::Get(), future.GetCallback()); + auto bucket = future.Take(); + EXPECT_TRUE(bucket.ok()); + return bucket->ToBucketLocator(); + } + GURL BodyUrl() const { GURL::Replacements replacements; replacements.SetPathStr("/body.html"); @@ -598,11 +611,11 @@ return kTestUrl.ReplaceComponents(replacements); } - void InitCache(CacheStorage* cache_storage) { + void InitCache(CacheStorage* cache_storage, + const storage::BucketLocator& bucket_locator) { cache_ = std::make_unique<TestCacheStorageCache>( - blink::StorageKey(url::Origin::Create(kTestUrl)), kCacheName, - temp_dir_path_, cache_storage, quota_manager_proxy_, - blob_storage_context_); + bucket_locator, kCacheName, temp_dir_path_, cache_storage, + quota_manager_proxy_, blob_storage_context_); cache_->Init(); } @@ -1943,12 +1956,12 @@ base::Time response_time(base::Time::Now()); blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse()); response->response_time = response_time; - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_modified_count()); EXPECT_TRUE(Put(no_body_request_, std::move(response))); // Storage notification happens after the operation returns, so continue the // event loop. base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_modified_count()); const size_t kSize = 10; scoped_refptr<net::IOBuffer> buffer = @@ -1957,7 +1970,7 @@ EXPECT_TRUE( WriteSideData(no_body_request_->url, response_time, buffer, kSize)); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(2, quota_manager_proxy_->notify_bucket_modified_count()); ASSERT_TRUE(Delete(no_body_request_)); } @@ -2002,31 +2015,31 @@ } TEST_P(CacheStorageCacheTestP, QuotaManagerModified) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_modified_count()); EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse())); // Storage notification happens after the operation returns, so continue the // event loop. base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count()); - EXPECT_LT(0, quota_manager_proxy_->last_notified_delta()); - int64_t sum_delta = quota_manager_proxy_->last_notified_delta(); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_modified_count()); + EXPECT_LT(0, quota_manager_proxy_->last_notified_bucket_delta()); + int64_t sum_delta = quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_TRUE(Put(body_request_, CreateBlobBodyResponse())); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count()); - EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta()); - sum_delta += quota_manager_proxy_->last_notified_delta(); + EXPECT_EQ(2, quota_manager_proxy_->notify_bucket_modified_count()); + EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_bucket_delta()); + sum_delta += quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_TRUE(Delete(body_request_)); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count()); - sum_delta += quota_manager_proxy_->last_notified_delta(); + EXPECT_EQ(3, quota_manager_proxy_->notify_bucket_modified_count()); + sum_delta += quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_TRUE(Delete(no_body_request_)); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count()); - sum_delta += quota_manager_proxy_->last_notified_delta(); + EXPECT_EQ(4, quota_manager_proxy_->notify_bucket_modified_count()); + sum_delta += quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_EQ(0, sum_delta); } @@ -2361,7 +2374,7 @@ base::RunLoop().RunUntilIdle(); // Create a new Cache in the same space. - InitCache(nullptr); + InitCache(nullptr, GetOrCreateBucket(kTestUrl)); // Now attempt to read the same response from the cache. It should fail. EXPECT_FALSE(Match(body_request_));
diff --git a/content/browser/cache_storage/cache_storage_context_impl.cc b/content/browser/cache_storage/cache_storage_context_impl.cc index 180fe63..551d40a 100644 --- a/content/browser/cache_storage/cache_storage_context_impl.cc +++ b/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -78,12 +78,17 @@ {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + DCHECK(!dispatcher_host_); + dispatcher_host_ = + std::make_unique<CacheStorageDispatcherHost>(this, quota_manager_proxy_); + DCHECK(!cache_manager_); cache_manager_ = CacheStorageManager::Create( user_data_directory, std::move(cache_task_runner), base::SequencedTaskRunnerHandle::Get(), quota_manager_proxy_, base::MakeRefCounted<BlobStorageContextWrapper>( - std::move(blob_storage_context))); + std::move(blob_storage_context)), + dispatcher_host_->AsWeakPtr()); mojo::MakeSelfOwnedReceiver( std::make_unique<CacheStorageQuotaClient>( @@ -161,8 +166,6 @@ result.ok() ? absl::make_optional(result->ToBucketLocator()) : absl::nullopt; - if (!dispatcher_host_) - dispatcher_host_ = std::make_unique<CacheStorageDispatcherHost>(this); dispatcher_host_->AddReceiver(cross_origin_embedder_policy, std::move(coep_reporter), storage_key, bucket, owner, std::move(receiver));
diff --git a/content/browser/cache_storage/cache_storage_context_impl.h b/content/browser/cache_storage/cache_storage_context_impl.h index f639b1f..1a651fa 100644 --- a/content/browser/cache_storage/cache_storage_context_impl.h +++ b/content/browser/cache_storage/cache_storage_context_impl.h
@@ -16,7 +16,7 @@ #include "components/services/storage/public/cpp/quota_error_or.h" #include "components/services/storage/public/mojom/blob_storage_context.mojom.h" #include "components/services/storage/public/mojom/cache_storage_control.mojom.h" -#include "components/services/storage/public/mojom/quota_client.mojom-forward.h" +#include "components/services/storage/public/mojom/quota_client.mojom.h" #include "content/browser/cache_storage/cache_storage_manager.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -24,6 +24,7 @@ #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h" +#include "storage/browser/quota/quota_manager_proxy.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-forward.h" @@ -33,7 +34,6 @@ } namespace storage { -class QuotaManagerProxy; struct BucketInfo; } @@ -88,6 +88,11 @@ return cache_manager_; } + const scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return quota_manager_proxy_; + } + bool is_incognito() const { return is_incognito_; } private:
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc index cb4e3fd..ab70c74 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" @@ -31,6 +32,7 @@ #include "services/network/public/cpp/cross_origin_resource_policy.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" @@ -652,10 +654,12 @@ // initialize it here. Also, eagerly initializing memory cache mode does // not really provide any performance benefit. if (!incognito) { - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); - if (cache_storage) { - cache_storage->Init(); - } + GetOrCreateCacheStorage( + base::BindOnce([](content::CacheStorage* cache_storage) { + if (cache_storage) { + cache_storage->Init(); + } + })); } } @@ -702,13 +706,17 @@ }, base::TimeTicks::Now(), trace_id, std::move(callback)); - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); - if (!cache_storage) { - std::move(cb).Run(std::vector<std::string>()); - return; - } + GetOrCreateCacheStorage(base::BindOnce( + [](int64_t trace_id, content::CacheStorage::EnumerateCachesCallback cb, + content::CacheStorage* cache_storage) { + if (!cache_storage) { + std::move(cb).Run(std::vector<std::string>()); + return; + } - cache_storage->EnumerateCaches(trace_id, std::move(cb)); + cache_storage->EnumerateCaches(trace_id, std::move(cb)); + }, + trace_id, std::move(cb))); } void Delete(const std::u16string& cache_name, @@ -746,13 +754,19 @@ return; } - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); - if (!cache_storage) { - std::move(cb).Run(MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); - return; - } + GetOrCreateCacheStorage(base::BindOnce( + [](std::string utf8_cache_name, int64_t trace_id, + content::CacheStorage::ErrorCallback cb, + content::CacheStorage* cache_storage) { + if (!cache_storage) { + std::move(cb).Run( + MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); + return; + } - cache_storage->DoomCache(utf8_cache_name, trace_id, std::move(cb)); + cache_storage->DoomCache(utf8_cache_name, trace_id, std::move(cb)); + }, + std::move(utf8_cache_name), trace_id, std::move(cb))); } void Has(const std::u16string& cache_name, @@ -793,14 +807,20 @@ return; } - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); - if (!cache_storage) { - std::move(cb).Run(/* has_cache = */ false, - MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); - return; - } + GetOrCreateCacheStorage(base::BindOnce( + [](std::string utf8_cache_name, int64_t trace_id, + content::CacheStorage::BoolAndErrorCallback cb, + content::CacheStorage* cache_storage) { + if (!cache_storage) { + std::move(cb).Run( + /* has_cache = */ false, + MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); + return; + } - cache_storage->HasCache(utf8_cache_name, trace_id, std::move(cb)); + cache_storage->HasCache(utf8_cache_name, trace_id, std::move(cb)); + }, + std::move(utf8_cache_name), trace_id, std::move(cb))); } void Match(blink::mojom::FetchAPIRequestPtr request, @@ -886,27 +906,36 @@ return; } - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); - if (!cache_storage) { - std::move(cb).Run(CacheStorageError::kErrorNotFound, nullptr); - return; - } + GetOrCreateCacheStorage(base::BindOnce( + [](blink::mojom::FetchAPIRequestPtr request, + blink::mojom::MultiCacheQueryOptionsPtr match_options, + bool in_related_fetch_event, int64_t trace_id, + content::CacheStorageCache::ResponseCallback cb, + content::CacheStorage* cache_storage) { + if (!cache_storage) { + std::move(cb).Run(CacheStorageError::kErrorNotFound, nullptr); + return; + } - CacheStorageSchedulerPriority priority = - CacheStorageSchedulerPriority::kNormal; - if (in_related_fetch_event) - priority = CacheStorageSchedulerPriority::kHigh; + CacheStorageSchedulerPriority priority = + CacheStorageSchedulerPriority::kNormal; + if (in_related_fetch_event) + priority = CacheStorageSchedulerPriority::kHigh; - if (!match_options->cache_name) { - cache_storage->MatchAllCaches(std::move(request), + if (!match_options->cache_name) { + cache_storage->MatchAllCaches( + std::move(request), std::move(match_options->query_options), + priority, trace_id, std::move(cb)); + return; + } + std::string cache_name = + base::UTF16ToUTF8(*match_options->cache_name); + cache_storage->MatchCache(std::move(cache_name), std::move(request), std::move(match_options->query_options), priority, trace_id, std::move(cb)); - return; - } - std::string cache_name = base::UTF16ToUTF8(*match_options->cache_name); - cache_storage->MatchCache(std::move(cache_name), std::move(request), - std::move(match_options->query_options), priority, - trace_id, std::move(cb)); + }, + std::move(request), std::move(match_options), in_related_fetch_event, + trace_id, std::move(cb))); } void Open(const std::u16string& cache_name, @@ -919,7 +948,6 @@ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "cache_name", utf8_cache_name); - content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); auto cb = base::BindOnce( [](base::WeakPtr<CacheStorageImpl> self, base::TimeTicks start_time, int64_t trace_id, blink::mojom::CacheStorage::OpenCallback callback, @@ -973,28 +1001,73 @@ return; } - if (!cache_storage) { - std::move(cb).Run(CacheStorageCacheHandle(), - MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); - return; - } - - cache_storage->OpenCache(utf8_cache_name, trace_id, std::move(cb)); + GetOrCreateCacheStorage(base::BindOnce( + [](std::string utf8_cache_name, int64_t trace_id, + content::CacheStorage::CacheAndErrorCallback cb, + content::CacheStorage* cache_storage) { + if (!cache_storage) { + std::move(cb).Run( + CacheStorageCacheHandle(), + MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); + return; + } + cache_storage->OpenCache(utf8_cache_name, trace_id, std::move(cb)); + }, + std::move(utf8_cache_name), trace_id, std::move(cb))); } private: + void UpdateOrCreateBucketCallback( + base::OnceCallback<void(content::CacheStorage*)> callback, + storage::QuotaErrorOr<storage::BucketInfo> result) { + if (result.ok()) { + bucket_ = result->ToBucketLocator(); + } else { + bucket_ = absl::nullopt; + std::move(callback).Run(nullptr); + return; + } + cache_storage_handle_ = host_->OpenCacheStorage(bucket_.value(), owner_); + std::move(callback).Run(cache_storage_handle_.value()); + } // Helper method that returns the current CacheStorageHandle value. If the // handle is closed, then it attempts to open a new CacheStorageHandle // automatically. This automatic open is necessary to re-attach to the // backend after the browser storage has been wiped. - content::CacheStorage* GetOrCreateCacheStorage() { + void GetOrCreateCacheStorage( + base::OnceCallback<void(content::CacheStorage*)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(host_); - if (!bucket_.has_value()) - return nullptr; - if (!cache_storage_handle_.value()) + if (!bucket_.has_value()) { + std::move(callback).Run(nullptr); + return; + } + + // If the stored bucket locator is out-of-date, request a new one + // asynchronously. The `CacheStorageManager` stores all Cache Storage + // instances in a map keyed on the bucket locator and owner, but issues can + // arise if the map gets populated with two Cache Storage instances + // corresponding to the same storage key and owner (specifically for + // first-party contexts). This scenario could occur if we don't invalidate + // old bucket locators here. If a `CacheStorageImpl` instance created before + // bucket deletion uses a bucket locator with the old bucket ID and a + // `CacheStorageImpl` instance created after bucket deletion uses a bucket + // locator with a new bucket ID, both could eventually call into + // `CacheStorageManager::OpenCacheStorage()`, causing two entries in the + // map to be created for the same storage key. For more details, see the + // comments above the `CacheStorageManager::CacheStoragePathIsUnique()` + // check in `CacheStorageManager::OpenCacheStorage()`. + if (host_->WasNotifiedOfBucketDataDeletion(bucket_.value())) { + host_->UpdateOrCreateBucket( + storage_key_, + base::BindOnce(&CacheStorageImpl::UpdateOrCreateBucketCallback, + weak_factory_.GetWeakPtr(), std::move(callback))); + return; + } + if (!cache_storage_handle_.value()) { cache_storage_handle_ = host_->OpenCacheStorage(bucket_.value(), owner_); - return cache_storage_handle_.value(); + } + std::move(callback).Run(cache_storage_handle_.value()); } // Owns this. @@ -1002,7 +1075,7 @@ const blink::StorageKey storage_key_; // absl::nullopt when bucket retrieval has failed. - const absl::optional<storage::BucketLocator> bucket_; + absl::optional<storage::BucketLocator> bucket_; const CrossOriginEmbedderPolicy cross_origin_embedder_policy_; mojo::Remote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_; @@ -1014,8 +1087,9 @@ }; CacheStorageDispatcherHost::CacheStorageDispatcherHost( - CacheStorageContextImpl* context) - : context_(context) { + CacheStorageContextImpl* context, + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) + : context_(context), quota_manager_proxy_(quota_manager_proxy) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } @@ -1032,6 +1106,16 @@ storage::mojom::CacheStorageOwner owner, mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (bucket.has_value() && WasNotifiedOfBucketDataDeletion(bucket.value())) { + // The list of deleted buckets gets added to each time + // `CacheStorageManager::DeleteBucketData()` is called, but it's not + // guaranteed that this means the bucket was actually deleted. To avoid + // a bucket being mistakenly considered deleted forever, treat a + // call to `CacheStorageDispatcherHost::AddReceiver` with a given bucket + // locator to be a signal that the corresponding bucket has not actually + // been deleted. + deleted_buckets_.erase(bucket.value()); + } bool incognito = context_ ? context_->is_incognito() : false; auto impl = std::make_unique<CacheStorageImpl>( this, storage_key, bucket, incognito, cross_origin_embedder_policy, @@ -1061,4 +1145,26 @@ return manager->OpenCacheStorage(bucket_locator, owner); } +void CacheStorageDispatcherHost::UpdateOrCreateBucket( + const blink::StorageKey& storage_key, + base::OnceCallback<void(storage::QuotaErrorOr<storage::BucketInfo>)> + callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + quota_manager_proxy_->UpdateOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(storage_key), + base::SequencedTaskRunnerHandle::Get(), std::move(callback)); +} + +bool CacheStorageDispatcherHost::WasNotifiedOfBucketDataDeletion( + const storage::BucketLocator& bucket_locator) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return deleted_buckets_.find(bucket_locator) != deleted_buckets_.end(); +} + +void CacheStorageDispatcherHost::NotifyBucketDataDeleted( + const storage::BucketLocator& bucket_locator) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + deleted_buckets_.insert(bucket_locator); +} + } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.h b/content/browser/cache_storage/cache_storage_dispatcher_host.h index 091c282..2489782 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.h +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -35,7 +35,9 @@ // from other sequences. class CacheStorageDispatcherHost { public: - explicit CacheStorageDispatcherHost(CacheStorageContextImpl* context); + CacheStorageDispatcherHost( + CacheStorageContextImpl* context, + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy); CacheStorageDispatcherHost(const CacheStorageDispatcherHost&) = delete; CacheStorageDispatcherHost& operator=(const CacheStorageDispatcherHost&) = @@ -58,6 +60,15 @@ storage::mojom::CacheStorageOwner owner, mojo::PendingReceiver<blink::mojom::CacheStorage> receiver); + base::WeakPtr<CacheStorageDispatcherHost> AsWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + bool WasNotifiedOfBucketDataDeletion( + const storage::BucketLocator& bucket_locator); + + void NotifyBucketDataDeleted(const storage::BucketLocator& bucket_locator); + private: class CacheStorageImpl; class CacheImpl; @@ -70,15 +81,24 @@ CacheStorageHandle OpenCacheStorage( const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner); + void UpdateOrCreateBucket( + const blink::StorageKey& storage_key, + base::OnceCallback<void(storage::QuotaErrorOr<storage::BucketInfo>)> + callback); // `this` is owned by `context_`. const raw_ptr<CacheStorageContextImpl> context_; + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; mojo::UniqueReceiverSet<blink::mojom::CacheStorage> receivers_; mojo::UniqueAssociatedReceiverSet<blink::mojom::CacheStorageCache> cache_receivers_; + std::set<storage::BucketLocator> deleted_buckets_; + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<CacheStorageDispatcherHost> weak_ptr_factory_{this}; }; } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc index 201301b..cfd61373 100644 --- a/content/browser/cache_storage/cache_storage_manager.cc +++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -9,9 +9,10 @@ #include <map> #include <numeric> #include <set> +#include <tuple> #include <utility> -#include "base/barrier_closure.h" +#include "base/barrier_callback.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/containers/id_map.h" @@ -19,7 +20,11 @@ #include "base/files/file_util.h" #include "base/hash/sha1.h" #include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" +#include "base/notreached.h" +#include "base/sequence_checker.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/task/sequenced_task_runner.h" @@ -27,12 +32,14 @@ #include "base/time/time.h" #include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "components/services/storage/public/cpp/constants.h" +#include "components/services/storage/public/mojom/storage_usage_info.mojom-forward.h" #include "content/browser/cache_storage/cache_storage.h" #include "content/browser/cache_storage/cache_storage.pb.h" #include "content/browser/cache_storage/cache_storage_quota_client.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/storage_directory_util.h" #include "storage/common/database/database_identifier.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" @@ -46,7 +53,7 @@ return base::DeletePathRecursively(path); } -void DeleteStorageKeyDidDeleteDir( +void DeleteBucketDidDeleteDir( storage::mojom::QuotaClient::DeleteBucketDataCallback callback, bool rv) { // On scheduler sequence. @@ -57,6 +64,22 @@ : blink::mojom::QuotaStatusCode::kErrorAbort)); } +void DeleteStorageKeyDidDeleteAllData( + storage::mojom::QuotaClient::DeleteBucketDataCallback callback, + std::vector<blink::mojom::QuotaStatusCode> results) { + // On scheduler sequence. + for (auto result : results) { + if (result != blink::mojom::QuotaStatusCode::kOk) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); + return; + } + } + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), blink::mojom::QuotaStatusCode::kOk)); +} + // Calculate the sum of all cache sizes in this store, but only if all sizes are // known. If one or more sizes are not known then return kSizeUnknown. int64_t GetCacheStorageSize(const base::FilePath& base_path, @@ -150,7 +173,9 @@ const base::FilePath& index_file_directory_path, storage::mojom::CacheStorageOwner owner, const base::FilePath& profile_path, - std::vector<storage::mojom::StorageUsageInfoPtr>& usages) { + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>>& usage_tuples, + bool is_origin_path = false) { if (!base::PathExists(index_file_directory_path)) { return; } @@ -194,43 +219,104 @@ } DCHECK(!storage_key.origin().GetURL().is_empty()); - auto origin_path = CacheStorageManager::ConstructStorageKeyPath( - profile_path, storage_key, owner); - if (index_file_directory_path != origin_path) { - storage::mojom::CacheStorageOwner other_owner = - owner == storage::mojom::CacheStorageOwner::kCacheAPI - ? storage::mojom::CacheStorageOwner::kBackgroundFetch - : storage::mojom::CacheStorageOwner::kCacheAPI; - auto other_owner_path = CacheStorageManager::ConstructStorageKeyPath( - profile_path, storage_key, other_owner); - // Some of the paths in the |index_file_directory_path| directory are for a - // different |owner|. That is valid and expected, but if the path doesn't - // match the calculated path for either |owner|, then it is invalid. - if (index_file_directory_path != other_owner_path) - RecordIndexValidationResult(IndexResult::kPathMismatch); + storage::BucketLocator bucket_locator{}; + + if (index.has_bucket_id() && index.has_bucket_is_default()) { + bucket_locator = storage::BucketLocator( + storage::BucketId(index.bucket_id()), storage_key, + blink::mojom::StorageType::kTemporary, index.bucket_is_default()); + // TODO(https://crbug.com/1218097): Is there a way to validate that this + // bucket information is valid? + } else { + // If the index file has no bucket information then it's from before we + // had non-default buckets and third-party storage partitioning + // implemented. That means these index files will always use the + // origin-based path format. Populate our BucketLocator with enough + // data to construct the appropriate path from it below. + bucket_locator.is_default = true; + bucket_locator.storage_key = storage_key; + // TODO(https://crbug.com/1218097): Once enough time has passed it should be + // safe to treat this case as an index validation error. + } + + auto bucket_path = CacheStorageManager::ConstructBucketPath( + profile_path, bucket_locator, owner); + if (index_file_directory_path != bucket_path) { + if (is_origin_path) { + // For paths corresponding to the legacy Cache Storage directory structure + // (where the bucket ID is not in the path), + // `ValidateAndAddUsageFromPath()` can get called with an + // `index_file_directory_path` that corresponds to a Cache Storage + // instance from a different `owner`. That is valid and expected because + // the directory entries from different owners are stored alongside each + // other and are not easily distinguishable (the directory name is a + // hash of the origin + the owner), so it's easiest to just compute the + // two possible origin paths here and compare. If the path doesn't match + // the calculated path for either `owner` then it is invalid. With the new + // directory structure for non-default buckets and third-party contexts, + // we only call `ValidateAndAddUsageFromPath()` with Cache Storage + // instances for the appropriate owner, so this check isn't needed in that + // case. We return early if this instance corresponds to another owner to + // avoid recording an index validation error and polluting the metrics + // derived from them. + storage::mojom::CacheStorageOwner other_owner = + owner == storage::mojom::CacheStorageOwner::kCacheAPI + ? storage::mojom::CacheStorageOwner::kBackgroundFetch + : storage::mojom::CacheStorageOwner::kCacheAPI; + auto other_owner_path = CacheStorageManager::ConstructBucketPath( + profile_path, bucket_locator, other_owner); + if (index_file_directory_path == other_owner_path) + return; + } + RecordIndexValidationResult(IndexResult::kPathMismatch); return; } int64_t storage_size = GetCacheStorageSize(index_file_directory_path, index_last_modified, index); - usages.emplace_back(storage::mojom::StorageUsageInfo::New( - storage_key.origin(), storage_size, file_info.last_modified)); + usage_tuples.emplace_back( + bucket_locator, + storage::mojom::StorageUsageInfo::New(storage_key.origin(), storage_size, + file_info.last_modified)); RecordIndexValidationResult(IndexResult::kOk); } -// Open the various cache directories' index files and extract their storage -// keys, sizes (if current), and last modified times. +void GetStorageKeyAndLastModifiedGotBucket( + storage::mojom::StorageUsageInfoPtr info, + base::OnceCallback<void(std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>)> + callback, + storage::QuotaErrorOr<storage::BucketInfo> result) { + storage::BucketLocator bucket_locator{}; + if (result.ok()) { + bucket_locator = result->ToBucketLocator(); + } + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + std::make_tuple(bucket_locator, + storage::mojom::StorageUsageInfo::New( + info->origin, info->total_size_bytes, + info->last_modified)))); +} + +// Open the various cache directories' index files and extract their bucket +// locators, sizes (if current), and last modified times. void GetStorageKeysAndLastModifiedOnTaskRunner( + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner, - std::vector<storage::mojom::StorageUsageInfoPtr> usages, + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> usage_tuples, + base::FilePath profile_path, storage::mojom::CacheStorageOwner owner, - base::OnceCallback<void(std::vector<storage::mojom::StorageUsageInfoPtr>)> + base::OnceCallback< + void(std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>>)> callback) { - // TODO(awillia): This is in braces so that in a future CL when we add code to - // search the directory for third-party / named bucket index files we don't - // need new variable names. + // Add entries to `usage_tuples` from the directory for default buckets + // corresponding to first-party contexts. { base::FilePath first_party_default_buckets_root_path = CacheStorageManager::ConstructFirstPartyDefaultRootPath(profile_path); @@ -241,31 +327,129 @@ base::FilePath path; while (!(path = file_enum.Next()).empty()) { - ValidateAndAddUsageFromPath(path, owner, profile_path, usages); + ValidateAndAddUsageFromPath(path, owner, profile_path, usage_tuples, + true /* is_origin_path */); } } - scheduler_task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(usages))); + // Add entries to `usage_tuples` from the directory for non-default + // buckets and for buckets corresponding to third-party contexts. + base::FilePath third_party_and_non_default_root_path = + CacheStorageManager::ConstructThirdPartyAndNonDefaultRootPath( + profile_path); + { + base::FileEnumerator file_enum(third_party_and_non_default_root_path, + false /* recursive */, + base::FileEnumerator::DIRECTORIES); + base::FilePath path; + while (!(path = file_enum.Next()).empty()) { + base::FilePath cache_storage_path = + owner == storage::mojom::CacheStorageOwner::kCacheAPI + ? path.Append(storage::kCacheStorageDirectory) + : path.Append(storage::kBackgroundFetchDirectory); + if (!base::PathExists(cache_storage_path)) { + continue; + } + ValidateAndAddUsageFromPath(cache_storage_path, owner, profile_path, + usage_tuples); + } + } + + if (usage_tuples.empty()) { + scheduler_task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), std::move(usage_tuples))); + return; + } + + if (!quota_manager_proxy) { + // If we don't have a `QuotaManagerProxy` then don't attempt to resolve + // any missing bucket IDs. + scheduler_task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), std::move(usage_tuples))); + return; + } + + // For any index file that didn't have bucket information, ensure that a + // bucket exists for it and then populate the bucket ID in our structure. + const auto barrier_callback = base::BarrierCallback< + std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>( + usage_tuples.size(), std::move(callback)); + + for (const auto& usage_tuple : usage_tuples) { + const storage::BucketLocator& bucket_locator = std::get<0>(usage_tuple); + const storage::mojom::StorageUsageInfoPtr& info = std::get<1>(usage_tuple); + if (bucket_locator.id) { + scheduler_task_runner->PostTask( + FROM_HERE, + base::BindOnce( + barrier_callback, + std::make_tuple(std::move(bucket_locator), + storage::mojom::StorageUsageInfo::New( + info->origin, info->total_size_bytes, + info->last_modified)))); + continue; + } + // Note: Since bucket_locator.id will only be empty for unmigrated + // CacheStorage indices, and since these predate non-default buckets, + // it's safe to assume that this CacheStorage instance should use the + // default bucket. + quota_manager_proxy->UpdateOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(bucket_locator.storage_key), + scheduler_task_runner, + base::BindOnce( + &GetStorageKeyAndLastModifiedGotBucket, + storage::mojom::StorageUsageInfo::New( + info->origin, info->total_size_bytes, info->last_modified), + barrier_callback)); + } } void AllOriginSizesReported( - std::vector<storage::mojom::StorageUsageInfoPtr> usages, - storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback - callback) { + storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback, + std::vector<storage::mojom::StorageUsageInfoPtr> usages) { + // We should return only one entry per origin, so condense down all results + // before passing them to the callback. We condense by adding total size + // bytes and using the latest last_modified value. + std::map<url::Origin, int64_t> origin_to_total_size_bytes; + std::map<url::Origin, base::Time> origin_to_last_modified; + for (const auto& usage : usages) { + origin_to_total_size_bytes[usage->origin] += usage->total_size_bytes; + // Save off the most recent valid last modified time. + if (origin_to_last_modified.count(usage->origin) == 0 || + (!usage->last_modified.is_null() && + (origin_to_last_modified[usage->origin].is_null() || + usage->last_modified > origin_to_last_modified[usage->origin]))) { + origin_to_last_modified[usage->origin] = usage->last_modified; + } + } + + std::vector<storage::mojom::StorageUsageInfoPtr> new_usages; + new_usages.reserve(origin_to_total_size_bytes.size()); + + for (const auto& origin_usage_info : origin_to_total_size_bytes) { + new_usages.emplace_back(storage::mojom::StorageUsageInfo::New( + origin_usage_info.first, origin_usage_info.second, + origin_to_last_modified[origin_usage_info.first])); + } + // On scheduler sequence. base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(usages))); + FROM_HERE, base::BindOnce(std::move(callback), std::move(new_usages))); } -void OneOriginSizeReported(base::OnceClosure callback, - storage::mojom::StorageUsageInfoPtr* usage, - int64_t size) { +void OneOriginSizeReported( + base::OnceCallback<void(storage::mojom::StorageUsageInfoPtr)> callback, + const url::Origin origin, + const base::Time last_modified, + int64_t size) { // On scheduler sequence. DCHECK_NE(size, CacheStorage::kSizeUnknown); - (*usage)->total_size_bytes = size; - base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, - std::move(callback)); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), storage::mojom::StorageUsageInfo::New( + origin, size, last_modified))); } } // namespace @@ -276,7 +460,8 @@ scoped_refptr<base::SequencedTaskRunner> cache_task_runner, scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - scoped_refptr<BlobStorageContextWrapper> blob_storage_context) { + scoped_refptr<BlobStorageContextWrapper> blob_storage_context, + base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host) { DCHECK(cache_task_runner); DCHECK(scheduler_task_runner); DCHECK(quota_manager_proxy); @@ -285,7 +470,8 @@ return base::WrapRefCounted(new CacheStorageManager( profile_path, std::move(cache_task_runner), std::move(scheduler_task_runner), std::move(quota_manager_proxy), - std::move(blob_storage_context))); + std::move(blob_storage_context), + std::move(cache_storage_dispatcher_host))); } // static @@ -294,7 +480,8 @@ scoped_refptr<CacheStorageManager> manager(new CacheStorageManager( old_manager->profile_path(), old_manager->cache_task_runner(), old_manager->scheduler_task_runner(), old_manager->quota_manager_proxy_, - old_manager->blob_storage_context_)); + old_manager->blob_storage_context_, + old_manager->cache_storage_dispatcher_host_)); return manager; } @@ -302,38 +489,23 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } +#if DCHECK_IS_ON() +bool CacheStorageManager::CacheStoragePathIsUnique(const base::FilePath& path) { + for (const auto& bucket_info : cache_storage_map_) { + const auto& bucket_locator = bucket_info.first.first; + const auto owner = bucket_info.first.second; + if (path == CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner)) { + return false; + } + } + return true; +} +#endif + CacheStorageHandle CacheStorageManager::OpenCacheStorage( const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) { - // TODO(https://crbug.com/1304786): unify two OpenCacheStorage - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Wait to create the MemoryPressureListener until the first CacheStorage - // object is needed. This ensures we create the listener on the correct - // thread. - if (!memory_pressure_listener_) { - memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( - FROM_HERE, base::BindRepeating(&CacheStorageManager::OnMemoryPressure, - base::Unretained(this))); - } - - const blink::StorageKey& storage_key = bucket_locator.storage_key; - CacheStorageMap::const_iterator it = - cache_storage_map_.find({storage_key, owner}); - if (it == cache_storage_map_.end()) { - CacheStorage* cache_storage = new CacheStorage( - ConstructBucketPath(profile_path_, bucket_locator, owner), - IsMemoryBacked(), cache_task_runner_.get(), scheduler_task_runner_, - quota_manager_proxy_, blob_storage_context_, this, storage_key, owner); - cache_storage_map_[{storage_key, owner}] = base::WrapUnique(cache_storage); - return cache_storage->CreateHandle(); - } - return it->second.get()->CreateHandle(); -} - -CacheStorageHandle CacheStorageManager::OpenCacheStorage( - const blink::StorageKey& storage_key, - storage::mojom::CacheStorageOwner owner) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Wait to create the MemoryPressureListener until the first CacheStorage @@ -346,44 +518,61 @@ } CacheStorageMap::const_iterator it = - cache_storage_map_.find({storage_key, owner}); + cache_storage_map_.find({bucket_locator, owner}); if (it == cache_storage_map_.end()) { + const auto bucket_path = CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner); +#if DCHECK_IS_ON() + // Each CacheStorage instance expects to exclusively own it's corresponding + // origin / bucket path, and if it doesn't then the underlying scheduler for + // that instance will block, maybe indefinitely, if an existing instance + // using that directory is alive. The effects of a stalled scheduler can + // manifest in peculiar ways, so to make debugging easier emit a warning + // here if we observe that there will be path conflicts. One case where this + // can happen is when a bucket was deleted very recently and a CacheStorage + // instance is created using a new bucket id (for the same storage key / + // default bucket). If we haven't yet deleted the existing CacheStorage + // instance via `DeleteBucketData()` then we will temporarily hit this + // condition. This should be fine, though, because once the original + // CacheStorage instance is deleted the scheduler of the second instance + // will no longer be blocked. + DLOG_IF(WARNING, !CacheStoragePathIsUnique(bucket_path)) + << "Multiple CacheStorage instances using the same directory detected"; +#endif CacheStorage* cache_storage = new CacheStorage( - ConstructStorageKeyPath(profile_path_, storage_key, owner), - IsMemoryBacked(), cache_task_runner_.get(), scheduler_task_runner_, - quota_manager_proxy_, blob_storage_context_, this, storage_key, owner); - cache_storage_map_[{storage_key, owner}] = base::WrapUnique(cache_storage); + bucket_path, IsMemoryBacked(), cache_task_runner_.get(), + scheduler_task_runner_, quota_manager_proxy_, blob_storage_context_, + this, bucket_locator, owner); + cache_storage_map_[{bucket_locator, owner}] = + base::WrapUnique(cache_storage); return cache_storage->CreateHandle(); } return it->second.get()->CreateHandle(); } -// TODO(https://crbug.com/1304786): replace StorageKey with BucketLocator void CacheStorageManager::NotifyCacheListChanged( - const blink::StorageKey& storage_key) { + const storage::BucketLocator& bucket_locator) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& observer : observers_) - observer->OnCacheListChanged(storage_key); + observer->OnCacheListChanged(bucket_locator.storage_key); } -// TODO(https://crbug.com/1304786): replace StorageKey with BucketLocator void CacheStorageManager::NotifyCacheContentChanged( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, const std::string& name) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& observer : observers_) - observer->OnCacheContentChanged(storage_key, name); + observer->OnCacheContentChanged(bucket_locator.storage_key, name); } -// TODO(https://crbug.com/1304786): replace StorageKey with BucketLocator void CacheStorageManager::CacheStorageUnreferenced( CacheStorage* cache_storage, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(cache_storage); cache_storage->AssertUnreferenced(); - auto it = cache_storage_map_.find({storage_key, owner}); + auto it = cache_storage_map_.find({bucket_locator, owner}); DCHECK(it != cache_storage_map_.end()); DCHECK(it->second.get() == cache_storage); @@ -398,16 +587,20 @@ callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::vector<storage::mojom::StorageUsageInfoPtr> usages; + std::vector< + std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>> + usages; if (IsMemoryBacked()) { - for (const auto& storage_keys_details : cache_storage_map_) { - if (storage_keys_details.first.second != owner) + for (const auto& bucket_details : cache_storage_map_) { + if (bucket_details.first.second != owner) continue; - usages.emplace_back(storage::mojom::StorageUsageInfo::New( - storage_keys_details.first.first.origin(), - /*total_size_bytes=*/0, - /*last_modified=*/base::Time())); + const storage::BucketLocator& bucket_locator = bucket_details.first.first; + usages.emplace_back(bucket_locator, + storage::mojom::StorageUsageInfo::New( + bucket_locator.storage_key.origin(), + /*total_size_bytes=*/0, + /*last_modified=*/base::Time())); } GetAllStorageKeysUsageGetSizes(owner, std::move(callback), std::move(usages)); @@ -418,80 +611,84 @@ FROM_HERE, base::BindOnce( &GetStorageKeysAndLastModifiedOnTaskRunner, + base::WrapRefCounted(quota_manager_proxy_.get()), base::WrapRefCounted(scheduler_task_runner_.get()), std::move(usages), profile_path_, owner, base::BindOnce(&CacheStorageManager::GetAllStorageKeysUsageGetSizes, - base::WrapRefCounted(this), owner, + weak_ptr_factory_.GetWeakPtr(), owner, std::move(callback)))); } -// TODO(https://crbug.com/1304786): Rename to or add GetAllBucketsUsageGetSizes void CacheStorageManager::GetAllStorageKeysUsageGetSizes( storage::mojom::CacheStorageOwner owner, storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback, - std::vector<storage::mojom::StorageUsageInfoPtr> usages) { + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> usage_tuples) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // The origin GURL and last modified times are set in |usages| but not the // size in bytes. Call each CacheStorage's Size() function to fill that out. - - if (usages.empty()) { + std::vector<storage::mojom::StorageUsageInfoPtr> usages; + if (usage_tuples.empty()) { scheduler_task_runner_->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(usages))); return; } - auto* usages_ptr = &usages[0]; - size_t usages_count = usages.size(); - base::RepeatingClosure barrier_closure = base::BarrierClosure( - usages_count, base::BindOnce(&AllOriginSizesReported, std::move(usages), - std::move(callback))); + const auto barrier_callback = + base::BarrierCallback<storage::mojom::StorageUsageInfoPtr>( + usage_tuples.size(), + base::BindOnce(&AllOriginSizesReported, std::move(callback))); - for (size_t i = 0; i < usages_count; ++i) { - auto& usage = usages_ptr[i]; - if (usage->total_size_bytes != CacheStorage::kSizeUnknown || - !IsValidQuotaStorageKey(blink::StorageKey(usage->origin))) { - scheduler_task_runner_->PostTask(FROM_HERE, barrier_closure); + for (const auto& usage_tuple : usage_tuples) { + const storage::BucketLocator& bucket_locator = std::get<0>(usage_tuple); + const storage::mojom::StorageUsageInfoPtr& info = std::get<1>(usage_tuple); + if (info->total_size_bytes != CacheStorage::kSizeUnknown || + !IsValidQuotaStorageKey(bucket_locator.storage_key)) { + scheduler_task_runner_->PostTask( + FROM_HERE, base::BindOnce(barrier_callback, + storage::mojom::StorageUsageInfo::New( + info->origin, info->total_size_bytes, + info->last_modified))); continue; } - CacheStorageHandle cache_storage = - OpenCacheStorage(blink::StorageKey(usage->origin), owner); + CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner); CacheStorage::From(cache_storage) - ->Size(base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage)); + ->Size(base::BindOnce(&OneOriginSizeReported, barrier_callback, + info->origin, info->last_modified)); } } -// TODO(https://crbug.com/1304786): rename to or add GetBucketUsage -void CacheStorageManager::GetStorageKeyUsage( - const blink::StorageKey& storage_key, +void CacheStorageManager::GetBucketUsage( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::GetBucketUsageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (IsMemoryBacked()) { - auto it = cache_storage_map_.find({storage_key, owner}); + auto it = cache_storage_map_.find({bucket_locator, owner}); if (it == cache_storage_map_.end()) { scheduler_task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), /*usage=*/0)); return; } - CacheStorageHandle cache_storage = OpenCacheStorage(storage_key, owner); + CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner); CacheStorage::From(cache_storage)->Size(std::move(callback)); return; } cache_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&base::PathExists, ConstructStorageKeyPath( - profile_path_, storage_key, owner)), - base::BindOnce(&CacheStorageManager::GetStorageKeyUsageDidGetExists, - base::WrapRefCounted(this), storage_key, owner, + base::BindOnce(&base::PathExists, + CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner)), + base::BindOnce(&CacheStorageManager::GetBucketUsageDidGetExists, + weak_ptr_factory_.GetWeakPtr(), bucket_locator, owner, std::move(callback))); } -// TODO(https://crbug.com/1304786): Rename to or add GetBucketUsageDidGetExists -void CacheStorageManager::GetStorageKeyUsageDidGetExists( - const blink::StorageKey& storage_key, +void CacheStorageManager::GetBucketUsageDidGetExists( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::GetBucketUsageCallback callback, bool exists) { @@ -501,11 +698,12 @@ FROM_HERE, base::BindOnce(std::move(callback), /*usage=*/0)); return; } - CacheStorageHandle cache_storage = OpenCacheStorage(storage_key, owner); + CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner); CacheStorage::From(cache_storage)->Size(std::move(callback)); } -// TODO(https://crbug.com/1304786): remove or keep for bucket migration +// Used by QuotaClient which only wants the storage keys that have data in the +// default bucket. void CacheStorageManager::GetStorageKeys( storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback) { @@ -513,9 +711,16 @@ if (IsMemoryBacked()) { std::vector<blink::StorageKey> storage_keys; - for (const auto& key_value : cache_storage_map_) - if (key_value.first.second == owner) - storage_keys.push_back(key_value.first.first); + for (const auto& key_value : cache_storage_map_) { + if (key_value.first.second != owner) + continue; + + const storage::BucketLocator& bucket_locator = key_value.first.first; + if (!bucket_locator.is_default) + continue; + + storage_keys.push_back(key_value.first.first.storage_key); + } scheduler_task_runner_->PostTask( FROM_HERE, @@ -523,19 +728,81 @@ return; } - std::vector<storage::mojom::StorageUsageInfoPtr> usages; + std::vector< + std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>> + usage_tuples; cache_task_runner_->PostTask( FROM_HERE, base::BindOnce( &GetStorageKeysAndLastModifiedOnTaskRunner, - base::WrapRefCounted(scheduler_task_runner_.get()), std::move(usages), - profile_path_, owner, + base::WrapRefCounted(quota_manager_proxy_.get()), + base::WrapRefCounted(scheduler_task_runner_.get()), + std::move(usage_tuples), profile_path_, owner, base::BindOnce(&CacheStorageManager::ListStorageKeysOnTaskRunner, - base::WrapRefCounted(this), std::move(callback)))); + weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); } -// TODO(https://crbug.com/1304786): rename to or add DeleteBucketData +void CacheStorageManager::DeleteStorageKeyDataGotAllBucketInfo( + const blink::StorageKey storage_key, + storage::mojom::CacheStorageOwner owner, + base::OnceCallback<void(std::vector<blink::mojom::QuotaStatusCode>)> + callback, + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> usage_tuples) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (usage_tuples.empty()) { + std::vector<blink::mojom::QuotaStatusCode> results{ + blink::mojom::QuotaStatusCode::kOk}; + scheduler_task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), std::move(results))); + return; + } + + int instance_count = 0; + for (const std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>& usage_tuple : + usage_tuples) { + const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple); + if (!bucket_locator.is_default || + storage_key != bucket_locator.storage_key) { + continue; + } + instance_count += 1; + } + + const auto barrier_callback = + base::BarrierCallback<blink::mojom::QuotaStatusCode>(instance_count, + std::move(callback)); + + for (const std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>& usage_tuple : + usage_tuples) { + const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple); + if (!bucket_locator.is_default || + storage_key != bucket_locator.storage_key) { + continue; + } + if (bucket_locator.id) { + // The bucket locator is fully formed, so use the same steps to delete as + // `DeleteBucketData()`. + DeleteBucketDataDidGetExists(owner, barrier_callback, bucket_locator, + /*exists=*/true); + } else { + // This must be for an unmigrated cache storage instance using an origin + // path, so just directly delete the directory. + PostTaskAndReplyWithResult( + cache_task_runner_.get(), FROM_HERE, + base::BindOnce(&DeleteDir, CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner)), + base::BindOnce(&DeleteBucketDidDeleteDir, barrier_callback)); + } + } +} + +// TODO(https://crbug.com/1218097): Delete this method in favor of the one that +// takes in a `BucketLocator` once `StoragePolicyUpdate` uses more than just +// origin. Note: This only deletes data associated with the default bucket. void CacheStorageManager::DeleteStorageKeyData( const blink::StorageKey& storage_key, storage::mojom::CacheStorageOwner owner, @@ -543,33 +810,89 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (IsMemoryBacked()) { - auto it = cache_storage_map_.find({storage_key, owner}); + // Note: since the number of CacheStorage instances is usually small, just + // search for the corresponding `storage::BucketLocator` key given a + // `blink::StorageKey`. + for (const auto& key_value : cache_storage_map_) { + if (key_value.first.second != owner) + continue; + const storage::BucketLocator& bucket_locator = key_value.first.first; + if (!bucket_locator.is_default || + bucket_locator.storage_key != storage_key) + continue; + DeleteBucketDataDidGetExists(owner, std::move(callback), bucket_locator, + /*exists=*/true); + return; + } + scheduler_task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + blink::mojom::QuotaStatusCode::kOk)); + return; + } + // Note that we can't call `QuotaManagerProxy::GetBucket()` and then use the + // same steps as `DeleteBucketData()` here because this method is called + // during shutdown and the quota code might be at various stages of shutting + // down as well. Instead, build a list of cache storage instances from disk + // and either use the bucket locators from index files or directly delete any + // unmigrated cache storage origin paths. + std::vector< + std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>> + usage_tuples; + cache_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &GetStorageKeysAndLastModifiedOnTaskRunner, nullptr, + base::WrapRefCounted(scheduler_task_runner_.get()), + std::move(usage_tuples), profile_path_, owner, + base::BindOnce( + &CacheStorageManager::DeleteStorageKeyDataGotAllBucketInfo, + weak_ptr_factory_.GetWeakPtr(), storage_key, owner, + base::BindOnce(&DeleteStorageKeyDidDeleteAllData, + std::move(callback))))); +} + +void CacheStorageManager::DeleteBucketData( + const storage::BucketLocator& bucket_locator, + storage::mojom::CacheStorageOwner owner, + storage::mojom::QuotaClient::DeleteBucketDataCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // `DeleteBucketData()` is called when the bucket corresponding to + // `bucket_locator` has been destroyed, which means we should notify + // `cache_storage_dispatcher_host_` that any `CacheStorageImpl` objects with a + // cached version of this `BucketLocator` should invalidate the copy they + // have. + if (cache_storage_dispatcher_host_) { + cache_storage_dispatcher_host_->NotifyBucketDataDeleted(bucket_locator); + } + + if (IsMemoryBacked()) { + auto it = cache_storage_map_.find({bucket_locator, owner}); if (it == cache_storage_map_.end()) { scheduler_task_runner_->PostTask( FROM_HERE, base::BindOnce(std::move(callback), blink::mojom::QuotaStatusCode::kOk)); return; } - DeleteStorageKeyDataDidGetExists(storage_key, owner, std::move(callback), - /*exists=*/true); + DeleteBucketDataDidGetExists(owner, std::move(callback), bucket_locator, + /*exists=*/true); return; } cache_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&base::PathExists, ConstructStorageKeyPath( - profile_path_, storage_key, owner)), - base::BindOnce(&CacheStorageManager::DeleteStorageKeyDataDidGetExists, - base::WrapRefCounted(this), storage_key, owner, - std::move(callback))); + base::BindOnce(&base::PathExists, + CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner)), + base::BindOnce(&CacheStorageManager::DeleteBucketDataDidGetExists, + weak_ptr_factory_.GetWeakPtr(), owner, std::move(callback), + bucket_locator)); } -// TODO(https://crbug.com/1304786): rename to or add -// DeleteBucketDataDidGetExists -void CacheStorageManager::DeleteStorageKeyDataDidGetExists( - const blink::StorageKey& storage_key, +void CacheStorageManager::DeleteBucketDataDidGetExists( storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::DeleteBucketDataCallback callback, + storage::BucketLocator bucket_locator, bool exists) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -580,23 +903,27 @@ return; } - // Create the CacheStorage for the storage key if it hasn't been loaded yet. - CacheStorageHandle handle = OpenCacheStorage(storage_key, owner); + // Create the CacheStorage for the bucket if it hasn't been loaded yet. + CacheStorageHandle handle = OpenCacheStorage(bucket_locator, owner); - auto it = cache_storage_map_.find({storage_key, owner}); + auto it = cache_storage_map_.find({bucket_locator, owner}); DCHECK(it != cache_storage_map_.end()); CacheStorage* cache_storage = it->second.release(); cache_storage->ResetManager(); - cache_storage_map_.erase({storage_key, owner}); + cache_storage_map_.erase({bucket_locator, owner}); + cache_storage->GetSizeThenCloseAllCaches( - base::BindOnce(&CacheStorageManager::DeleteStorageKeyDidClose, - base::WrapRefCounted(this), storage_key, owner, + base::BindOnce(&CacheStorageManager::DeleteBucketDidClose, + weak_ptr_factory_.GetWeakPtr(), bucket_locator, owner, std::move(callback), base::WrapUnique(cache_storage))); } -// TODO(https://crbug.com/1304786): rename to or add -// DeleteBucketDataDidGetExists +// TODO(https://crbug.com/1218097): Delete this method in favor of the one that +// takes in a `BucketLocator` if we can convert `StoragePolicyUpdate` to +// provide enough info to reconstruct a `storage::BucketLocator`. +// Note: This only deletes data associated with the default bucket for a given +// `blink::StorageKey`. void CacheStorageManager::DeleteStorageKeyData( const blink::StorageKey& storage_key, storage::mojom::CacheStorageOwner owner) { @@ -609,9 +936,8 @@ observers_.Add(std::move(observer)); } -// TODO(https://crbug.com/1304786): rename to or add DeleteBucketDidClose -void CacheStorageManager::DeleteStorageKeyDidClose( - const blink::StorageKey& storage_key, +void CacheStorageManager::DeleteBucketDidClose( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::DeleteBucketDataCallback callback, std::unique_ptr<CacheStorage> cache_storage, @@ -622,13 +948,13 @@ // CacheStorage operations posted after GetSizeThenCloseAllCaches is called. cache_storage.reset(); - quota_manager_proxy_->NotifyStorageModified( - CacheStorageQuotaClient::GetClientTypeFromOwner(owner), storage_key, - blink::mojom::StorageType::kTemporary, -origin_size, base::Time::Now(), - base::SequencedTaskRunnerHandle::Get(), base::DoNothing()); + quota_manager_proxy_->NotifyBucketModified( + CacheStorageQuotaClient::GetClientTypeFromOwner(owner), bucket_locator.id, + -origin_size, base::Time::Now(), base::SequencedTaskRunnerHandle::Get(), + base::DoNothing()); if (owner == storage::mojom::CacheStorageOwner::kCacheAPI) - NotifyCacheListChanged(storage_key); + NotifyCacheListChanged(bucket_locator); if (IsMemoryBacked()) { scheduler_task_runner_->PostTask( @@ -639,9 +965,9 @@ PostTaskAndReplyWithResult( cache_task_runner_.get(), FROM_HERE, - base::BindOnce(&DeleteDir, ConstructStorageKeyPath(profile_path_, - storage_key, owner)), - base::BindOnce(&DeleteStorageKeyDidDeleteDir, std::move(callback))); + base::BindOnce(&DeleteDir, CacheStorageManager::ConstructBucketPath( + profile_path_, bucket_locator, owner)), + base::BindOnce(&DeleteBucketDidDeleteDir, std::move(callback))); } CacheStorageManager::CacheStorageManager( @@ -649,28 +975,20 @@ scoped_refptr<base::SequencedTaskRunner> cache_task_runner, scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - scoped_refptr<BlobStorageContextWrapper> blob_storage_context) + scoped_refptr<BlobStorageContextWrapper> blob_storage_context, + base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host) : profile_path_(profile_path), cache_task_runner_(std::move(cache_task_runner)), scheduler_task_runner_(std::move(scheduler_task_runner)), quota_manager_proxy_(std::move(quota_manager_proxy)), - blob_storage_context_(std::move(blob_storage_context)) { + blob_storage_context_(std::move(blob_storage_context)), + cache_storage_dispatcher_host_(std::move(cache_storage_dispatcher_host)) { DCHECK(cache_task_runner_); DCHECK(scheduler_task_runner_); DCHECK(quota_manager_proxy_); DCHECK(blob_storage_context_); } -// TODO(awillia): This will be removed. -// static -base::FilePath CacheStorageManager::ConstructStorageKeyPath( - const base::FilePath& profile_path, - const blink::StorageKey& storage_key, - storage::mojom::CacheStorageOwner owner) { - return ConstructOriginPath(profile_path, storage_key.origin(), owner); -} - -// static base::FilePath CacheStorageManager::ConstructBucketPath( const base::FilePath& profile_path, const storage::BucketLocator& bucket_locator, @@ -722,7 +1040,13 @@ base::FilePath CacheStorageManager::ConstructFirstPartyDefaultRootPath( const base::FilePath& profile_path) { return profile_path.Append(storage::kServiceWorkerDirectory) - .AppendASCII(CacheStorage::kCacheStorage); + .Append(storage::kCacheStorageDirectory); +} + +// static +base::FilePath CacheStorageManager::ConstructThirdPartyAndNonDefaultRootPath( + const base::FilePath& profile_path) { + return profile_path.Append(storage::kWebStorageDirectory); } // Used by QuotaClient which only wants the storage keys that have data in the @@ -730,14 +1054,21 @@ // of buckets. void CacheStorageManager::ListStorageKeysOnTaskRunner( storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback, - std::vector<mojo::StructPtr<storage::mojom::StorageUsageInfo>> usages) { + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> usage_tuples) { std::vector<blink::StorageKey> out_storage_keys; - for (const storage::mojom::StorageUsageInfoPtr& usage : usages) - out_storage_keys.emplace_back(blink::StorageKey(usage->origin)); + for (const std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>& usage_tuple : + usage_tuples) { + const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple); + if (!bucket_locator.id || !bucket_locator.is_default) { + continue; + } + out_storage_keys.emplace_back(bucket_locator.storage_key); + } scheduler_task_runner_->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(out_storage_keys))); } - } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h index ed9e364..131e6dd 100644 --- a/content/browser/cache_storage/cache_storage_manager.h +++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/dcheck_is_on.h" #include "base/files/file_path.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/scoped_refptr.h" @@ -22,6 +23,7 @@ #include "content/browser/cache_storage/cache_storage.h" #include "content/browser/cache_storage/cache_storage_cache.h" #include "content/browser/cache_storage/cache_storage_context_impl.h" +#include "content/browser/cache_storage/cache_storage_dispatcher_host.h" #include "content/browser/cache_storage/cache_storage_handle.h" #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" @@ -52,7 +54,8 @@ scoped_refptr<base::SequencedTaskRunner> cache_task_runner, scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - scoped_refptr<BlobStorageContextWrapper> blob_storage_context); + scoped_refptr<BlobStorageContextWrapper> blob_storage_context, + base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host); // Create a new manager using the underlying configuration of the given // manager, but with its own list of storage objects. This is only used @@ -63,12 +66,6 @@ CacheStorageManager(const CacheStorageManager&) = delete; CacheStorageManager& operator=(const CacheStorageManager&) = delete; - // Map a database identifier (computed from a storage key) to the path. - static base::FilePath ConstructStorageKeyPath( - const base::FilePath& profile_path, - const blink::StorageKey& storage_key, - storage::mojom::CacheStorageOwner owner); - // Map a database identifier (computed from a BucketLocator) to the path. static base::FilePath ConstructBucketPath( const base::FilePath& profile_path, @@ -92,8 +89,8 @@ storage::mojom::CacheStorageOwner owner, storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback); - void GetStorageKeyUsage( - const blink::StorageKey& storage_key, + void GetBucketUsage( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::GetBucketUsageCallback callback); void GetStorageKeys( @@ -103,13 +100,17 @@ const blink::StorageKey& storage_key, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::DeleteBucketDataCallback callback); + void DeleteBucketData( + const storage::BucketLocator& bucket_locator, + storage::mojom::CacheStorageOwner owner, + storage::mojom::QuotaClient::DeleteBucketDataCallback callback); void DeleteStorageKeyData(const blink::StorageKey& storage_key, storage::mojom::CacheStorageOwner owner); void AddObserver( mojo::PendingRemote<storage::mojom::CacheStorageObserver> observer); - void NotifyCacheListChanged(const blink::StorageKey& storage_key); - void NotifyCacheContentChanged(const blink::StorageKey& storage_key, + void NotifyCacheListChanged(const storage::BucketLocator& bucket_locator); + void NotifyCacheContentChanged(const storage::BucketLocator& bucket_locator, const std::string& name); base::FilePath profile_path() const { return profile_path_; } @@ -117,21 +118,28 @@ static base::FilePath ConstructFirstPartyDefaultRootPath( const base::FilePath& profile_path); + static base::FilePath ConstructThirdPartyAndNonDefaultRootPath( + const base::FilePath& profile_path); + // This method is called when the last CacheStorageHandle for a particular // instance is destroyed and its reference count drops to zero. void CacheStorageUnreferenced(CacheStorage* cache_storage, - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner); protected: friend class base::RefCounted<CacheStorageManager>; - CacheStorageManager( + // TODO(https://crbug.com/1353198): NOINLINE here is needed to prevent a crash + // when ThinLTO is enabled on x86 Android chrome-branded release-mode builds. + // Remove this once the underlying issue is resolved. + NOINLINE CacheStorageManager( const base::FilePath& path, scoped_refptr<base::SequencedTaskRunner> cache_task_runner, scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, - scoped_refptr<BlobStorageContextWrapper> blob_storage_context); + scoped_refptr<BlobStorageContextWrapper> blob_storage_context, + base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host); virtual ~CacheStorageManager(); private: @@ -139,7 +147,7 @@ friend class CacheStorageContextImpl; typedef std::map< - std::pair<blink::StorageKey, storage::mojom::CacheStorageOwner>, + std::pair<storage::BucketLocator, storage::mojom::CacheStorageOwner>, std::unique_ptr<CacheStorage>> CacheStorageMap; @@ -147,22 +155,33 @@ storage::mojom::CacheStorageOwner owner, storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback, - std::vector<storage::mojom::StorageUsageInfoPtr> usage_info); + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> + usage_tuples); - void GetStorageKeyUsageDidGetExists( - const blink::StorageKey& storage_key, + void DeleteStorageKeyDataGotAllBucketInfo( + const blink::StorageKey storage_key, + storage::mojom::CacheStorageOwner owner, + base::OnceCallback<void(std::vector<blink::mojom::QuotaStatusCode>)> + callback, + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> + usage_tuples); + + void GetBucketUsageDidGetExists( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::GetBucketUsageCallback callback, bool exists); - void DeleteStorageKeyDataDidGetExists( - const blink::StorageKey& storage_key, + void DeleteBucketDataDidGetExists( storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::DeleteBucketDataCallback callback, + storage::BucketLocator bucket_locator, bool exists); - void DeleteStorageKeyDidClose( - const blink::StorageKey& storage_key, + void DeleteBucketDidClose( + const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, storage::mojom::QuotaClient::DeleteBucketDataCallback callback, std::unique_ptr<CacheStorage> cache_storage, @@ -178,7 +197,9 @@ void ListStorageKeysOnTaskRunner( storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback, - std::vector<mojo::StructPtr<storage::mojom::StorageUsageInfo>> usages); + std::vector<std::tuple<storage::BucketLocator, + storage::mojom::StorageUsageInfoPtr>> + usage_tuples); bool IsMemoryBacked() const { return profile_path_.empty(); } @@ -186,6 +207,10 @@ void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel level); +#if DCHECK_IS_ON() + bool CacheStoragePathIsUnique(const base::FilePath& path); +#endif + // Stores the storage partition (profile) path unless the CacheStorage should // be in-memory only, in which case this is empty. const base::FilePath profile_path_; @@ -202,9 +227,14 @@ const scoped_refptr<BlobStorageContextWrapper> blob_storage_context_; + const base::WeakPtr<CacheStorageDispatcherHost> + cache_storage_dispatcher_host_; + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<CacheStorageManager> weak_ptr_factory_{this}; }; } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index 3b95e82f..aa312621 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -31,6 +31,8 @@ #include "build/build_config.h" #include "components/services/storage/public/cpp/buckets/bucket_info.h" #include "components/services/storage/public/cpp/buckets/bucket_locator.h" +#include "components/services/storage/public/cpp/buckets/constants.h" +#include "components/services/storage/public/cpp/constants.h" #include "components/services/storage/public/cpp/quota_error_or.h" #include "components/services/storage/public/mojom/cache_storage_control.mojom.h" #include "components/services/storage/public/mojom/storage_usage_info.mojom.h" @@ -82,8 +84,11 @@ enum class StorageKeyAndBucketTestCase { kFirstPartyDefault, + kFirstPartyNamed, kFirstPartyDefaultPartitionEnabled, + kFirstPartyNamedPartitionEnabled, kThirdPartyDefault, + kThirdPartyNamed, }; using blink::mojom::StorageType; @@ -259,6 +264,12 @@ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); CreateStorageManager(); + + // Instantiate these after `quota_manager_proxy_` has been initialized. + bucket_locator1_ = + GetOrCreateBucket(storage_key1_, storage::kDefaultBucketName); + bucket_locator2_ = + GetOrCreateBucket(storage_key2_, storage::kDefaultBucketName); } void TearDown() override { @@ -375,7 +386,7 @@ cache_manager_ = CacheStorageManager::Create( temp_dir_path, base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_, - blob_storage_context_); + blob_storage_context_, nullptr); } void RecreateStorageManager() { @@ -385,10 +396,10 @@ cache_manager_ = CacheStorageManager::CreateForTesting(legacy_manager); } - bool FlushCacheStorageIndex(const blink::StorageKey& storage_key) { + bool FlushCacheStorageIndex(const storage::BucketLocator& bucket_locator) { callback_bool_ = false; base::RunLoop loop; - auto* impl = CacheStorage::From(CacheStorageForKey(storage_key)); + auto* impl = CacheStorage::From(CacheStorageForBucket(bucket_locator)); bool write_was_scheduled = impl->InitiateScheduledIndexWriteForTest( base::BindOnce(&CacheStorageManagerTest::BoolCallback, base::Unretained(this), &loop)); @@ -423,14 +434,14 @@ histogram_tester.ExpectTotalCount(base + "QueueLength." + op_name, 1); } - bool Open(const blink::StorageKey& storage_key, + bool Open(const storage::BucketLocator& bucket_locator, const std::string& cache_name, storage::mojom::CacheStorageOwner owner = storage::mojom::CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->OpenCache( cache_name, /* trace_id = */ 0, base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback, @@ -447,14 +458,14 @@ return !error; } - bool Has(const blink::StorageKey& storage_key, + bool Has(const storage::BucketLocator& bucket_locator, const std::string& cache_name, storage::mojom::CacheStorageOwner owner = storage::mojom::CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->HasCache( cache_name, /* trace_id = */ 0, base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback, @@ -464,14 +475,14 @@ return callback_bool_; } - bool Delete(const blink::StorageKey& storage_key, + bool Delete(const storage::BucketLocator& bucket_locator, const std::string& cache_name, storage::mojom::CacheStorageOwner owner = storage::mojom::CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->DoomCache( cache_name, /* trace_id = */ 0, base::BindOnce(&CacheStorageManagerTest::ErrorCallback, @@ -481,13 +492,13 @@ return callback_bool_; } - size_t Keys(const blink::StorageKey& storage_key, + size_t Keys(const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner = storage::mojom::CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->EnumerateCaches( /* trace_id = */ 0, base::BindOnce(&CacheStorageManagerTest::CacheMetadataCallback, @@ -497,7 +508,7 @@ return cache_names_.size(); } - bool StorageMatch(const blink::StorageKey& storage_key, + bool StorageMatch(const storage::BucketLocator& bucket_locator, const std::string& cache_name, const GURL& url, blink::mojom::CacheQueryOptionsPtr match_options = nullptr, @@ -505,12 +516,13 @@ storage::mojom::CacheStorageOwner::kCacheAPI) { auto request = blink::mojom::FetchAPIRequest::New(); request->url = url; - return StorageMatchWithRequest(storage_key, cache_name, std::move(request), - std::move(match_options), owner); + return StorageMatchWithRequest(bucket_locator, cache_name, + std::move(request), std::move(match_options), + owner); } bool StorageMatchWithRequest( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, const std::string& cache_name, blink::mojom::FetchAPIRequestPtr request, blink::mojom::CacheQueryOptionsPtr match_options = nullptr, @@ -519,7 +531,7 @@ base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->MatchCache( cache_name, std::move(request), std::move(match_options), CacheStorageSchedulerPriority::kNormal, /* trace_id = */ 0, @@ -532,17 +544,17 @@ } bool StorageMatchAll( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, const GURL& url, blink::mojom::CacheQueryOptionsPtr match_options = nullptr) { auto request = blink::mojom::FetchAPIRequest::New(); request->url = url; - return StorageMatchAllWithRequest(storage_key, std::move(request), + return StorageMatchAllWithRequest(bucket_locator, std::move(request), std::move(match_options)); } bool StorageMatchAllWithRequest( - const blink::StorageKey& storage_key, + const storage::BucketLocator& bucket_locator, blink::mojom::FetchAPIRequestPtr request, blink::mojom::CacheQueryOptionsPtr match_options = nullptr, storage::mojom::CacheStorageOwner owner = @@ -550,7 +562,7 @@ base::HistogramTester histogram_tester; base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->MatchAllCaches( std::move(request), std::move(match_options), CacheStorageSchedulerPriority::kNormal, /* trace_id = */ 0, @@ -562,7 +574,7 @@ return callback_error_ == CacheStorageError::kSuccess; } - bool Write(const blink::StorageKey& storage_key, + bool Write(const storage::BucketLocator& bucket_locator, storage::mojom::CacheStorageOwner owner, const std::string& cache_name, const std::string& request_url) { @@ -571,7 +583,7 @@ base::RunLoop loop; CacheStorageHandle cache_storage = - cache_manager_->OpenCacheStorage(storage_key, owner); + cache_manager_->OpenCacheStorage(bucket_locator, owner); cache_storage.value()->WriteToCache( cache_name, std::move(request), blink::mojom::FetchAPIResponse::New(), /* trace_id = */ 0, @@ -706,17 +718,18 @@ return callback_error_ == CacheStorageError::kSuccess; } - CacheStorageHandle CacheStorageForKey(const blink::StorageKey& storage_key) { + CacheStorageHandle CacheStorageForBucket( + const storage::BucketLocator& bucket_locator) { return cache_manager_->OpenCacheStorage( - storage_key, storage::mojom::CacheStorageOwner::kCacheAPI); + bucket_locator, storage::mojom::CacheStorageOwner::kCacheAPI); } - int64_t GetStorageKeyUsage(const blink::StorageKey& storage_key, - storage::mojom::CacheStorageOwner owner = - storage::mojom::CacheStorageOwner::kCacheAPI) { + int64_t GetBucketUsage(const storage::BucketLocator& bucket_locator, + storage::mojom::CacheStorageOwner owner = + storage::mojom::CacheStorageOwner::kCacheAPI) { base::RunLoop loop; - cache_manager_->GetStorageKeyUsage( - storage_key, owner, + cache_manager_->GetBucketUsage( + bucket_locator, owner, base::BindOnce(&CacheStorageManagerTest::UsageCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -761,9 +774,20 @@ return future.Get(); } - int64_t GetSizeThenCloseAllCaches(const blink::StorageKey& storage_key) { + blink::mojom::QuotaStatusCode DeleteBucketData( + const storage::BucketLocator& bucket_locator, + storage::mojom::CacheStorageOwner owner = + storage::mojom::CacheStorageOwner::kCacheAPI) { + base::test::TestFuture<::blink::mojom::QuotaStatusCode> future; + cache_manager_->DeleteBucketData(bucket_locator, owner, + future.GetCallback()); + return future.Get(); + } + + int64_t GetSizeThenCloseAllCaches( + const storage::BucketLocator& bucket_locator) { base::RunLoop loop; - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator); CacheStorage::From(cache_storage) ->GetSizeThenCloseAllCaches( base::BindOnce(&CacheStorageManagerTest::UsageCallback, @@ -772,9 +796,9 @@ return callback_usage_; } - int64_t Size(const blink::StorageKey& storage_key) { + int64_t Size(const storage::BucketLocator& bucket_locator) { base::RunLoop loop; - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator); CacheStorage::From(cache_storage) ->Size(base::BindOnce(&CacheStorageManagerTest::UsageCallback, base::Unretained(this), &loop)); @@ -837,6 +861,8 @@ blink::StorageKey storage_key1_; blink::StorageKey storage_key2_; + storage::BucketLocator bucket_locator1_; + storage::BucketLocator bucket_locator2_; int64_t callback_usage_; }; @@ -870,13 +896,37 @@ net::features::kThirdPartyStoragePartitioning); } + std::string bucket_name; switch (test_case_) { case (StorageKeyAndBucketTestCase::kFirstPartyDefault): case (StorageKeyAndBucketTestCase::kFirstPartyDefaultPartitionEnabled): - // For these cases, the storage keys are already initialized correctly. - break; case (StorageKeyAndBucketTestCase::kThirdPartyDefault): - // Recreate storage keys. + bucket_name = storage::kDefaultBucketName; + break; + case (StorageKeyAndBucketTestCase::kFirstPartyNamed): + case (StorageKeyAndBucketTestCase::kFirstPartyNamedPartitionEnabled): + case (StorageKeyAndBucketTestCase::kThirdPartyNamed): + bucket_name = "non-default"; + break; + } + + switch (test_case_) { + case (StorageKeyAndBucketTestCase::kFirstPartyDefault): + case (StorageKeyAndBucketTestCase::kFirstPartyDefaultPartitionEnabled): + // For this case, the storage keys and bucket locators are already + // initialized correctly. + break; + case (StorageKeyAndBucketTestCase::kFirstPartyNamed): + case (StorageKeyAndBucketTestCase::kFirstPartyNamedPartitionEnabled): + // For this case, the storage keys are initialized correctly but we + // need to create new named buckets. + bucket_locator1_ = GetOrCreateBucket(storage_key1_, bucket_name); + bucket_locator2_ = GetOrCreateBucket(storage_key2_, bucket_name); + break; + + case (StorageKeyAndBucketTestCase::kThirdPartyDefault): + case (StorageKeyAndBucketTestCase::kThirdPartyNamed): + // Recreate storage keys and buckets. storage_key1_ = blink::StorageKey(url::Origin::Create(GURL("http://example1.com")), @@ -885,13 +935,19 @@ blink::StorageKey(url::Origin::Create(GURL("http://example2.com")), url::Origin::Create(GURL("http://example3.com"))); + + bucket_locator1_ = GetOrCreateBucket(storage_key1_, bucket_name); + bucket_locator2_ = GetOrCreateBucket(storage_key2_, bucket_name); break; } } bool ThirdPartyStoragePartitioningEnabled() { return test_case_ == StorageKeyAndBucketTestCase:: kFirstPartyDefaultPartitionEnabled || - test_case_ == StorageKeyAndBucketTestCase::kThirdPartyDefault; + test_case_ == + StorageKeyAndBucketTestCase::kFirstPartyNamedPartitionEnabled || + test_case_ == StorageKeyAndBucketTestCase::kThirdPartyDefault || + test_case_ == StorageKeyAndBucketTestCase::kThirdPartyNamed; } private: @@ -904,202 +960,205 @@ } TEST_P(CacheStorageManagerTestP, OpenCache) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); } TEST_P(CacheStorageManagerTestP, OpenTwoCaches) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); } TEST_P(CacheStorageManagerTestP, OpenSameCacheDifferentOwners) { - EXPECT_TRUE( - Open(storage_key1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI)); + EXPECT_TRUE(Open(bucket_locator1_, "foo", + storage::mojom::CacheStorageOwner::kCacheAPI)); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_NE(callback_cache_handle_.value(), cache_handle.value()); } TEST_P(CacheStorageManagerTestP, CachePointersDiffer) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_NE(callback_cache_handle_.value(), cache_handle.value()); } TEST_P(CacheStorageManagerTestP, Open2CachesSameNameDiffKeys) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key2_, "foo")); + EXPECT_TRUE(Open(bucket_locator2_, "foo")); EXPECT_NE(cache_handle.value(), callback_cache_handle_.value()); } TEST_P(CacheStorageManagerTestP, OpenExistingCache) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_EQ(callback_cache_handle_.value(), cache_handle.value()); } TEST_P(CacheStorageManagerTestP, HasCache) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Has(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Has(bucket_locator1_, "foo")); EXPECT_TRUE(callback_bool_); } TEST_P(CacheStorageManagerTestP, HasCacheDifferentOwners) { - EXPECT_TRUE(Open(storage_key1_, "public", + EXPECT_TRUE(Open(bucket_locator1_, "public", storage::mojom::CacheStorageOwner::kCacheAPI)); - EXPECT_TRUE(Open(storage_key1_, "bgf", + EXPECT_TRUE(Open(bucket_locator1_, "bgf", storage::mojom::CacheStorageOwner::kBackgroundFetch)); - EXPECT_TRUE(Has(storage_key1_, "public", + EXPECT_TRUE(Has(bucket_locator1_, "public", storage::mojom::CacheStorageOwner::kCacheAPI)); EXPECT_TRUE(callback_bool_); - EXPECT_FALSE( - Has(storage_key1_, "bgf", storage::mojom::CacheStorageOwner::kCacheAPI)); + EXPECT_FALSE(Has(bucket_locator1_, "bgf", + storage::mojom::CacheStorageOwner::kCacheAPI)); EXPECT_FALSE(callback_bool_); - EXPECT_TRUE(Has(storage_key1_, "bgf", + EXPECT_TRUE(Has(bucket_locator1_, "bgf", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_TRUE(callback_bool_); - EXPECT_FALSE(Has(storage_key1_, "public", + EXPECT_FALSE(Has(bucket_locator1_, "public", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_FALSE(callback_bool_); } TEST_P(CacheStorageManagerTestP, HasNonExistent) { - EXPECT_FALSE(Has(storage_key1_, "foo")); + EXPECT_FALSE(Has(bucket_locator1_, "foo")); } TEST_P(CacheStorageManagerTestP, DeleteCache) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Delete(storage_key1_, "foo")); - EXPECT_FALSE(Has(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); + EXPECT_FALSE(Has(bucket_locator1_, "foo")); } TEST_P(CacheStorageManagerTestP, DeleteTwice) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Delete(storage_key1_, "foo")); - EXPECT_FALSE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); + EXPECT_FALSE(Delete(bucket_locator1_, "foo")); EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_); } TEST_P(CacheStorageManagerTestP, DeleteCacheReducesKeySize) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); // The quota manager gets updated after the put operation runs its callback so // run the event loop. base::RunLoop().RunUntilIdle(); - int64_t put_delta = quota_manager_proxy_->last_notified_delta(); + int64_t put_delta = quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_LT(0, put_delta); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // Drop the cache handle so that the cache can be erased from disk. callback_cache_handle_ = CacheStorageCacheHandle(); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(-1 * quota_manager_proxy_->last_notified_delta(), put_delta); + EXPECT_EQ(-1 * quota_manager_proxy_->last_notified_bucket_delta(), put_delta); } TEST_P(CacheStorageManagerTestP, EmptyKeys) { - EXPECT_EQ(0u, Keys(storage_key1_)); + EXPECT_EQ(0u, Keys(bucket_locator1_)); } TEST_P(CacheStorageManagerTestP, SomeKeys) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); - EXPECT_TRUE(Open(storage_key2_, "baz")); - EXPECT_EQ(2u, Keys(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE(Open(bucket_locator2_, "baz")); + EXPECT_EQ(2u, Keys(bucket_locator1_)); std::vector<std::string> expected_keys; expected_keys.push_back("foo"); expected_keys.push_back("bar"); EXPECT_EQ(expected_keys, GetIndexNames()); - EXPECT_EQ(1u, Keys(storage_key2_)); + EXPECT_EQ(1u, Keys(bucket_locator2_)); EXPECT_STREQ("baz", GetFirstIndexName().c_str()); } TEST_P(CacheStorageManagerTestP, DeletedKeysGone) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); - EXPECT_TRUE(Open(storage_key2_, "baz")); - EXPECT_TRUE(Delete(storage_key1_, "bar")); - EXPECT_EQ(1u, Keys(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE(Open(bucket_locator2_, "baz")); + EXPECT_TRUE(Delete(bucket_locator1_, "bar")); + EXPECT_EQ(1u, Keys(bucket_locator1_)); EXPECT_STREQ("foo", GetFirstIndexName().c_str()); } TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_TRUE( - StorageMatch(storage_key1_, "foo", GURL("http://example.com/foo"))); + StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/foo"))); } TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_FALSE( - StorageMatch(storage_key1_, "foo", GURL("http://example.com/bar"))); + StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/bar"))); EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_FALSE( - StorageMatch(storage_key1_, "bar", GURL("http://example.com/foo"))); + StorageMatch(bucket_locator1_, "bar", GURL("http://example.com/foo"))); EXPECT_EQ(CacheStorageError::kErrorCacheNameNotFound, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_TRUE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); + EXPECT_TRUE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); } TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_FALSE(StorageMatchAll(storage_key1_, GURL("http://example.com/bar"))); + EXPECT_FALSE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/bar"))); EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchAllNoCaches) { - EXPECT_FALSE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); + EXPECT_FALSE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_); } TEST_P(CacheStorageManagerTestP, StorageMatchDifferentOwners) { - EXPECT_TRUE( - Open(storage_key1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI)); + EXPECT_TRUE(Open(bucket_locator1_, "foo", + storage::mojom::CacheStorageOwner::kCacheAPI)); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), GURL("http://example.com/public"))); - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/bgf"))); // Check the public cache. - EXPECT_TRUE(StorageMatch(storage_key1_, "foo", + EXPECT_TRUE(StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/public"), nullptr, storage::mojom::CacheStorageOwner::kCacheAPI)); - EXPECT_FALSE(StorageMatch(storage_key1_, "foo", + EXPECT_FALSE(StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/bgf"), nullptr, storage::mojom::CacheStorageOwner::kCacheAPI)); // Check the internal cache. EXPECT_FALSE(StorageMatch( - storage_key1_, "foo", GURL("http://example.com/public"), nullptr, + bucket_locator1_, "foo", GURL("http://example.com/public"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_TRUE(StorageMatch( - storage_key1_, "foo", GURL("http://example.com/bgf"), nullptr, + bucket_locator1_, "foo", GURL("http://example.com/bgf"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); } @@ -1107,14 +1166,14 @@ // Deleting a cache and creating one with the same name and adding an entry // with the same URL should work. (see crbug.com/542668) const GURL kTestURL = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL)); EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kTestURL)); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // The cache is deleted but the handle to one of its entries is still // open. Creating a new cache in the same directory would fail on Windows. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL)); } @@ -1124,14 +1183,14 @@ // 1. Create cache A and hang onto the handle const GURL kTestURL = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); // 2. Doom the cache - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // 3. Create cache B (with the same name) - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // 4. Drop handle to A cache_handle = CacheStorageCacheHandle(); @@ -1144,39 +1203,40 @@ // This test reproduces crbug.com/630036. // 1. Cache A with name "foo" is created const GURL kTestURL = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); // 2. Cache A is doomed, but js hangs onto the handle. - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // 3. Cache B with name "foo" is created - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // 4. Cache B is doomed, and both handles are reset. - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); cache_handle = CacheStorageCacheHandle(); // Do some busy work on a different cache to move the cache pool threads // along and trigger the bug. - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL)); EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kTestURL)); } TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // |request_1| and |request_2| has the same url. auto request_1 = blink::mojom::FetchAPIRequest::New(); request_1->url = GURL("http://example.com/foo"); auto request_2 = BackgroundFetchSettledFetch::CloneRequest(request_1); EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_.value(), std::move(request_1), 200)); - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_.value(), std::move(request_2), 201)); - EXPECT_TRUE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); + EXPECT_TRUE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); // The caches need to be searched in order of creation, so verify that the // response came from the first cache. @@ -1184,44 +1244,45 @@ } TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_TRUE(Open(storage_key1_, "baz")); + EXPECT_TRUE(Open(bucket_locator1_, "baz")); - EXPECT_TRUE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); + EXPECT_TRUE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); } TEST_P(CacheStorageManagerTestP, Chinese) { - EXPECT_TRUE(Open(storage_key1_, "你好")); + EXPECT_TRUE(Open(bucket_locator1_, "你好")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "你好")); + EXPECT_TRUE(Open(bucket_locator1_, "你好")); EXPECT_EQ(callback_cache_handle_.value(), cache_handle.value()); - EXPECT_EQ(1u, Keys(storage_key1_)); + EXPECT_EQ(1u, Keys(bucket_locator1_)); EXPECT_STREQ("你好", GetFirstIndexName().c_str()); } TEST_F(CacheStorageManagerTest, EmptyKey) { - EXPECT_TRUE(Open(storage_key1_, "")); + EXPECT_TRUE(Open(bucket_locator1_, "")); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "")); + EXPECT_TRUE(Open(bucket_locator1_, "")); EXPECT_EQ(cache_handle.value(), callback_cache_handle_.value()); - EXPECT_EQ(1u, Keys(storage_key1_)); + EXPECT_EQ(1u, Keys(bucket_locator1_)); EXPECT_STREQ("", GetFirstIndexName().c_str()); - EXPECT_TRUE(Has(storage_key1_, "")); - EXPECT_TRUE(Delete(storage_key1_, "")); - EXPECT_EQ(0u, Keys(storage_key1_)); + EXPECT_TRUE(Has(bucket_locator1_, "")); + EXPECT_TRUE(Delete(bucket_locator1_, "")); + EXPECT_EQ(0u, Keys(bucket_locator1_)); } TEST_P(CacheStorageManagerStorageKeyAndBucketTestP, DataPersists) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); - EXPECT_TRUE(Open(storage_key1_, "baz")); - EXPECT_TRUE(Open(storage_key2_, "raz")); - EXPECT_TRUE(Delete(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "baz")); + EXPECT_TRUE(Open(bucket_locator2_, "raz")); + EXPECT_TRUE(Delete(bucket_locator1_, "bar")); RecreateStorageManager(); - EXPECT_EQ(2u, Keys(storage_key1_)); + EXPECT_EQ(2u, Keys(bucket_locator1_)); std::vector<std::string> expected_keys; expected_keys.push_back("foo"); expected_keys.push_back("baz"); @@ -1229,18 +1290,18 @@ } TEST_F(CacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key2_, "baz")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator2_, "baz")); RecreateStorageManager(); - EXPECT_EQ(0u, Keys(storage_key1_)); + EXPECT_EQ(0u, Keys(bucket_locator1_)); } TEST_F(CacheStorageManagerTest, BadCacheName) { // Since the implementation writes cache names to disk, ensure that we don't // escape the directory. const std::string bad_name = "../../../../../../../../../../../../../../foo"; - EXPECT_TRUE(Open(storage_key1_, bad_name)); - EXPECT_EQ(1u, Keys(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, bad_name)); + EXPECT_EQ(1u, Keys(bucket_locator1_)); EXPECT_STREQ(bad_name.c_str(), GetFirstIndexName().c_str()); } @@ -1249,17 +1310,19 @@ // escape the directory. blink::StorageKey bad_key(url::Origin::Create( GURL("http://../../../../../../../../../../../../../../foo"))); - EXPECT_TRUE(Open(bad_key, "foo")); - EXPECT_EQ(1u, Keys(bad_key)); + storage::BucketLocator bad_bucket_locator = + GetOrCreateBucket(bad_key, storage::kDefaultBucketName); + EXPECT_TRUE(Open(bad_bucket_locator, "foo")); + EXPECT_EQ(1u, Keys(bad_bucket_locator)); EXPECT_STREQ("foo", GetFirstIndexName().c_str()); } // Dropping a reference to a cache should not immediately destroy it. These // warm cache objects are kept alive to optimize the next open. TEST_F(CacheStorageManagerTest, DropReference) { - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key1_); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator1_); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::WeakPtr<CacheStorageCache> cache = CacheStorageCache::From(callback_cache_handle_)->AsWeakPtr(); // Run a cache operation to ensure that the cache has finished initializing so @@ -1281,9 +1344,9 @@ TEST_F(CacheStorageManagerTest, DropReferenceAndDelete) { // Hold a reference to the CacheStorage to permit the warmed // CacheStorageCache to be kept alive. - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key1_); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator1_); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::WeakPtr<CacheStorageCache> cache = CacheStorageCache::From(callback_cache_handle_)->AsWeakPtr(); // Run a cache operation to ensure that the cache has finished initializing so @@ -1296,7 +1359,7 @@ "CacheStorage is still referenced"; // Delete() should trigger its destruction, however. - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(cache) @@ -1308,9 +1371,9 @@ TEST_F(CacheStorageManagerTest, DropReferenceAndMemoryPressure) { // Hold a reference to the CacheStorage to permit the warmed // CacheStorageCache to be kept alive. - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key1_); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator1_); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::WeakPtr<CacheStorageCache> cache = CacheStorageCache::From(callback_cache_handle_)->AsWeakPtr(); // Run a cache operation to ensure that the cache has finished initializing so @@ -1343,7 +1406,7 @@ TEST_F(CacheStorageManagerTest, DropReferenceDuringQuery) { // Setup the cache and execute an operation to make sure all initialization // is complete. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::WeakPtr<CacheStorageCache> cache = CacheStorageCache::From(callback_cache_handle_)->AsWeakPtr(); EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), @@ -1380,10 +1443,10 @@ const GURL kFooURL("http://example.com/foo"); const GURL kBarURL("http://example.com/bar"); const GURL kBazURL("http://example.com/baz"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // Verify that the existing cache handle still works. EXPECT_TRUE(CacheMatch(original_handle.value(), kFooURL)); @@ -1391,11 +1454,11 @@ EXPECT_TRUE(CacheMatch(original_handle.value(), kBarURL)); // The cache shouldn't be visible to subsequent storage operations. - EXPECT_EQ(0u, Keys(storage_key1_)); + EXPECT_EQ(0u, Keys(bucket_locator1_)); // Open a new cache with the same name, it should create a new cache, but not // interfere with the original cache. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); CacheStorageCacheHandle new_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(new_handle.value(), kBazURL)); @@ -1416,18 +1479,18 @@ const GURL kBazURL("http://example.com/baz"); const std::string kCacheName = "foo"; - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); auto original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - EXPECT_TRUE(Delete(storage_key1_, kCacheName)); + EXPECT_TRUE(Delete(bucket_locator1_, kCacheName)); // Now a second cache using the same name, but with different data. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); auto new_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(new_handle.value(), kFooURL)); EXPECT_TRUE(CachePut(new_handle.value(), kBarURL)); EXPECT_TRUE(CachePut(new_handle.value(), kBazURL)); - auto new_cache_size = Size(storage_key1_); + auto new_cache_size = Size(bucket_locator1_); // Now modify the first cache. EXPECT_TRUE(CachePut(original_handle.value(), kBarURL)); @@ -1435,12 +1498,12 @@ // Now deref both caches, and recreate the storage manager. original_handle = CacheStorageCacheHandle(); new_handle = CacheStorageCacheHandle(); - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); DestroyStorageManager(); CreateStorageManager(); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); - EXPECT_EQ(new_cache_size, Size(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); + EXPECT_EQ(new_cache_size, Size(bucket_locator1_)); } TEST_F(CacheStorageManagerTest, TestErrorInitializingCache) { @@ -1449,13 +1512,13 @@ const GURL kFooURL("http://example.com/foo"); const std::string kCacheName = "foo"; - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); auto original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - auto size_before_close = Size(storage_key1_); + auto size_before_close = Size(bucket_locator1_); EXPECT_GT(size_before_close, 0); - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key1_); + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator1_); auto cache_handle = CacheStorage::From(cache_storage)->GetLoadedCache(kCacheName); base::FilePath cache_path = CacheStorageCache::From(cache_handle)->path(); @@ -1466,8 +1529,8 @@ // Do our best to flush any pending cache_storage index file writes to disk // before proceeding. This does not guarantee the simple disk_cache index // is written, though. - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); - EXPECT_FALSE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); + EXPECT_FALSE(FlushCacheStorageIndex(bucket_locator1_)); DestroyStorageManager(); @@ -1490,8 +1553,8 @@ CreateStorageManager(); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); - EXPECT_EQ(0, Size(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); + EXPECT_EQ(0, Size(bucket_locator1_)); } TEST_P(CacheStorageManagerStorageKeyAndBucketTestP, @@ -1499,26 +1562,38 @@ const GURL kFooURL("http://example.com/foo"); const std::string kCacheName = "foo"; - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); auto original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - auto size_before_close = Size(storage_key1_); + auto size_before_close = Size(bucket_locator1_); EXPECT_GT(size_before_close, 0); // Double-check that the CacheStorage files have been written to the // directory we expect. - base::FilePath calculated_path = CacheStorageManager::ConstructStorageKeyPath( - cache_manager_->profile_path(), storage_key1_, + base::FilePath calculated_path = CacheStorageManager::ConstructBucketPath( + cache_manager_->profile_path(), bucket_locator1_, storage::mojom::CacheStorageOwner::kCacheAPI); base::FilePath expected_path; - // Default buckets and first-party contexts should use the legacy path - // format. We'll hardcode the origin hash corresponding to - // `storage_key1_.origin()`. - expected_path = temp_dir_.GetPath() - .AppendASCII("Service Worker") - .AppendASCII(CacheStorage::kCacheStorage) - .AppendASCII("0430f1a484a0ea6d8de562488c5fbeec0111d16f"); + if (!bucket_locator1_.is_default || (ThirdPartyStoragePartitioningEnabled() && + storage_key1_.IsThirdPartyContext())) { + // Named buckets and third-party contexts should use the new directory + // format. + expected_path = + temp_dir_.GetPath() + .AppendASCII("WebStorage") + .AppendASCII(base::NumberToString(bucket_locator1_.id.value())) + .Append(storage::kCacheStorageDirectory); + } else { + // Default buckets and first-party contexts should use the legacy path + // format. We'll hardcode the origin hash corresponding to + // `storage_key1_.origin()`. + expected_path = + temp_dir_.GetPath() + .AppendASCII("Service Worker") + .Append(storage::kCacheStorageDirectory) + .AppendASCII("0430f1a484a0ea6d8de562488c5fbeec0111d16f"); + } EXPECT_EQ(expected_path, calculated_path); @@ -1528,29 +1603,29 @@ CreateStorageManager(); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); - EXPECT_EQ(size_before_close, Size(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); + EXPECT_EQ(size_before_close, Size(bucket_locator1_)); } TEST_F(CacheStorageManagerTest, CacheSizePaddedAfterReopen) { const GURL kFooURL = storage_key1_.origin().GetURL().Resolve("foo"); const std::string kCacheName = "foo"; - int64_t put_delta = quota_manager_proxy_->last_notified_delta(); + int64_t put_delta = quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_EQ(0, put_delta); - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_modified_count()); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_); base::RunLoop().RunUntilIdle(); - put_delta += quota_manager_proxy_->last_notified_delta(); + put_delta += quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_EQ(0, put_delta); - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_modified_count()); EXPECT_TRUE( CachePut(original_handle.value(), kFooURL, FetchResponseType::kOpaque)); - int64_t cache_size_before_close = Size(storage_key1_); + int64_t cache_size_before_close = Size(bucket_locator1_); base::FilePath storage_dir = CacheStorageCache::From(original_handle)->path().DirName(); original_handle = CacheStorageCacheHandle(); @@ -1560,27 +1635,27 @@ EXPECT_EQ(cache_size_before_close, GetQuotaKeyUsage(storage_key1_)); base::RunLoop().RunUntilIdle(); - put_delta = quota_manager_proxy_->last_notified_delta(); + put_delta = quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_GT(put_delta, 0); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_modified_count()); EXPECT_EQ(GetQuotaKeyUsage(storage_key1_), put_delta); // Close the caches and cache manager. - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); DestroyStorageManager(); // Create a new CacheStorageManager that hasn't yet loaded the key. CreateStorageManager(); RecreateStorageManager(); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); base::RunLoop().RunUntilIdle(); - put_delta = quota_manager_proxy_->last_notified_delta(); + put_delta = quota_manager_proxy_->last_notified_bucket_delta(); EXPECT_EQ(0, put_delta); - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_modified_count()); - EXPECT_EQ(cache_size_before_close, Size(storage_key1_)); + EXPECT_EQ(cache_size_before_close, Size(bucket_locator1_)); } TEST_F(CacheStorageManagerTest, QuotaCorrectAfterReopen) { @@ -1593,13 +1668,13 @@ // Create a new cache. int64_t cache_size; { - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); base::RunLoop().RunUntilIdle(); const GURL kFooURL = storage_key1_.origin().GetURL().Resolve("foo"); EXPECT_TRUE(CachePut(cache_handle.value(), kFooURL, response_type)); - cache_size = Size(storage_key1_); + cache_size = Size(bucket_locator1_); EXPECT_EQ(cache_size, GetQuotaKeyUsage(storage_key1_)); } @@ -1608,7 +1683,7 @@ base::RunLoop().RunUntilIdle(); // Now reopen the cache. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_); base::RunLoop().RunUntilIdle(); EXPECT_EQ(cache_size, GetQuotaKeyUsage(storage_key1_)); @@ -1623,25 +1698,25 @@ // With a memory cache the cache can't be freed from memory until the client // calls delete. TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryLosesReferenceOnlyAfterDelete) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::WeakPtr<CacheStorageCache> cache = CacheStorageCache::From(callback_cache_handle_)->AsWeakPtr(); callback_cache_handle_ = CacheStorageCacheHandle(); EXPECT_TRUE(cache); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(cache); } TEST_P(CacheStorageManagerTestP, DeleteBeforeRelease) { - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); EXPECT_TRUE(callback_cache_handle_.value()); } TEST_P(CacheStorageManagerTestP, OpenRunsSerially) { - EXPECT_FALSE(Delete(storage_key1_, "tmp")); // Init storage. - CacheStorageHandle cache_storage = CacheStorageForKey(storage_key1_); + EXPECT_FALSE(Delete(bucket_locator1_, "tmp")); // Init storage. + CacheStorageHandle cache_storage = CacheStorageForBucket(bucket_locator1_); auto* impl = CacheStorage::From(cache_storage); auto id = impl->StartAsyncOperationForTesting(); @@ -1659,32 +1734,49 @@ EXPECT_TRUE(callback_cache_handle_.value()); } -TEST_P(CacheStorageManagerTestP, GetStorageKeyUsage) { - EXPECT_EQ(0, GetStorageKeyUsage(storage_key1_)); - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_EQ(0, GetStorageKeyUsage(storage_key1_)); +TEST_P(CacheStorageManagerTestP, GetBucketUsage) { + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_)); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - int64_t foo_size = GetStorageKeyUsage(storage_key1_); - EXPECT_LT(0, GetStorageKeyUsage(storage_key1_)); - EXPECT_EQ(0, GetStorageKeyUsage(storage_key2_)); + int64_t foo_size = GetBucketUsage(bucket_locator1_); + EXPECT_LT(0, GetBucketUsage(bucket_locator1_)); + EXPECT_EQ(0, GetBucketUsage(bucket_locator2_)); // Add the same entry into a second cache, the size should double. - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_EQ(2 * foo_size, GetStorageKeyUsage(storage_key1_)); + EXPECT_EQ(2 * foo_size, GetBucketUsage(bucket_locator1_)); +} + +TEST_P(CacheStorageManagerStorageKeyAndBucketTestP, GetBucketUsage) { + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_)); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + int64_t foo_size = GetBucketUsage(bucket_locator1_); + EXPECT_LT(0, GetBucketUsage(bucket_locator1_)); + EXPECT_EQ(0, GetBucketUsage(bucket_locator2_)); + + // Add the same entry into a second cache, the size should double. + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + EXPECT_EQ(2 * foo_size, GetBucketUsage(bucket_locator1_)); } TEST_F(CacheStorageManagerMemoryOnlyTest, GetAllStorageKeysUsage) { EXPECT_EQ(0ULL, GetAllStorageKeysUsage().size()); // Put one entry in a cache on origin 1. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); // Put two entries (of identical size) in a cache on origin 2. - EXPECT_TRUE(Open(storage_key2_, "foo")); + EXPECT_TRUE(Open(bucket_locator2_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_TRUE( @@ -1709,23 +1801,17 @@ TEST_P(CacheStorageManagerStorageKeyAndBucketTestP, GetAllStorageKeysUsage) { EXPECT_EQ(0ULL, GetAllStorageKeysUsage().size()); // Put one entry in a cache on origin 1. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); // Put two entries (of identical size) in a cache on origin 2. - EXPECT_TRUE(Open(storage_key2_, "foo")); + EXPECT_TRUE(Open(bucket_locator2_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar"))); - // TODO(awillia): GetAllStorageKeysUsage() won't work for third-party storage - // keys until a later CL, so skip for now. - if (storage_key1_.IsThirdPartyContext()) { - return; - } - std::vector<storage::mojom::StorageUsageInfoPtr> usage = GetAllStorageKeysUsage(); ASSERT_EQ(2ULL, usage.size()); @@ -1746,7 +1832,7 @@ GetAllStorageKeysUsageWithPadding) { EXPECT_EQ(0ULL, GetAllStorageKeysUsage().size()); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); base::FilePath storage_dir = CacheStorageCache::From(callback_cache_handle_)->path().DirName(); base::FilePath index_path = @@ -1768,7 +1854,7 @@ GURL("http://example.com/foo"), FetchResponseType::kOpaque)); - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); // We want to verify that padded values are read from the index // file. If the index is out-of-date, though, the code falls back @@ -1796,17 +1882,17 @@ .size()); // Put one entry in a cache of owner 1. - EXPECT_TRUE( - Open(storage_key1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI)); + EXPECT_TRUE(Open(bucket_locator1_, "foo", + storage::mojom::CacheStorageOwner::kCacheAPI)); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); // Put two entries (of identical size) in two origins in a cache of owner 2. - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_TRUE(Open(storage_key2_, "foo", + EXPECT_TRUE(Open(bucket_locator2_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar"))); @@ -1847,18 +1933,18 @@ // Write a single value (V1) to the cache. const GURL kFooURL = storage_key1_.origin().GetURL().Resolve("foo"); const std::string kCacheName = "foo"; - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - int64_t cache_size_v1 = Size(storage_key1_); + int64_t cache_size_v1 = Size(bucket_locator1_); base::FilePath storage_dir = CacheStorageCache::From(original_handle)->path().DirName(); original_handle = CacheStorageCacheHandle(); EXPECT_GE(cache_size_v1, 0); // Close the caches and cache manager. - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); DestroyStorageManager(); // Save a copy of the V1 index. @@ -1873,7 +1959,7 @@ RecreateStorageManager(); // Create a second value (V2) in the cache. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); original_handle = std::move(callback_cache_handle_); const GURL kBarURL = storage_key1_.origin().GetURL().Resolve("bar"); EXPECT_TRUE(CachePut(original_handle.value(), kBarURL)); @@ -1887,7 +1973,7 @@ EXPECT_GT(usage_before_close, 0); // Flush the index to ensure we can read it correctly from the index file. - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); // Close the caches and cache manager. DestroyStorageManager(); @@ -1921,22 +2007,144 @@ EXPECT_FALSE(usage[0]->last_modified.is_null()); } +TEST_P(CacheStorageManagerTestP, GetAllStorageKeysUsageAggregateBucketUsages) { + const storage::BucketLocator bucket_locator3 = + GetOrCreateBucket(storage_key1_, "non-default"); + + const storage::BucketLocator bucket_locator4 = + GetOrCreateBucket(storage_key2_, "non-default"); + + ASSERT_EQ(0ULL, GetAllStorageKeysUsage().size()); + + EXPECT_TRUE(Open(bucket_locator3, "foo")); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + + // Put an entry (of identical size) in a cache on origin 2. + EXPECT_TRUE(Open(bucket_locator2_, "foo")); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + + std::vector<storage::mojom::StorageUsageInfoPtr> original_usage = + GetAllStorageKeysUsage(); + ASSERT_EQ(2ULL, original_usage.size()); + + int original_storage_key1_index = + blink::StorageKey(original_usage[0]->origin) == storage_key1_ ? 0 : 1; + int original_storage_key2_index = + blink::StorageKey(original_usage[1]->origin) == storage_key2_ ? 1 : 0; + EXPECT_NE(original_storage_key1_index, original_storage_key2_index); + + EXPECT_EQ(original_usage[original_storage_key1_index]->total_size_bytes, + original_usage[original_storage_key2_index]->total_size_bytes); + + // Now open a cache using the default bucket and add the entry there as well. + // `GetAllStorageKeysUsage()` should still return a list with two entries, but + // the corresponding sizes should be double. + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + + EXPECT_TRUE(Open(bucket_locator4, "foo")); + EXPECT_TRUE( + CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); + + std::vector<storage::mojom::StorageUsageInfoPtr> new_usage = + GetAllStorageKeysUsage(); + ASSERT_EQ(2ULL, new_usage.size()); + + int new_storage_key1_index = + blink::StorageKey(new_usage[0]->origin) == storage_key1_ ? 0 : 1; + int new_storage_key2_index = + blink::StorageKey(new_usage[1]->origin) == storage_key2_ ? 1 : 0; + EXPECT_NE(new_storage_key1_index, new_storage_key2_index); + + EXPECT_EQ(new_usage[new_storage_key1_index]->total_size_bytes, + new_usage[new_storage_key2_index]->total_size_bytes); + EXPECT_EQ(2 * original_usage[original_storage_key1_index]->total_size_bytes, + new_usage[new_storage_key1_index]->total_size_bytes); + EXPECT_EQ(2 * original_usage[original_storage_key2_index]->total_size_bytes, + new_usage[new_storage_key2_index]->total_size_bytes); +} + +TEST_P(CacheStorageManagerTestP, GetStorageKeysIgnoresKeysFromNamedBuckets) { + // `GetStorageKeys()` should only return storage keys associated with + // default buckets, so create separate storage keys that we expect to not find + // in the list returned by `GetStorageKeys()`. + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + + url::Origin test_origin = url::Origin::Create(GURL("http://example4.com")); + + auto storage_key3 = blink::StorageKey(test_origin); + + auto storage_key4 = + blink::StorageKey(test_origin, + + url::Origin::Create(GURL("http://example5.com"))); + + const storage::BucketLocator bucket_locator3 = + GetOrCreateBucket(storage_key3, "non-default"); + + const storage::BucketLocator bucket_locator4 = + GetOrCreateBucket(storage_key4, "non-default"); + + ASSERT_EQ(0ULL, GetAllStorageKeysUsage().size()); + + GURL test_url = GURL("http://example.com/foo"); + + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + + EXPECT_TRUE(Open(bucket_locator2_, "bar")); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + + EXPECT_TRUE(Open(bucket_locator3, "baz")); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + + EXPECT_TRUE(Open(bucket_locator4, "cool")); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + + std::vector<blink::StorageKey> storage_keys = GetStorageKeys(); + ASSERT_EQ(2ULL, storage_keys.size()); + EXPECT_NE(storage_keys[0].origin(), test_origin); + EXPECT_NE(storage_keys[1].origin(), test_origin); + ASSERT_EQ(3ULL, GetAllStorageKeysUsage().size()); + + EXPECT_EQ(DeleteBucketData(bucket_locator1_), + blink::mojom::QuotaStatusCode::kOk); + + EXPECT_EQ(DeleteBucketData(bucket_locator2_), + blink::mojom::QuotaStatusCode::kOk); + + EXPECT_EQ(DeleteBucketData(bucket_locator3), + blink::mojom::QuotaStatusCode::kOk); + + EXPECT_EQ(DeleteBucketData(bucket_locator4), + blink::mojom::QuotaStatusCode::kOk); + + ASSERT_EQ(0ULL, GetStorageKeys().size()); + } +} + TEST_F(CacheStorageManagerTest, GetKeySizeWithOldIndex) { // Write a single value (V1) to the cache. const GURL kFooURL = storage_key1_.origin().GetURL().Resolve("foo"); const std::string kCacheName = "foo"; - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_); EXPECT_TRUE(CachePut(original_handle.value(), kFooURL)); - int64_t cache_size_v1 = Size(storage_key1_); + int64_t cache_size_v1 = Size(bucket_locator1_); base::FilePath storage_dir = CacheStorageCache::From(original_handle)->path().DirName(); original_handle = CacheStorageCacheHandle(); EXPECT_GE(cache_size_v1, 0); // Close the caches and cache manager. - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); DestroyStorageManager(); // Save a copy of the V1 index. @@ -1951,12 +2159,12 @@ RecreateStorageManager(); // Reopen the cache and write a second value (V2). - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); original_handle = std::move(callback_cache_handle_); const GURL kBarURL = storage_key1_.origin().GetURL().Resolve("bar"); EXPECT_TRUE(CachePut(original_handle.value(), kBarURL)); original_handle = CacheStorageCacheHandle(); - int64_t cache_size_v2 = Size(storage_key1_); + int64_t cache_size_v2 = Size(bucket_locator1_); EXPECT_GE(cache_size_v2, 0); // Close the caches and cache manager. @@ -1973,33 +2181,33 @@ // Reopen the cache and ensure the size is correct for the V2 value. CreateStorageManager(); - EXPECT_TRUE(Open(storage_key1_, kCacheName)); - EXPECT_EQ(cache_size_v2, Size(storage_key1_)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); + EXPECT_EQ(cache_size_v2, Size(bucket_locator1_)); } TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo2"))); - EXPECT_TRUE(Open(storage_key1_, "bar")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar"))); - int64_t origin_size = GetStorageKeyUsage(storage_key1_); + int64_t origin_size = GetBucketUsage(bucket_locator1_); EXPECT_LT(0, origin_size); - EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(storage_key1_)); + EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(bucket_locator1_)); EXPECT_FALSE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/baz"))); } TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCachesTwoOwners) { - EXPECT_TRUE( - Open(storage_key1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI)); + EXPECT_TRUE(Open(bucket_locator1_, "foo", + storage::mojom::CacheStorageOwner::kCacheAPI)); CacheStorageCacheHandle public_handle = std::move(callback_cache_handle_); - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); CacheStorageCacheHandle bgf_handle = std::move(callback_cache_handle_); @@ -2007,20 +2215,20 @@ CachePut(public_handle.value(), GURL("http://example.com/public"))); EXPECT_TRUE(CachePut(bgf_handle.value(), GURL("http://example.com/bgf"))); - int64_t origin_size = GetStorageKeyUsage(storage_key1_); + int64_t origin_size = GetBucketUsage(bucket_locator1_); EXPECT_LT(0, origin_size); - EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(storage_key1_)); + EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(bucket_locator1_)); EXPECT_FALSE(CachePut(public_handle.value(), GURL("http://example.com/baz"))); } TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCachesAfterDelete) { // Tests that doomed caches are also deleted by GetSizeThenCloseAllCaches. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - int64_t size_after_put = GetStorageKeyUsage(storage_key1_); + int64_t size_after_put = GetBucketUsage(bucket_locator1_); EXPECT_LT(0, size_after_put); // Keep a handle to a (soon-to-be deleted cache). @@ -2028,36 +2236,36 @@ // Delete will only doom the cache because there is still at least one handle // referencing an open cache. - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); // GetSizeThenCloseAllCaches should close the cache (which is then deleted) // even though there is still an open handle. - EXPECT_EQ(size_after_put, GetSizeThenCloseAllCaches(storage_key1_)); - EXPECT_EQ(0, GetStorageKeyUsage(storage_key1_)); + EXPECT_EQ(size_after_put, GetSizeThenCloseAllCaches(bucket_locator1_)); + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_)); } TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) { // Create a referenced cache. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); // Create an unreferenced directory next to the referenced one. auto* legacy_manager = static_cast<CacheStorageManager*>(cache_manager_.get()); - base::FilePath origin_path = CacheStorageManager::ConstructStorageKeyPath( - legacy_manager->profile_path(), storage_key1_, + base::FilePath origin_path = CacheStorageManager::ConstructBucketPath( + legacy_manager->profile_path(), bucket_locator1_, storage::mojom::CacheStorageOwner::kCacheAPI); base::FilePath unreferenced_path = origin_path.AppendASCII("bar"); EXPECT_TRUE(CreateDirectory(unreferenced_path)); EXPECT_TRUE(base::DirectoryExists(unreferenced_path)); - // Create a new StorageManager so that the next time the cache is opened - // the unreferenced directory can be deleted. + // Create a new StorageManager so that the next time the cache is opened the + // unreferenced directory can be deleted. RecreateStorageManager(); // Verify that the referenced cache still works. - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), GURL("http://example.com/foo"))); @@ -2066,61 +2274,62 @@ } TEST_P(CacheStorageManagerTestP, OpenCacheStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, HasStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); - EXPECT_FALSE(Has(storage_key1_, "foo")); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); + EXPECT_FALSE(Has(bucket_locator1_, "foo")); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, DeleteStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); - EXPECT_FALSE(Delete(storage_key1_, "foo")); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); + EXPECT_FALSE(Delete(bucket_locator1_, "foo")); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, KeysStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); - EXPECT_EQ(0u, Keys(storage_key1_)); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); + EXPECT_EQ(0u, Keys(bucket_locator1_)); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, MatchCacheStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); EXPECT_FALSE( - StorageMatch(storage_key1_, "foo", GURL("http://example.com/foo"))); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/foo"))); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, MatchAllCachesStorageAccessed) { - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); - EXPECT_FALSE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); - EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); + EXPECT_FALSE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); + EXPECT_EQ(1, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, SizeStorageAccessed) { - EXPECT_EQ(0, Size(storage_key1_)); + EXPECT_EQ(0, Size(bucket_locator1_)); // Size is not part of the web API and should not notify the quota manager of // an access. - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, SizeThenCloseStorageAccessed) { - EXPECT_EQ(0, GetSizeThenCloseAllCaches(storage_key1_)); + EXPECT_EQ(0, GetSizeThenCloseAllCaches(bucket_locator1_)); // GetSizeThenCloseAllCaches is not part of the web API and should not notify // the quota manager of an access. - EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count()); + EXPECT_EQ(0, quota_manager_proxy_->notify_bucket_accessed_count()); } TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Created) { auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_list_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(1, observer->notify_list_changed_count); EXPECT_TRUE( @@ -2133,14 +2342,14 @@ auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_list_changed_count); - EXPECT_FALSE(Delete(storage_key1_, "foo")); + EXPECT_FALSE(Delete(bucket_locator1_, "foo")); // Give any unexpected observer tasks a chance to run. base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, observer->notify_list_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(1, observer->notify_list_changed_count); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(2, observer->notify_list_changed_count); } @@ -2149,13 +2358,13 @@ auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_list_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(1, observer->notify_list_changed_count); - EXPECT_TRUE(Delete(storage_key1_, "foo")); + EXPECT_TRUE(Delete(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(2, observer->notify_list_changed_count); - EXPECT_TRUE(Open(storage_key2_, "foo2")); + EXPECT_TRUE(Open(bucket_locator1_, "foo2")); observer->Wait(); EXPECT_EQ(3, observer->notify_list_changed_count); } @@ -2164,7 +2373,7 @@ auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_content_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(0, observer->notify_content_changed_count); EXPECT_TRUE( @@ -2184,10 +2393,10 @@ auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_content_changed_count); - EXPECT_FALSE(Delete(storage_key1_, "foo")); + EXPECT_FALSE(Delete(bucket_locator1_, "foo")); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, observer->notify_content_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(0, observer->notify_content_changed_count); EXPECT_TRUE( @@ -2209,7 +2418,7 @@ auto observer = CreateObserver(); EXPECT_EQ(0, observer->notify_content_changed_count); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); observer->Wait(); EXPECT_EQ(0, observer->notify_content_changed_count); EXPECT_TRUE( @@ -2231,42 +2440,44 @@ } TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreSearch) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo?bar"))); EXPECT_FALSE( - StorageMatch(storage_key1_, "foo", GURL("http://example.com/foo"))); + StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/foo"))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_search = true; - EXPECT_TRUE(StorageMatch(storage_key1_, "foo", GURL("http://example.com/foo"), + EXPECT_TRUE(StorageMatch(bucket_locator1_, "foo", + GURL("http://example.com/foo"), std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreMethod) { GURL url = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), url)); auto post_request = blink::mojom::FetchAPIRequest::New(); post_request->url = url; post_request->method = "POST"; EXPECT_FALSE(StorageMatchWithRequest( - storage_key1_, "foo", + bucket_locator1_, "foo", BackgroundFetchSettledFetch::CloneRequest(post_request))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_method = true; - EXPECT_TRUE(StorageMatchWithRequest( - storage_key1_, "foo", std::move(post_request), std::move(match_options))); + EXPECT_TRUE(StorageMatchWithRequest(bucket_locator1_, "foo", + std::move(post_request), + std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) { GURL url = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); auto request = blink::mojom::FetchAPIRequest::New(); request->url = url; @@ -2282,57 +2493,59 @@ std::move(request_1), std::move(response_headers))); EXPECT_TRUE( - StorageMatchWithRequest(storage_key1_, "foo", std::move(request_2))); + StorageMatchWithRequest(bucket_locator1_, "foo", std::move(request_2))); request->headers["vary_foo"] = "bar"; // |request_3| and |request_4| has the same url and headers. auto request_3 = BackgroundFetchSettledFetch::CloneRequest(request); auto request_4 = BackgroundFetchSettledFetch::CloneRequest(request); EXPECT_FALSE( - StorageMatchWithRequest(storage_key1_, "foo", std::move(request_3))); + StorageMatchWithRequest(bucket_locator1_, "foo", std::move(request_3))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_vary = true; EXPECT_TRUE(StorageMatchWithRequest( - storage_key1_, "foo", std::move(request_4), std::move(match_options))); + bucket_locator1_, "foo", std::move(request_4), std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreSearch) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo?bar"))); - EXPECT_FALSE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"))); + EXPECT_FALSE( + StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_search = true; - EXPECT_TRUE(StorageMatchAll(storage_key1_, GURL("http://example.com/foo"), + EXPECT_TRUE(StorageMatchAll(bucket_locator1_, GURL("http://example.com/foo"), std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreMethod) { GURL url = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE(CachePut(callback_cache_handle_.value(), url)); auto post_request = blink::mojom::FetchAPIRequest::New(); post_request->url = url; post_request->method = "POST"; EXPECT_FALSE(StorageMatchAllWithRequest( - storage_key1_, BackgroundFetchSettledFetch::CloneRequest(post_request))); + bucket_locator1_, + BackgroundFetchSettledFetch::CloneRequest(post_request))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_method = true; - EXPECT_TRUE(StorageMatchAllWithRequest(storage_key1_, std::move(post_request), - std::move(match_options))); + EXPECT_TRUE(StorageMatchAllWithRequest( + bucket_locator1_, std::move(post_request), std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) { GURL url = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); auto request = blink::mojom::FetchAPIRequest::New(); request->url = url; @@ -2346,48 +2559,50 @@ EXPECT_TRUE(CachePutWithRequestAndHeaders( callback_cache_handle_.value(), std::move(request_1), response_headers)); - EXPECT_TRUE(StorageMatchAllWithRequest(storage_key1_, std::move(request_2))); + EXPECT_TRUE( + StorageMatchAllWithRequest(bucket_locator1_, std::move(request_2))); request->headers["vary_foo"] = "bar"; // |request_3| and |request_4| has the same url and headers. auto request_3 = BackgroundFetchSettledFetch::CloneRequest(request); auto request_4 = BackgroundFetchSettledFetch::CloneRequest(request); - EXPECT_FALSE(StorageMatchAllWithRequest(storage_key1_, std::move(request_3))); + EXPECT_FALSE( + StorageMatchAllWithRequest(bucket_locator1_, std::move(request_3))); blink::mojom::CacheQueryOptionsPtr match_options = blink::mojom::CacheQueryOptions::New(); match_options->ignore_vary = true; - EXPECT_TRUE(StorageMatchAllWithRequest(storage_key1_, std::move(request_4), + EXPECT_TRUE(StorageMatchAllWithRequest(bucket_locator1_, std::move(request_4), std::move(match_options))); } TEST_P(CacheStorageManagerTestP, StorageWriteToCache) { - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); - EXPECT_TRUE(Write(storage_key1_, + EXPECT_TRUE(Write(bucket_locator1_, storage::mojom::CacheStorageOwner::kBackgroundFetch, "foo", "http://example.com/foo")); // Match request we just wrote. EXPECT_TRUE(StorageMatch( - storage_key1_, "foo", GURL("http://example.com/foo"), nullptr, + bucket_locator1_, "foo", GURL("http://example.com/foo"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); // Don't match with different origin. EXPECT_FALSE(StorageMatch( - storage_key2_, "foo", GURL("http://example.com/foo"), nullptr, + bucket_locator2_, "foo", GURL("http://example.com/foo"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); // Don't match with different cache name. EXPECT_FALSE(StorageMatch( - storage_key1_, "bar", GURL("http://example.com/foo"), nullptr, + bucket_locator1_, "bar", GURL("http://example.com/foo"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); // Don't match with different request. EXPECT_FALSE(StorageMatch( - storage_key1_, "foo", GURL("http://example.com/bar"), nullptr, + bucket_locator1_, "foo", GURL("http://example.com/bar"), nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); // Don't match with different owner. - EXPECT_FALSE(StorageMatch(storage_key1_, "foo", + EXPECT_FALSE(StorageMatch(bucket_locator1_, "foo", GURL("http://example.com/foo"), nullptr, storage::mojom::CacheStorageOwner::kCacheAPI)); } @@ -2403,35 +2618,35 @@ const GURL kResource("https://example.com/foo"); // Opening a new cache should require writing the index. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant)); - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); // Allow the cache to close. callback_cache_handle_ = CacheStorageCacheHandle(); // Opening an existing cache should *not* require writing the index. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant)); - EXPECT_FALSE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_FALSE(FlushCacheStorageIndex(bucket_locator1_)); // Putting a value in the cache should require writing the index. EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kResource)); - EXPECT_TRUE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_TRUE(FlushCacheStorageIndex(bucket_locator1_)); // Allow the cache to close. callback_cache_handle_ = CacheStorageCacheHandle(); // Opening an existing cache after writing a value should *not* require // writing the index. - EXPECT_TRUE(Open(storage_key1_, kCacheName)); + EXPECT_TRUE(Open(bucket_locator1_, kCacheName)); EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant)); EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kResource)); - EXPECT_FALSE(FlushCacheStorageIndex(storage_key1_)); + EXPECT_FALSE(FlushCacheStorageIndex(bucket_locator1_)); } TEST_P(CacheStorageManagerTestP, SlowPutCompletesWithoutExternalRef) { - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); auto request = blink::mojom::FetchAPIRequest::New(); request->url = GURL("http://example.com/foo"); @@ -2473,7 +2688,7 @@ } TEST_P(CacheStorageManagerTestP, StoragePutPartialContentForBackgroundFetch) { - EXPECT_TRUE(Open(storage_key1_, "foo", + EXPECT_TRUE(Open(bucket_locator1_, "foo", storage::mojom::CacheStorageOwner::kBackgroundFetch)); auto request = blink::mojom::FetchAPIRequest::New(); request->url = GURL("http://example.com/foo"); @@ -2482,7 +2697,8 @@ EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_.value(), std::move(request), 206)); EXPECT_TRUE(StorageMatchAllWithRequest( - storage_key1_, std::move(request_clone), /* match_options= */ nullptr, + bucket_locator1_, std::move(request_clone), + /* match_options= */ nullptr, storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_EQ(206, callback_cache_handle_response_->status_code); } @@ -2492,70 +2708,147 @@ scoped_feature_list.InitAndEnableFeature( net::features::kThirdPartyStoragePartitioning); + const auto named_bucket_locator1 = + GetOrCreateBucket(storage_key1_, "non-default"); + const auto partitioned_storage_key1 = blink::StorageKey(url::Origin::Create(GURL("http://example1.com")), url::Origin::Create(GURL("http://example3.com"))); + const auto partitioned_default_bucket_locator1 = + GetOrCreateBucket(partitioned_storage_key1, storage::kDefaultBucketName); + const auto partitioned_named_bucket_locator1 = + GetOrCreateBucket(partitioned_storage_key1, "non-default"); + GURL test_url = GURL("http://example.com/foo"); - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + for (const storage::mojom::CacheStorageOwner owner : + {storage::mojom::CacheStorageOwner::kCacheAPI, + storage::mojom::CacheStorageOwner::kBackgroundFetch}) { + EXPECT_TRUE(Open(bucket_locator1_, "foo", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); - EXPECT_TRUE(Open(storage_key2_, "foo")); - EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + EXPECT_TRUE(Open(bucket_locator2_, "foo", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); - EXPECT_TRUE(Open(partitioned_storage_key1, "baz")); - EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); + EXPECT_TRUE(Open(partitioned_default_bucket_locator1, "baz", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); - // TODO(awillia): This will only be two in the `!MemoryOnly()` case since - // `GetStorageKeys()` builds the list from disk and right now first-party - // and third-party storage keys share a directory. This will be fixed by - // the buckets integration. - if (MemoryOnly()) { - EXPECT_EQ(3ULL, GetStorageKeys().size()); - } else { - EXPECT_EQ(2ULL, GetStorageKeys().size()); - } + EXPECT_EQ(3ULL, GetStorageKeys(owner).size()); - EXPECT_EQ(DeleteStorageKeyData(storage_key1_), - blink::mojom::QuotaStatusCode::kOk); + EXPECT_EQ(DeleteStorageKeyData(storage_key1_, owner), + blink::mojom::QuotaStatusCode::kOk); - auto storage_keys = GetStorageKeys(); - if (MemoryOnly()) { + auto storage_keys = GetStorageKeys(owner); EXPECT_EQ(2ULL, storage_keys.size()); EXPECT_NE(storage_keys[0], storage_key1_); EXPECT_NE(storage_keys[1], storage_key1_); - } else { + + EXPECT_EQ(DeleteStorageKeyData(partitioned_storage_key1, owner), + blink::mojom::QuotaStatusCode::kOk); + + storage_keys = GetStorageKeys(owner); EXPECT_EQ(1ULL, storage_keys.size()); - EXPECT_NE(storage_keys[0], storage_key1_); - } + EXPECT_EQ(storage_keys[0], storage_key2_); - EXPECT_EQ(DeleteStorageKeyData(partitioned_storage_key1), - blink::mojom::QuotaStatusCode::kOk); + // Now test how named buckets are handled. + EXPECT_TRUE(Open(named_bucket_locator1, "bar", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); - storage_keys = GetStorageKeys(); - EXPECT_EQ(1ULL, storage_keys.size()); - EXPECT_EQ(storage_keys[0], storage_key2_); + EXPECT_TRUE(Open(partitioned_named_bucket_locator1, "foo", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), test_url)); - EXPECT_EQ(DeleteStorageKeyData(storage_key2_), - blink::mojom::QuotaStatusCode::kOk); + // Note that we use `GetAllStorageKeysUsage()` here because + // `GetStorageKeys()` won't return storage keys only associated with named + // buckets. The latter returns results aggregated by origin, but we can use + // the sizes to know whether data was deleted. + auto usages = GetAllStorageKeysUsage(owner); + EXPECT_EQ(2ULL, usages.size()); - EXPECT_EQ(0ULL, GetAllStorageKeysUsage().size()); + int origin1_index = usages[0]->origin == storage_key1_.origin() ? 0 : 1; + int origin2_index = usages[1]->origin == storage_key2_.origin() ? 1 : 0; + EXPECT_NE(origin1_index, origin2_index); - if (!MemoryOnly()) { - auto* legacy_manager = - static_cast<CacheStorageManager*>(cache_manager_.get()); - for (const auto& storage_key : - {storage_key1_, storage_key2_, partitioned_storage_key1}) { - base::FilePath path = CacheStorageManager::ConstructStorageKeyPath( - legacy_manager->profile_path(), storage_key, - storage::mojom::CacheStorageOwner::kCacheAPI); - EXPECT_FALSE(base::PathExists(path)); + EXPECT_EQ(2 * usages[origin2_index]->total_size_bytes, + usages[origin1_index]->total_size_bytes); + + EXPECT_EQ(DeleteStorageKeyData(storage_key1_, owner), + blink::mojom::QuotaStatusCode::kOk); + + EXPECT_EQ(DeleteStorageKeyData(partitioned_storage_key1, owner), + blink::mojom::QuotaStatusCode::kOk); + + // TODO(https://crbug.com/1218097): We don't currently delete named bucket + // data when `DeleteStorageKeyData()` is called, but when we do, update this + // test condition. + usages = GetAllStorageKeysUsage(owner); + EXPECT_EQ(2ULL, usages.size()); + + origin1_index = usages[0]->origin == storage_key1_.origin() ? 0 : 1; + origin2_index = usages[1]->origin == storage_key2_.origin() ? 1 : 0; + EXPECT_NE(origin1_index, origin2_index); + + EXPECT_EQ(2 * usages[origin2_index]->total_size_bytes, + usages[origin1_index]->total_size_bytes); + + EXPECT_EQ(DeleteStorageKeyData(storage_key2_, owner), + blink::mojom::QuotaStatusCode::kOk); + + EXPECT_EQ(1ULL, GetAllStorageKeysUsage(owner).size()); + + if (!MemoryOnly()) { + auto* legacy_manager = + static_cast<CacheStorageManager*>(cache_manager_.get()); + // TODO(https://crbug.com/1218097): When we support deleting named + // buckets, check that the files for those get deleted as well. + for (const auto& bucket_locator : {bucket_locator2_}) { + base::FilePath bucket_path = CacheStorageManager::ConstructBucketPath( + legacy_manager->profile_path(), bucket_locator, owner); + EXPECT_FALSE(base::PathExists(bucket_path)); + } } } } +TEST_F(CacheStorageManagerMemoryOnlyTest, DeleteBucketData) { + for (const storage::mojom::CacheStorageOwner owner : + {storage::mojom::CacheStorageOwner::kCacheAPI, + storage::mojom::CacheStorageOwner::kBackgroundFetch}) { + EXPECT_TRUE(Open(bucket_locator1_, "foo", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), + GURL("http://example.com/foo"))); + + EXPECT_LT(0, GetBucketUsage(bucket_locator1_, owner)); + EXPECT_EQ(DeleteBucketData(bucket_locator1_, owner), + blink::mojom::QuotaStatusCode::kOk); + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_, owner)); + } +} + +TEST_P(CacheStorageManagerStorageKeyAndBucketTestP, DeleteBucketData) { + for (const storage::mojom::CacheStorageOwner owner : + {storage::mojom::CacheStorageOwner::kCacheAPI, + storage::mojom::CacheStorageOwner::kBackgroundFetch}) { + EXPECT_TRUE(Open(bucket_locator1_, "foo", owner)); + EXPECT_TRUE(CachePut(callback_cache_handle_.value(), + GURL("http://example.com/foo"))); + + EXPECT_LT(0, GetBucketUsage(bucket_locator1_, owner)); + + base::FilePath calculated_path = CacheStorageManager::ConstructBucketPath( + cache_manager_->profile_path(), bucket_locator1_, owner); + + EXPECT_TRUE(base::PathExists(calculated_path)); + + EXPECT_EQ(DeleteBucketData(bucket_locator1_, owner), + blink::mojom::QuotaStatusCode::kOk); + EXPECT_EQ(0, GetBucketUsage(bucket_locator1_, owner)); + + EXPECT_FALSE(base::PathExists(calculated_path)); + } +} + class CacheStorageQuotaClientTest : public CacheStorageManagerTest { public: CacheStorageQuotaClientTest(const CacheStorageQuotaClientTest&) = delete; @@ -2629,56 +2922,53 @@ }; TEST_P(CacheStorageQuotaClientTestP, QuotaGetBucketUsage) { - auto bucket1 = GetOrCreateBucket(storage_key1_, storage::kDefaultBucketName); - EXPECT_EQ(0, QuotaGetBucketUsage(bucket1)); - EXPECT_TRUE(Open(bucket1.storage_key, "foo")); + EXPECT_EQ(0, QuotaGetBucketUsage(bucket_locator1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_LT(0, QuotaGetBucketUsage(bucket1)); + EXPECT_LT(0, QuotaGetBucketUsage(bucket_locator1_)); } TEST_P(CacheStorageQuotaClientTestP, QuotaGetStorageKeysForType) { EXPECT_EQ(0u, QuotaGetStorageKeysForType()); - EXPECT_TRUE(Open(storage_key1_, "foo")); - EXPECT_TRUE(Open(storage_key1_, "bar")); - EXPECT_TRUE(Open(storage_key2_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE(Open(bucket_locator2_, "foo")); EXPECT_EQ(2u, QuotaGetStorageKeysForType()); } TEST_P(CacheStorageQuotaClientTestP, QuotaGetStorageKeysForTypeDifferentOwners) { EXPECT_EQ(0u, QuotaGetStorageKeysForType()); - EXPECT_TRUE(Open(storage_key1_, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // The |quota_client_| is registered for // storage::mojom::CacheStorageOwner::kCacheAPI, so this Open is ignored. - EXPECT_TRUE(Open(storage_key2_, "bar", + EXPECT_TRUE(Open(bucket_locator2_, "bar", storage::mojom::CacheStorageOwner::kBackgroundFetch)); EXPECT_EQ(1u, QuotaGetStorageKeysForType()); } TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteBucketData) { - auto bucket1 = GetOrCreateBucket(storage_key1_, storage::kDefaultBucketName); - auto bucket2 = GetOrCreateBucket(storage_key2_, storage::kDefaultBucketName); - EXPECT_EQ(0, QuotaGetBucketUsage(bucket1)); - EXPECT_TRUE(Open(bucket1.storage_key, "foo")); + EXPECT_EQ(0, QuotaGetBucketUsage(bucket_locator1_)); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // Call put to test that initialized caches are properly deleted too. EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); - EXPECT_TRUE(Open(bucket1.storage_key, "bar")); - EXPECT_TRUE(Open(bucket2.storage_key, "baz")); + EXPECT_TRUE(Open(bucket_locator1_, "bar")); + EXPECT_TRUE(Open(bucket_locator2_, "baz")); - int64_t storage_key1_size = QuotaGetBucketUsage(bucket1); + int64_t storage_key1_size = QuotaGetBucketUsage(bucket_locator1_); EXPECT_LT(0, storage_key1_size); - EXPECT_TRUE(QuotaDeleteBucketData(bucket1)); + EXPECT_TRUE(QuotaDeleteBucketData(bucket_locator1_)); EXPECT_EQ(-1 * storage_key1_size, - quota_manager_proxy_->last_notified_delta()); - EXPECT_EQ(0, QuotaGetBucketUsage(bucket1)); - EXPECT_FALSE(Has(bucket1.storage_key, "foo")); - EXPECT_FALSE(Has(bucket1.storage_key, "bar")); - EXPECT_TRUE(Has(bucket2.storage_key, "baz")); - EXPECT_TRUE(Open(bucket1.storage_key, "foo")); + quota_manager_proxy_->last_notified_bucket_delta()); + EXPECT_EQ(0, QuotaGetBucketUsage(bucket_locator1_)); + EXPECT_FALSE(Has(bucket_locator1_, "foo")); + EXPECT_FALSE(Has(bucket_locator1_, "bar")); + EXPECT_TRUE(Has(bucket_locator2_, "baz")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); } TEST_P(CacheStorageQuotaClientTestP, QuotaNonDefaultBucket) { @@ -2688,13 +2978,11 @@ } TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyBucket) { - auto bucket1 = GetOrCreateBucket(storage_key1_, storage::kDefaultBucketName); - EXPECT_TRUE(QuotaDeleteBucketData(bucket1)); + EXPECT_TRUE(QuotaDeleteBucketData(bucket_locator1_)); } TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedKeyData) { - auto bucket1 = GetOrCreateBucket(storage_key1_, storage::kDefaultBucketName); - EXPECT_TRUE(Open(bucket1.storage_key, "foo")); + EXPECT_TRUE(Open(bucket_locator1_, "foo")); // Call put to test that initialized caches are properly deleted too. EXPECT_TRUE( CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo"))); @@ -2710,8 +2998,8 @@ quota_client_ = std::make_unique<CacheStorageQuotaClient>( cache_manager_, storage::mojom::CacheStorageOwner::kCacheAPI); - EXPECT_TRUE(QuotaDeleteBucketData(bucket1)); - EXPECT_EQ(0, QuotaGetBucketUsage(bucket1)); + EXPECT_TRUE(QuotaDeleteBucketData(bucket_locator1_)); + EXPECT_EQ(0, QuotaGetBucketUsage(bucket_locator1_)); } class CacheStorageIndexMigrationTest : public CacheStorageManagerTest { @@ -2728,11 +3016,14 @@ auto* legacy_manager = static_cast<CacheStorageManager*>(cache_manager_.get()); base::FilePath profile_path = legacy_manager->profile_path(); - base::FilePath storage_dir = CacheStorageManager::ConstructStorageKeyPath( - profile_path, storage_key1_, + base::FilePath storage_dir = CacheStorageManager::ConstructBucketPath( + profile_path, bucket_locator1_, storage::mojom::CacheStorageOwner::kCacheAPI); EXPECT_TRUE(base::CreateDirectory( CacheStorageManager::ConstructFirstPartyDefaultRootPath(profile_path))); + EXPECT_TRUE(base::CreateDirectory( + CacheStorageManager::ConstructThirdPartyAndNonDefaultRootPath( + profile_path))); // Destroy the manager while we operate on the underlying files. DestroyStorageManager(); @@ -2767,18 +3058,18 @@ int64_t total_usage = -1; usages = GetAllStorageKeysUsage(); for (auto& usage : usages) { - if (usage->origin == storage_key1_.origin()) { + if (usage->origin == bucket_locator1_.storage_key.origin()) { total_usage = usage->total_size_bytes; break; } } // Double-check that total_usage is comparable with what's returned by - // `GetStorageKeyUsage()`. Note that in my testing the value returned by - // `GetStorageKeyUsage()` here is larger than total_usage by 256, possibly + // `GetBucketUsage()`. Note that in my testing the value returned by + // `GetBucketUsage()` here is larger than total_usage by 256, possibly // because the migration increases the calculated size depending on how // and/or when the calculation is done. - EXPECT_LE(total_usage, GetStorageKeyUsage(storage_key1_)); + EXPECT_LE(total_usage, GetBucketUsage(bucket_locator1_)); // Destroy the manager and then ensure that all tasks have completed before // continuing. We can't rely on `FlushCacheStorageIndex()` here because it @@ -2827,19 +3118,30 @@ })); } -TEST_F(CacheStorageIndexMigrationTest, StorageKeyMigration) { +TEST_F(CacheStorageIndexMigrationTest, BucketMigration) { DoTest("content/test/data/cache_storage/storage_key/", base::BindLambdaForTesting( [this](const proto::CacheStorageIndex& original_index, const proto::CacheStorageIndex& upgraded_index, int64_t total_usage) { EXPECT_FALSE(original_index.has_storage_key()); + EXPECT_FALSE(original_index.has_bucket_id()); + EXPECT_FALSE(original_index.has_bucket_is_default()); + EXPECT_TRUE(upgraded_index.has_storage_key()); + EXPECT_TRUE(upgraded_index.has_bucket_id()); + EXPECT_TRUE(upgraded_index.has_bucket_is_default()); absl::optional<blink::StorageKey> result = blink::StorageKey::Deserialize(upgraded_index.storage_key()); ASSERT_TRUE(result.has_value()); EXPECT_EQ(this->storage_key1_, result.value()); + + storage::BucketLocator bucket_locator = storage::BucketLocator( + storage::BucketId(upgraded_index.bucket_id()), + result.value(), StorageType::kTemporary, + upgraded_index.bucket_is_default()); + EXPECT_EQ(this->bucket_locator1_, bucket_locator); })); } @@ -2854,7 +3156,10 @@ ::testing::Values( StorageKeyAndBucketTestCase::kFirstPartyDefault, StorageKeyAndBucketTestCase::kFirstPartyDefaultPartitionEnabled, - StorageKeyAndBucketTestCase::kThirdPartyDefault)); + StorageKeyAndBucketTestCase::kFirstPartyNamed, + StorageKeyAndBucketTestCase::kFirstPartyNamedPartitionEnabled, + StorageKeyAndBucketTestCase::kThirdPartyDefault, + StorageKeyAndBucketTestCase::kThirdPartyNamed)); INSTANTIATE_TEST_SUITE_P(CacheStorageQuotaClientTests, CacheStorageQuotaClientTestP,
diff --git a/content/browser/cache_storage/cache_storage_quota_client.cc b/content/browser/cache_storage/cache_storage_quota_client.cc index 8434ed0b..fb67bd9 100644 --- a/content/browser/cache_storage/cache_storage_quota_client.cc +++ b/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -7,7 +7,6 @@ #include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/cache_storage/cache_storage_manager.h" #include "storage/browser/quota/quota_client_type.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" namespace content { @@ -29,21 +28,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(bucket.type, blink::mojom::StorageType::kTemporary); - // Skip non-default buckets until Storage Buckets are supported for - // CacheStorage. - // TODO(crbug.com/1218097): Integrate CacheStorage with StorageBuckets. - if (!bucket.is_default) { - std::move(callback).Run(0); - return; - } - if (!CacheStorageManager::IsValidQuotaStorageKey(bucket.storage_key)) { std::move(callback).Run(0); return; } - cache_manager_->GetStorageKeyUsage(bucket.storage_key, owner_, - std::move(callback)); + cache_manager_->GetBucketUsage(bucket, owner_, std::move(callback)); } void CacheStorageQuotaClient::GetStorageKeysForType( @@ -61,21 +51,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(bucket.type, blink::mojom::StorageType::kTemporary); - // Skip non-default buckets until Storage Buckets are supported for - // CacheStorage. - // TODO(crbug.com/1218097): Integrate CacheStorage with StorageBuckets. - if (!bucket.is_default) { - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); - return; - } - if (!CacheStorageManager::IsValidQuotaStorageKey(bucket.storage_key)) { std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); return; } - cache_manager_->DeleteStorageKeyData(bucket.storage_key, owner_, - std::move(callback)); + cache_manager_->DeleteBucketData(bucket, owner_, std::move(callback)); } void CacheStorageQuotaClient::PerformStorageCleanup(
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index af8447f..9d57b9e 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -34,7 +34,6 @@ #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" -#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/ipc/common/gpu_client_ids.h" #include "gpu/ipc/common/gpu_watchdog_timeout.h" @@ -290,31 +289,7 @@ gpu_client_tracing_id_( memory_instrumentation::mojom::kServiceTracingProcessId), gpu_memory_buffer_manager_( - new GpuMemoryBufferManagerSingleton(gpu_client_id_)) { - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuShaderDiskCache)) { - DCHECK(GetContentClient()); - base::FilePath cache_dir = - GetContentClient()->browser()->GetShaderDiskCacheDirectory(); - if (!cache_dir.empty()) { - GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - &BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO, - gpu_client_id_, cache_dir)); - } - - base::FilePath gr_cache_dir = - GetContentClient()->browser()->GetGrShaderDiskCacheDirectory(); - if (!gr_cache_dir.empty()) { - GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - &BrowserGpuChannelHostFactory::InitializeGrShaderDiskCacheOnIO, - gr_cache_dir)); - } - } -} + new GpuMemoryBufferManagerSingleton(gpu_client_id_)) {} BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -472,20 +447,4 @@ #endif // BUILDFLAG(IS_ANDROID) } -// static -void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO( - int gpu_client_id, - const base::FilePath& cache_dir) { - GetGpuDiskCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir); - GetGpuDiskCacheFactorySingleton()->SetCacheInfo( - gpu::kDisplayCompositorClientId, cache_dir); -} - -// static -void BrowserGpuChannelHostFactory::InitializeGrShaderDiskCacheOnIO( - const base::FilePath& cache_dir) { - GetGpuDiskCacheFactorySingleton()->SetCacheInfo(gpu::kGrShaderCacheClientId, - cache_dir); -} - } // namespace content
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index 04106e1..a3dfbbaf 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -74,10 +74,6 @@ void GpuChannelEstablished(EstablishRequest* request); void RestartTimeout(); - static void InitializeShaderDiskCacheOnIO(int gpu_client_id, - const base::FilePath& cache_dir); - static void InitializeGrShaderDiskCacheOnIO(const base::FilePath& cache_dir); - const int gpu_client_id_; const uint64_t gpu_client_tracing_id_; scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
diff --git a/content/browser/gpu/gpu_disk_cache_factory.cc b/content/browser/gpu/gpu_disk_cache_factory.cc index e07eafe..e69da52 100644 --- a/content/browser/gpu/gpu_disk_cache_factory.cc +++ b/content/browser/gpu/gpu_disk_cache_factory.cc
@@ -4,6 +4,10 @@ #include "content/browser/gpu/gpu_disk_cache_factory.h" +#include "base/command_line.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/common/content_client.h" +#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/ipc/host/gpu_disk_cache.h" namespace content { @@ -14,7 +18,25 @@ void CreateFactoryInstance() { DCHECK(!factory_instance); - factory_instance = new gpu::GpuDiskCacheFactory(); + // Setup static reserved handles and their mapping to specific paths. + gpu::GpuDiskCacheFactory::HandleToPathMap handle_to_path_map; + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableGpuShaderDiskCache)) { + base::FilePath compositor_cache_dir = + GetContentClient()->browser()->GetShaderDiskCacheDirectory(); + if (!compositor_cache_dir.empty()) { + handle_to_path_map.emplace(gpu::kDisplayCompositorGpuDiskCacheHandle, + compositor_cache_dir); + } + base::FilePath gr_cache_dir = + GetContentClient()->browser()->GetGrShaderDiskCacheDirectory(); + if (!gr_cache_dir.empty()) { + handle_to_path_map.emplace(gpu::kGrShaderGpuDiskCacheHandle, + gr_cache_dir); + } + } + + factory_instance = new gpu::GpuDiskCacheFactory(handle_to_path_map); } } // namespace
diff --git a/content/browser/gpu/peak_gpu_memory_tracker_impl_browsertest.cc b/content/browser/gpu/peak_gpu_memory_tracker_impl_browsertest.cc index 9c1de043..2527ec2 100644 --- a/content/browser/gpu/peak_gpu_memory_tracker_impl_browsertest.cc +++ b/content/browser/gpu/peak_gpu_memory_tracker_impl_browsertest.cc
@@ -59,10 +59,12 @@ void EstablishGpuChannel(int32_t client_id, uint64_t client_tracing_id, bool is_gpu_host, - bool cache_shaders_on_disk, EstablishGpuChannelCallback callback) override {} void SetChannelClientPid(int32_t client_id, base::ProcessId client_pid) override {} + void SetChannelDiskCacheHandle( + int32_t client_id, + const gpu::GpuDiskCacheHandle& handle) override {} void CloseChannel(int32_t client_id) override {} #if BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) @@ -116,9 +118,9 @@ #if BUILDFLAG(IS_WIN) void RequestDXGIInfo(RequestDXGIInfoCallback callback) override {} #endif - void LoadedShader(int32_t client_id, - const std::string& key, - const std::string& data) override {} + void LoadedBlob(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) override {} void WakeUpGpu() override {} void GpuSwitched(gl::GpuPreference active_gpu_heuristic) override {} void DisplayAdded() override {}
diff --git a/content/browser/media/media_internals_audio_focus_helper.cc b/content/browser/media/media_internals_audio_focus_helper.cc index abc3a2fd..bfad6fb 100644 --- a/content/browser/media/media_internals_audio_focus_helper.cc +++ b/content/browser/media/media_internals_audio_focus_helper.cc
@@ -150,19 +150,19 @@ if (!EnsureServiceConnection()) return; - audio_focus_data_.DictClear(); + audio_focus_data_.clear(); request_state_.clear(); // We should go backwards through the stack so the top of the stack is // always shown first in the list. - base::ListValue stack_data; + base::Value::List stack_data; for (const auto& session : base::Reversed(stack)) { if (!session->request_id.has_value()) continue; std::string id_string = session->request_id.value().ToString(); - base::DictionaryValue media_session_data; - media_session_data.SetKey(kAudioFocusIdKey, base::Value(id_string)); + base::Value::Dict media_session_data; + media_session_data.Set(kAudioFocusIdKey, id_string); stack_data.Append(std::move(media_session_data)); request_state_.emplace(id_string, session.Clone()); @@ -174,12 +174,12 @@ base::Unretained(this), id_string)); } - audio_focus_data_.SetKey(kAudioFocusSessionsKey, std::move(stack_data)); + audio_focus_data_.Set(kAudioFocusSessionsKey, std::move(stack_data)); // If the stack is empty then we should send an update to the web ui to clear // the list. if (stack.empty()) - SerializeAndSendUpdate(kAudioFocusFunction, &audio_focus_data_); + SerializeAndSendUpdate(kAudioFocusFunction, audio_focus_data_); } void MediaInternalsAudioFocusHelper::DidGetAudioFocusDebugInfo( @@ -190,36 +190,35 @@ if (!EnsureServiceConnection()) return; - base::Value* sessions_list = - audio_focus_data_.FindKey(kAudioFocusSessionsKey); + base::Value::List* sessions_list = + audio_focus_data_.FindList(kAudioFocusSessionsKey); DCHECK(sessions_list); bool updated = false; - for (auto& session : sessions_list->GetListDeprecated()) { - if (session.FindKey(kAudioFocusIdKey)->GetString() != id) + for (auto& value : *sessions_list) { + base::Value::Dict& session = value.GetDict(); + if (session.Find(kAudioFocusIdKey)->GetString() != id) continue; auto state = request_state_.find(id); DCHECK(state != request_state_.end()); - session.SetKey("name", - base::Value(BuildNameString(state->second, info->name))); - session.SetKey("owner", base::Value(info->owner)); - session.SetKey("state", - base::Value(BuildStateString(state->second, info->state))); + session.Set("name", BuildNameString(state->second, info->name)); + session.Set("owner", info->owner); + session.Set("state", BuildStateString(state->second, info->state)); updated = true; } if (!updated) return; - SerializeAndSendUpdate(kAudioFocusFunction, &audio_focus_data_); + SerializeAndSendUpdate(kAudioFocusFunction, audio_focus_data_); } void MediaInternalsAudioFocusHelper::SerializeAndSendUpdate( - const std::string& function, - const base::Value* value) { - base::ValueView args[] = {*value}; + base::StringPiece function, + const base::Value::Dict& value) { + base::ValueView args[] = {value}; return MediaInternals::GetInstance()->SendUpdate( content::WebUI::GetJavascriptCall(function, args)); }
diff --git a/content/browser/media/media_internals_audio_focus_helper.h b/content/browser/media/media_internals_audio_focus_helper.h index b7b0d85..a2564cf 100644 --- a/content/browser/media/media_internals_audio_focus_helper.h +++ b/content/browser/media/media_internals_audio_focus_helper.h
@@ -56,8 +56,8 @@ const std::string& id, media_session::mojom::MediaSessionDebugInfoPtr info); - void SerializeAndSendUpdate(const std::string& function, - const base::Value* value); + void SerializeAndSendUpdate(base::StringPiece function, + const base::Value::Dict& value); // Build the name of the request to display and inject values from |state|. std::string BuildNameString( @@ -74,7 +74,7 @@ mojo::Remote<media_session::mojom::AudioFocusManagerDebug> audio_focus_debug_; // Must only be accessed on the UI thread. - base::DictionaryValue audio_focus_data_; + base::Value::Dict audio_focus_data_; std::map<std::string, media_session::mojom::AudioFocusRequestStatePtr> request_state_;
diff --git a/content/browser/media/media_internals_cdm_helper.cc b/content/browser/media/media_internals_cdm_helper.cc index 4ca95c3..4f174ae5 100644 --- a/content/browser/media/media_internals_cdm_helper.cc +++ b/content/browser/media/media_internals_cdm_helper.cc
@@ -60,71 +60,69 @@ } } -base::Value VideoCodecProfilesToValue( +base::Value::List VideoCodecProfilesToList( const base::flat_set<media::VideoCodecProfile>& profiles) { - base::Value list(base::Value::Type::LIST); + base::Value::List list; for (const auto& profile : profiles) list.Append(media::GetProfileName(profile)); return list; } -base::Value CdmCapabilityToValue(const media::CdmCapability& cdm_capability) { - base::Value dict(base::Value::Type::DICTIONARY); +base::Value::Dict CdmCapabilityToDict( + const media::CdmCapability& cdm_capability) { + base::Value::Dict dict; - base::Value audio_codec_list(base::Value::Type::LIST); + base::Value::List audio_codec_list; for (const auto& audio_codec : cdm_capability.audio_codecs) audio_codec_list.Append(media::GetCodecName(audio_codec)); - dict.SetKey("Audio Codecs", std::move(audio_codec_list)); + dict.Set("Audio Codecs", std::move(audio_codec_list)); - auto* video_codec_dict = - dict.SetKey("Video Codecs", base::Value(base::Value::Type::DICTIONARY)); + auto* video_codec_dict = dict.EnsureDict("Video Codecs"); for (const auto& [video_codec, video_codec_info] : cdm_capability.video_codecs) { auto codec_name = media::GetCodecName(video_codec); auto& profiles = video_codec_info.supported_profiles; - video_codec_dict->SetPath(codec_name, VideoCodecProfilesToValue(profiles)); + video_codec_dict->Set(codec_name, VideoCodecProfilesToList(profiles)); } - base::Value encryption_scheme_list(base::Value::Type::LIST); + base::Value::List encryption_scheme_list; for (const auto& encryption_scheme : cdm_capability.encryption_schemes) { encryption_scheme_list.Append( media::GetEncryptionSchemeName(encryption_scheme)); } - dict.SetKey("Encryption Schemes", std::move(encryption_scheme_list)); + dict.Set("Encryption Schemes", std::move(encryption_scheme_list)); - base::Value session_type_list(base::Value::Type::LIST); + base::Value::List session_type_list; for (const auto& session_type : cdm_capability.session_types) session_type_list.Append(GetCdmSessionTypeName(session_type)); - dict.SetKey("Session Types", std::move(session_type_list)); + dict.Set("Session Types", std::move(session_type_list)); return dict; } -base::Value CdmInfoToValue(const CdmInfo& cdm_info) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("key_system", cdm_info.key_system); - dict.SetStringKey("robustness", - GetCdmInfoRobustnessName(cdm_info.robustness)); - dict.SetStringKey("name", cdm_info.name); - dict.SetStringKey("version", cdm_info.version.GetString()); - dict.SetStringKey("path", cdm_info.path.AsUTF8Unsafe()); - dict.SetStringKey("status", GetCdmInfoCapabilityStatusName(cdm_info.status)); +base::Value::Dict CdmInfoToDict(const CdmInfo& cdm_info) { + base::Value::Dict dict; + dict.Set("key_system", cdm_info.key_system); + dict.Set("robustness", GetCdmInfoRobustnessName(cdm_info.robustness)); + dict.Set("name", cdm_info.name); + dict.Set("version", cdm_info.version.GetString()); + dict.Set("path", cdm_info.path.AsUTF8Unsafe()); + dict.Set("status", GetCdmInfoCapabilityStatusName(cdm_info.status)); if (cdm_info.capability) { - dict.SetKey("capability", - CdmCapabilityToValue(cdm_info.capability.value())); + dict.Set("capability", CdmCapabilityToDict(cdm_info.capability.value())); } else { // This could happen if hardware secure capabilities are overridden or // hardware video decode is disabled from command line. - dict.SetStringKey("capability", "No Capability"); + dict.Set("capability", "No Capability"); } return dict; } -std::u16string SerializeUpdate(const std::string& function, - const base::Value* value) { - base::ValueView args[] = {*value}; +std::u16string SerializeUpdate(base::StringPiece function, + const base::Value::List& value) { + base::ValueView args[] = {value}; return content::WebUI::GetJavascriptCall(function, args); } @@ -146,14 +144,14 @@ KeySystemCapabilities /*capabilities*/) { auto cdms = CdmRegistryImpl::GetInstance()->GetRegisteredCdms(); - base::Value cdm_list(base::Value::Type::LIST); + base::Value::List cdm_list; for (const auto& cdm_info : cdms) { DCHECK(cdm_info.status != CdmInfo::Status::kUninitialized); - cdm_list.Append(CdmInfoToValue(cdm_info)); + cdm_list.Append(CdmInfoToDict(cdm_info)); } return MediaInternals::GetInstance()->SendUpdate( - SerializeUpdate("media.updateRegisteredCdms", &cdm_list)); + SerializeUpdate("media.updateRegisteredCdms", cdm_list)); } } // namespace content
diff --git a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc index b5428a75..85f7dd2 100644 --- a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc +++ b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc
@@ -80,7 +80,7 @@ // confident that somebody has set it already. DCHECK(child_contents_); - // Start observering our WebContents. Note that this is safe, since we're + // Start observing our WebContents. Note that this is safe, since we're // owned by the opener WebContents. Observe(opener_web_contents_); @@ -121,11 +121,10 @@ } void DocumentPictureInPictureWindowControllerImpl::WebContentsDestroyed() { - // The opener is being destroyed. - - // Stop observing, and forget `opener_web_contents_`. This will also prevent - // `NotifyAndStopObserving` not to try to send messages to the opener, which - // is not safe during teardown. + // The opener web contents are being destroyed. Stop observing, and forget + // `opener_web_contents_`. This will also prevent `NotifyAndStopObserving` + // from trying to send messages to the opener, which is not safe during + // teardown. Observe(/*web_contents=*/nullptr); opener_web_contents_ = nullptr; Close(/*should_pause_video=*/true);
diff --git a/content/browser/preloading/prerender/prerender_host.cc b/content/browser/preloading/prerender/prerender_host.cc index 8d3edd0..7cd9b35 100644 --- a/content/browser/preloading/prerender/prerender_host.cc +++ b/content/browser/preloading/prerender/prerender_host.cc
@@ -23,11 +23,13 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/back_forward_cache.h" #include "content/public/browser/navigation_controller.h" +#include "content/public/browser/prerender_trigger_type.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/referrer.h" #include "net/base/load_flags.h" +#include "net/http/http_request_headers.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/loader/referrer.mojom.h" @@ -330,30 +332,41 @@ DCHECK(navigation_request.IsInPrimaryMainFrame()); // Compare BeginNavigationParams. - if (!AreBeginNavigationParamsCompatibleWithNavigation( - navigation_request.begin_params())) { + ActivationNavigationParamsMatch result = + AreBeginNavigationParamsCompatibleWithNavigation( + navigation_request.begin_params()); + if (result != ActivationNavigationParamsMatch::kOk) { + RecordPrerenderActivationNavigationParamsMatch(result, trigger_type(), + embedder_histogram_suffix()); return false; } // Compare CommonNavigationParams. - if (!AreCommonNavigationParamsCompatibleWithNavigation( - navigation_request.common_params())) { + result = AreCommonNavigationParamsCompatibleWithNavigation( + navigation_request.common_params()); + if (result != ActivationNavigationParamsMatch::kOk) { + RecordPrerenderActivationNavigationParamsMatch(result, trigger_type(), + embedder_histogram_suffix()); return false; } + RecordPrerenderActivationNavigationParamsMatch( + ActivationNavigationParamsMatch::kOk, trigger_type(), + embedder_histogram_suffix()); return true; } -bool PrerenderHost::AreBeginNavigationParamsCompatibleWithNavigation( +PrerenderHost::ActivationNavigationParamsMatch +PrerenderHost::AreBeginNavigationParamsCompatibleWithNavigation( const blink::mojom::BeginNavigationParams& potential_activation) { if (potential_activation.initiator_frame_token != begin_params_->initiator_frame_token) { - return false; + return ActivationNavigationParamsMatch::kInitiatorFrameToken; } if (!AreHttpRequestHeadersCompatible(potential_activation.headers, begin_params_->headers)) { - return false; + return ActivationNavigationParamsMatch::kHttpRequestHeader; } // Don't activate a prerendered page if the potential activation request @@ -365,37 +378,37 @@ int cache_load_flags = net::LOAD_VALIDATE_CACHE | net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; if (potential_activation.load_flags & cache_load_flags) { - return false; + return ActivationNavigationParamsMatch::kCacheLoadFlags; } if (potential_activation.load_flags != begin_params_->load_flags) { - return false; + return ActivationNavigationParamsMatch::kLoadFlags; } if (potential_activation.skip_service_worker != begin_params_->skip_service_worker) { - return false; + return ActivationNavigationParamsMatch::kSkipServiceWorker; } if (potential_activation.mixed_content_context_type != begin_params_->mixed_content_context_type) { - return false; + return ActivationNavigationParamsMatch::kMixedContentContextType; } // Initial prerender navigation cannot be a form submission. DCHECK(!begin_params_->is_form_submission); if (potential_activation.is_form_submission != begin_params_->is_form_submission) { - return false; + return ActivationNavigationParamsMatch::kIsFormSubmission; } if (potential_activation.searchable_form_url != begin_params_->searchable_form_url) { - return false; + return ActivationNavigationParamsMatch::kSearchableFormUrl; } if (potential_activation.searchable_form_encoding != begin_params_->searchable_form_encoding) { - return false; + return ActivationNavigationParamsMatch::kSearchableFormEncoding; } // Trust token params can be set only on subframe navigations, so both values @@ -403,14 +416,14 @@ DCHECK(!begin_params_->trust_token_params); if (potential_activation.trust_token_params != begin_params_->trust_token_params) { - return false; + return ActivationNavigationParamsMatch::kTrustTokenParams; } // Web bundle token cannot be set due because it is only set for child // frame navigations. DCHECK(!begin_params_->web_bundle_token); if (potential_activation.web_bundle_token) { - return false; + return ActivationNavigationParamsMatch::kWebBundleToken; } // Don't require equality for request_context_type because link clicks @@ -423,23 +436,24 @@ case blink::mojom::RequestContextType::LOCATION: break; default: - return false; + return ActivationNavigationParamsMatch::kRequestContextType; } // Since impression should not be set, no need to compare contents. DCHECK(!begin_params_->impression); if (potential_activation.impression.has_value()) { - return false; + return ActivationNavigationParamsMatch::kImpressionHasValue; } // No need to test for devtools_initiator because this field is used for // tracking what triggered a network request, and prerender activation will // not use network requests. - return true; + return ActivationNavigationParamsMatch::kOk; } -bool PrerenderHost::AreCommonNavigationParamsCompatibleWithNavigation( +PrerenderHost::ActivationNavigationParamsMatch +PrerenderHost::AreCommonNavigationParamsCompatibleWithNavigation( const blink::mojom::CommonNavigationParams& potential_activation) { // The CommonNavigationParams::url field is expected to be the same for both // initial and activation prerender navigations, as the PrerenderHost @@ -453,17 +467,17 @@ } if (potential_activation.initiator_origin != common_params_->initiator_origin) { - return false; + return ActivationNavigationParamsMatch::kInitiatorOrigin; } if (potential_activation.transition != common_params_->transition) { - return false; + return ActivationNavigationParamsMatch::kTransition; } DCHECK_EQ(common_params_->navigation_type, blink::mojom::NavigationType::DIFFERENT_DOCUMENT); if (potential_activation.navigation_type != common_params_->navigation_type) { - return false; + return ActivationNavigationParamsMatch::kNavigationType; } // We don't check download_policy as it affects whether the download triggered @@ -477,21 +491,20 @@ DCHECK(common_params_->base_url_for_data_url.is_empty()); if (potential_activation.base_url_for_data_url != common_params_->base_url_for_data_url) { - return false; + return ActivationNavigationParamsMatch::kBaseUrlForDataUrl; } - // The previews_state is always set to NO_PREVIEWS in BeginNavigation and the - // previews code was removed, so no need to compare it here as it's not used. - // TODO(crbug.com/1232909): remove this previews_state. - + // TODO(crbug.com/1352891): This if branch should be removed because method + // parameter change is detected earlier by checking the HTTP request headers + // changes. if (potential_activation.method != common_params_->method) { - return false; + return ActivationNavigationParamsMatch::kHttpRequestHeader; } // Initial prerender navigation can't be a form submission. DCHECK(!common_params_->post_data); if (potential_activation.post_data != common_params_->post_data) { - return false; + return ActivationNavigationParamsMatch::kPostData; } // No need to compare source_location, as it's only passed to the DevTools for @@ -501,7 +514,7 @@ DCHECK(!common_params_->started_from_context_menu); if (potential_activation.started_from_context_menu != common_params_->started_from_context_menu) { - return false; + return ActivationNavigationParamsMatch::kStartedFromContextMenu; } // has_user_gesture doesn't affect any of the security properties of the @@ -522,18 +535,18 @@ if (potential_activation.initiator_origin_trial_features != common_params_->initiator_origin_trial_features) { - return false; + return ActivationNavigationParamsMatch::kInitiatorOriginTrialFeature; } if (potential_activation.href_translate != common_params_->href_translate) { - return false; + return ActivationNavigationParamsMatch::kHrefTranslate; } // Initial prerender navigation can't be a history navigation. DCHECK(!common_params_->is_history_navigation_in_new_child_frame); if (potential_activation.is_history_navigation_in_new_child_frame != common_params_->is_history_navigation_in_new_child_frame) { - return false; + return ActivationNavigationParamsMatch::kIsHistoryNavigationInNewChildFrame; } // The spec mandates matching the referrer policy, and not the referrer URL @@ -542,15 +555,15 @@ // https://wicg.github.io/nav-speculation/prerendering.html#navigate-activation if (potential_activation.referrer->policy != common_params_->referrer->policy) { - return false; + return ActivationNavigationParamsMatch::kReferrerPolicy; } if (potential_activation.request_destination != common_params_->request_destination) { - return false; + return ActivationNavigationParamsMatch::kRequestDestination; } - return true; + return ActivationNavigationParamsMatch::kOk; } RenderFrameHostImpl* PrerenderHost::GetPrerenderedMainFrameHost() {
diff --git a/content/browser/preloading/prerender/prerender_host.h b/content/browser/preloading/prerender/prerender_host.h index 2379510..c5828a9 100644 --- a/content/browser/preloading/prerender/prerender_host.h +++ b/content/browser/preloading/prerender/prerender_host.h
@@ -101,6 +101,39 @@ kMaxValue = kDataSaverEnabled, }; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. This enum corresponds to + // PrerenderActivationNavigationParamsMatch in + // tools/metrics/histograms/test_data/enums.xml + enum class ActivationNavigationParamsMatch { + kOk = 0, + kInitiatorFrameToken = 1, + kHttpRequestHeader = 2, + kCacheLoadFlags = 3, + kLoadFlags = 4, + kSkipServiceWorker = 5, + kMixedContentContextType = 6, + kIsFormSubmission = 7, + kSearchableFormUrl = 8, + kSearchableFormEncoding = 9, + kTrustTokenParams = 10, + kWebBundleToken = 11, + kRequestContextType = 12, + kImpressionHasValue = 13, + kInitiatorOrigin = 14, + kTransition = 15, + kNavigationType = 16, + kBaseUrlForDataUrl = 17, + kPostData = 18, + kStartedFromContextMenu = 19, + kInitiatorOriginTrialFeature = 20, + kHrefTranslate = 21, + kIsHistoryNavigationInNewChildFrame = 22, + kReferrerPolicy = 23, + kRequestDestination = 24, + kMaxValue = kRequestDestination, + }; + PrerenderHost(const PrerenderAttributes& attributes, WebContents& web_contents, base::WeakPtr<PreloadingAttempt> attempt); @@ -221,9 +254,11 @@ void SetEligibility(PreloadingEligibility eligibility); void SetFailureReason(FinalStatus status); - bool AreBeginNavigationParamsCompatibleWithNavigation( + ActivationNavigationParamsMatch + AreBeginNavigationParamsCompatibleWithNavigation( const blink::mojom::BeginNavigationParams& potential_activation); - bool AreCommonNavigationParamsCompatibleWithNavigation( + ActivationNavigationParamsMatch + AreCommonNavigationParamsCompatibleWithNavigation( const blink::mojom::CommonNavigationParams& potential_activation); const PrerenderAttributes attributes_;
diff --git a/content/browser/preloading/prerender/prerender_host_registry_unittest.cc b/content/browser/preloading/prerender/prerender_host_registry_unittest.cc index 9fd569f..fc0a0c2 100644 --- a/content/browser/preloading/prerender/prerender_host_registry_unittest.cc +++ b/content/browser/preloading/prerender/prerender_host_registry_unittest.cc
@@ -252,6 +252,23 @@ status, 1); } + void ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch result) { + histogram_tester_.ExpectUniqueSample( + "Prerender.Experimental.ActivationNavigationParamsMatch." + "SpeculationRule", + result, 1); + } + + void ExpectBucketCountOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch result, + base::HistogramBase::Count count) { + histogram_tester_.ExpectBucketCount( + "Prerender.Experimental.ActivationNavigationParamsMatch." + "SpeculationRule", + result, count); + } + private: base::test::ScopedFeatureList scoped_feature_list_; PrerenderWebContentsDelegate web_contents_delegate_; @@ -766,6 +783,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { // Do not change any params, so activation happens. }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kOk); } TEST_F(PrerenderHostRegistryTest, @@ -776,6 +795,8 @@ navigation->SetInitiatorFrame(nullptr); navigation->set_initiator_origin(url::Origin::Create(kOriginalUrl)); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kInitiatorFrameToken); } TEST_F(PrerenderHostRegistryTest, @@ -784,6 +805,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_request_headers("User-Agent: Test"); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kHttpRequestHeader); } // Tests that the Purpose header is ignored when comparing request headers. @@ -792,6 +815,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_request_headers("Purpose: Test"); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kOk); } TEST_F(PrerenderHostRegistryTest, @@ -800,6 +825,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_load_flags(net::LOAD_ONLY_FROM_CACHE); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kLoadFlags); // If the potential activation request requires validation or bypass of the // browser cache, the prerendered page should not be activated. @@ -815,6 +842,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_load_flags(net::LOAD_DISABLE_CACHE); }))); + ExpectBucketCountOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kCacheLoadFlags, 3); } TEST_F(PrerenderHostRegistryTest, @@ -823,6 +852,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_skip_service_worker(true); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kSkipServiceWorker); } TEST_F(PrerenderHostRegistryTest, @@ -832,6 +863,8 @@ navigation->set_mixed_content_context_type( blink::mojom::MixedContentContextType::kNotMixedContent); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kMixedContentContextType); } TEST_F(PrerenderHostRegistryTest, @@ -840,6 +873,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->SetIsFormSubmission(true); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kIsFormSubmission); } TEST_F(PrerenderHostRegistryTest, @@ -849,6 +884,8 @@ const GURL kOriginalUrl("https://example.com/"); navigation->set_searchable_form_url(kOriginalUrl); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kSearchableFormUrl); } TEST_F(PrerenderHostRegistryTest, @@ -857,6 +894,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_searchable_form_encoding("Test encoding"); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kSearchableFormEncoding); } TEST_F(PrerenderHostRegistryTest, @@ -865,6 +904,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_initiator_origin(url::Origin()); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kInitiatorOrigin); } TEST_F(PrerenderHostRegistryTest, @@ -877,6 +918,8 @@ navigation->set_should_check_main_world_csp( network::mojom::CSPDisposition::DO_NOT_CHECK); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kOk); } TEST_F(PrerenderHostRegistryTest, @@ -885,6 +928,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->SetMethod("POST"); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kHttpRequestHeader); } TEST_F(PrerenderHostRegistryTest, @@ -893,6 +938,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->set_href_translate("test"); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kHrefTranslate); } TEST_F(PrerenderHostRegistryTest, @@ -901,6 +948,8 @@ base::BindLambdaForTesting([](NavigationSimulatorImpl* navigation) { navigation->SetTransition(ui::PAGE_TRANSITION_FORM_SUBMIT); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kTransition); } TEST_F(PrerenderHostRegistryTest, @@ -910,6 +959,8 @@ navigation->set_request_context_type( blink::mojom::RequestContextType::AUDIO); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kRequestContextType); } TEST_F(PrerenderHostRegistryTest, @@ -920,6 +971,8 @@ web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL(), network::mojom::ReferrerPolicy::kAlways)); }))); + ExpectUniqueSampleOfActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch::kReferrerPolicy); } // End navigation parameter matching tests ---------
diff --git a/content/browser/preloading/prerender/prerender_metrics.cc b/content/browser/preloading/prerender/prerender_metrics.cc index 2b22f880..692d9ac 100644 --- a/content/browser/preloading/prerender/prerender_metrics.cc +++ b/content/browser/preloading/prerender/prerender_metrics.cc
@@ -130,4 +130,15 @@ } } +void RecordPrerenderActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch result, + PrerenderTriggerType trigger_type, + const std::string& embedder_suffix) { + base::UmaHistogramEnumeration( + GenerateHistogramName( + "Prerender.Experimental.ActivationNavigationParamsMatch", + trigger_type, embedder_suffix), + result); +} + } // namespace content
diff --git a/content/browser/preloading/prerender/prerender_metrics.h b/content/browser/preloading/prerender/prerender_metrics.h index cc8fed1..c2ca65d 100644 --- a/content/browser/preloading/prerender/prerender_metrics.h +++ b/content/browser/preloading/prerender/prerender_metrics.h
@@ -48,6 +48,13 @@ const PrerenderAttributes& attributes, ukm::SourceId prerendered_ukm_id); +// Records which navigation parameters are different between activation and +// initial prerender navigation when activation fails. +void RecordPrerenderActivationNavigationParamsMatch( + PrerenderHost::ActivationNavigationParamsMatch result, + PrerenderTriggerType trigger_type, + const std::string& embedder_suffix); + } // namespace content #endif // CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_METRICS_H_
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 42024d1..9cfb0528 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -6071,6 +6071,9 @@ const GURL& blocked_url, const GURL& initiator_url, blink::mojom::NavigationBlockedReason reason) { + // Cross-origin navigations are not allowed in prerendering so we can not + // reach here while prerendering. + DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPrerendering); delegate_->OnDidBlockNavigation(blocked_url, initiator_url, reason); }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index fe9c77d..449c321 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -295,16 +295,6 @@ RenderProcessHost::AnalyzeHungRendererFunction g_analyze_hung_renderer = nullptr; -void CacheShaderInfo(int32_t id, base::FilePath path) { - if (GetGpuDiskCacheFactorySingleton()) - GetGpuDiskCacheFactorySingleton()->SetCacheInfo(id, path); -} - -void RemoveShaderInfo(int32_t id) { - if (GetGpuDiskCacheFactorySingleton()) - GetGpuDiskCacheFactorySingleton()->RemoveCacheInfo(id); -} - // the global list of all renderer processes base::IDMap<RenderProcessHost*>& GetAllHosts() { static base::NoDestructor<base::IDMap<RenderProcessHost*>> s_all_hosts; @@ -1521,12 +1511,6 @@ // Initialize |child_process_activity_time_| to a reasonable value. mark_child_process_activity_time(); - if (!GetBrowserContext()->IsOffTheRecord() && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuShaderDiskCache)) { - CacheShaderInfo(GetID(), storage_partition_impl_->GetPath()); - } - // This instance of PushMessagingManager is only used from clients // bound to service workers (i.e. PushProvider), since frame-bound // clients will rely on BrowserInterfaceBroker instead. Therefore, @@ -1544,6 +1528,22 @@ gpu_client_.reset( new viz::GpuClient(std::make_unique<BrowserGpuClientDelegate>(), id, tracing_id, GetUIThreadTaskRunner({}))); + + // Set cache information after the GpuClient has been initialized. Note that + // we also check if the factory is initialized because in tests the factory + // may never have been initialized properly. + if (!GetBrowserContext()->IsOffTheRecord() && + !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableGpuShaderDiskCache)) { + if (auto* cache_factory = GetGpuDiskCacheFactorySingleton()) { + for (const gpu::GpuDiskCacheType type : gpu::kGpuDiskCacheTypes) { + auto handle = cache_factory->GetCacheHandle( + type, storage_partition_impl_->GetPath().Append( + gpu::GetGpuDiskCacheSubdir(type))); + gpu_client_->SetDiskCacheHandle(handle); + } + } + } } // static @@ -1620,9 +1620,9 @@ UnregisterHost(GetID()); - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuShaderDiskCache)) { - RemoveShaderInfo(GetID()); + // Remove the cache handles for the client at teardown if relevant. + if (GetGpuDiskCacheFactorySingleton()) { + gpu_client_->RemoveDiskCacheHandles(); } // "Cleanup in progress"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 6cb172a..311dd90 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1005,8 +1005,6 @@ } visual_properties.is_fullscreen_granted = delegate_->IsFullscreen(); - visual_properties.window_controls_overlay_rect = - delegate_->GetWindowsControlsOverlayRect(); if (is_frame_widget) visual_properties.display_mode = delegate_->GetDisplayMode(); @@ -1083,6 +1081,8 @@ if (is_top_most_widget) { visual_properties.compositor_viewport_pixel_rect = gfx::Rect(view_->GetCompositorViewportPixelSize()); + visual_properties.window_controls_overlay_rect = + delegate_->GetWindowsControlsOverlayRect(); } else { visual_properties.compositor_viewport_pixel_rect = properties_from_parent_local_root_.compositor_viewport;
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index 2b89dfe..92e9d561 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" #include "components/offline_pages/buildflags/buildflags.h" #include "content/browser/loader/navigation_url_loader_impl.h" @@ -24,6 +25,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" +#include "content/public/common/content_features.h" #include "net/base/load_flags.h" #include "net/base/url_util.h" #include "services/network/public/cpp/resource_request_body.h" @@ -62,6 +64,24 @@ } #endif // BUILDFLAG(ENABLE_OFFLINE_PAGES) +void RecordSkipReason( + ServiceWorkerControlleeRequestHandler::FetchHandlerSkipReason skip_reason) { + base::UmaHistogramEnumeration("ServiceWorker.FetchHandler.SkipReason", + skip_reason); +} + +const char* FetchHandlerTypeToString( + ServiceWorkerVersion::FetchHandlerType type) { + switch (type) { + case ServiceWorkerVersion::FetchHandlerType::kNoHandler: + return "no handler"; + case ServiceWorkerVersion::FetchHandlerType::kNotSkippable: + return "not skippable"; + case ServiceWorkerVersion::FetchHandlerType::kEmptyFetchHandler: + return "empty fetch handler"; + } +} + } // namespace ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler( @@ -410,6 +430,8 @@ if (active_version->fetch_handler_existence() != ServiceWorkerVersion::FetchHandlerExistence::EXISTS) { + RecordSkipReason(FetchHandlerSkipReason::kNoFetchHandler); + TRACE_EVENT_WITH_FLOW1( "ServiceWorker", "ServiceWorkerControlleeRequestHandler::ContinueWithActivatedVersion", @@ -420,6 +442,24 @@ return; } + if (features::kSkipEmptyFetchHandler.Get() && + active_version->fetch_handler_type() == + ServiceWorkerVersion::FetchHandlerType::kEmptyFetchHandler) { + RecordSkipReason(FetchHandlerSkipReason::kSkippedForEmptyFetchHandler); + + TRACE_EVENT_WITH_FLOW2( + "ServiceWorker", + "ServiceWorkerControlleeRequestHandler::ContinueWithActivatedVersion", + TRACE_ID_LOCAL(this), + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "Info", + "The fetch handler is skippable. Falling back to network", + "FetchHandlerType", + FetchHandlerTypeToString(active_version->fetch_handler_type())); + CompleteWithoutLoader(); + return; + } + RecordSkipReason(FetchHandlerSkipReason::kNotSkipped); + // Finally, we want to forward to the service worker! Make a // ServiceWorkerMainResourceLoader which does that work. loader_wrapper_ = std::make_unique<ServiceWorkerMainResourceLoaderWrapper>(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h index 4f19252..28dc933 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.h +++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -43,6 +43,16 @@ // ServiceWorkerMainResourceLoader to perform the resource load. class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler final { public: + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class FetchHandlerSkipReason { + kNoFetchHandler = 0, + kNotSkipped = 1, + kSkippedForEmptyFetchHandler = 2, + + kMaxValue = kSkippedForEmptyFetchHandler, + }; + // If |skip_service_worker| is true, service workers are bypassed for // request interception. ServiceWorkerControlleeRequestHandler(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc index fe8050d..4356a04c 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -12,6 +12,8 @@ #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "components/offline_pages/buildflags/buildflags.h" #include "content/browser/service_worker/embedded_worker_test_helper.h" #include "content/browser/service_worker/service_worker_container_host.h" @@ -467,6 +469,90 @@ EXPECT_EQ(GURL("https://host/scope/doc"), container_host_->url()); } +class ServiceWorkerSkipEmptyFetchHandlerTest + : public ServiceWorkerControlleeRequestHandlerTest { + public: + ServiceWorkerSkipEmptyFetchHandlerTest() { + scoped_feature_list_.InitFromCommandLine( + "ServiceWorkerSkipIgnorableFetchHandler:SkipEmptyFetchHandler/true", + ""); + } + ~ServiceWorkerSkipEmptyFetchHandlerTest() override = default; + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(ServiceWorkerSkipEmptyFetchHandlerTest, HasNotSkippedMetrics) { + base::HistogramTester tester; + + version_->set_fetch_handler_type( + ServiceWorkerVersion::FetchHandlerType::kNotSkippable); + version_->SetStatus(ServiceWorkerVersion::ACTIVATED); + registration_->SetWaitingVersion(version_); + base::RunLoop loop; + context()->registry()->StoreRegistration( + registration_.get(), version_.get(), + base::BindLambdaForTesting( + [&loop](blink::ServiceWorkerStatusCode status) { loop.Quit(); })); + loop.Run(); + + // Conduct a main resource load. + ServiceWorkerRequestTestResources test_resources( + this, GURL("https://host/scope/doc"), + network::mojom::RequestDestination::kDocument); + test_resources.MaybeCreateLoader(); + EXPECT_FALSE(test_resources.loader()); + EXPECT_FALSE(version_->HasControllee()); + + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(test_resources.loader()); + EXPECT_TRUE(version_->HasControllee()); + tester.ExpectUniqueSample("ServiceWorker.FetchHandler.SkipReason", + ServiceWorkerControlleeRequestHandler:: + FetchHandlerSkipReason::kNotSkipped, + 1); + + test_resources.ResetHandler(); +} + +TEST_F(ServiceWorkerSkipEmptyFetchHandlerTest, + HasSkippedForEmptyFetchHandlerMetrics) { + base::HistogramTester tester; + + version_->set_fetch_handler_type( + ServiceWorkerVersion::FetchHandlerType::kEmptyFetchHandler); + version_->SetStatus(ServiceWorkerVersion::ACTIVATED); + registration_->SetWaitingVersion(version_); + base::RunLoop loop; + context()->registry()->StoreRegistration( + registration_.get(), version_.get(), + base::BindLambdaForTesting( + [&loop](blink::ServiceWorkerStatusCode status) { loop.Quit(); })); + loop.Run(); + + // Conduct a main resource load. + ServiceWorkerRequestTestResources test_resources( + this, GURL("https://host/scope/doc"), + network::mojom::RequestDestination::kDocument); + test_resources.MaybeCreateLoader(); + EXPECT_FALSE(test_resources.loader()); + EXPECT_FALSE(version_->HasControllee()); + + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(test_resources.loader()); + EXPECT_TRUE(version_->HasControllee()); + tester.ExpectUniqueSample( + "ServiceWorker.FetchHandler.SkipReason", + ServiceWorkerControlleeRequestHandler::FetchHandlerSkipReason:: + kSkippedForEmptyFetchHandler, + 1); + + test_resources.ResetHandler(); +} + #if BUILDFLAG(ENABLE_OFFLINE_PAGES) TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithOfflineHeader) { version_->set_fetch_handler_type(
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 1c12459c..ed2ca33 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -2506,11 +2506,16 @@ GetGpuDiskCacheFactorySingleton(); // May be null in tests where it is difficult to plumb through a test // storage partition. - if (gpu_cache_factory) { - gpu_cache_factory->ClearByPath( - path, begin, end, - base::BindOnce(&ClearedGpuCache, CreateTaskCompletionClosure( - TracingDataType::kGpuCache))); + if (!path.empty() && gpu_cache_factory) { + // Clear the path for all the different GPU cache sub-types. + base::RepeatingClosure barrier = base::BarrierClosure( + gpu::kGpuDiskCacheTypes.size(), + CreateTaskCompletionClosure(TracingDataType::kGpuCache)); + for (gpu::GpuDiskCacheType type : gpu::kGpuDiskCacheTypes) { + gpu_cache_factory->ClearByPath( + path.Append(gpu::GetGpuDiskCacheSubdir(type)), begin, end, + base::BindOnce(&ClearedGpuCache, barrier)); + } } }
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 2aea21f..4e283a23 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -106,7 +106,6 @@ namespace content { namespace { -const int kDefaultClientId = 42; const char kCacheKey[] = "key"; const char kCacheValue[] = "cached value"; @@ -756,16 +755,16 @@ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), browser_context_(new TestBrowserContext()) { InitGpuDiskCacheFactorySingleton(); - GetGpuDiskCacheFactorySingleton()->SetCacheInfo( - kDefaultClientId, - browser_context()->GetDefaultStoragePartition()->GetPath()); - cache_ = GetGpuDiskCacheFactorySingleton()->Get(kDefaultClientId); + + gpu::GpuDiskCacheType type = gpu::GpuDiskCacheType::kGlShaders; + auto handle = GetGpuDiskCacheFactorySingleton()->GetCacheHandle( + type, browser_context()->GetDefaultStoragePartition()->GetPath().Append( + gpu::GetGpuDiskCacheSubdir(type))); + cache_ = + GetGpuDiskCacheFactorySingleton()->Create(handle, base::DoNothing()); } - ~StoragePartitionShaderClearTest() override { - cache_ = nullptr; - GetGpuDiskCacheFactorySingleton()->RemoveCacheInfo(kDefaultClientId); - } + ~StoragePartitionShaderClearTest() override { cache_ = nullptr; } void InitCache() { net::TestCompletionCallback available_cb;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 7f60d03..3e2342d2 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -125,10 +125,18 @@ // Listens to all mouse drag events during a drag and drop and sends them to // the renderer. -class WebDragSourceAura : public content::WebContentsObserver { +class WebDragSourceAura : public content::WebContentsObserver, + public aura::WindowObserver { public: WebDragSourceAura(aura::Window* window, WebContentsImpl* contents) - : WebContentsObserver(contents), window_(window) {} + : WebContentsObserver(contents), window_(window) { + window_->AddObserver(this); + } + + ~WebDragSourceAura() override { + if (window_) + window_->RemoveObserver(this); + } WebDragSourceAura(const WebDragSourceAura&) = delete; WebDragSourceAura& operator=(const WebDragSourceAura&) = delete; @@ -141,6 +149,15 @@ void WebContentsDestroyed() override { CancelDrag(); } + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override { + window_->RemoveObserver(this); + window_ = nullptr; + } + + aura::Window* window() const { return window_; } + + private: void CancelDrag() { if (!window_) return; @@ -148,15 +165,14 @@ // Cancel the drag if it is still in progress. aura::client::DragDropClient* dnd_client = aura::client::GetDragDropClient(window_->GetRootWindow()); + + window_->RemoveObserver(this); + window_ = nullptr; + if (dnd_client && dnd_client->IsDragDropInProgress()) dnd_client->DragCancel(); - - window_ = nullptr; } - aura::Window* window() const { return window_; } - - private: raw_ptr<aura::Window> window_; };
diff --git a/content/browser/web_package/web_bundle_network_browsertest.cc b/content/browser/web_package/web_bundle_network_browsertest.cc index 52c7f3bef..019fc1d61 100644 --- a/content/browser/web_package/web_bundle_network_browsertest.cc +++ b/content/browser/web_package/web_bundle_network_browsertest.cc
@@ -326,7 +326,7 @@ TestNavigationFailure(embedded_test_server()->GetURL(wbn_path), "Failed to read metadata of Web Bundle file: Wrong " - "CBOR array size of the top-level structure"); + "magic bytes."); } IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest, DataDecoderRestart) { @@ -676,8 +676,7 @@ SetContents("This is an invalid Web Bundle file."); HistoryBackAndWaitUntilConsoleError( - "Failed to read metadata of Web Bundle file: Wrong CBOR array size of " - "the top-level structure"); + "Failed to read metadata of Web Bundle file: Wrong magic bytes."); } IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc index f478ccb4..e445a62 100644 --- a/content/browser/webauth/webauth_browsertest.cc +++ b/content/browser/webauth/webauth_browsertest.cc
@@ -1596,6 +1596,46 @@ ASSERT_EQ(kExcludeCredentialsRangeErrorMessage, *result); } +// No `kAndroidAccessory` on Windows. +#if !BUILDFLAG(IS_WIN) +IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest, + DuplicateTransportStrings) { + // By setting the transport to `kAndroidAccessory`, and having explicit + // transports in the getInfo of ['hybrid', 'internal'], this test confirms + // that 'hybrid' doesn't get included twice. Since `kAndroidAccessory` and + // `kHybrid` are different values that both happen to get converted to the + // string "hybrid", this requires deduplication. + device::test::VirtualFidoDeviceFactory* virtual_device_factory = + InjectVirtualFidoDeviceFactory(); + virtual_device_factory->SetTransport( + device::FidoTransportProtocol::kAndroidAccessory); + device::VirtualCtap2Device::Config config; + config.transports_in_get_info = {device::FidoTransportProtocol::kHybrid, + device::FidoTransportProtocol::kInternal}; + config.include_transports_in_attestation_certificate = false; + virtual_device_factory->SetCtap2Config(config); + + EXPECT_TRUE( + NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"))); + + CreateParameters parameters; + constexpr char kJavascript[] = + "navigator.credentials.create({ publicKey: {" + " challenge: new TextEncoder().encode('climb a mountain')," + " rp: { id: 'www.acme.com', name: 'name' }," + " user: { id: new Uint8Array([0]), name: 'name', displayName: 'dn' }," + " pubKeyCredParams: [{ type: 'public-key', alg: '-7'}]," + "}}).then(c => window.domAutomationController.send(" + " 'webauth: ' + c.response.getTransports())," + " e => window.domAutomationController.send(" + " 'webauth: ' + e.toString()));"; + absl::optional<std::string> result = ExecuteScriptAndExtractPrefixedString( + shell()->web_contents(), kJavascript, "webauth: "); + ASSERT_TRUE(result); + EXPECT_EQ(result, "webauth: hybrid,internal"); +} +#endif + class WebAuthLocalClientBackForwardCacheBrowserTest : public WebAuthLocalClientBrowserTest { protected:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 701aee4..1d8a6de 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -804,6 +804,20 @@ const base::Feature kSkipEarlyCommitPendingForCrashedFrame{ "SkipEarlyCommitPendingForCrashedFrame", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables skipping the service worker fetch handler if the fetch handler is +// identified as ignorable. +const base::Feature kServiceWorkerSkipIgnorableFetchHandler{ + "ServiceWorkerSkipIgnorableFetchHandler", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// This feature param controls if the empty service worker fetch handler is +// skipped. +constexpr base::FeatureParam<bool> kSkipEmptyFetchHandler{ + &kServiceWorkerSkipIgnorableFetchHandler, + "SkipEmptyFetchHandler", + false, +}; + // Run video capture service in the Browser process as opposed to a dedicated // utility process const base::Feature kRunVideoCaptureServiceInBrowserProcess{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index f256351..95586c2 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -235,6 +235,9 @@ CONTENT_EXPORT extern const base::Feature kDisableProcessReuse; CONTENT_EXPORT extern const base::Feature kSkipEarlyCommitPendingForCrashedFrame; +CONTENT_EXPORT extern const base::Feature + kServiceWorkerSkipIgnorableFetchHandler; +CONTENT_EXPORT extern const base::FeatureParam<bool> kSkipEmptyFetchHandler; CONTENT_EXPORT extern const base::Feature kUserMediaCaptureOnFocus; CONTENT_EXPORT extern const base::Feature kWebLockScreenApi; CONTENT_EXPORT extern const base::Feature kWebOTP;
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 02f708b..2f370b1c 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -111,6 +111,16 @@ crbug.com/1161570 [ mac nvidia debug ] GpuCrash_InfoForHardwareGpu [ Skip ] crbug.com/1161570 [ mac nvidia debug ] GpuCrash_InfoForDualHardwareGpus [ Skip ] +# Flaky hangs on Mac Debug Intel. Attempted to suppress with +# RetryOnFailure, but test was persistently flaky. Test is reliable in +# Release mode, and no root cause was obvious, so permanently skipping +# on this configuration. +crbug.com/1297151 [ mac intel debug ] GpuCrash_InfoForHardwareGpu [ Skip ] + +# Flaky hangs on Mac Debug AMD, stalling the test suite for 60 minutes. +crbug.com/1327754 [ mac amd debug ] GpuCrash_InfoForHardwareGpu [ Skip ] +crbug.com/1327754 [ mac amd debug ] GpuCrash_InfoForDualHardwareGpus [ Skip ] + # Vulkan enabled on linux, the crash fallback logic is different. crbug.com/1334650 [ linux ] GpuCrash_InfoForHardwareGpu [ Skip ] @@ -130,10 +140,6 @@ crbug.com/923134 [ mac ] ContextLost_WebGL2Blocked [ Skip ] crbug.com/923134 [ android ] ContextLost_WebGL2Blocked [ Skip ] -# Flaky hangs on Mac Debug AMD, stalling the test suite for 60 minutes. -crbug.com/1327754 [ mac amd debug ] GpuCrash_InfoForHardwareGpu [ Skip ] -crbug.com/1327754 [ mac amd debug ] GpuCrash_InfoForDualHardwareGpus [ Skip ] - ################### # Failures/Flakes # ################### @@ -145,7 +151,6 @@ # Flaking on Mac / Linux crbug.com/1284424 [ mac ] ContextLost_WebGPUStressRequestDeviceAndRemoveLoop [ RetryOnFailure ] crbug.com/1284424 [ linux ] ContextLost_WebGPUStressRequestDeviceAndRemoveLoop [ RetryOnFailure ] -crbug.com/1338955 [ mac debug intel-0x3e9b passthrough ] GpuCrash_InfoForHardwareGpu [ RetryOnFailure ] # Flaking on Nexus 5X crbug.com/965268 [ android android-nexus-5x ] ContextLost_WebGLBlockedAfterJSNavigation [ Failure ] @@ -163,9 +168,6 @@ crbug.com/1205899 [ linux display-server-wayland ] ContextLost_WebGLBlockedAfterJSNavigation [ RetryOnFailure ] crbug.com/1337793 [ linux display-server-wayland ] ContextLost_WebGLContextLostOverlyLargeUniform [ Failure ] -# GpuCrash_Info* flakes on Mac Debug (AMD, Intel) -crbug.com/1297151 [ mac intel debug no-passthrough ] GpuCrash_InfoForHardwareGpu [ RetryOnFailure ] - # Flaky on Fuchsia crbug.com/1302749 [ fuchsia ] ContextLost_WebGLContextLostFromQuantity [ RetryOnFailure ]
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index cb35473..8fbec391 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -737,13 +737,13 @@ deps += [ "//ash/components/audio", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", "//chromeos/ash/components/dbus/cec_service", "//chromeos/ash/components/dbus/media_analytics", "//chromeos/ash/components/dbus/media_analytics:media_perception_proto", "//chromeos/ash/components/dbus/upstart", "//chromeos/ash/components/network", - "//chromeos/dbus:test_support", "//chromeos/dbus/permission_broker", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", @@ -984,13 +984,13 @@ "//chrome/browser/ash/crosapi:browser_util", "//chrome/common:constants", "//chromeos:test_support", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", "//chromeos/ash/components/dbus/media_analytics", "//chromeos/ash/components/dbus/media_analytics:media_perception_proto", "//chromeos/ash/components/dbus/shill", "//chromeos/ash/components/dbus/upstart", "//chromeos/ash/components/network:test_support", - "//chromeos/dbus:test_support", "//chromeos/dbus/permission_broker", "//chromeos/dbus/power", "//chromeos/login/login_state",
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc index 16d6707..a3ff2ff 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc
@@ -597,15 +597,13 @@ bool include_empty) { std::set<std::string> result; - const base::Value* items = - local_state_->GetDictionary(kLockScreenDataPrefKey); - if (!items) - return result; - const base::Value* user_data = items->FindDictPath(user_id_); + const base::Value::Dict& items = + local_state_->GetValueDict(kLockScreenDataPrefKey); + const base::Value::Dict* user_data = items.FindDictByDottedPath(user_id_); if (!user_data) return result; - for (auto it : user_data->DictItems()) { + for (auto it : *user_data) { if (it.second.is_int() && (include_empty || it.second.GetInt() > 0)) { result.insert(it.first); } else if (it.second.is_dict()) { @@ -622,16 +620,14 @@ std::set<ExtensionId> LockScreenItemStorage::GetExtensionsToMigrate() { std::set<ExtensionId> result; - const base::Value* items = - local_state_->GetDictionary(kLockScreenDataPrefKey); + const base::Value::Dict& items = + local_state_->GetValueDict(kLockScreenDataPrefKey); - if (!items) - return result; - const base::Value* user_data = items->FindDictPath(user_id_); + const base::Value::Dict* user_data = items.FindDictByDottedPath(user_id_); if (!user_data) return result; - for (auto it : user_data->DictItems()) { + for (auto it : *user_data) { if (it.second.is_int()) result.insert(it.first); }
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index aca17d0..6b27622 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -594,14 +594,26 @@ "chrome-untrusted://terminal/*" ] }], - "sockets.tcpServer": { + "sockets.tcpServer": [{ "dependencies": ["manifest:sockets"], "contexts": ["blessed_extension"] - }, - "sockets.udp": { + },{ + "channel": "stable", + "contexts": ["webui_untrusted"], + "matches": [ + "chrome-untrusted://terminal/*" + ] + }], + "sockets.udp": [{ "dependencies": ["manifest:sockets"], "contexts": ["blessed_extension"] - }, + },{ + "channel": "stable", + "contexts": ["webui_untrusted"], + "matches": [ + "chrome-untrusted://terminal/*" + ] + }], "storage": { "dependencies": ["permission:storage"], "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc index 816dfef..4b663c1 100644 --- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc +++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -561,19 +561,11 @@ return ax_tree_->GetFromId(node_id); } -ui::AXTreeID AutomationAXTreeWrapper::GetTreeID() const { - return ax_tree_id_; -} - ui::AXTreeID AutomationAXTreeWrapper::GetParentTreeID() const { AutomationAXTreeWrapper* parent_tree = GetParentOfTreeId(ax_tree_id_); return parent_tree ? parent_tree->GetTreeID() : ui::AXTreeIDUnknown(); } -ui::AXNode* AutomationAXTreeWrapper::GetRootAsAXNode() const { - return ax_tree_->root(); -} - ui::AXNode* AutomationAXTreeWrapper::GetParentNodeFromParentTreeAsAXNode() const { AutomationAXTreeWrapper* wrapper = const_cast<AutomationAXTreeWrapper*>(this);
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.h b/extensions/renderer/api/automation/automation_ax_tree_wrapper.h index cf84917..a790d761 100644 --- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.h +++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.h
@@ -110,9 +110,7 @@ ui::AXNode* GetNodeFromTree(const ui::AXTreeID tree_id, const ui::AXNodeID node_id) const override; ui::AXNode* GetNodeFromTree(const ui::AXNodeID node_id) const override; - ui::AXTreeID GetTreeID() const override; ui::AXTreeID GetParentTreeID() const override; - ui::AXNode* GetRootAsAXNode() const override; ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override; private:
diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc index d068b23..6b75f3ed 100644 --- a/extensions/renderer/extension_frame_helper.cc +++ b/extensions/renderer/extension_frame_helper.cc
@@ -576,15 +576,6 @@ void ExtensionFrameHelper::NotifyDidCreateScriptContext(int32_t world_id) { did_create_script_context_ = true; - if (world_id == blink::kMainDOMWorldId && - base::FeatureList::IsEnabled( - extensions_features::kAvoidEarlyExtensionScriptContextCreation)) { - // Grant cross browsing instance frame lookup if we are an extension. This - // should match the conditions in FindFrame. - content::RenderFrame* frame = render_frame(); - if (GetExtensionFromFrame(frame)) - frame->SetAllowsCrossBrowsingInstanceFrameLookup(); - } } void ExtensionFrameHelper::OnDestruct() { @@ -609,4 +600,23 @@ Send(new ExtensionHostMsg_UpdateDraggableRegions(routing_id(), regions)); } +void ExtensionFrameHelper::DidClearWindowObject() { + // DidClearWindowObject() is called right at the end of + // DocumentLoader::CreateParserPostCommit(). This is late enough in the commit + // process that it won't interfere with any optimizations, since the code + // below may cause the V8 context to be initialized. + // + // Calling this multiple times in a page load is safe because + // SetAllowsCrossBrowsingInstanceFrameLookup() just sets a bool to true on the + // SecurityOrigin. + if (base::FeatureList::IsEnabled( + extensions_features::kAvoidEarlyExtensionScriptContextCreation)) { + // Grant cross browsing instance frame lookup if we are an extension. This + // should match the conditions in FindFrame. + content::RenderFrame* frame = render_frame(); + if (GetExtensionFromFrame(frame)) + frame->SetAllowsCrossBrowsingInstanceFrameLookup(); + } +} + } // namespace extensions
diff --git a/extensions/renderer/extension_frame_helper.h b/extensions/renderer/extension_frame_helper.h index 0ccaf96..f9045007 100644 --- a/extensions/renderer/extension_frame_helper.h +++ b/extensions/renderer/extension_frame_helper.h
@@ -167,6 +167,7 @@ bool OnMessageReceived(const IPC::Message& message) override; void OnDestruct() override; void DraggableRegionsChanged() override; + void DidClearWindowObject() override; // IPC handlers. void OnExtensionValidateMessagePort(int worker_thread_id, const PortId& id);
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index a3bbd29a..5f5278f2 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -369,8 +369,8 @@ ] deps += [ "//ash/components/audio", + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/audio", - "//chromeos/dbus:test_support", ] }
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc index c31dda2..f9d4814 100644 --- a/extensions/shell/browser/shell_browser_main_parts.cc +++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -128,13 +128,13 @@ ash::shill_clients::Initialize(bus); ash::hermes_clients::Initialize(bus); ash::CrasAudioClient::Initialize(bus); - chromeos::CrosDisksClient::Initialize(bus); + ash::CrosDisksClient::Initialize(bus); chromeos::PowerManagerClient::Initialize(bus); } else { ash::shill_clients::InitializeFakes(); ash::hermes_clients::InitializeFakes(); ash::CrasAudioClient::InitializeFake(); - chromeos::CrosDisksClient::InitializeFake(); + ash::CrosDisksClient::InitializeFake(); chromeos::PowerManagerClient::InitializeFake(); } @@ -309,7 +309,7 @@ ash::NetworkHandler::Shutdown(); ash::disks::DiskMountManager::Shutdown(); chromeos::PowerManagerClient::Shutdown(); - chromeos::CrosDisksClient::Shutdown(); + ash::CrosDisksClient::Shutdown(); ash::CrasAudioClient::Shutdown(); ash::shill_clients::Shutdown(); #endif
diff --git a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc index 204c58e..bd83ae5 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
@@ -32,6 +32,7 @@ #include "ui/display/test/scoped_screen_override.h" #include "ui/events/event.h" #include "ui/events/event_dispatcher.h" +#include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/rect.h" @@ -132,6 +133,10 @@ // Dispatch a keypress on the window tree host to verify it is processed. ui::KeyEvent key_press(u'a', ui::VKEY_A, ui::DomCode::NONE, ui::EF_NONE); + ui::Event::Properties properties; + properties.emplace(ui::kPropertyKeyboardImeFlag, + std::vector<uint8_t>{ui::kPropertyKeyboardImeIgnoredFlag}); + key_press.SetProperties(properties); ui::EventDispatchDetails details = controller_->GetPrimaryHost()->dispatcher()->DispatchEvent( controller_->GetPrimaryHost()->window(), &key_press);
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn index 43847a4..39432cb 100644 --- a/gpu/ipc/common/BUILD.gn +++ b/gpu/ipc/common/BUILD.gn
@@ -78,6 +78,8 @@ sources = [ "command_buffer_id.h", "gpu_client_ids.h", + "gpu_disk_cache_type.cc", + "gpu_disk_cache_type.h", "gpu_memory_buffer_impl.cc", "gpu_memory_buffer_impl.h", "gpu_memory_buffer_impl_shared_memory.cc", @@ -313,6 +315,7 @@ "context_result.mojom", "device_perf_info.mojom", "dx_diag_node.mojom", + "gpu_disk_cache_type.mojom", "gpu_feature_info.mojom", "gpu_info.mojom", "gpu_peak_memory.mojom", @@ -531,6 +534,34 @@ ] traits_headers = [ "vulkan_ycbcr_info_mojom_traits.h" ] }, + { + types = [ + # Each specific handle is declared here to ensure that nullable is set. + { + mojom = "gpu.mojom.GpuDiskCacheGlShaderHandle" + cpp = "::gpu::GpuDiskCacheGlShaderHandle" + nullable_is_same_type = true + }, + { + mojom = "gpu.mojom.GpuDiskCacheDawnWebGPUHandle" + cpp = "::gpu::GpuDiskCacheDawnWebGPUHandle" + nullable_is_same_type = true + }, + + # General types that are the ones generally exposed in interfaces. + { + mojom = "gpu.mojom.GpuDiskCacheHandle" + cpp = "::gpu::GpuDiskCacheHandle" + nullable_is_same_type = true + }, + { + mojom = "gpu.mojom.GpuDiskCacheType" + cpp = "::gpu::GpuDiskCacheType" + }, + ] + traits_sources = [ "gpu_disk_cache_type_mojom_traits.cc" ] + traits_headers = [ "gpu_disk_cache_type_mojom_traits.h" ] + }, ] blink_cpp_typemaps = [
diff --git a/gpu/ipc/common/gpu_disk_cache_type.cc b/gpu/ipc/common/gpu_disk_cache_type.cc new file mode 100644 index 0000000..e3ca5df --- /dev/null +++ b/gpu/ipc/common/gpu_disk_cache_type.cc
@@ -0,0 +1,65 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/ipc/common/gpu_disk_cache_type.h" + +#include "base/notreached.h" + +namespace gpu { + +std::ostream& operator<<(std::ostream& s, const GpuDiskCacheType& type) { + switch (type) { + case GpuDiskCacheType::kGlShaders: + s << "gpu::GpuDiskCacheType::kGlShaders"; + break; + case GpuDiskCacheType::kDawnWebGPU: + s << "gpu::GpuDiskCacheType::kDawnWebGPU"; + break; + } + return s; +} + +std::ostream& operator<<(std::ostream& s, const GpuDiskCacheHandle& handle) { + switch (GetHandleType(handle)) { + case GpuDiskCacheType::kGlShaders: + s << "GlShaderHandle(" + << absl::get<gpu::GpuDiskCacheGlShaderHandle>(handle).value() << ")"; + break; + case GpuDiskCacheType::kDawnWebGPU: + s << "DawnWebGPUHandle(" + << absl::get<gpu::GpuDiskCacheDawnWebGPUHandle>(handle).value() << ")"; + break; + } + return s; +} + +base::FilePath::StringType GetGpuDiskCacheSubdir(GpuDiskCacheType type) { + switch (type) { + case GpuDiskCacheType::kGlShaders: + return FILE_PATH_LITERAL("GPUCache"); + case GpuDiskCacheType::kDawnWebGPU: + return FILE_PATH_LITERAL("DawnCache"); + } + NOTREACHED(); + return FILE_PATH_LITERAL(""); +} + +GpuDiskCacheType GetHandleType(const GpuDiskCacheHandle& handle) { + if (absl::holds_alternative<gpu::GpuDiskCacheGlShaderHandle>(handle)) + return GpuDiskCacheType::kGlShaders; + DCHECK(absl::holds_alternative<gpu::GpuDiskCacheDawnWebGPUHandle>(handle)); + return GpuDiskCacheType::kDawnWebGPU; +} + +bool IsReservedGpuDiskCacheHandle(const GpuDiskCacheHandle& handle) { + if (absl::holds_alternative<gpu::GpuDiskCacheGlShaderHandle>(handle)) { + const auto& gl_shader_handle = + absl::get<gpu::GpuDiskCacheGlShaderHandle>(handle); + return gl_shader_handle == kDisplayCompositorGpuDiskCacheHandle || + gl_shader_handle == kGrShaderGpuDiskCacheHandle; + } + return false; +} + +} // namespace gpu
diff --git a/gpu/ipc/common/gpu_disk_cache_type.h b/gpu/ipc/common/gpu_disk_cache_type.h new file mode 100644 index 0000000..22ddc53 --- /dev/null +++ b/gpu/ipc/common/gpu_disk_cache_type.h
@@ -0,0 +1,87 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_H_ +#define GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_H_ + +#include <array> +#include <limits> +#include <ostream> + +#include "base/files/file_path.h" +#include "base/types/id_type.h" +#include "gpu/gpu_export.h" +#include "third_party/abseil-cpp/absl/types/variant.h" + +namespace gpu { + +// +// GPU disk cache types and utilities to get the appropriate subdirs. +// + +// The GPU process can uses multiple different caches for different purposes. In +// order to differentiate between the different caches (which generally map to +// different physical disk paths), and add type safety when using them, these +// types explicitly define what a cache for the GPU process will be used for. +enum class GpuDiskCacheType { + kGlShaders, + kDawnWebGPU, +}; + +// Stream operator implemented for GpuDiskCacheType for debugging. +GPU_EXPORT std::ostream& operator<<(std::ostream& s, + const GpuDiskCacheType& type); + +static constexpr std::array<GpuDiskCacheType, 2> kGpuDiskCacheTypes = { + GpuDiskCacheType::kGlShaders, + GpuDiskCacheType::kDawnWebGPU, +}; +GPU_EXPORT base::FilePath::StringType GetGpuDiskCacheSubdir( + GpuDiskCacheType type); + +// +// Typed GPU disk cache handles (1:1 with GpuDiskCacheType) +// (Correlates physical paths with cross-process in-memory cache mirrors.) +// Note that the handles currently do not need to be unguessable because they +// are only used between the browser and the GPU process. +// + +// Shader handles allow negative values for representing reserved handles. +using GpuDiskCacheGlShaderHandle = + base::IdType<class GpuDiskCacheGlShader, + int32_t, + std::numeric_limits<int32_t>::min(), + 1>; + +// Dawn cache handles (for the most part, these should be 1:1 per profile). +using GpuDiskCacheDawnWebGPUHandle = + base::IdType32<class GpuDiskCacheDawnWebGPU>; + +// +// Variant handle that encompasses all possible handles, and utilities. +// +using GpuDiskCacheHandle = absl::variant<absl::monostate, + GpuDiskCacheGlShaderHandle, + GpuDiskCacheDawnWebGPUHandle>; +GPU_EXPORT GpuDiskCacheType GetHandleType(const GpuDiskCacheHandle& handle); + +// Stream operator implemented for GpuDiskCacheHandle for debugging. +GPU_EXPORT std::ostream& operator<<(std::ostream& s, + const GpuDiskCacheHandle& handle); + +// +// Reserved cache handles that are specifically used for static caches. +// + +// The handle used by the display compositor running in the GPU process. +constexpr GpuDiskCacheGlShaderHandle kDisplayCompositorGpuDiskCacheHandle(-1); + +// The handle used for storing shaders created by skia in the GPU process. +constexpr GpuDiskCacheGlShaderHandle kGrShaderGpuDiskCacheHandle(-2); + +GPU_EXPORT bool IsReservedGpuDiskCacheHandle(const GpuDiskCacheHandle& handle); + +} // namespace gpu + +#endif // GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_H_
diff --git a/gpu/ipc/common/gpu_disk_cache_type.mojom b/gpu/ipc/common/gpu_disk_cache_type.mojom new file mode 100644 index 0000000..be47d53 --- /dev/null +++ b/gpu/ipc/common/gpu_disk_cache_type.mojom
@@ -0,0 +1,35 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module gpu.mojom; + +// Corresponds to C++ type gpu::GpuDiskCacheType +enum GpuDiskCacheType { + kGlShaders, + kDawnWebGPU, +}; + +// +// Typed handles +// + +// Corresponds to C++ type gpu::GpuDiskCacheGlShaderHandle +struct GpuDiskCacheGlShaderHandle { + int32 value; +}; + +// Corresponds to C++ type gpu::GpuDiskCacheDawnWebGPUHandle +struct GpuDiskCacheDawnWebGPUHandle { + int32 value; +}; + +// +// Union handle +// + +// Corresponds to C++ type gpu::GpuDiskCacheHandle +union GpuDiskCacheHandle { + GpuDiskCacheGlShaderHandle gl_shader_handle; + GpuDiskCacheDawnWebGPUHandle dawn_webgpu_handle; +}; \ No newline at end of file
diff --git a/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.cc b/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.cc new file mode 100644 index 0000000..b3c4e96 --- /dev/null +++ b/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.cc
@@ -0,0 +1,106 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/ipc/common/gpu_disk_cache_type_mojom_traits.h" + +#include "base/notreached.h" +#include "third_party/abseil-cpp/absl/types/variant.h" + +namespace mojo { + +// static +gpu::mojom::GpuDiskCacheType +EnumTraits<gpu::mojom::GpuDiskCacheType, gpu::GpuDiskCacheType>::ToMojom( + gpu::GpuDiskCacheType gpu_disk_cache_type) { + switch (gpu_disk_cache_type) { + case gpu::GpuDiskCacheType::kGlShaders: + return gpu::mojom::GpuDiskCacheType::kGlShaders; + case gpu::GpuDiskCacheType::kDawnWebGPU: + return gpu::mojom::GpuDiskCacheType::kDawnWebGPU; + } + + NOTREACHED() << "Invalid gpu::GpuDiskCacheType: " << gpu_disk_cache_type; + return gpu::mojom::GpuDiskCacheType::kGlShaders; +} + +// static +bool EnumTraits<gpu::mojom::GpuDiskCacheType, gpu::GpuDiskCacheType>::FromMojom( + gpu::mojom::GpuDiskCacheType input, + gpu::GpuDiskCacheType* out) { + switch (input) { + case gpu::mojom::GpuDiskCacheType::kGlShaders: + *out = gpu::GpuDiskCacheType::kGlShaders; + return true; + case gpu::mojom::GpuDiskCacheType::kDawnWebGPU: + *out = gpu::GpuDiskCacheType::kDawnWebGPU; + return true; + default: + break; + } + NOTREACHED() << "Invalid gpu::mojom::GpuDiskCacheType: " << input; + return false; +} + +// static +bool UnionTraits<gpu::mojom::GpuDiskCacheHandleDataView, + gpu::GpuDiskCacheHandle>::IsNull(const gpu::GpuDiskCacheHandle& + handle) { + return absl::holds_alternative<absl::monostate>(handle); +} + +void UnionTraits<gpu::mojom::GpuDiskCacheHandleDataView, + gpu::GpuDiskCacheHandle>::SetToNull(gpu::GpuDiskCacheHandle* + handle) { + *handle = gpu::GpuDiskCacheHandle(); +} + +// static +bool UnionTraits< + gpu::mojom::GpuDiskCacheHandleDataView, + gpu::GpuDiskCacheHandle>::Read(gpu::mojom::GpuDiskCacheHandleDataView input, + gpu::GpuDiskCacheHandle* output) { + using Tag = gpu::mojom::GpuDiskCacheHandleDataView::Tag; + switch (input.tag()) { + case Tag::kGlShaderHandle: { + gpu::GpuDiskCacheGlShaderHandle handle; + bool ret = input.ReadGlShaderHandle(&handle); + *output = handle; + return ret; + } + case Tag::kDawnWebgpuHandle: { + gpu::GpuDiskCacheDawnWebGPUHandle handle; + bool ret = input.ReadDawnWebgpuHandle(&handle); + *output = handle; + return ret; + } + } + return false; +} + +// static +gpu::mojom::GpuDiskCacheHandleDataView::Tag UnionTraits< + gpu::mojom::GpuDiskCacheHandleDataView, + gpu::GpuDiskCacheHandle>::GetTag(const gpu::GpuDiskCacheHandle& handle) { + using Tag = gpu::mojom::GpuDiskCacheHandleDataView::Tag; + if (absl::holds_alternative<gpu::GpuDiskCacheGlShaderHandle>(handle)) + return Tag::kGlShaderHandle; + DCHECK(absl::holds_alternative<gpu::GpuDiskCacheDawnWebGPUHandle>(handle)); + return Tag::kDawnWebgpuHandle; +} + +// static +gpu::GpuDiskCacheGlShaderHandle +UnionTraits<gpu::mojom::GpuDiskCacheHandleDataView, gpu::GpuDiskCacheHandle>:: + gl_shader_handle(const gpu::GpuDiskCacheHandle& handle) { + return absl::get<gpu::GpuDiskCacheGlShaderHandle>(handle); +} + +// static +gpu::GpuDiskCacheDawnWebGPUHandle +UnionTraits<gpu::mojom::GpuDiskCacheHandleDataView, gpu::GpuDiskCacheHandle>:: + dawn_webgpu_handle(const gpu::GpuDiskCacheHandle& handle) { + return absl::get<gpu::GpuDiskCacheDawnWebGPUHandle>(handle); +} + +} // namespace mojo
diff --git a/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.h b/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.h new file mode 100644 index 0000000..7a9da0f --- /dev/null +++ b/gpu/ipc/common/gpu_disk_cache_type_mojom_traits.h
@@ -0,0 +1,72 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_MOJOM_TRAITS_H_ +#define GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_MOJOM_TRAITS_H_ + +#include "gpu/gpu_export.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" +#include "gpu/ipc/common/gpu_disk_cache_type.mojom.h" + +namespace mojo { + +template <> +struct GPU_EXPORT + EnumTraits<gpu::mojom::GpuDiskCacheType, gpu::GpuDiskCacheType> { + static gpu::mojom::GpuDiskCacheType ToMojom(gpu::GpuDiskCacheType support); + static bool FromMojom(gpu::mojom::GpuDiskCacheType input, + gpu::GpuDiskCacheType* out); +}; + +namespace internal { + +template <typename MojomDataViewType, typename HandleType> +struct GpuDiskCacheHandleMojomTraitsHelper { + static bool IsNull(const HandleType& handle) { return handle.is_null(); } + + static void SetToNull(HandleType* handle) { *handle = HandleType(); } + + static bool Read(MojomDataViewType& input, HandleType* output) { + *output = HandleType(input.value()); + return true; + } + + static int32_t value(const HandleType& input) { return *input; } +}; + +} // namespace internal + +template <> +struct StructTraits<gpu::mojom::GpuDiskCacheGlShaderHandleDataView, + gpu::GpuDiskCacheGlShaderHandle> + : public internal::GpuDiskCacheHandleMojomTraitsHelper< + gpu::mojom::GpuDiskCacheGlShaderHandleDataView, + gpu::GpuDiskCacheGlShaderHandle> {}; + +template <> +struct StructTraits<gpu::mojom::GpuDiskCacheDawnWebGPUHandleDataView, + gpu::GpuDiskCacheDawnWebGPUHandle> + : public internal::GpuDiskCacheHandleMojomTraitsHelper< + gpu::mojom::GpuDiskCacheDawnWebGPUHandleDataView, + gpu::GpuDiskCacheDawnWebGPUHandle> {}; + +template <> +struct GPU_EXPORT UnionTraits<gpu::mojom::GpuDiskCacheHandleDataView, + gpu::GpuDiskCacheHandle> { + static bool IsNull(const gpu::GpuDiskCacheHandle& handle); + static void SetToNull(gpu::GpuDiskCacheHandle* handle); + + static bool Read(gpu::mojom::GpuDiskCacheHandleDataView input, + gpu::GpuDiskCacheHandle* output); + static gpu::mojom::GpuDiskCacheHandleDataView::Tag GetTag( + const gpu::GpuDiskCacheHandle& handle); + static gpu::GpuDiskCacheGlShaderHandle gl_shader_handle( + const gpu::GpuDiskCacheHandle& handle); + static gpu::GpuDiskCacheDawnWebGPUHandle dawn_webgpu_handle( + const gpu::GpuDiskCacheHandle& handle); +}; + +} // namespace mojo + +#endif // GPU_IPC_COMMON_GPU_DISK_CACHE_TYPE_MOJOM_TRAITS_H_
diff --git a/gpu/ipc/host/gpu_disk_cache.cc b/gpu/ipc/host/gpu_disk_cache.cc index c5dae10..96608f5 100644 --- a/gpu/ipc/host/gpu_disk_cache.cc +++ b/gpu/ipc/host/gpu_disk_cache.cc
@@ -24,9 +24,6 @@ namespace { -static const base::FilePath::CharType kGpuCachePath[] = - FILE_PATH_LITERAL("GPUCache"); - #if !BUILDFLAG(IS_ANDROID) size_t GetCustomCacheSizeBytesIfExists(base::StringPiece switch_string) { const base::CommandLine& process_command_line = @@ -130,9 +127,8 @@ public: GpuDiskCacheClearHelper(GpuDiskCacheFactory* factory, scoped_refptr<GpuDiskCache> cache, - const base::FilePath& path, - const base::Time& delete_begin, - const base::Time& delete_end, + base::Time delete_begin, + base::Time delete_end, base::OnceClosure callback); GpuDiskCacheClearHelper(const GpuDiskCacheClearHelper&) = delete; @@ -152,7 +148,6 @@ raw_ptr<GpuDiskCacheFactory> factory_; scoped_refptr<GpuDiskCache> cache_; OpType op_type_ = VERIFY_CACHE_SETUP; - base::FilePath path_; base::Time delete_begin_; base::Time delete_end_; base::OnceClosure callback_; @@ -377,13 +372,11 @@ GpuDiskCacheClearHelper::GpuDiskCacheClearHelper( GpuDiskCacheFactory* factory, scoped_refptr<GpuDiskCache> cache, - const base::FilePath& path, - const base::Time& delete_begin, - const base::Time& delete_end, + base::Time delete_begin, + base::Time delete_end, base::OnceClosure callback) : factory_(factory), cache_(std::move(cache)), - path_(path), delete_begin_(delete_begin), delete_end_(delete_end), callback_(std::move(callback)) {} @@ -417,7 +410,7 @@ case TERMINATE: std::move(callback_).Run(); // Calling CacheCleared() destroys |this|. - factory_->CacheCleared(path_); + factory_->CacheCleared(cache_.get()); rv = net::ERR_IO_PENDING; // Break the loop. break; } @@ -427,37 +420,90 @@ //////////////////////////////////////////////////////////////////////////////// // GpuDiskCacheFactory -GpuDiskCacheFactory::GpuDiskCacheFactory() = default; +GpuDiskCacheFactory::GpuDiskCacheFactory( + const HandleToPathMap& reserved_handles) { + for (const auto& [handle, path] : reserved_handles) { + CHECK(IsReservedGpuDiskCacheHandle(handle)); + handle_to_path_map_[handle] = path; + path_to_handle_map_[path] = handle; + } +} GpuDiskCacheFactory::~GpuDiskCacheFactory() = default; -void GpuDiskCacheFactory::SetCacheInfo(int32_t client_id, - const base::FilePath& path) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - client_id_to_path_map_[client_id] = path; -} - -void GpuDiskCacheFactory::RemoveCacheInfo(int32_t client_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - client_id_to_path_map_.erase(client_id); -} - -scoped_refptr<GpuDiskCache> GpuDiskCacheFactory::Get(int32_t client_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ClientIdToPathMap::iterator iter = client_id_to_path_map_.find(client_id); - if (iter == client_id_to_path_map_.end()) - return nullptr; - return GpuDiskCacheFactory::GetByPath(iter->second); -} - -scoped_refptr<GpuDiskCache> GpuDiskCacheFactory::GetByPath( +GpuDiskCacheHandle GpuDiskCacheFactory::GetCacheHandle( + GpuDiskCacheType type, const base::FilePath& path) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + auto it = path_to_handle_map_.find(path); + if (it != path_to_handle_map_.end()) { + DCHECK(GetHandleType(it->second) == type); + return it->second; + } + + // Create a new handle and record it. We don't expect large number of handles + // and the system cannot handle it since the map is not culled. As a result, + // we are returning an empty for the handle which will result in Get/Create + // returning nullptr, effectively stopping cache usage when we run out of + // handles. + GpuDiskCacheHandle handle; + if (next_available_handle_ == std::numeric_limits<int32_t>::max()) { + LOG(ERROR) << "GpuDiskCacheFactory ran out of handles for caches, caching " + "will be disabled until a new session."; + return handle; + } + + int32_t raw_handle = next_available_handle_++; + switch (type) { + case GpuDiskCacheType::kGlShaders: + handle = GpuDiskCacheGlShaderHandle(raw_handle); + break; + case GpuDiskCacheType::kDawnWebGPU: + handle = GpuDiskCacheDawnWebGPUHandle(raw_handle); + break; + } + handle_to_path_map_[handle] = path; + path_to_handle_map_[path] = handle; + + return handle; +} + +scoped_refptr<GpuDiskCache> GpuDiskCacheFactory::Get( + const GpuDiskCacheHandle& handle) { + auto handle_it = handle_to_path_map_.find(handle); + if (handle_it != handle_to_path_map_.end()) { + auto path_it = gpu_cache_map_.find(handle_it->second); + if (path_it != gpu_cache_map_.end()) { + return path_it->second; + } + } + return nullptr; +} + +scoped_refptr<GpuDiskCache> GpuDiskCacheFactory::Create( + const GpuDiskCacheHandle& handle, + const BlobLoadedForCacheCallback& blob_loaded_cb) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(Get(handle) == nullptr); + + auto it = handle_to_path_map_.find(handle); + if (it == handle_to_path_map_.end()) { + return nullptr; + } + return GetOrCreateByPath(it->second, + base::BindRepeating(blob_loaded_cb, handle)); +} + +scoped_refptr<GpuDiskCache> GpuDiskCacheFactory::GetOrCreateByPath( + const base::FilePath& path, + const GpuDiskCache::BlobLoadedCallback& blob_loaded_cb) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto iter = gpu_cache_map_.find(path); if (iter != gpu_cache_map_.end()) return iter->second; - auto cache = base::WrapRefCounted(new GpuDiskCache(this, path)); + auto cache = + base::WrapRefCounted(new GpuDiskCache(this, path, blob_loaded_cb)); cache->Init(); return cache; } @@ -473,57 +519,57 @@ gpu_cache_map_.erase(key); } -void GpuDiskCacheFactory::ClearByPath(const base::FilePath& path, - const base::Time& delete_begin, - const base::Time& delete_end, - base::OnceClosure callback) { +void GpuDiskCacheFactory::ClearByCache(scoped_refptr<GpuDiskCache> cache, + base::Time delete_begin, + base::Time delete_end, + base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!callback.is_null()); - if (path.empty()) { + if (!cache) { std::move(callback).Run(); return; } auto helper = std::make_unique<GpuDiskCacheClearHelper>( - this, GetByPath(path), path, delete_begin, delete_end, - std::move(callback)); + this, cache, delete_begin, delete_end, std::move(callback)); - // We could receive requests to clear the same path with different + // We could receive requests to clear the same cache with different // begin/end times. So, we keep a list of requests. If we haven't seen this - // path before we kick off the clear and add it to the list. If we have see it - // already, then we already have a clear running. We add this clear to the + // cache before we kick off the clear and add it to the list. If we have see + // it already, then we already have a clear running. We add this clear to the // list and wait for any previous clears to finish. - auto iter = gpu_clear_map_.find(path); - if (iter != gpu_clear_map_.end()) { - iter->second.push(std::move(helper)); + auto& queued_requests = gpu_clear_map_[cache.get()]; + queued_requests.push(std::move(helper)); + + // If this is the first clear request, then we need to start the clear + // operation on the helper. + if (queued_requests.size() == 1) { + queued_requests.front()->Clear(); + } +} + +void GpuDiskCacheFactory::ClearByPath(const base::FilePath& path, + base::Time delete_begin, + base::Time delete_end, + base::OnceClosure callback) { + // Don't need to do anything if the path is empty. + if (path.empty()) { + std::move(callback).Run(); return; } - // Insert the helper in the map before calling Clear(), since it can lead to a - // call back into CacheCleared(). - GpuDiskCacheClearHelper* helper_ptr = helper.get(); - gpu_clear_map_.insert( - std::pair<base::FilePath, ClearHelperQueue>(path, ClearHelperQueue())); - gpu_clear_map_[path].push(std::move(helper)); - helper_ptr->Clear(); + // We may end up creating the cache if the path that is specified isn't + // already an opened path. In this case, we don't need to set a blob loaded + // callback since the cache is being cleared anyways, hence the DoNothing + // callback. + ClearByCache(GetOrCreateByPath(path), delete_begin, delete_end, + std::move(callback)); } -void GpuDiskCacheFactory::ClearByClientId(int32_t client_id, - const base::Time& delete_begin, - const base::Time& delete_end, - base::OnceClosure callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - auto iter = client_id_to_path_map_.find(client_id); - if (iter == client_id_to_path_map_.end()) - return; - return ClearByPath(iter->second, delete_begin, delete_end, - std::move(callback)); -} - -void GpuDiskCacheFactory::CacheCleared(const base::FilePath& path) { +void GpuDiskCacheFactory::CacheCleared(GpuDiskCache* cache) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - auto iter = gpu_clear_map_.find(path); + auto iter = gpu_clear_map_.find(cache); if (iter == gpu_clear_map_.end()) { LOG(ERROR) << "Completed clear but missing clear helper."; return; @@ -545,8 +591,11 @@ // GpuDiskCache GpuDiskCache::GpuDiskCache(GpuDiskCacheFactory* factory, - const base::FilePath& cache_path) - : factory_(factory), cache_path_(cache_path) { + const base::FilePath& cache_path, + const BlobLoadedCallback& blob_loaded_cb) + : factory_(factory), + cache_path_(cache_path), + blob_loaded_cb_(blob_loaded_cb) { factory_->AddToCache(cache_path_, this); } @@ -561,11 +610,10 @@ } is_initialized_ = true; - // TODO(dawn:549) Add GPU_CACHE type and replace SHADER_CACHE here. disk_cache::BackendResult rv = disk_cache::CreateCacheBackend( net::SHADER_CACHE, net::CACHE_BACKEND_DEFAULT, - /*file_operations=*/nullptr, cache_path_.Append(kGpuCachePath), - CacheSizeBytes(), disk_cache::ResetHandling::kResetOnError, + /*file_operations=*/nullptr, cache_path_, CacheSizeBytes(), + disk_cache::ResetHandling::kResetOnError, /*net_log=*/nullptr, base::BindOnce(&GpuDiskCache::CacheCreatedCallback, this)); @@ -586,8 +634,8 @@ entries_.insert(std::make_pair(raw_ptr, std::move(shim))); } -int GpuDiskCache::Clear(const base::Time begin_time, - const base::Time end_time, +int GpuDiskCache::Clear(base::Time begin_time, + base::Time end_time, net::CompletionOnceCallback completion_callback) { int rv; if (begin_time.is_null()) { @@ -618,8 +666,7 @@ return; } backend_ = std::move(result.backend); - helper_ = - std::make_unique<GpuDiskCacheReadHelper>(this, blob_loaded_callback_); + helper_ = std::make_unique<GpuDiskCacheReadHelper>(this, blob_loaded_cb_); helper_->LoadCache(); }
diff --git a/gpu/ipc/host/gpu_disk_cache.h b/gpu/ipc/host/gpu_disk_cache.h index b4f87d08..e463b1b0 100644 --- a/gpu/ipc/host/gpu_disk_cache.h +++ b/gpu/ipc/host/gpu_disk_cache.h
@@ -7,15 +7,17 @@ #include <stdint.h> -#include <map> #include <string> #include <unordered_map> +#include "base/callback_helpers.h" +#include "base/containers/flat_map.h" #include "base/containers/queue.h" #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/threading/thread_checker.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "net/base/completion_once_callback.h" #include "net/disk_cache/disk_cache.h" @@ -35,10 +37,6 @@ GpuDiskCache(const GpuDiskCache&) = delete; GpuDiskCache& operator=(const GpuDiskCache&) = delete; - void SetBlobLoadedCallback(const BlobLoadedCallback& callback) { - blob_loaded_callback_ = callback; - } - // Store the |blob| into the cache under |key|. void Cache(const std::string& key, const std::string& blob); @@ -47,8 +45,8 @@ // The return value is a net error code. If this method returns // ERR_IO_PENDING, the |completion_callback| will be invoked when the // operation completes. - int Clear(const base::Time begin_time, - const base::Time end_time, + int Clear(base::Time begin_time, + base::Time end_time, net::CompletionOnceCallback completion_callback); // Sets a callback for when the cache is available. If the cache is @@ -76,7 +74,9 @@ friend class GpuDiskCacheReadHelper; friend class GpuDiskCacheFactory; - GpuDiskCache(GpuDiskCacheFactory* factory, const base::FilePath& cache_path); + GpuDiskCache(GpuDiskCacheFactory* factory, + const base::FilePath& cache_path, + const BlobLoadedCallback& blob_loaded_cb); ~GpuDiskCache(); void Init(); @@ -93,7 +93,7 @@ bool is_initialized_ = false; net::CompletionOnceCallback available_callback_; net::CompletionOnceCallback cache_complete_callback_; - BlobLoadedCallback blob_loaded_callback_; + BlobLoadedCallback blob_loaded_cb_; std::unique_ptr<disk_cache::Backend> backend_; @@ -106,37 +106,53 @@ // create one per profile directory. class GpuDiskCacheFactory { public: - GpuDiskCacheFactory(); + using HandleToPathMap = base::flat_map<GpuDiskCacheHandle, base::FilePath>; + using BlobLoadedForCacheCallback = base::RepeatingCallback< + void(const GpuDiskCacheHandle&, const std::string&, const std::string&)>; + + // Constructor allows passing in reserved handles and their corresponding + // paths. + explicit GpuDiskCacheFactory( + const HandleToPathMap& reserved_handles = HandleToPathMap()); GpuDiskCacheFactory(const GpuDiskCacheFactory&) = delete; GpuDiskCacheFactory& operator=(const GpuDiskCacheFactory&) = delete; ~GpuDiskCacheFactory(); + // Clear the given gpu disk |cache|. This supports unbounded deletes in + // either direction by using null Time values for either |begin_time| or + // |end_time|. The |callback| will be executed when the clear is complete. + void ClearByCache(scoped_refptr<GpuDiskCache> cache, + base::Time begin_time, + base::Time end_time, + base::OnceClosure callback); + // Clear the gpu disk cache for the given |path|. This supports unbounded // deletes in either direction by using null Time values for either // |begin_time| or |end_time|. The |callback| will be executed when the // clear is complete. void ClearByPath(const base::FilePath& path, - const base::Time& begin_time, - const base::Time& end_time, + base::Time begin_time, + base::Time end_time, base::OnceClosure callback); - // Same as ClearByPath, but looks up the cache by |client_id|. The |callback| - // will be executed when the clear is complete. - void ClearByClientId(int32_t client_id, - const base::Time& begin_time, - const base::Time& end_time, - base::OnceClosure callback); + // Looks up a |path| and returns a cache handle for it (registering it if + // necessary) for the given |type|. + GpuDiskCacheHandle GetCacheHandle(GpuDiskCacheType type, + const base::FilePath& path); - // Retrieve the gpu disk cache for the provided |client_id|. - scoped_refptr<GpuDiskCache> Get(int32_t client_id); + // Retrieve the gpu disk cache with the given |handle| if the handle has an + // associated path. Returns nullptr if there is no associated path or the + // cache was never explicitly created. + scoped_refptr<GpuDiskCache> Get(const GpuDiskCacheHandle& handle); - // Set the |path| to be used for the disk cache for |client_id|. - void SetCacheInfo(int32_t client_id, const base::FilePath& path); - - // Remove the path mapping for |client_id|. - void RemoveCacheInfo(int32_t client_id); + // Creates an non-existing gpu cache given a handle that was previously + // registered via GetCacheHandle. Returns nullptr if there was no associated + // path. + scoped_refptr<GpuDiskCache> Create( + const GpuDiskCacheHandle& handle, + const BlobLoadedForCacheCallback& blob_loaded_cb = base::DoNothing()); // Set the provided |cache| into the cache map for the given |path|. void AddToCache(const base::FilePath& path, GpuDiskCache* cache); @@ -147,21 +163,36 @@ private: friend class GpuDiskCacheClearHelper; - scoped_refptr<GpuDiskCache> GetByPath(const base::FilePath& path); - void CacheCleared(const base::FilePath& path); + scoped_refptr<GpuDiskCache> GetOrCreateByPath( + const base::FilePath& path, + const GpuDiskCache::BlobLoadedCallback& blob_loaded_cb = + base::DoNothing()); + + void CacheCleared(GpuDiskCache* cache); THREAD_CHECKER(thread_checker_); - using PathToCacheMap = std::map<base::FilePath, GpuDiskCache*>; - PathToCacheMap gpu_cache_map_; + // Implementation of bi-directional mapping from path to handle and handle to + // path for both way lookup. Entries in these maps are removed when the last + // scoped_ptr of the respective cache is destroyed, unless the handle is a + // special reserved handle, in which case we do not remove the entry. + HandleToPathMap handle_to_path_map_; + using PathToHandleMap = + base::flat_map<base::FilePath, gpu::GpuDiskCacheHandle>; + PathToHandleMap path_to_handle_map_; - using ClientIdToPathMap = std::map<int32_t, base::FilePath>; - ClientIdToPathMap client_id_to_path_map_; + using PathToCacheMap = base::flat_map<base::FilePath, GpuDiskCache*>; + PathToCacheMap gpu_cache_map_; using ClearHelperQueue = base::queue<std::unique_ptr<GpuDiskCacheClearHelper>>; - using PathToClearHelperQueueMap = std::map<base::FilePath, ClearHelperQueue>; - PathToClearHelperQueueMap gpu_clear_map_; + using CacheToClearHelperQueueMap = + base::flat_map<GpuDiskCache*, ClearHelperQueue>; + CacheToClearHelperQueueMap gpu_clear_map_; + + // Handles are all int32_t types underneath so we can allocate them all via + // this incrementing internal counter. + int32_t next_available_handle_ = 0; }; } // namespace gpu
diff --git a/gpu/ipc/host/gpu_disk_cache_unittest.cc b/gpu/ipc/host/gpu_disk_cache_unittest.cc index 362e44a..8a99c39 100644 --- a/gpu/ipc/host/gpu_disk_cache_unittest.cc +++ b/gpu/ipc/host/gpu_disk_cache_unittest.cc
@@ -4,6 +4,7 @@ #include "gpu/ipc/host/gpu_disk_cache.h" +#include "base/callback_helpers.h" #include "base/files/scoped_temp_dir.h" #include "base/test/bind.h" #include "base/test/task_environment.h" @@ -14,7 +15,6 @@ namespace gpu { namespace { -const int kDefaultClientId = 42; const char kCacheKey[] = "key"; const char kCacheValue[] = "cached value"; const char kCacheKey2[] = "key2"; @@ -23,7 +23,7 @@ } // namespace class GpuDiskCacheTest : public testing::Test { - public: + protected: GpuDiskCacheTest() = default; GpuDiskCacheTest(const GpuDiskCacheTest&) = delete; @@ -35,15 +35,13 @@ void InitCache() { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - factory_.SetCacheInfo(kDefaultClientId, cache_path()); + handle_ = + factory_.GetCacheHandle(GpuDiskCacheType::kGlShaders, cache_path()); } GpuDiskCacheFactory* factory() { return &factory_; } - private: void TearDown() override { - factory_.RemoveCacheInfo(kDefaultClientId); - // Run all pending tasks before destroying TaskEnvironment. Otherwise, // SimpleEntryImpl instances bound to pending tasks are destroyed in an // incorrect state (see |state_| DCHECK in ~SimpleEntryImpl). @@ -53,12 +51,13 @@ base::test::TaskEnvironment task_environment_; base::ScopedTempDir temp_dir_; GpuDiskCacheFactory factory_; + GpuDiskCacheHandle handle_; }; TEST_F(GpuDiskCacheTest, ClearsCache) { InitCache(); - scoped_refptr<GpuDiskCache> cache = factory()->Get(kDefaultClientId); + scoped_refptr<GpuDiskCache> cache = factory()->Create(handle_); ASSERT_TRUE(cache.get() != nullptr); net::TestCompletionCallback available_cb; @@ -82,7 +81,7 @@ TEST_F(GpuDiskCacheTest, ClearByPathTriggersCallback) { InitCache(); - factory()->Get(kDefaultClientId)->Cache(kCacheKey, kCacheValue); + factory()->Create(handle_)->Cache(kCacheKey, kCacheValue); net::TestCompletionCallback test_callback; factory()->ClearByPath( cache_path(), base::Time(), base::Time::Max(), @@ -104,7 +103,7 @@ InitCache(); // Create a cache and wait for it to open. - scoped_refptr<GpuDiskCache> cache = factory()->Get(kDefaultClientId); + scoped_refptr<GpuDiskCache> cache = factory()->Create(handle_); ASSERT_TRUE(cache.get() != nullptr); net::TestCompletionCallback available_cb; int rv = cache->SetAvailableCallback(available_cb.callback()); @@ -112,14 +111,13 @@ EXPECT_EQ(0, cache->Size()); // Start writing an entry to the cache but delete it before the backend has - // finished opening the entry. There is a race here, so this usually (but - // not always) crashes if there is a problem. + // finished opening the entry. There is a race here, so this usually (but not + // always) crashes if there is a problem. cache->Cache(kCacheKey, kCacheValue); cache = nullptr; - // Open a new cache (to pass time on the cache thread) and verify all is - // well. - cache = factory()->Get(kDefaultClientId); + // Open a new cache (to pass time on the cache thread) and verify all is well. + cache = factory()->Create(handle_); ASSERT_TRUE(cache.get() != nullptr); net::TestCompletionCallback available_cb2; int rv2 = cache->SetAvailableCallback(available_cb2.callback()); @@ -130,7 +128,7 @@ InitCache(); // Create a cache and wait for it to open. - scoped_refptr<GpuDiskCache> cache = factory()->Get(kDefaultClientId); + scoped_refptr<GpuDiskCache> cache = factory()->Create(handle_); ASSERT_TRUE(cache.get() != nullptr); net::TestCompletionCallback available_cb; int rv = cache->SetAvailableCallback(available_cb.callback()); @@ -148,13 +146,13 @@ // Close, re-open, and verify that two entries were loaded. cache = nullptr; - cache = factory()->Get(kDefaultClientId); - ASSERT_TRUE(cache.get() != nullptr); int loaded_calls = 0; - cache->SetBlobLoadedCallback(base::BindLambdaForTesting( - [&loaded_calls](const std::string& key, const std::string& value) { - ++loaded_calls; - })); + cache = factory()->Create( + handle_, base::BindLambdaForTesting( + [&loaded_calls]( + const GpuDiskCacheHandle& handle, const std::string& key, + const std::string& value) { ++loaded_calls; })); + ASSERT_TRUE(cache.get() != nullptr); net::TestCompletionCallback available_cb2; int rv2 = cache->SetAvailableCallback(available_cb2.callback()); ASSERT_EQ(net::OK, available_cb2.GetResult(rv2));
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index 166b8ac..b5bf5b2 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc
@@ -1032,9 +1032,26 @@ } #endif // BUILDFLAG(IS_FUCHSIA) +void GpuChannel::RegisterCacheHandle(const gpu::GpuDiskCacheHandle& handle) { + gpu::GpuDiskCacheType type = gpu::GetHandleType(handle); + + // We should never be registering multiple different caches of the same type. + const auto it = caches_.find(type); + if (it != caches_.end() && it->second != handle) { + LOG(ERROR) << "GpuChannel cannot register multiple different caches of the " + "same type."; + return; + } + + caches_[gpu::GetHandleType(handle)] = handle; +} + void GpuChannel::CacheShader(const std::string& key, const std::string& shader) { - gpu_channel_manager_->delegate()->StoreShaderToDisk(client_id_, key, shader); + const auto it = caches_.find(gpu::GpuDiskCacheType::kGlShaders); + if (it != caches_.end()) { + gpu_channel_manager_->delegate()->StoreBlobToDisk(it->second, key, shader); + } } uint64_t GpuChannel::GetMemoryUsage() const {
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h index 4da8ec77..878aac1 100644 --- a/gpu/ipc/service/gpu_channel.h +++ b/gpu/ipc/service/gpu_channel.h
@@ -25,6 +25,7 @@ #include "gpu/command_buffer/common/context_result.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/ipc/common/gpu_channel.mojom.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "gpu/ipc/service/command_buffer_stub.h" #include "gpu/ipc/service/gpu_ipc_service_export.h" #include "gpu/ipc/service/shared_image_stub.h" @@ -139,6 +140,7 @@ // Called to remove a listener for a particular message routing ID. void RemoveRoute(int32_t route_id); + void RegisterCacheHandle(const gpu::GpuDiskCacheHandle& handle); void CacheShader(const std::string& key, const std::string& shader); uint64_t GetMemoryUsage() const; @@ -254,6 +256,9 @@ // Map of stream id to scheduler sequence id. base::flat_map<int32_t, SequenceId> stream_sequences_; + // Map of disk cache type to the handle. + base::flat_map<gpu::GpuDiskCacheType, gpu::GpuDiskCacheHandle> caches_; + // The lifetime of objects of this class is managed by a GpuChannelManager. // The GpuChannelManager destroy all the GpuChannels that they own when they // are destroyed. So a raw pointer is safe.
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index 4587d857c..a1faf51 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -459,13 +459,9 @@ const base::UnguessableToken& channel_token, int client_id, uint64_t client_tracing_id, - bool is_gpu_host, - bool cache_shaders_on_disk) { + bool is_gpu_host) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (gr_shader_cache_ && cache_shaders_on_disk) - gr_shader_cache_->CacheClientIdOnDisk(client_id); - std::unique_ptr<GpuChannel> gpu_channel = GpuChannel::Create( this, channel_token, scheduler_, sync_point_manager_, share_group_, task_runner_, io_task_runner_, client_id, client_tracing_id, is_gpu_host, @@ -503,6 +499,22 @@ } } +void GpuChannelManager::SetChannelDiskCacheHandle( + int client_id, + const gpu::GpuDiskCacheHandle& handle) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + GpuChannel* gpu_channel = LookupChannel(client_id); + if (gpu_channel) { + gpu_channel->RegisterCacheHandle(handle); + } + + // Record the client id for the shader specific cache. + if (gr_shader_cache_ && + gpu::GetHandleType(handle) == gpu::GpuDiskCacheType::kGlShaders) { + gr_shader_cache_->CacheClientIdOnDisk(client_id); + } +} + void GpuChannelManager::InternalDestroyGpuMemoryBuffer( gfx::GpuMemoryBufferId id, int client_id) { @@ -525,19 +537,31 @@ } } -void GpuChannelManager::PopulateShaderCache(int32_t client_id, - const std::string& key, - const std::string& program) { +void GpuChannelManager::PopulateCache(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& data) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (client_id == kGrShaderCacheClientId) { - if (gr_shader_cache_) - gr_shader_cache_->PopulateCache(key, program); - return; - } + switch (gpu::GetHandleType(handle)) { + case gpu::GpuDiskCacheType::kGlShaders: { + auto gl_shader_handle = + absl::get<gpu::GpuDiskCacheGlShaderHandle>(handle); + if (gl_shader_handle == kGrShaderGpuDiskCacheHandle) { + if (gr_shader_cache_) + gr_shader_cache_->PopulateCache(key, data); + return; + } - if (program_cache()) - program_cache()->LoadProgram(key, program); + if (program_cache()) + program_cache()->LoadProgram(key, data); + break; + } + case gpu::GpuDiskCacheType::kDawnWebGPU: { + // TODO(dawn:549) Implement populating cache for Dawn. + NOTREACHED(); + break; + } + } } void GpuChannelManager::LoseAllContexts() { @@ -960,7 +984,7 @@ void GpuChannelManager::StoreShader(const std::string& key, const std::string& shader) { - delegate_->StoreShaderToDisk(kGrShaderCacheClientId, key, shader); + delegate_->StoreBlobToDisk(kGrShaderGpuDiskCacheHandle, key, shader); } void GpuChannelManager::SetImageDecodeAcceleratorWorkerForTesting(
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h index 5ede05a06..00db0475 100644 --- a/gpu/ipc/service/gpu_channel_manager.h +++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -34,6 +34,7 @@ #include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_preferences.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "gpu/ipc/common/gpu_peak_memory.h" #include "gpu/ipc/service/gpu_ipc_service_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -114,14 +115,15 @@ GpuChannel* EstablishChannel(const base::UnguessableToken& channel_token, int client_id, uint64_t client_tracing_id, - bool is_gpu_host, - bool cache_shaders_on_disk); + bool is_gpu_host); void SetChannelClientPid(int client_id, base::ProcessId client_pid); + void SetChannelDiskCacheHandle(int client_id, + const gpu::GpuDiskCacheHandle& handle); - void PopulateShaderCache(int32_t client_id, - const std::string& key, - const std::string& program); + void PopulateCache(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& program); void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id, const SyncToken& sync_token);
diff --git a/gpu/ipc/service/gpu_channel_manager_delegate.h b/gpu/ipc/service/gpu_channel_manager_delegate.h index dbe8f26..ef4b4bfb 100644 --- a/gpu/ipc/service/gpu_channel_manager_delegate.h +++ b/gpu/ipc/service/gpu_channel_manager_delegate.h
@@ -8,6 +8,7 @@ #include "build/build_config.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/config/gpu_info.h" +#include "gpu/ipc/common/gpu_disk_cache_type.h" #include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/service/display_context.h" @@ -51,12 +52,12 @@ error::ContextLostReason reason, const GURL& active_url) = 0; - // Tells the delegate to cache the given shader information in persistent + // Tells the delegate to cache the given blob information in persistent // storage. The embedder is expected to repopulate the in-memory cache through // the respective GpuChannelManager API. - virtual void StoreShaderToDisk(int32_t client_id, - const std::string& key, - const std::string& shader) = 0; + virtual void StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& shader) = 0; // Cleanly exits the GPU process in response to an error. This will not exit // with in-process GPU as that would also exit the browser. This can only be
diff --git a/gpu/ipc/service/gpu_channel_manager_unittest.cc b/gpu/ipc/service/gpu_channel_manager_unittest.cc index 9b02192..930ec23 100644 --- a/gpu/ipc/service/gpu_channel_manager_unittest.cc +++ b/gpu/ipc/service/gpu_channel_manager_unittest.cc
@@ -181,8 +181,7 @@ ASSERT_TRUE(channel_manager()); GpuChannel* channel = channel_manager()->EstablishChannel( - base::UnguessableToken::Create(), kClientId, kClientTracingId, false, - true); + base::UnguessableToken::Create(), kClientId, kClientTracingId, false); EXPECT_TRUE(channel); EXPECT_EQ(channel_manager()->LookupChannel(kClientId), channel); }
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc index c26e6e97..a1294bc 100644 --- a/gpu/ipc/service/gpu_channel_test_common.cc +++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -54,9 +54,9 @@ void DidLoseContext(bool offscreen, error::ContextLostReason reason, const GURL& active_url) override {} - void StoreShaderToDisk(int32_t client_id, - const std::string& key, - const std::string& shader) override {} + void StoreBlobToDisk(const gpu::GpuDiskCacheHandle& handle, + const std::string& key, + const std::string& shader) override {} void MaybeExitOnContextLost() override { is_exiting_ = true; } bool IsExiting() const override { return is_exiting_; } #if BUILDFLAG(IS_WIN) @@ -118,7 +118,7 @@ uint64_t kClientTracingId = 1; GpuChannel* channel = channel_manager()->EstablishChannel( base::UnguessableToken::Create(), client_id, kClientTracingId, - is_gpu_host, true); + is_gpu_host); base::ProcessId kProcessId = 1; channel->set_client_pid(kProcessId); return channel;
diff --git a/infra/config/console-header.star b/infra/config/console-header.star index 4c48480c4..adf5681 100644 --- a/infra/config/console-header.star +++ b/infra/config/console-header.star
@@ -232,6 +232,11 @@ url = "/p/{}/g/chromium.chromiumos".format(settings.project), alt = "ChromiumOS console", ), + headers.link( + text = "flakiness", + url = "/p/{}/g/chromium.flakiness".format(settings.project), + alt = "Chromium Flakiness console", + ), ], ), headers.link_group(
diff --git a/infra/config/generated/builders/ci/mac-backuprefptr-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/mac-backuprefptr-x64-fyi-rel/properties.json index 8e72d66..99768ef 100644 --- a/infra/config/generated/builders/ci/mac-backuprefptr-x64-fyi-rel/properties.json +++ b/infra/config/generated/builders/ci/mac-backuprefptr-x64-fyi-rel/properties.json
@@ -1,8 +1,50 @@ { - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "mac-backuprefptr-x64-fyi-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_bits": 64, + "target_platform": "mac" + }, + "legacy_gclient_config": { + "config": "chromium" + }, + "legacy_test_results_config": { + "config": "staging_server" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "mac-backuprefptr-x64-fyi-rel", + "project": "chromium" + } + ] + } + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 250, + "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index ad794dbd..9e86d1e 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -3385,7 +3385,10 @@ ' "cache_silo": "Comparison Mac - cache siloed",' ' "instance": "rbe-chromium-trusted-test",' ' "jobs": 250,' - ' "metrics_project": "chromium-reclient-metrics"' + ' "metrics_project": "chromium-reclient-metrics",' + ' "rewrapper_env": {' + ' "RBE_exec_strategy": "racing"' + ' }' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [],' @@ -3541,7 +3544,10 @@ ' "cache_silo": "Comparison Mac - cache siloed",' ' "instance": "rbe-chromium-trusted-test",' ' "jobs": 250,' - ' "metrics_project": "chromium-reclient-metrics"' + ' "metrics_project": "chromium-reclient-metrics",' + ' "rewrapper_env": {' + ' "RBE_exec_strategy": "racing"' + ' }' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [],' @@ -4020,7 +4026,10 @@ ' "cache_silo": "Comparison ios - cache siloed",' ' "instance": "rbe-chromium-trusted-test",' ' "jobs": 250,' - ' "metrics_project": "chromium-reclient-metrics"' + ' "metrics_project": "chromium-reclient-metrics",' + ' "rewrapper_env": {' + ' "RBE_exec_strategy": "racing"' + ' }' ' },' ' "$recipe_engine/resultdb/test_presentation": {' ' "column_keys": [],' @@ -36162,13 +36171,11 @@ builders { name: "linux-chromeos-rel" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:16" + dimensions: "builder:linux-chromeos-rel" + dimensions: "cores:8" dimensions: "cpu:x86-64" - dimensions: "free_space:standard" dimensions: "os:Ubuntu-18.04" dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:1" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest" @@ -36891,13 +36898,11 @@ builders { name: "linux-lacros-builder-rel" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:16" + dimensions: "builder:linux-lacros-builder-rel" + dimensions: "cores:8" dimensions: "cpu:x86-64" - dimensions: "free_space:standard" dimensions: "os:Ubuntu-18.04" dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:1" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest" @@ -37214,13 +37219,11 @@ builders { name: "linux-lacros-dbg" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:16" + dimensions: "builder:linux-lacros-dbg" + dimensions: "cores:8" dimensions: "cpu:x86-64" - dimensions: "free_space:standard" dimensions: "os:Ubuntu-18.04" dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:1" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest" @@ -39847,6 +39850,7 @@ name: "mac-backuprefptr-x64-fyi-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" + dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" dimensions: "os:Mac" @@ -45411,6 +45415,56 @@ } } buckets { + name: "flaky-reproducer" + acls { + role: WRITER + group: "mdb/chrome-flakiness" + } + acls { + group: "all" + } + acls { + role: SCHEDULER + group: "project-chromium-tryjob-access" + } + swarming { + builders { + name: "runner" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:0" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "recipe": "flakiness/reproducer"' + '}' + execution_timeout_secs: 7200 + build_numbers: NO + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + } + } + } +} +buckets { name: "goma" acls { role: WRITER
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 97cfa9c..c586f63 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -836,6 +836,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -1591,6 +1596,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -2070,6 +2080,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -2424,6 +2439,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -3110,6 +3130,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -3445,6 +3470,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -4043,6 +4073,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -4461,6 +4496,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -4865,6 +4905,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -5307,6 +5352,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -5866,6 +5916,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -6330,6 +6385,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -6476,6 +6536,11 @@ category: "flakiness" short_name: "model" } + builders { + name: "buildbucket/luci.chromium.flaky-reproducer/runner" + category: "flakiness" + short_name: "reproducer" + } } consoles { id: "chromium.fuchsia" @@ -6701,6 +6766,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -7065,6 +7135,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -7553,6 +7628,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -8440,6 +8520,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -8866,6 +8951,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -9266,6 +9356,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -9661,6 +9756,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -10293,6 +10393,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -10702,6 +10807,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -11126,6 +11236,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -11575,6 +11690,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -11934,6 +12054,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -12383,6 +12508,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -12733,6 +12863,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -13107,6 +13242,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -13581,6 +13721,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -13950,6 +14095,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -14360,6 +14510,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -14749,6 +14904,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -15149,6 +15309,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -15482,6 +15647,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles" @@ -15829,6 +15999,11 @@ url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" } + links { + text: "flakiness" + url: "/p/chromium/g/chromium.flakiness" + alt: "Chromium Flakiness console" + } } links { name: "Branch Consoles"
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg index b3d9d9f1..d6ba620 100644 --- a/infra/config/generated/luci/realms.cfg +++ b/infra/config/generated/luci/realms.cfg
@@ -327,6 +327,25 @@ } } realms { + name: "flaky-reproducer" + bindings { + role: "role/buildbucket.builderServiceAccount" + principals: "user:chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + } + bindings { + role: "role/buildbucket.owner" + principals: "group:mdb/chrome-flakiness" + } + bindings { + role: "role/buildbucket.reader" + principals: "group:all" + } + bindings { + role: "role/buildbucket.triggerer" + principals: "group:project-chromium-tryjob-access" + } +} +realms { name: "goma" bindings { role: "role/buildbucket.builderServiceAccount"
diff --git a/infra/config/recipes.star b/infra/config/recipes.star index 56e0851..806f545 100644 --- a/infra/config/recipes.star +++ b/infra/config/recipes.star
@@ -205,6 +205,10 @@ ) build_recipe( + name = "recipe:flakiness/reproducer", +) + +build_recipe( name = "recipe:findit/chromium/single_revision", bootstrappable = POLYMORPHIC, )
diff --git a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star index 1a15302..bff8cba3 100644 --- a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star +++ b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
@@ -702,8 +702,7 @@ # This builder build 2 chrome(Ash and Lacros), so it need # more time. # TODO(crbug.com/1345687): use normal machines. - cores = 16, - ssd = True, + builderless = False, ) ci.builder( @@ -735,8 +734,7 @@ main_console_view = "main", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, # TODO(crbug.com/1345687): use normal machines. - cores = 16, - ssd = True, + builderless = False, ) ci.thin_tester( @@ -801,8 +799,7 @@ main_console_view = "main", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, # TODO(crbug.com/1345687): use normal machines. - cores = 16, - ssd = True, + builderless = False, ) # For Chromebox for meetings(CfM)
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index d7ecd32..b2c4862 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -797,9 +797,29 @@ category = "backuprefptr|mac", short_name = "64rel", ), - cores = None, notifies = ["chrome-memory-safety"], os = os.MAC_ANY, + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_bits = 64, + target_platform = builder_config.target_platform.MAC, + ), + test_results_config = builder_config.test_results_config( + config = "staging_server", + ), + build_gs_bucket = "chromium-fyi-archive", + ), + goma_backend = None, + reclient_jobs = reclient.jobs.DEFAULT, + reclient_instance = reclient.instance.DEFAULT_TRUSTED, ) ci.builder( @@ -940,6 +960,9 @@ reclient_jobs = 250, os = os.MAC_DEFAULT, cores = None, + reclient_rewrapper_env = { + "RBE_exec_strategy": "racing", + }, ) ci.builder( @@ -957,6 +980,9 @@ reclient_jobs = 250, os = os.MAC_DEFAULT, cores = None, + reclient_rewrapper_env = { + "RBE_exec_strategy": "racing", + }, ) ci.builder( @@ -1026,6 +1052,9 @@ os = os.MAC_DEFAULT, cores = None, xcode = xcode.x14main, + reclient_rewrapper_env = { + "RBE_exec_strategy": "racing", + }, ) ci.builder(
diff --git a/infra/config/subprojects/flakiness/reproducer.star b/infra/config/subprojects/flakiness/reproducer.star new file mode 100644 index 0000000..0c0c720a2 --- /dev/null +++ b/infra/config/subprojects/flakiness/reproducer.star
@@ -0,0 +1,41 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +load("//lib/builders.star", "builders", "os") +load("//lib/try.star", "try_") +load("//lib/consoles.star", "consoles") + +luci.bucket( + name = "flaky-reproducer", + acls = [ + acl.entry( + roles = acl.BUILDBUCKET_READER, + groups = "all", + ), + acl.entry( + roles = acl.BUILDBUCKET_TRIGGERER, + groups = "project-chromium-tryjob-access", + ), + acl.entry( + roles = acl.BUILDBUCKET_OWNER, + groups = "mdb/chrome-flakiness", + ), + ], +) + +builders.builder( + name = "runner", + bucket = "flaky-reproducer", + executable = "recipe:flakiness/reproducer", + build_numbers = False, + execution_timeout = 2 * time.hour, + os = os.LINUX_DEFAULT, + pool = "luci.chromium.try", + service_account = try_.DEFAULT_SERVICE_ACCOUNT, + console_view_entry = consoles.console_view_entry( + console_view = "chromium.flakiness", + category = "flakiness", + short_name = "reproducer", + ), +)
diff --git a/infra/config/subprojects/flakiness/subproject.star b/infra/config/subprojects/flakiness/subproject.star index c196c63b..ae81ca9b 100644 --- a/infra/config/subprojects/flakiness/subproject.star +++ b/infra/config/subprojects/flakiness/subproject.star
@@ -3,3 +3,4 @@ # found in the LICENSE file. exec("./flakiness.star") +exec("./reproducer.star")
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index b3858b9f..7703119 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -79,6 +79,7 @@ #import "ios/chrome/browser/ui/default_promo/default_browser_utils.h" #import "ios/chrome/browser/ui/download/features.h" #include "ios/chrome/browser/ui/first_run/fre_field_trial.h" +#import "ios/chrome/browser/ui/first_run/trending_queries_field_trial.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" #import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" @@ -1108,7 +1109,7 @@ flag_descriptions::kTrendingQueriesModuleDescription, flags_ui::kOsIos, FEATURE_WITH_PARAMS_VALUE_TYPE(kTrendingQueriesModule, kTrendingQueriesModuleVariations, - "TrendingQueriesModule")}, + kTrendingQueriesFieldTrialName)}, {"autofill-parse-iban-fields", flag_descriptions::kAutofillParseIBANFieldsName, flag_descriptions::kAutofillParseIBANFieldsDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/ntp/features.mm b/ios/chrome/browser/ntp/features.mm index 0a2c0ed2..3d8d3913 100644 --- a/ios/chrome/browser/ntp/features.mm +++ b/ios/chrome/browser/ntp/features.mm
@@ -71,7 +71,7 @@ NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; dateFormatter.dateStyle = NSDateFormatterShortStyle; dateFormatter.timeStyle = NSDateFormatterShortStyle; - dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + dateFormatter.locale = [NSLocale autoupdatingCurrentLocale]; [[NSUserDefaults standardUserDefaults] setObject:[dateFormatter stringFromDate:timestamp] forKey:@"FeedLastBackgroundRefreshTimestamp"]; @@ -125,7 +125,7 @@ } return base::GetFieldTrialParamByFeatureAsDouble(kEnableFeedBackgroundRefresh, kMaxCacheAgeInSeconds, - /*default=*/60 * 60); + /*default=*/8 * 60 * 60); } double GetBackgroundRefreshIntervalInSeconds() {
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 4d86ea0..f4b3a464 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -74,7 +74,6 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h" #include "ios/chrome/browser/ui/first_run/fre_field_trial.h" -#import "ios/chrome/browser/ui/first_run/trending_queries_field_trial.h" #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/voice/voice_search_prefs_registration.h" @@ -128,7 +127,6 @@ update_client::RegisterPrefs(registry); variations::VariationsService::RegisterPrefs(registry); fre_field_trial::RegisterLocalStatePrefs(registry); - trending_queries_field_trial::RegisterLocalStatePrefs(registry); component_updater::RegisterComponentUpdateServicePrefs(registry); component_updater::AutofillStatesComponentInstallerPolicy::RegisterPrefs( registry);
diff --git a/ios/chrome/browser/resources/Settings.bundle/ExperimentalFeedRefresh.plist b/ios/chrome/browser/resources/Settings.bundle/ExperimentalFeedRefresh.plist index 1c23a8f..c062993c 100644 --- a/ios/chrome/browser/resources/Settings.bundle/ExperimentalFeedRefresh.plist +++ b/ios/chrome/browser/resources/Settings.bundle/ExperimentalFeedRefresh.plist
@@ -5,6 +5,36 @@ <key>PreferenceSpecifiers</key> <array> <dict> + <key>Title</key> + <string>Debug Settings</string> + <key>Type</key> + <string>PSGroupSpecifier</string> + <key>FooterText</key> + <string>This is not available in stable.</string> + </dict> + <dict> + <key>Type</key> + <string>PSToggleSwitchSpecifier</string> + <key>Title</key> + <string>Enable notifications when background refreshes are completed</string> + <key>Key</key> + <string>FeedBackgroundRefreshNotificationEnabled</string> + <key>DefaultValue</key> + <false/> + </dict> + <dict> + <key>Type</key> + <string>PSTextFieldSpecifier</string> + <key>Title</key> + <string>Last Foreground Refresh Timestamp</string> + <key>Key</key> + <string>FeedLastForegroundRefreshTimestamp</string> + <key>DefaultValue</key> + <string></string> + <key>KeyboardType</key> + <string>Alphabet</string> + </dict> + <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> @@ -40,7 +70,7 @@ <key>Type</key> <string>PSGroupSpecifier</string> <key>FooterText</key> - <string>Foreground refreshes occur on cold starts and new NTPs. They do not occur on app foregrounding.</string> + <string>Foreground refreshes occur on cold starts, new NTPs, and switching tabs to an NTP. They do not occur on app foregrounding.</string> </dict> <dict> <key>Type</key> @@ -104,24 +134,6 @@ <key>DefaultValue</key> <false/> </dict> - <dict> - <key>Title</key> - <string>Debug Settings</string> - <key>Type</key> - <string>PSGroupSpecifier</string> - <key>FooterText</key> - <string>This is not available in stable.</string> - </dict> - <dict> - <key>Type</key> - <string>PSToggleSwitchSpecifier</string> - <key>Title</key> - <string>Enable notifications when background refreshes are completed</string> - <key>Key</key> - <string>FeedBackgroundRefreshNotificationEnabled</string> - <key>DefaultValue</key> - <false/> - </dict> </array> </dict> </plist>
diff --git a/ios/chrome/browser/ui/first_run/trending_queries_field_trial.cc b/ios/chrome/browser/ui/first_run/trending_queries_field_trial.cc index 767c59f..e9e5644586 100644 --- a/ios/chrome/browser/ui/first_run/trending_queries_field_trial.cc +++ b/ios/chrome/browser/ui/first_run/trending_queries_field_trial.cc
@@ -7,7 +7,6 @@ #import "base/feature_list.h" #import "base/metrics/field_trial.h" #import "base/metrics/field_trial_params.h" -#import "components/prefs/pref_registry_simple.h" #import "components/prefs/pref_service.h" #import "components/version_info/version_info.h" #import "ios/chrome/browser/first_run/first_run.h" @@ -15,14 +14,10 @@ #import "ios/chrome/browser/ui/first_run/ios_first_run_field_trials.h" #import "ios/chrome/common/channel_info.h" +// Name of the Trending Queries Field Trial. +const char kTrendingQueriesFieldTrialName[] = "TrendingQueries"; + namespace { -// String local state preference with the name of the assigned trial group. -// Empty if no group has been assigned yet. -const char kTrialVersionPrefName[] = "trending_queries.trial_group"; -// Default local state pref value. -const int kDefaultPrefValue = -1; -// The current trial version; should be updated when the experiment is modified. -const int kCurrentTrialVersion = 1; // Group names for the Trending Queries feature. const char kTrendingQueriesEnabledAllUsersGroup[] = "EnabledAllUsers-V1"; @@ -69,17 +64,19 @@ // Creates the trial config, initializes the trial that puts clients into // different groups, and returns the version number of the current trial. There -// are 5 groups other than the default group: +// are 6 groups other than the default group: // - Control // - Enabled for All users // - Enabled for All users and Hide Shortcuts // - Enabled for signed out users // - Enabled for users that had the feed disabled -int CreateTrendingQueriesTrial( +// - Disabled for All users and Hide Shortcuts (essentially only showing +// Most Visited and pushing up the feed) +void CreateTrendingQueriesTrial( std::map<variations::VariationID, int> weight_by_id, const base::FieldTrial::EntropyProvider& low_entropy_provider, base::FeatureList* feature_list) { - FirstRunFieldTrialConfig config(kTrendingQueriesModule.name); + FirstRunFieldTrialConfig config(kTrendingQueriesFieldTrialName); // Control group. config.AddGroup(kTrendingQueriesControlGroup, kTrendingQueriesControlID, @@ -94,7 +91,7 @@ params[kTrendingQueriesDisabledFeedParam] = "false"; params[kTrendingQueriesSignedOutParam] = "false"; params[kTrendingQueriesNeverShowModuleParam] = "false"; - base::AssociateFieldTrialParams(kTrendingQueriesModule.name, + base::AssociateFieldTrialParams(kTrendingQueriesFieldTrialName, kTrendingQueriesEnabledAllUsersGroup, params); config.AddGroup(kTrendingQueriesEnabledAllUsersHideShortcutsGroup, @@ -105,7 +102,7 @@ params[kTrendingQueriesSignedOutParam] = "false"; params[kTrendingQueriesNeverShowModuleParam] = "false"; base::AssociateFieldTrialParams( - kTrendingQueriesModule.name, + kTrendingQueriesFieldTrialName, kTrendingQueriesEnabledAllUsersHideShortcutsGroup, params); config.AddGroup(kTrendingQueriesEnabledDisabledFeedGroup, @@ -115,7 +112,7 @@ params[kTrendingQueriesDisabledFeedParam] = "true"; params[kTrendingQueriesSignedOutParam] = "false"; params[kTrendingQueriesNeverShowModuleParam] = "false"; - base::AssociateFieldTrialParams(kTrendingQueriesModule.name, + base::AssociateFieldTrialParams(kTrendingQueriesFieldTrialName, kTrendingQueriesEnabledDisabledFeedGroup, params); @@ -126,7 +123,7 @@ params[kTrendingQueriesDisabledFeedParam] = "false"; params[kTrendingQueriesSignedOutParam] = "true"; params[kTrendingQueriesNeverShowModuleParam] = "false"; - base::AssociateFieldTrialParams(kTrendingQueriesModule.name, + base::AssociateFieldTrialParams(kTrendingQueriesFieldTrialName, kTrendingQueriesEnabledSignedOutGroup, params); @@ -137,7 +134,7 @@ params[kTrendingQueriesDisabledFeedParam] = "false"; params[kTrendingQueriesSignedOutParam] = "false"; params[kTrendingQueriesNeverShowModuleParam] = "true"; - base::AssociateFieldTrialParams(kTrendingQueriesModule.name, + base::AssociateFieldTrialParams(kTrendingQueriesFieldTrialName, kTrendingQueriesEnabledNeverShowModuleGroup, params); @@ -157,52 +154,35 @@ feature_list->RegisterFieldTrialOverride( kTrendingQueriesModule.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get()); + } else if (group_name == kTrendingQueriesControlGroup) { + feature_list->RegisterFieldTrialOverride( + kTrendingQueriesModule.name, + base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial.get()); } - - return kCurrentTrialVersion; -} - -void RegisterLocalStatePrefs(PrefRegistrySimple* registry) { - registry->RegisterIntegerPref(kTrialVersionPrefName, kDefaultPrefValue); } void Create(const base::FieldTrial::EntropyProvider& low_entropy_provider, base::FeatureList* feature_list, PrefService* local_state) { - // The client would not be assigned to any group because features controlled - // by the experiment is already overridden from the command line. This handles - // scenarios where FRE is forced for testing purposes. - // Also return early if the feature is already enabled for this client. This - // is needed for explicit flag settings in chrome://flags. - if (feature_list->IsFeatureOverriddenFromCommandLine( - kTrendingQueriesModule.name) || - base::FeatureList::IsEnabled(kTrendingQueriesModule)) { + // Don't create the trial if it was already created for testing. This is only + // expected when the browser is used for development purpose. The trial + // created when the about flag is set will have the same name as the + // `kTrendingQueriesModule`. This condition is to avoid having multiple trials + // overriding the same feature. A trial might have also been created with the + // commandline arguments. + if (base::FieldTrialList::TrialExists(kTrendingQueriesFieldTrialName)) { return; } - if (local_state->GetInteger(kTrialVersionPrefName) != kDefaultPrefValue) { - // User has already been bucketed. - return; - } - - // Create trial and group for the first time, and store the experiment - // version in prefs for subsequent runs. - int trial_version = CreateTrendingQueriesTrial( - GetGroupWeights(), low_entropy_provider, feature_list); - // Persist the experiment version for subsequent runs. - local_state->SetInteger(kTrialVersionPrefName, trial_version); + CreateTrendingQueriesTrial(GetGroupWeights(), low_entropy_provider, + feature_list); } -namespace testing { - -int CreateTrendingQueriesTrialForTesting( +void CreateTrendingQueriesTrialForTesting( std::map<variations::VariationID, int> weights_by_id, const base::FieldTrial::EntropyProvider& low_entropy_provider, base::FeatureList* feature_list) { - return CreateTrendingQueriesTrial(weights_by_id, low_entropy_provider, - feature_list); + CreateTrendingQueriesTrial(weights_by_id, low_entropy_provider, feature_list); } -} // namespace testing - } // namespace trending_queries_field_trial
diff --git a/ios/chrome/browser/ui/first_run/trending_queries_field_trial.h b/ios/chrome/browser/ui/first_run/trending_queries_field_trial.h index a36ca7b3..be7ccc73 100644 --- a/ios/chrome/browser/ui/first_run/trending_queries_field_trial.h +++ b/ios/chrome/browser/ui/first_run/trending_queries_field_trial.h
@@ -9,7 +9,8 @@ #include "components/variations/variations_associated_data.h" class PrefService; -class PrefRegistrySimple; + +extern const char kTrendingQueriesFieldTrialName[]; namespace { @@ -27,8 +28,6 @@ namespace trending_queries_field_trial { -void RegisterLocalStatePrefs(PrefRegistrySimple* registry); - // Creates a field trial to control the Trending Queries feature so that it is // shown on the NTP after first run. // @@ -37,16 +36,12 @@ base::FeatureList* feature_list, PrefService* local_state); -namespace testing { - // Exposes CreateTrendingQueriesTrial() for testing FieldTrial set-up. -int CreateTrendingQueriesTrialForTesting( +void CreateTrendingQueriesTrialForTesting( std::map<variations::VariationID, int> weights_by_id, const base::FieldTrial::EntropyProvider& low_entropy_provider, base::FeatureList* feature_list); -} // namespace testing - } // namespace trending_queries_field_trial #endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_TRENDING_QUERIES_FIELD_TRIAL_H_
diff --git a/ios/chrome/browser/ui/first_run/trending_queries_field_trial_unittest.mm b/ios/chrome/browser/ui/first_run/trending_queries_field_trial_unittest.mm index e1a5a5dd..91c0deb 100644 --- a/ios/chrome/browser/ui/first_run/trending_queries_field_trial_unittest.mm +++ b/ios/chrome/browser/ui/first_run/trending_queries_field_trial_unittest.mm
@@ -40,17 +40,32 @@ base::MockEntropyProvider low_entropy_provider_; }; -// Tests control field trial. -TEST_F(TrendingQueriesFieldTrialTest, TestControl) { +// Tests default field trial group. +TEST_F(TrendingQueriesFieldTrialTest, TestDefault) { auto feature_list = std::make_unique<base::FeatureList>(); - weight_by_id_[kTrendingQueriesControlID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); + EXPECT_FALSE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); +} + +// Tests control field trial. +TEST_F(TrendingQueriesFieldTrialTest, TestControl) { + auto feature_list = std::make_unique<base::FeatureList>(); + weight_by_id_[kTrendingQueriesControlID] = 100; + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( + weight_by_id_, low_entropy_provider_, feature_list.get()); + + // Substitute the existing feature list with the one with field trial + // configurations we are testing, and check assertions. + scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_FALSE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); } @@ -58,13 +73,14 @@ TEST_F(TrendingQueriesFieldTrialTest, TestEnabledAllUsers) { auto feature_list = std::make_unique<base::FeatureList>(); weight_by_id_[kTrendingQueriesEnabledAllUsersID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_TRUE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); EXPECT_FALSE(base::GetFieldTrialParamByFeatureAsBool( kTrendingQueriesModule, kTrendingQueriesHideShortcutsParam, true)); @@ -80,13 +96,14 @@ TEST_F(TrendingQueriesFieldTrialTest, TestEnabledHideShortcuts) { auto feature_list = std::make_unique<base::FeatureList>(); weight_by_id_[kTrendingQueriesEnabledAllUsersHideShortcutsID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_TRUE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); EXPECT_TRUE(base::GetFieldTrialParamByFeatureAsBool( kTrendingQueriesModule, kTrendingQueriesHideShortcutsParam, false)); @@ -102,13 +119,14 @@ TEST_F(TrendingQueriesFieldTrialTest, TestEnabledDisabledFeed) { auto feature_list = std::make_unique<base::FeatureList>(); weight_by_id_[kTrendingQueriesEnabledDisabledFeedID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_TRUE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); EXPECT_FALSE(base::GetFieldTrialParamByFeatureAsBool( kTrendingQueriesModule, kTrendingQueriesHideShortcutsParam, true)); @@ -124,13 +142,14 @@ TEST_F(TrendingQueriesFieldTrialTest, TestEnabledSignedOut) { auto feature_list = std::make_unique<base::FeatureList>(); weight_by_id_[kTrendingQueriesEnabledSignedOutID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_TRUE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); EXPECT_TRUE(base::GetFieldTrialParamByFeatureAsBool( kTrendingQueriesModule, kTrendingQueriesHideShortcutsParam, false)); @@ -146,13 +165,14 @@ TEST_F(TrendingQueriesFieldTrialTest, TestEnabledNeverShowModule) { auto feature_list = std::make_unique<base::FeatureList>(); weight_by_id_[kTrendingQueriesEnabledNeverShowModuleID] = 100; - trending_queries_field_trial::testing::CreateTrendingQueriesTrialForTesting( + trending_queries_field_trial::CreateTrendingQueriesTrialForTesting( weight_by_id_, low_entropy_provider_, feature_list.get()); // Substitute the existing feature list with the one with field trial // configurations we are testing, and check assertions. scoped_feature_list_.InitWithFeatureList(std::move(feature_list)); - ASSERT_TRUE(base::FieldTrialList::IsTrialActive(kTrendingQueriesModule.name)); + ASSERT_TRUE( + base::FieldTrialList::IsTrialActive(kTrendingQueriesFieldTrialName)); EXPECT_TRUE(base::FeatureList::IsEnabled(kTrendingQueriesModule)); EXPECT_TRUE(base::GetFieldTrialParamByFeatureAsBool( kTrendingQueriesModule, kTrendingQueriesHideShortcutsParam, false));
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_action_list.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_action_list.swift index 7eb93339..ce4d66b1 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_action_list.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_action_list.swift
@@ -27,7 +27,7 @@ } .simultaneousGesture( DragGesture().onChanged({ _ in - metricsHandler?.popupMenuScrolled() + metricsHandler?.popupMenuScrolledVertically() }) ) .accessibilityIdentifier(kPopupMenuToolsMenuActionListId)
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift index a5005b41..f2f9f09 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift
@@ -36,6 +36,18 @@ /// Space above the list pushing them down from the grabber. static let topMargin: CGFloat = 20 + + /// The name for the coordinate space of the scroll view, so children can + /// find their positioning in the scroll view. + static let coordinateSpaceName = "destinations" + } + + /// `PreferenceKey` to track the leading offset of the scroll view. + struct ScrollViewLeadingOffset: PreferenceKey { + static var defaultValue: CGFloat = .greatestFiniteMagnitude + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = min(value, nextValue()) + } } /// The current dynamic type size. @@ -49,6 +61,9 @@ weak var metricsHandler: PopupMenuMetricsHandler? + /// Tracks the list's current offset, to see when it scrolls. + @State var listOffset: CGFloat = 0 + var body: some View { GeometryReader { geometry in ScrollViewReader { proxy in @@ -62,21 +77,29 @@ iconPadding: spacing.iconPadding) let alignment: VerticalAlignment = sizeCategory >= .accessibilityMedium ? .center : .top - VStack { - Spacer(minLength: Constants.topMargin) - LazyHStack(alignment: alignment, spacing: 0) { - ForEach(destinations) { destination in - OverflowMenuDestinationView( - destination: destination, layoutParameters: layoutParameters, - metricsHandler: metricsHandler - ).id(destination.destinationName) + ZStack { + VStack { + Spacer(minLength: Constants.topMargin) + LazyHStack(alignment: alignment, spacing: 0) { + // Make sure the space to the first icon is constant, so add extra + // spacing before the first item. + Spacer(minLength: Constants.iconInitialSpace - spacing.iconSpacing) + ForEach(destinations) { destination in + OverflowMenuDestinationView( + destination: destination, layoutParameters: layoutParameters, + metricsHandler: metricsHandler + ).id(destination.destinationName) + } } } + GeometryReader { innerGeometry in + let offset = innerGeometry.frame(in: .named(Constants.coordinateSpaceName)).minX + Color.clear + .preference(key: ScrollViewLeadingOffset.self, value: offset) + } } - // Make sure the space to the first icon is constant, so add extra - // spacing before the first item. - .padding([.leading], Constants.iconInitialSpace - spacing.iconSpacing) } + .coordinateSpace(name: Constants.coordinateSpaceName) .accessibilityIdentifier(kPopupMenuToolsMenuTableViewId) .onAppear { if layoutDirection == .rightToLeft { @@ -84,6 +107,12 @@ } } } + .onPreferenceChange(ScrollViewLeadingOffset.self) { value in + if value != listOffset { + metricsHandler?.popupMenuScrolledHorizontally() + } + listOffset = value + } } }
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm index edd1a29..cd12f96 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
@@ -9,6 +9,8 @@ #import "base/metrics/histogram_macros.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" +#import "components/feature_engagement/public/event_constants.h" +#import "components/feature_engagement/public/tracker.h" #import "ios/chrome/browser/application_context.h" #import "ios/chrome/browser/bookmarks/bookmark_model_factory.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" @@ -97,8 +99,10 @@ // Time when the tools menu opened. @property(nonatomic, assign) NSTimeInterval toolsMenuOpenTime; -// Whether the tools menu was scrolled while it was open. -@property(nonatomic, assign) BOOL toolsMenuWasScrolled; +// Whether the tools menu was scrolled vertically while it was open. +@property(nonatomic, assign) BOOL toolsMenuWasScrolledVertically; +// Whether the tools menu was scrolled horizontally while it was open. +@property(nonatomic, assign) BOOL toolsMenuWasScrolledHorizontally; // Whether the user took an action on the tools menu while it was open. @property(nonatomic, assign) BOOL toolsMenuUserTookAction; @@ -193,7 +197,7 @@ self.toolsMenuOpenTime = 0; IOSOverflowMenuActionType actionType; - if (self.toolsMenuWasScrolled) { + if (self.toolsMenuWasScrolledVertically) { if (self.toolsMenuUserTookAction) { actionType = IOSOverflowMenuActionType::kScrollAction; } else { @@ -207,7 +211,13 @@ } } base::UmaHistogramEnumeration("IOS.OverflowMenu.ActionType", actionType); - self.toolsMenuWasScrolled = NO; + + if (!self.toolsMenuWasScrolledHorizontally && + !self.toolsMenuUserTookAction) { + [self trackToolsMenuNoHorizontalScrollOrAction]; + } + self.toolsMenuWasScrolledVertically = NO; + self.toolsMenuWasScrolledHorizontally = NO; self.toolsMenuUserTookAction = NO; } @@ -278,13 +288,17 @@ - (void)sheetPresentationControllerDidChangeSelectedDetentIdentifier: (UISheetPresentationController*)sheetPresentationController API_AVAILABLE(ios(15)) { - [self popupMenuScrolled]; + [self popupMenuScrolledVertically]; } #pragma mark - PopupMenuMetricsHandler -- (void)popupMenuScrolled { - self.toolsMenuWasScrolled = YES; +- (void)popupMenuScrolledVertically { + self.toolsMenuWasScrolledVertically = YES; +} + +- (void)popupMenuScrolledHorizontally { + self.toolsMenuWasScrolledHorizontally = YES; } - (void)popupMenuTookAction { @@ -351,7 +365,8 @@ // if not needed. if (type == PopupMenuTypeToolsMenu) { self.toolsMenuOpenTime = [NSDate timeIntervalSinceReferenceDate]; - self.toolsMenuWasScrolled = NO; + self.toolsMenuWasScrolledVertically = NO; + self.toolsMenuWasScrolledHorizontally = NO; self.toolsMenuUserTookAction = NO; if (IsNewOverflowMenuEnabled()) { if (@available(iOS 15, *)) { @@ -524,4 +539,19 @@ } } +- (void)trackToolsMenuNoHorizontalScrollOrAction { + ChromeBrowserState* browserState = self.browser->GetBrowserState(); + if (!browserState) { + return; + } + feature_engagement::Tracker* tracker = + feature_engagement::TrackerFactory::GetForBrowserState(browserState); + if (!tracker) { + return; + } + + tracker->NotifyEvent( + feature_engagement::events::kOverflowMenuNoHorizontalScrollOrAction); +} + @end
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_metrics_handler.h b/ios/chrome/browser/ui/popup_menu/popup_menu_metrics_handler.h index f77ee66..ae728a1 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_metrics_handler.h +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_metrics_handler.h
@@ -9,8 +9,12 @@ // happen in the view, so it can fire the correct metrics. @protocol PopupMenuMetricsHandler -// Called when the popup menu is scrolled. -- (void)popupMenuScrolled; +// Called when the popup menu is scrolled vertically. +- (void)popupMenuScrolledVertically; + +// Called when the popup menu is scrolled horizontally. This is only fired on +// the new popup menu. The ond one doesn't have a horizontal scroll. +- (void)popupMenuScrolledHorizontally; // Called when the user takes an action in the popup menu. - (void)popupMenuTookAction;
diff --git a/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm b/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm index 320fea1..6e1f63d 100644 --- a/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm +++ b/ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.mm
@@ -200,7 +200,7 @@ #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView*)scrollView { - [self.metricsHandler popupMenuScrolled]; + [self.metricsHandler popupMenuScrolledVertically]; } #pragma mark - UITableViewDelegate
diff --git a/media/capture/video/linux/video_capture_device_linux.cc b/media/capture/video/linux/video_capture_device_linux.cc index 3f2848a..ff48504 100644 --- a/media/capture/video/linux/video_capture_device_linux.cc +++ b/media/capture/video/linux/video_capture_device_linux.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/bind.h" +#include "base/synchronization/waitable_event.h" #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" #include "build/build_config.h" @@ -99,11 +100,16 @@ if (!capture_impl_) return; // Wrong state. - task_runner_->PostTask(FROM_HERE, - base::BindOnce(&V4L2CaptureDelegate::StopAndDeAllocate, - capture_impl_->GetWeakPtr())); - task_runner_->DeleteSoon(FROM_HERE, std::move(capture_impl_)); - capture_impl_ = nullptr; + // Shutdown must be synchronous, otherwise the next created capture device + // may conflict. + base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + if (task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VideoCaptureDeviceLinux::StopAndDeAllocateInternal, + base::Unretained(this), base::Unretained(&waiter)))) { + waiter.Wait(); + } } void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) { @@ -144,4 +150,13 @@ capture_impl_->GetWeakPtr(), rotation)); } +void VideoCaptureDeviceLinux::StopAndDeAllocateInternal( + base::WaitableEvent* waiter) { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(capture_impl_); + capture_impl_->StopAndDeAllocate(); + capture_impl_.reset(); + waiter->Signal(); +} + } // namespace media
diff --git a/media/capture/video/linux/video_capture_device_linux.h b/media/capture/video/linux/video_capture_device_linux.h index 0d2d413b..1d24f59 100644 --- a/media/capture/video/linux/video_capture_device_linux.h +++ b/media/capture/video/linux/video_capture_device_linux.h
@@ -18,6 +18,10 @@ #include "media/capture/video/video_capture_device.h" #include "media/capture/video_capture_types.h" +namespace base { +class WaitableEvent; +} + namespace media { class V4L2CaptureDelegate; @@ -54,6 +58,8 @@ const VideoCaptureDeviceDescriptor device_descriptor_; private: + void StopAndDeAllocateInternal(base::WaitableEvent* waiter); + const scoped_refptr<V4L2CaptureDevice> v4l2_; // Internal delegate doing the actual capture setting, buffer allocation and
diff --git a/media/formats/hls/common_playlist_unittest.cc b/media/formats/hls/common_playlist_unittest.cc index aef8c96..f994f79 100644 --- a/media/formats/hls/common_playlist_unittest.cc +++ b/media/formats/hls/common_playlist_unittest.cc
@@ -106,7 +106,6 @@ { // Default version is 1 auto fork = builder; - fork.ExpectPlaylist(HasVersion, 1); fork.ExpectOk(); } @@ -127,16 +126,24 @@ for (int i = 1; i <= 10; ++i) { auto fork = builder; fork.AppendLine("#EXT-X-VERSION:" + base::NumberToString(i)); - fork.ExpectPlaylist(HasVersion, i); + fork.SetVersion(i); fork.ExpectOk(); } for (int i : {11, 12, 100, 999}) { - // Versions 11+ are not supported by this parser + // Versions 11+ are not supported by this implementation auto fork = builder; fork.AppendLine("#EXT-X-VERSION:" + base::NumberToString(i)); + fork.SetVersion(i); fork.ExpectError(ParseStatusCode::kPlaylistHasUnsupportedVersion); } + + // Version must match what's expected + builder.SetVersion(5); + builder.ExpectError(ParseStatusCode::kPlaylistHasVersionMismatch); + + builder.AppendLine("#EXT-X-VESION:3"); + builder.ExpectError(ParseStatusCode::kPlaylistHasVersionMismatch); } TYPED_TEST(HlsCommonPlaylistTest, XIndependentSegmentsTag) {
diff --git a/media/formats/hls/media_playlist.cc b/media/formats/hls/media_playlist.cc index b142cb5..fc70d89 100644 --- a/media/formats/hls/media_playlist.cc +++ b/media/formats/hls/media_playlist.cc
@@ -15,6 +15,7 @@ #include "media/formats/hls/media_segment.h" #include "media/formats/hls/multivariant_playlist.h" #include "media/formats/hls/parse_status.h" +#include "media/formats/hls/playlist.h" #include "media/formats/hls/playlist_common.h" #include "media/formats/hls/source_string.h" #include "media/formats/hls/tags.h" @@ -59,7 +60,14 @@ ParseStatus::Or<MediaPlaylist> MediaPlaylist::Parse( base::StringPiece source, GURL uri, + types::DecimalInteger version, const MultivariantPlaylist* parent_playlist) { + DCHECK(version != 0); + if (version < Playlist::kMinSupportedVersion || + version > Playlist::kMaxSupportedVersion) { + return ParseStatusCode::kPlaylistHasUnsupportedVersion; + } + if (!uri.is_valid()) { return ParseStatusCode::kInvalidUri; } @@ -400,6 +408,11 @@ byterange_tag.reset(); } + // Version must match what was expected. + if (!common_state.CheckVersion(version)) { + return ParseStatusCode::kPlaylistHasVersionMismatch; + } + if (!target_duration_tag.has_value()) { return ParseStatusCode::kMediaPlaylistMissingTargetDuration; } @@ -507,7 +520,7 @@ return MediaPlaylist( CtorArgs{.uri = std::move(uri), - .version = common_state.GetVersion(), + .version = version, .independent_segments = independent_segments, .target_duration = target_duration, .partial_segment_info = std::move(partial_segment_info),
diff --git a/media/formats/hls/media_playlist.h b/media/formats/hls/media_playlist.h index a5194d4..9971c9f2 100644 --- a/media/formats/hls/media_playlist.h +++ b/media/formats/hls/media_playlist.h
@@ -130,14 +130,19 @@ bool CanBlockReload() const { return can_block_reload_; } // Attempts to parse the media playlist represented by `source`. `uri` must be - // a valid, non-empty GURL referring to the URI of this playlist. If this - // playlist was found through a multivariant playlist, `parent_playlist` must - // point to that playlist in order to support persistent properties and - // imported variables. Otherwise, it should be `nullptr`. If `source` is - // invalid, this returns an error. Otherwise, the parsed playlist is returned. + // a valid, non-empty GURL referring to the URI of this playlist. + // `version` is the HLS version expected to be given by a + // `EXT-X-VERSION` tag in this playlist (or `Playlist::kDefaultVersion` if + // none), which may be determined via `Playlist::IdentifyPlaylist`, or from a + // previous version of this playlist. If this playlist was found through a + // multivariant playlist, `parent_playlist` must point to that playlist in + // order to support persistent properties and imported variables. Otherwise, + // it should be `nullptr`. If `source` is invalid, this returns an error. + // Otherwise, the parsed playlist is returned. static ParseStatus::Or<MediaPlaylist> Parse( base::StringPiece source, GURL uri, + types::DecimalInteger version, const MultivariantPlaylist* parent_playlist); private:
diff --git a/media/formats/hls/media_playlist_fuzzer.cc b/media/formats/hls/media_playlist_fuzzer.cc index abe4cb3c..ad5b7161 100644 --- a/media/formats/hls/media_playlist_fuzzer.cc +++ b/media/formats/hls/media_playlist_fuzzer.cc
@@ -48,10 +48,10 @@ data_provider.ConsumeRandomLengthString(); // Determine playlist version (ignore type mismatch) - GetPlaylistVersion(multivariant_playlist_source); + const auto version = GetPlaylistVersion(multivariant_playlist_source); auto multivariant_playlist_result = media::hls::MultivariantPlaylist::Parse( multivariant_playlist_source, - GURL("http://localhost/multi_playlist.m3u8")); + GURL("http://localhost/multi_playlist.m3u8"), version); if (multivariant_playlist_result.has_error()) { return 0; } @@ -63,10 +63,10 @@ auto media_playlist_source = data_provider.ConsumeRemainingBytesAsString(); // Determine playlist version (ignore type mismatch) - GetPlaylistVersion(media_playlist_source); + const auto version = GetPlaylistVersion(media_playlist_source); media::hls::MediaPlaylist::Parse(media_playlist_source, GURL("http://localhost/playlist.m3u8"), - multivariant_playlist.get()); + version, multivariant_playlist.get()); return 0; }
diff --git a/media/formats/hls/media_playlist_unittest.cc b/media/formats/hls/media_playlist_unittest.cc index a9890af..2d8f567 100644 --- a/media/formats/hls/media_playlist_unittest.cc +++ b/media/formats/hls/media_playlist_unittest.cc
@@ -14,6 +14,7 @@ #include "media/formats/hls/media_playlist_test_builder.h" #include "media/formats/hls/multivariant_playlist.h" #include "media/formats/hls/parse_status.h" +#include "media/formats/hls/playlist.h" #include "media/formats/hls/tags.h" #include "media/formats/hls/test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,7 +26,8 @@ MultivariantPlaylist CreateMultivariantPlaylist( std::initializer_list<base::StringPiece> lines, - GURL uri = GURL("http://localhost/multi_playlist.m3u8")) { + GURL uri = GURL("http://localhost/multi_playlist.m3u8"), + types::DecimalInteger version = Playlist::kDefaultVersion) { std::string source; for (auto line : lines) { source.append(line.data(), line.size()); @@ -34,7 +36,7 @@ // Parse the given source. Failure here isn't supposed to be part of the test, // so use a CHECK. - auto result = MultivariantPlaylist::Parse(source, std::move(uri)); + auto result = MultivariantPlaylist::Parse(source, std::move(uri), version); CHECK(result.has_value()); return std::move(result).value(); } @@ -46,7 +48,7 @@ builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-TARGETDURATION:10"); builder.AppendLine("#EXT-X-VERSION:5"); - builder.ExpectPlaylist(HasVersion, 5); + builder.SetVersion(5); builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10)); builder.AppendLine("#EXTINF:9.2,\t"); @@ -150,7 +152,7 @@ builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-TARGETDURATION:10"); builder.AppendLine("#EXT-X-VERSION:8"); - builder.ExpectPlaylist(HasVersion, 8); + builder.SetVersion(8); builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10)); builder.AppendLine(R"(#EXT-X-DEFINE:NAME="ROOT",VALUE="http://video.com")"); @@ -199,7 +201,8 @@ // Test importing variables in a playlist with a parent auto parent = CreateMultivariantPlaylist( {"#EXTM3U", "#EXT-X-VERSION:8", - R"(#EXT-X-DEFINE:NAME="IMPORTED",VALUE="HELLO")"}); + R"(#EXT-X-DEFINE:NAME="IMPORTED",VALUE="HELLO")"}, + GURL("http://localhost/multi_playlist.m3u8"), 8); { // Referring to a parent playlist variable without importing it is an error auto fork = builder; @@ -633,7 +636,6 @@ MediaPlaylistTestBuilder builder; builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-TARGETDURATION:10"); - builder.ExpectPlaylist(HasVersion, 1); builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10)); // Default discontinuity state is false @@ -849,7 +851,6 @@ MediaPlaylistTestBuilder builder; builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-TARGETDURATION:10"); - builder.ExpectPlaylist(HasVersion, 1); builder.ExpectPlaylist(HasTargetDuration, base::Seconds(10)); // Default gap state is false
diff --git a/media/formats/hls/multivariant_playlist.cc b/media/formats/hls/multivariant_playlist.cc index 7346ed2..4d8ac09 100644 --- a/media/formats/hls/multivariant_playlist.cc +++ b/media/formats/hls/multivariant_playlist.cc
@@ -39,7 +39,14 @@ // static ParseStatus::Or<MultivariantPlaylist> MultivariantPlaylist::Parse( base::StringPiece source, - GURL uri) { + GURL uri, + types::DecimalInteger version) { + DCHECK(version != 0); + if (version < Playlist::kMinSupportedVersion || + version > Playlist::kMaxSupportedVersion) { + return ParseStatusCode::kPlaylistHasUnsupportedVersion; + } + if (!uri.is_valid()) { return ParseStatusCode::kInvalidUri; } @@ -167,7 +174,12 @@ return ParseStatusCode::kXStreamInfTagNotFollowedByUri; } - return MultivariantPlaylist(std::move(uri), common_state.GetVersion(), + // Version must match what was expected. + if (!common_state.CheckVersion(version)) { + return ParseStatusCode::kPlaylistHasVersionMismatch; + } + + return MultivariantPlaylist(std::move(uri), version, common_state.independent_segments_tag.has_value(), std::move(variants), std::move(common_state.variable_dict));
diff --git a/media/formats/hls/multivariant_playlist.h b/media/formats/hls/multivariant_playlist.h index 28cd8ff..8802755f 100644 --- a/media/formats/hls/multivariant_playlist.h +++ b/media/formats/hls/multivariant_playlist.h
@@ -39,13 +39,13 @@ Kind GetKind() const override; // Attempts to parse the multivariant playlist represented by `source`. `uri` - // must be a valid, non-empty GURL referring to the URI of this playlist. If - // the playlist source is invalid, returns an error. If the playlist source - // contains tags specific to media playlists, the error code will be - // `kMultivariantPlaylistHasMediaPlaylistTag`, at which point the caller may - // choose to parse it as a media playlist instead. - static ParseStatus::Or<MultivariantPlaylist> Parse(base::StringPiece source, - GURL uri); + // must be a valid, non-empty GURL referring to the URI of this playlist. + // `version` is the HLS version expected to be given by an `EXT-X-VERSION` tag + // in this playlist (or `Playlist::kDefaultVersion` if none), which may be + // determined via `Playlist::IdentifyPlaylist`. If the playlist source is + // invalid, returns an error. + static ParseStatus::Or<MultivariantPlaylist> + Parse(base::StringPiece source, GURL uri, types::DecimalInteger version); private: MultivariantPlaylist(GURL uri,
diff --git a/media/formats/hls/multivariant_playlist_fuzzer.cc b/media/formats/hls/multivariant_playlist_fuzzer.cc index 79dc0284..2a49a6b 100644 --- a/media/formats/hls/multivariant_playlist_fuzzer.cc +++ b/media/formats/hls/multivariant_playlist_fuzzer.cc
@@ -39,11 +39,11 @@ const base::StringPiece source(reinterpret_cast<const char*>(data), size); // Determine playlist version (ignoring type mismatch) - GetPlaylistVersion(source); + const auto version = GetPlaylistVersion(source); // Try to parse it as a multivariant playlist media::hls::MultivariantPlaylist::Parse( - source, GURL("http://localhost/playlist.m3u8")); + source, GURL("http://localhost/playlist.m3u8"), version); return 0; }
diff --git a/media/formats/hls/multivariant_playlist_unittest.cc b/media/formats/hls/multivariant_playlist_unittest.cc index 5bc1809..230c84b7 100644 --- a/media/formats/hls/multivariant_playlist_unittest.cc +++ b/media/formats/hls/multivariant_playlist_unittest.cc
@@ -20,7 +20,7 @@ MultivariantPlaylistTestBuilder builder; builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-VERSION:8"); - builder.ExpectPlaylist(HasVersion, 8); + builder.SetVersion(8); builder.AppendLine( R"(#EXT-X-DEFINE:NAME="HOST",VALUE="http://www.example.com")");
diff --git a/media/formats/hls/parse_status.cc b/media/formats/hls/parse_status.cc index aa2756f1..158fc5e 100644 --- a/media/formats/hls/parse_status.cc +++ b/media/formats/hls/parse_status.cc
@@ -40,6 +40,7 @@ PARSE_STATUS_CODE_CASE(kMediaSegmentExceedsTargetDuration); PARSE_STATUS_CODE_CASE(kPlaylistHasDuplicateTags); PARSE_STATUS_CODE_CASE(kPlaylistHasUnsupportedVersion); + PARSE_STATUS_CODE_CASE(kPlaylistHasVersionMismatch); PARSE_STATUS_CODE_CASE(kMediaPlaylistHasMultivariantPlaylistTag); PARSE_STATUS_CODE_CASE(kMultivariantPlaylistHasMediaPlaylistTag); PARSE_STATUS_CODE_CASE(kVariableUndefined);
diff --git a/media/formats/hls/parse_status.h b/media/formats/hls/parse_status.h index 3015cac..a00fa2c 100644 --- a/media/formats/hls/parse_status.h +++ b/media/formats/hls/parse_status.h
@@ -37,6 +37,7 @@ kMediaSegmentExceedsTargetDuration, kPlaylistHasDuplicateTags, kPlaylistHasUnsupportedVersion, + kPlaylistHasVersionMismatch, kMediaPlaylistHasMultivariantPlaylistTag, kMultivariantPlaylistHasMediaPlaylistTag, kVariableUndefined,
diff --git a/media/formats/hls/playlist_common.cc b/media/formats/hls/playlist_common.cc index 7c8295a..bbe0010 100644 --- a/media/formats/hls/playlist_common.cc +++ b/media/formats/hls/playlist_common.cc
@@ -6,14 +6,16 @@ #include "base/notreached.h" #include "media/formats/hls/playlist.h" +#include "media/formats/hls/types.h" namespace media::hls { -types::DecimalInteger CommonParserState::GetVersion() const { +bool CommonParserState::CheckVersion( + types::DecimalInteger expected_version) const { if (version_tag.has_value()) { - return version_tag.value().version; + return expected_version == version_tag->version; } else { - return Playlist::kDefaultVersion; + return expected_version == Playlist::kDefaultVersion; } } @@ -104,11 +106,6 @@ if (error.has_value()) { return error; } - - // Max supported playlist version is 10 - if (state->version_tag->version > 10) { - return ParseStatusCode::kPlaylistHasUnsupportedVersion; - } break; } }
diff --git a/media/formats/hls/playlist_common.h b/media/formats/hls/playlist_common.h index a6965ff..edb726b3 100644 --- a/media/formats/hls/playlist_common.h +++ b/media/formats/hls/playlist_common.h
@@ -31,9 +31,10 @@ // playlist, or a media playlist without other variants). raw_ptr<const VariableDictionary> parent_variable_dict = nullptr; - // Returns the version specified by `version_tag`, or the default version if - // the playlist did not contain a version tag. - types::DecimalInteger GetVersion() const; + // Checks that the versions given by `expected_version` and `version_tag` + // match. If `version_tag` is `absl::nullopt`, the version given is implicitly + // `Playlist::kDefaultVersion`. + bool CheckVersion(types::DecimalInteger expected_version) const; }; // Validates that the first line of the given SourceLineIterator contains a
diff --git a/media/formats/hls/playlist_test_builder.h b/media/formats/hls/playlist_test_builder.h index 2970d22..b45ae53 100644 --- a/media/formats/hls/playlist_test_builder.h +++ b/media/formats/hls/playlist_test_builder.h
@@ -33,6 +33,9 @@ // Sets the URI for the playlist being built. void SetUri(GURL uri) { uri_ = std::move(uri); } + // Sets the expected version for the playlist being built. + void SetVersion(types::DecimalInteger version) { version_ = version; } + // Appends fragments of text to the playlist, without a trailing newline. template <typename... T> void Append(base::StringPiece text1, T&&... rem) { @@ -66,7 +69,8 @@ void ExpectError(ParseStatusCode code, const base::Location& from, Args&&... args) const { - auto result = PlaylistT::Parse(source_, uri_, std::forward<Args>(args)...); + auto result = + PlaylistT::Parse(source_, uri_, version_, std::forward<Args>(args)...); ASSERT_TRUE(result.has_error()) << from.ToString(); auto actual_code = std::move(result).error().code(); @@ -80,13 +84,17 @@ // expectations. template <typename... Args> void ExpectOk(const base::Location& from, Args&&... args) const { - auto result = PlaylistT::Parse(source_, uri_, std::forward<Args>(args)...); + auto result = + PlaylistT::Parse(source_, uri_, version_, std::forward<Args>(args)...); ASSERT_TRUE(result.has_value()) << "Error: " << ParseStatusCodeToString(std::move(result).error().code()) << "\n" << from.ToString(); auto playlist = std::move(result).value(); + // Ensure that playlist has expected version + EXPECT_EQ(playlist.GetVersion(), version_) << from.ToString(); + for (const auto& expectation : playlist_expectations_) { expectation.Run(playlist); } @@ -101,16 +109,10 @@ std::vector<base::RepeatingCallback<void(const PlaylistT&)>> playlist_expectations_; GURL uri_ = GURL("http://localhost/playlist.m3u8"); + types::DecimalInteger version_ = Playlist::kDefaultVersion; std::string source_; }; -// Checks that the playlist has the given version. -inline void HasVersion(types::DecimalInteger version, - const base::Location& from, - const Playlist& playlist) { - EXPECT_EQ(playlist.GetVersion(), version) << from.ToString(); -} - // Checks the playlist's `AreSegmentsIndependent` property against the given // value. inline void HasIndependentSegments(bool value,
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 4c25972..2e7ddf6e 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -176781,6 +176781,139 @@ { "name": "wrightcountymo911.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, { "name": "yatescountyny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, { "name": "yavapaivotes.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "accedeainternet.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "berlinal.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "boenyc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "bondcountysa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "casscoroadmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "catchteamca.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "chinovalleyaz.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cityofeuporams.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cityoffergusonky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cityoflorettotn.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cityofmarionia.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "clarkcoky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cleanenergy.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cnmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cohassetma.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "cohassetpolicema.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "coloradofamli.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "csusop.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "dallasfire.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "dallaspolice.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "dallaswater.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "darienvillagewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "davenportok.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "dearbornheightsmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "dnfsb.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "duquoinil.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "eatonbrowncountywi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "fairfaxsc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "fairmountfireco.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "farmingtonlaxwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "fcsm.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "flaminggorgefireandems.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "foresttownrcwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "frazeysburg.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "friendswoodtx.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "gallaghertownshippa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "grandfieldok.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "greenfieldlaxwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "hempsteadcitytx.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "herkimercountyny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "hillsdalecounty.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "howellcountymo911.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "huttotxedc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "jacksontwpmcpa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "jaspertn.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "jeffersoncountyny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "kenedytxedc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "kimballwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "klamathtribalhealth.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "kscds.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lafayettewcwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lakearthurnm.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lansingvotes.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "laruecountyky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "laruralevolution.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lascruces.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lasmallbizonline.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "legrand-ia.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "lindenlibrary-nj.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "louisianalifesciences.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "louisiananetzero.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "marshallruskwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "marshfieldvillagevt.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "massauditor.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "mendonvt.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "minersvillepa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "mnccc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "mondoviwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "montebelloca.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "mtwolfpa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "myfloridarx.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "mymaineconnection.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "nassautrafficny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "newberlinwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "newcarlisleohio.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "newshorehamri.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "njeda.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "njshield.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "northwoodoh.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "opportunitylouisiana.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "parkcountyco.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "pendletoncountywv.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "portsmouthnhpd.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "prestonadamscountywi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "prospectky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "pslf.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "publicnoticesbaycountyfl.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "publicserviceloanforgiveness.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "redhookny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "resilientlouisianacommission.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "richlandcenterwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "rosstwpmcpa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "secaucusnjpolice.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "shermancountyne.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "skokie.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "somersworthnh.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "springportny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "stampinggroundky.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "statspolicy.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "stevenspoint.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "stratfordwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "taosnm.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "throopny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "thurmanny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofbeecherwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofchesterwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofclearlakewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofdrummondmt.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofgibsonwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofgrantsburgwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofjanesvillewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofkeystonewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townoflibertyocwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofmarshfieldwi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofstockbridge.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "townofulyssesny.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "trussville.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "unionmissouri.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "villageofdousman.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "villageoflavallewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "villageofoakdalewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "villageofstockbridgewi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "vokimberlywi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "volusiasheriff.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "wake.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "wardnd.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "washingtoncountyhomeoh.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "washingtoncountymn.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "watsontownshipmi.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "wiltonmanors.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "winchendon-ma.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "wyomingcountypa.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, + { "name": "youngsvillenc.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true }, // END OF ETLD-OWNER REQUESTED ENTRIES // To avoid trailing comma changes from showing up in diffs, we place a
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 4f0dc7c7..9b4b488 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -95,7 +95,6 @@ "audio_silence_detector.h", "audio_volume_filter.h", "basic_desktop_environment.h", - "chromoting_messages.h", "desktop_and_cursor_conditional_composer.h", "desktop_environment.h", "evaluate_capability.h", @@ -244,7 +243,6 @@ "chromoting_host.h", "chromoting_host_context.cc", "chromoting_host_context.h", - "chromoting_messages.cc", "client_session.cc", "client_session.h", "client_session_events.h",
diff --git a/remoting/host/OWNERS b/remoting/host/OWNERS index 2316a02..fd49718 100644 --- a/remoting/host/OWNERS +++ b/remoting/host/OWNERS
@@ -1,8 +1 @@ -per-file *_messages*.h=set noparent -per-file *_messages*.h=file://ipc/SECURITY_OWNERS - -per-file *_messages.cc=set noparent -per-file *_messages.cc=file://ipc/SECURITY_OWNERS - per-file *event_reporter*=file://components/reporting/OWNERS -
diff --git a/remoting/host/base/BUILD.gn b/remoting/host/base/BUILD.gn index 975bbf9..21dbbdda 100644 --- a/remoting/host/base/BUILD.gn +++ b/remoting/host/base/BUILD.gn
@@ -9,7 +9,6 @@ "//remoting/host/*", "//remoting/test/*", "//remoting/tools/*", - "//tools/ipc_fuzzer/message_lib:ipc_message_lib", ] public = [
diff --git a/remoting/host/chromoting_messages.cc b/remoting/host/chromoting_messages.cc deleted file mode 100644 index f4406af..0000000 --- a/remoting/host/chromoting_messages.cc +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Get basic type definitions. -#define IPC_MESSAGE_IMPL -#include "remoting/host/chromoting_messages.h"
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h deleted file mode 100644 index 553b18e..0000000 --- a/remoting/host/chromoting_messages.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_CHROMOTING_MESSAGES_H_ -#define REMOTING_HOST_CHROMOTING_MESSAGES_H_ - -#include "ipc/ipc_message_start.h" - -#endif // REMOTING_HOST_CHROMOTING_MESSAGES_H_ - -// Multiply-included message file, no traditional include guard. -#include "ipc/ipc_message_macros.h" - -#define IPC_MESSAGE_START ChromotingMsgStart - -//----------------------------------------------------------------------------- -// Chromoting messages sent from the daemon. - -// Requests the receiving process to crash producing a crash dump. The daemon -// sends this message when a fatal error has been detected indicating that -// the receiving process misbehaves. The daemon passes the location of the code -// that detected the error. -IPC_MESSAGE_CONTROL(ChromotingDaemonMsg_Crash, - std::string /* function_name */, - std::string /* file_name */, - int /* line_number */)
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc index f509fe3c..4c57e2c 100644 --- a/remoting/host/daemon_process.cc +++ b/remoting/host/daemon_process.cc
@@ -23,7 +23,6 @@ #include "remoting/host/base/host_exit_codes.h" #include "remoting/host/base/screen_resolution.h" #include "remoting/host/branding.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/config_file_watcher.h" #include "remoting/host/desktop_session.h" #include "remoting/host/host_event_logger.h" @@ -82,15 +81,6 @@ SendHostConfigToNetworkProcess(serialized_config_); } -bool DaemonProcess::OnMessageReceived(const IPC::Message& message) { - DCHECK(caller_task_runner()->BelongsToCurrentThread()); - - LOG(ERROR) << "Received unexpected IPC type: " << message.type(); - CrashNetworkProcess(FROM_HERE); - - return false; -} - void DaemonProcess::OnPermanentError(int exit_code) { DCHECK(caller_task_runner()->BelongsToCurrentThread()); DCHECK(kMinPermanentErrorExitCode <= exit_code && @@ -113,7 +103,7 @@ // multiple times as that would indicate a logic error (or that the calling // process had possibly been compromised). In the case of the network process, // which handles network traffic and encoding, it's possible that there is a - // protocol error or OS driver fault which cases the process to crash. When + // protocol error or OS driver fault which causes the process to crash. When // that occurs, the daemon process will launch a new instance of the network // process (which is handled outside of this class) and that new instance will // attempt to retrieve the set of associated interfaces it needs to do its
diff --git a/remoting/host/daemon_process.h b/remoting/host/daemon_process.h index adc75482..886edd8 100644 --- a/remoting/host/daemon_process.h +++ b/remoting/host/daemon_process.h
@@ -68,7 +68,6 @@ // WorkerProcessIpcDelegate implementation. void OnChannelConnected(int32_t peer_pid) override; - bool OnMessageReceived(const IPC::Message& message) override; void OnPermanentError(int exit_code) override; void OnWorkerProcessStopped() override; void OnAssociatedInterfaceRequest(
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc index 6db1cd30..7a4bd6f9 100644 --- a/remoting/host/desktop_process.cc +++ b/remoting/host/desktop_process.cc
@@ -14,12 +14,12 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_pump_type.h" +#include "base/notreached.h" #include "base/task/current_thread.h" #include "build/build_config.h" #include "ipc/ipc_channel_proxy.h" #include "remoting/base/auto_thread.h" #include "remoting/base/auto_thread_task_runner.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/crash_process.h" #include "remoting/host/desktop_environment.h" #include "remoting/host/desktop_session_agent.h" @@ -92,15 +92,8 @@ bool DesktopProcess::OnMessageReceived(const IPC::Message& message) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DesktopProcess, message) - IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - CHECK(handled) << "Received unexpected IPC type: " << message.type(); - return handled; + NOTREACHED() << "Received unexpected IPC type: " << message.type(); + return false; } void DesktopProcess::OnChannelConnected(int32_t peer_pid) { @@ -112,11 +105,12 @@ void DesktopProcess::OnChannelError() { // Shutdown the desktop process. daemon_channel_.reset(); - if (desktop_agent_.get()) { + if (desktop_agent_) { desktop_agent_->Stop(); desktop_agent_ = nullptr; } desktop_session_request_handler_.reset(); + worker_process_control_.reset(); caller_task_runner_ = nullptr; input_task_runner_ = nullptr; @@ -124,6 +118,27 @@ desktop_environment_factory_.reset(); } +void DesktopProcess::OnAssociatedInterfaceRequest( + const std::string& interface_name, + mojo::ScopedInterfaceEndpointHandle handle) { + DCHECK(caller_task_runner_->BelongsToCurrentThread()); + if (interface_name == mojom::WorkerProcessControl::Name_) { + if (worker_process_control_.is_bound()) { + LOG(ERROR) << "Receiver already bound for associated interface: " + << mojom::WorkerProcessControl::Name_; + CrashProcess(__func__, __FILE__, __LINE__); + } + + mojo::PendingAssociatedReceiver<mojom::WorkerProcessControl> + pending_receiver(std::move(handle)); + worker_process_control_.Bind(std::move(pending_receiver)); + } else { + LOG(ERROR) << "Received unexpected associated interface request: " + << interface_name; + CrashProcess(__func__, __FILE__, __LINE__); + } +} + bool DesktopProcess::Start( std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); @@ -169,11 +184,11 @@ return true; } -void DesktopProcess::OnCrash(const std::string& function_name, - const std::string& file_name, - const int& line_number) { +void DesktopProcess::CrashProcess(const std::string& function_name, + const std::string& file_name, + int line_number) { // The daemon requested us to crash the process. - CrashProcess(function_name, file_name, line_number); + ::remoting::CrashProcess(function_name, file_name, line_number); } } // namespace remoting
diff --git a/remoting/host/desktop_process.h b/remoting/host/desktop_process.h index a386964..41889ab8 100644 --- a/remoting/host/desktop_process.h +++ b/remoting/host/desktop_process.h
@@ -34,7 +34,8 @@ class DesktopSessionAgent; class DesktopProcess : public DesktopSessionAgent::Delegate, - public IPC::Listener { + public IPC::Listener, + public mojom::WorkerProcessControl { public: DesktopProcess(scoped_refptr<AutoThreadTaskRunner> caller_task_runner, scoped_refptr<AutoThreadTaskRunner> input_task_runner, @@ -55,6 +56,14 @@ bool OnMessageReceived(const IPC::Message& message) override; void OnChannelConnected(int32_t peer_pid) override; void OnChannelError() override; + void OnAssociatedInterfaceRequest( + const std::string& interface_name, + mojo::ScopedInterfaceEndpointHandle handle) override; + + // mojom::WorkerProcessControl implementation. + void CrashProcess(const std::string& function_name, + const std::string& file_name, + int line_number) override; // Injects Secure Attention Sequence. void InjectSas(); @@ -68,13 +77,6 @@ std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory); private: - // Crashes the process in response to a daemon's request. The daemon passes - // the location of the code that detected the fatal error resulted in this - // request. See the declaration of ChromotingDaemonMsg_Crash message. - void OnCrash(const std::string& function_name, - const std::string& file_name, - const int& line_number); - // Task runner on which public methods of this class should be called. scoped_refptr<AutoThreadTaskRunner> caller_task_runner_; @@ -101,6 +103,9 @@ mojo::AssociatedRemote<mojom::DesktopSessionRequestHandler> desktop_session_request_handler_; + mojo::AssociatedReceiver<mojom::WorkerProcessControl> worker_process_control_{ + this}; + base::WeakPtrFactory<DesktopProcess> weak_factory_{this}; };
diff --git a/remoting/host/desktop_process_unittest.cc b/remoting/host/desktop_process_unittest.cc index 2514c7cb..a6451caf 100644 --- a/remoting/host/desktop_process_unittest.cc +++ b/remoting/host/desktop_process_unittest.cc
@@ -26,7 +26,6 @@ #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/base/host_exit_codes.h" #include "remoting/host/base/screen_resolution.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/desktop_process.h" #include "remoting/host/fake_keyboard_layout_monitor.h" #include "remoting/host/fake_mouse_cursor_monitor.h" @@ -116,12 +115,8 @@ } bool MockNetworkListener::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - - // TODO(alexeypa): handle received messages here. - - EXPECT_TRUE(handled); - return handled; + ADD_FAILURE() << "Unexpected call to OnMessageReceived()"; + return false; } } // namespace @@ -177,6 +172,7 @@ mojo::AssociatedRemote<mojom::DesktopSessionAgent> desktop_session_agent_; mojo::AssociatedRemote<mojom::DesktopSessionControl> desktop_session_control_; + mojo::AssociatedRemote<mojom::WorkerProcessControl> worker_process_control_; // Runs the daemon's end of the channel. base::test::SingleThreadTaskEnvironment task_environment_{ @@ -255,6 +251,7 @@ daemon_listener_.Disconnect(); desktop_session_agent_.reset(); desktop_session_control_.reset(); + worker_process_control_.reset(); network_channel_.reset(); io_task_runner_ = nullptr; @@ -298,6 +295,8 @@ io_task_runner_, std::move(pipe.handle1)); EXPECT_TRUE(desktop_process.Start(std::move(desktop_environment_factory))); + daemon_channel_->GetRemoteAssociatedInterface(&worker_process_control_); + ui_task_runner = nullptr; run_loop.Run(); } @@ -316,8 +315,8 @@ void DesktopProcessTest::SendCrashRequest() { base::Location location = FROM_HERE; - daemon_channel_->Send(new ChromotingDaemonMsg_Crash( - location.function_name(), location.file_name(), location.line_number())); + worker_process_control_->CrashProcess( + location.function_name(), location.file_name(), location.line_number()); } void DesktopProcessTest::SendStartSessionAgent() {
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc index 934e340..14bafcc 100644 --- a/remoting/host/desktop_session_proxy.cc +++ b/remoting/host/desktop_session_proxy.cc
@@ -14,6 +14,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/notreached.h" #include "base/process/process_handle.h" #include "base/task/single_thread_task_runner.h" #include "build/build_config.h"
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc index 63065519..24fd320 100644 --- a/remoting/host/desktop_session_win.cc +++ b/remoting/host/desktop_session_win.cc
@@ -28,12 +28,9 @@ #include "base/win/scoped_bstr.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" -#include "ipc/ipc_message_macros.h" -#include "ipc/ipc_platform_file.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/base/screen_resolution.h" #include "remoting/host/base/switches.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/daemon_process.h" #include "remoting/host/desktop_session.h" #include "remoting/host/host_main.h" @@ -606,15 +603,6 @@ VLOG(1) << "IPC: daemon <- desktop (" << peer_pid << ")"; } -bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) { - DCHECK(caller_task_runner_->BelongsToCurrentThread()); - - LOG(ERROR) << "Received unexpected IPC type: " << message.type(); - CrashDesktopProcess(FROM_HERE); - - return false; -} - void DesktopSessionWin::OnPermanentError(int exit_code) { DCHECK(caller_task_runner_->BelongsToCurrentThread());
diff --git a/remoting/host/desktop_session_win.h b/remoting/host/desktop_session_win.h index d86793d..5ef3fb4 100644 --- a/remoting/host/desktop_session_win.h +++ b/remoting/host/desktop_session_win.h
@@ -96,7 +96,6 @@ // WorkerProcessIpcDelegate implementation. void OnChannelConnected(int32_t peer_pid) override; - bool OnMessageReceived(const IPC::Message& message) override; void OnPermanentError(int exit_code) override; void OnWorkerProcessStopped() override; void OnAssociatedInterfaceRequest(
diff --git a/remoting/host/ipc_host_event_logger.cc b/remoting/host/ipc_host_event_logger.cc index b6be4b89..107a0af 100644 --- a/remoting/host/ipc_host_event_logger.cc +++ b/remoting/host/ipc_host_event_logger.cc
@@ -7,7 +7,6 @@ #include "base/check_op.h" #include "ipc/ipc_sender.h" #include "net/base/ip_endpoint.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/host_status_monitor.h" #include "remoting/protocol/transport.h"
diff --git a/remoting/host/mojom/desktop_session.mojom b/remoting/host/mojom/desktop_session.mojom index 95faec8..40b5e430 100644 --- a/remoting/host/mojom/desktop_session.mojom +++ b/remoting/host/mojom/desktop_session.mojom
@@ -566,3 +566,13 @@ // calling this method. DisconnectSession(ProtocolErrorCode error_code); }; + +// Allows the worker process launcher to send messages to a child process. +// The remote for this interface is owned in the high-privilege daemon process +// which uses the WorkerProcessLauncher class to spawn the low-privilege network +// process or high-privilege desktop integration process. The receiver is bound +// in the child process. +interface WorkerProcessControl { + // Instructs the receiving process to crash itself. + CrashProcess(string function_name, string file_name, int32 line_number); +};
diff --git a/remoting/host/mojom/remoting_host.mojom b/remoting/host/mojom/remoting_host.mojom index 30d130d0..a5a625ea 100644 --- a/remoting/host/mojom/remoting_host.mojom +++ b/remoting/host/mojom/remoting_host.mojom
@@ -12,13 +12,6 @@ // The remote for this interface is owned in the high-privilege daemon process // and the receiver is bound in the low-privilege network process. interface RemotingHostControl { - // Instructs the network process to crash itself. This is called when a higher - // privilege process detects abnormal behavior in the host process. After - // crashing, the daemon process will automatically restart the network - // process. - [EnableIf=is_win] - CrashHostProcess(string function_name, string file_name, int32 line_number); - // Provides host configuration details to the network process such as the // owner email and robot account to use for authentication to service APIs. // This method may be called multiple times as changes are detected in the
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 8f426cd9..8f52b9b9 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -19,6 +19,7 @@ #include "base/files/file_util.h" #include "base/memory/raw_ptr.h" #include "base/message_loop/message_pump_type.h" +#include "base/notreached.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringize_macros.h" @@ -60,7 +61,6 @@ #include "remoting/host/branding.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/config_file_watcher.h" #include "remoting/host/config_watcher.h" #include "remoting/host/crash_process.h" @@ -78,6 +78,7 @@ #include "remoting/host/ipc_desktop_environment.h" #include "remoting/host/ipc_host_event_logger.h" #include "remoting/host/me2me_desktop_environment.h" +#include "remoting/host/mojom/desktop_session.mojom.h" #include "remoting/host/mojom/remoting_host.mojom.h" #include "remoting/host/pairing_registry_delegate.h" #include "remoting/host/pin_hash.h" @@ -227,7 +228,8 @@ public HeartbeatSender::Delegate, public IPC::Listener, public base::RefCountedThreadSafe<HostProcess>, - public mojom::RemotingHostControl { + public mojom::RemotingHostControl, + public mojom::WorkerProcessControl { public: // |shutdown_watchdog| is armed when shutdown is started, and should be kept // alive as long as possible until the process exits (since destroying the @@ -368,11 +370,13 @@ void GoOffline(const std::string& host_offline_reason); void OnHostOfflineReasonAck(bool success); + // mojom::WorkerProcessControl implementation. + void CrashProcess(const std::string& function_name, + const std::string& file_name, + int line_number) override; + #if BUILDFLAG(IS_WIN) // mojom::RemotingHostControl implementation. - void CrashHostProcess(const std::string& function_name, - const std::string& file_name, - int line_number) override; void ApplyHostConfig(base::Value serialized_config) override; void InitializePairingRegistry( ::mojo::PlatformHandle privileged_handle, @@ -479,6 +483,8 @@ mojo::AssociatedReceiver<mojom::RemotingHostControl> remoting_host_control_{ this}; + mojo::AssociatedReceiver<mojom::WorkerProcessControl> + worker_process_control_{this}; #if BUILDFLAG(IS_APPLE) // When using the command line option to check the Accessibility or Screen @@ -869,8 +875,17 @@ mojo::PendingAssociatedReceiver<mojom::RemotingHostControl> pending_receiver(std::move(handle)); remoting_host_control_.Bind(std::move(pending_receiver)); - } else if (interface_name == mojom::DesktopSessionConnectionEvents::Name_) { + } else if (interface_name == mojom::WorkerProcessControl::Name_) { + if (worker_process_control_.is_bound()) { + LOG(ERROR) << "Receiver already bound for associated interface: " + << mojom::WorkerProcessControl::Name_; + CrashProcess(__FUNCTION__, __FILE__, __LINE__); + } + mojo::PendingAssociatedReceiver<mojom::WorkerProcessControl> + pending_receiver(std::move(handle)); + worker_process_control_.Bind(std::move(pending_receiver)); + } else if (interface_name == mojom::DesktopSessionConnectionEvents::Name_) { if (!desktop_session_connector_->BindConnectionEventsReceiver( std::move(handle))) { LOG(ERROR) << "Failed to bind Receiver for associated interface: " @@ -1903,14 +1918,12 @@ } } -#if BUILDFLAG(IS_WIN) -void HostProcess::CrashHostProcess(const std::string& function_name, - const std::string& file_name, - int line_number) { +void HostProcess::CrashProcess(const std::string& function_name, + const std::string& file_name, + int line_number) { // The daemon requested us to crash the process. - CrashProcess(function_name, file_name, line_number); + ::remoting::CrashProcess(function_name, file_name, line_number); } -#endif int HostProcessMain() { HOST_LOG << "Starting host process: version " << STRINGIZE(VERSION);
diff --git a/remoting/host/security_key/security_key_auth_handler_win.cc b/remoting/host/security_key/security_key_auth_handler_win.cc index e24d3ab..eba079d 100644 --- a/remoting/host/security_key/security_key_auth_handler_win.cc +++ b/remoting/host/security_key/security_key_auth_handler_win.cc
@@ -23,9 +23,7 @@ #include "ipc/ipc_channel.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" -#include "ipc/ipc_message_macros.h" #include "remoting/base/logging.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/client_session_details.h" #include "remoting/host/security_key/security_key_ipc_constants.h" #include "remoting/host/security_key/security_key_ipc_server.h"
diff --git a/remoting/host/security_key/security_key_auth_handler_win_unittest.cc b/remoting/host/security_key/security_key_auth_handler_win_unittest.cc index 68273fc..725c5fbe9 100644 --- a/remoting/host/security_key/security_key_auth_handler_win_unittest.cc +++ b/remoting/host/security_key/security_key_auth_handler_win_unittest.cc
@@ -15,7 +15,6 @@ #include "ipc/ipc_channel.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" -#include "ipc/ipc_message_macros.h" #include "remoting/host/host_mock_objects.h" #include "remoting/host/security_key/fake_security_key_ipc_client.h" #include "remoting/host/security_key/fake_security_key_ipc_server.h"
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn index 79044ec..05752767 100644 --- a/remoting/host/win/BUILD.gn +++ b/remoting/host/win/BUILD.gn
@@ -180,6 +180,7 @@ "//remoting/base", "//remoting/host:ipc_constants", "//remoting/host/base", + "//remoting/host/mojom", "//remoting/host/security_key", "//remoting/host/win:messages", "//remoting/host/win:remoting_lib_idl", @@ -441,6 +442,7 @@ "//remoting/host:settings", "//remoting/host/base", "//remoting/host/it2me:common", + "//remoting/host/mojom", "//remoting/host/native_messaging", "//remoting/host/remote_open_url:main", "//remoting/host/security_key:main",
diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc index 3fd6c41..577925b 100644 --- a/remoting/host/win/unprivileged_process_delegate.cc +++ b/remoting/host/win/unprivileged_process_delegate.cc
@@ -18,6 +18,7 @@ #include "base/command_line.h" #include "base/files/file.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -324,16 +325,6 @@ ReportProcessLaunched(std::move(worker_process)); } -void UnprivilegedProcessDelegate::Send(IPC::Message* message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (channel_) { - channel_->Send(message); - } else { - delete message; - } -} - void UnprivilegedProcessDelegate::GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) { channel_->GetRemoteAssociatedInterface(std::move(receiver)); @@ -341,9 +332,18 @@ void UnprivilegedProcessDelegate::CloseChannel() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + worker_process_control_.reset(); channel_.reset(); } +void UnprivilegedProcessDelegate::CrashProcess(const base::Location& location) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (worker_process_control_) { + worker_process_control_->CrashProcess( + location.function_name(), location.file_name(), location.line_number()); + } +} + void UnprivilegedProcessDelegate::KillProcess() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -359,8 +359,8 @@ bool UnprivilegedProcessDelegate::OnMessageReceived( const IPC::Message& message) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - return event_handler_->OnMessageReceived(message); + NOTREACHED() << "Received unexpected IPC type: " << message.type(); + return false; } void UnprivilegedProcessDelegate::OnChannelConnected(int32_t peer_pid) { @@ -375,6 +375,8 @@ return; } + channel_->GetRemoteAssociatedInterface(&worker_process_control_); + event_handler_->OnChannelConnected(peer_pid); }
diff --git a/remoting/host/win/unprivileged_process_delegate.h b/remoting/host/win/unprivileged_process_delegate.h index 69baab5..e20415d0f 100644 --- a/remoting/host/win/unprivileged_process_delegate.h +++ b/remoting/host/win/unprivileged_process_delegate.h
@@ -15,8 +15,10 @@ #include "base/sequence_checker.h" #include "base/win/scoped_handle.h" #include "ipc/ipc_listener.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" +#include "remoting/host/mojom/desktop_session.mojom.h" #include "remoting/host/win/worker_process_launcher.h" namespace base { @@ -48,10 +50,10 @@ // WorkerProcessLauncher::Delegate implementation. void LaunchProcess(WorkerProcessLauncher* event_handler) override; - void Send(IPC::Message* message) override; void GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) override; void CloseChannel() override; + void CrashProcess(const base::Location& location) override; void KillProcess() override; private: @@ -81,6 +83,8 @@ // The handle of the worker process, if launched. base::win::ScopedHandle worker_process_; + mojo::AssociatedRemote<mojom::WorkerProcessControl> worker_process_control_; + SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc index e1622cb7..277966e 100644 --- a/remoting/host/win/worker_process_launcher.cc +++ b/remoting/host/win/worker_process_launcher.cc
@@ -15,7 +15,6 @@ #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "remoting/host/base/host_exit_codes.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/worker_process_ipc_delegate.h" using base::win::ScopedHandle; @@ -59,10 +58,9 @@ : ipc_handler_(ipc_handler), launcher_delegate_(std::move(launcher_delegate)), exit_code_(CONTROL_C_EXIT), - ipc_enabled_(false), kill_process_timeout_(base::Seconds(kKillProcessTimeoutSeconds)), launch_backoff_(&kDefaultBackoffPolicy) { - DCHECK(ipc_handler_ != nullptr); + DCHECK(ipc_handler_); LaunchWorker(); } @@ -78,15 +76,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Ask the worker process to crash voluntarily if it is still connected. - if (ipc_enabled_) { - Send(new ChromotingDaemonMsg_Crash(location.function_name(), - location.file_name(), - location.line_number())); - } + launcher_delegate_->CrashProcess(location); - // Close the channel and ignore any not yet processed messages. + // Close the channel and ignore pending messages. launcher_delegate_->CloseChannel(); - ipc_enabled_ = false; // Give the worker process some time to crash. if (!kill_process_timer_.IsRunning()) { @@ -95,26 +88,14 @@ } } -void WorkerProcessLauncher::Send(IPC::Message* message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (ipc_enabled_) { - launcher_delegate_->Send(message); - } else { - delete message; - } -} - void WorkerProcessLauncher::GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) { - DCHECK(ipc_enabled_); launcher_delegate_->GetRemoteAssociatedInterface(std::move(receiver)); } void WorkerProcessLauncher::OnProcessLaunched( base::win::ScopedHandle worker_process) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!ipc_enabled_); DCHECK(!launch_timer_.IsRunning()); DCHECK(!process_watcher_.GetWatchedObject()); DCHECK(!worker_process_.IsValid()); @@ -124,7 +105,6 @@ return; } - ipc_enabled_ = true; worker_process_ = std::move(worker_process); } @@ -134,22 +114,9 @@ StopWorker(); } -bool WorkerProcessLauncher::OnMessageReceived( - const IPC::Message& message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!ipc_enabled_) - return false; - - return ipc_handler_->OnMessageReceived(message); -} - void WorkerProcessLauncher::OnChannelConnected(int32_t peer_pid) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!ipc_enabled_) - return; - // This can result in |this| being deleted, so this call must be the last in // this method. ipc_handler_->OnChannelConnected(peer_pid); @@ -174,9 +141,6 @@ mojo::ScopedInterfaceEndpointHandle handle) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!ipc_enabled_) - return; - ipc_handler_->OnAssociatedInterfaceRequest(interface_name, std::move(handle)); } @@ -198,7 +162,6 @@ void WorkerProcessLauncher::LaunchWorker() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!ipc_enabled_); DCHECK(!kill_process_timer_.IsRunning()); DCHECK(!launch_timer_.IsRunning()); DCHECK(!process_watcher_.GetWatchedObject()); @@ -255,9 +218,6 @@ launch_result_timer_.Stop(); } - // Ignore any remaining IPC messages. - ipc_enabled_ = false; - // Stop monitoring the worker process. process_watcher_.StopWatching(); worker_process_.Close();
diff --git a/remoting/host/win/worker_process_launcher.h b/remoting/host/win/worker_process_launcher.h index 035a4ebf..9856733 100644 --- a/remoting/host/win/worker_process_launcher.h +++ b/remoting/host/win/worker_process_launcher.h
@@ -29,10 +29,6 @@ class ScopedInterfaceEndpointHandle; } -namespace IPC { -class Message; -} // namespace IPC - namespace remoting { class WorkerProcessIpcDelegate; @@ -52,27 +48,25 @@ // been called. virtual void LaunchProcess(WorkerProcessLauncher* event_handler) = 0; - // Sends an IPC message to the worker process. The message will be silently - // dropped if the channel is closed. - // TODO(joedow): Remove this method after completing the migration to Mojo. - virtual void Send(IPC::Message* message) = 0; - // Provides a way to request an associated interface from the worker process // IPC channel. virtual void GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) = 0; // Closes the IPC channel. - // TODO(joedow): Remove this method after completing the migration to Mojo. virtual void CloseChannel() = 0; + // Ask the worker process to voluntarily crash and generate a dump. + // |location| represents the caller who made the original request. + virtual void CrashProcess(const base::Location& location) = 0; + // Terminates the worker process and closes the IPC channel. virtual void KillProcess() = 0; }; // Creates the launcher that will use |launcher_delegate| to manage the worker // process and |ipc_handler| to handle IPCs. The caller must ensure that - // |ipc_handler| must outlive this object. + // |ipc_handler| outlives this object. WorkerProcessLauncher(std::unique_ptr<Delegate> launcher_delegate, WorkerProcessIpcDelegate* ipc_handler); @@ -83,15 +77,10 @@ // Asks the worker process to crash and generate a dump, and closes the IPC // channel. |location| is passed to the worker so that it is on the stack in - // the dump. Restarts the worker process forcefully, if it does - // not exit on its own. + // the dump. Restarts the worker process forcefully, if it does not exit on + // its own. void Crash(const base::Location& location); - // Sends an IPC message to the worker process. The message will be silently - // dropped if Send() is called before Start() or after shutdown has been - // initiated. - void Send(IPC::Message* message); - // Provides a way to request an associated interface from the worker process // IPC channel. void GetRemoteAssociatedInterface( @@ -111,7 +100,6 @@ // Mirrors methods of IPC::Listener to be invoked by |Delegate|. |Delegate| // has to validate |peer_pid| if necessary. - bool OnMessageReceived(const IPC::Message& message); void OnChannelConnected(int32_t peer_pid); void OnChannelError(); void OnAssociatedInterfaceRequest(const std::string& interface_name, @@ -154,11 +142,6 @@ // code is used to determine whether the process has to be restarted. DWORD exit_code_; - // Indicates whether the worker process has been launched, after which IPC - // messages and events should be passed to the |ipc_handler_| delegate. - // TODO(joedow): Remove this member after completing the migration to Mojo. - bool ipc_enabled_; - // The timer used to delay termination of the worker process when an IPC error // occured or when Crash() request is pending base::OneShotTimer kill_process_timer_;
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc index 172fbd3d..2b418784 100644 --- a/remoting/host/win/worker_process_launcher_unittest.cc +++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -21,12 +21,12 @@ #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/message_pipe.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/base/host_exit_codes.h" -#include "remoting/host/chromoting_messages.h" #include "remoting/host/mojom/desktop_session.mojom.h" #include "remoting/host/win/launch_process_with_token.h" #include "remoting/host/worker_process_ipc_delegate.h" @@ -56,12 +56,12 @@ // WorkerProcessLauncher::Delegate interface. MOCK_METHOD(void, LaunchProcess, (WorkerProcessLauncher*), (override)); - MOCK_METHOD(void, Send, (IPC::Message*), (override)); MOCK_METHOD(void, GetRemoteAssociatedInterface, (mojo::GenericPendingAssociatedReceiver), (override)); MOCK_METHOD(void, CloseChannel, (), (override)); + MOCK_METHOD(void, CrashProcess, (const base::Location&), (override)); MOCK_METHOD(void, KillProcess, (), (override)); }; @@ -76,7 +76,6 @@ // WorkerProcessIpcDelegate interface. MOCK_METHOD(void, OnChannelConnected, (int32_t), (override)); - MOCK_METHOD(bool, OnMessageReceived, (const IPC::Message&), (override)); MOCK_METHOD(void, OnPermanentError, (int), (override)); MOCK_METHOD(void, OnWorkerProcessStopped, (), (override)); MOCK_METHOD(void, @@ -87,7 +86,8 @@ }; -class MockWorkerListener : public IPC::Listener { +class MockWorkerListener : public IPC::Listener, + public mojom::WorkerProcessControl { public: MockWorkerListener() {} @@ -96,22 +96,39 @@ ~MockWorkerListener() override {} - MOCK_METHOD(void, OnCrash, (const std::string&, const std::string&, int)); + // mojom::WorkerProcessControl mock. + MOCK_METHOD(void, + CrashProcess, + (const std::string&, const std::string&, int), + (override)); - // IPC::Listener implementation + // IPC::Listener implementation. bool OnMessageReceived(const IPC::Message& message) override; + void OnAssociatedInterfaceRequest( + const std::string& interface_name, + mojo::ScopedInterfaceEndpointHandle handle) override; + + private: + mojo::AssociatedReceiver<mojom::WorkerProcessControl> worker_process_control_{ + this}; }; bool MockWorkerListener::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(MockWorkerListener, message) - IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() + ADD_FAILURE() << "Unexpected call to OnMessageReceived()"; + return false; +} - EXPECT_TRUE(handled); - - return handled; +void MockWorkerListener::OnAssociatedInterfaceRequest( + const std::string& interface_name, + mojo::ScopedInterfaceEndpointHandle handle) { + ASSERT_EQ(interface_name, mojom::WorkerProcessControl::Name_); + mojo::PendingAssociatedReceiver<mojom::WorkerProcessControl> pending_receiver( + std::move(handle)); + worker_process_control_.Bind(std::move(pending_receiver)); + // Reset the receiver when the channel is closed to prevent any additional + // tasks from being posted. If we don't reset the receiver, many of the tests + // will appear to hang while waiting for the task runner to exit. + worker_process_control_.reset_on_disconnect(); } } // namespace @@ -124,7 +141,6 @@ ~WorkerProcessLauncherTest() override; void SetUp() override; - void TearDown() override; // IPC::Listener implementation. bool OnMessageReceived(const IPC::Message& message) override; @@ -138,6 +154,7 @@ WorkerProcessLauncher* event_handler); void FailLaunchAndStopWorker( WorkerProcessLauncher* event_handler); + void CrashProcess(const base::Location& location); void KillProcess(); void TerminateWorker(DWORD exit_code); @@ -199,6 +216,7 @@ mojo::AssociatedRemote<mojom::DesktopSessionStateHandler> desktop_session_state_handler_; + mojo::AssociatedRemote<mojom::WorkerProcessControl> worker_process_control_; // An event that is used to emulate the worker process's handle. ScopedHandle worker_process_; @@ -217,29 +235,23 @@ base::BindOnce(&WorkerProcessLauncherTest::QuitMainMessageLoop, base::Unretained(this))); - // Set up process launcher delegate + // Set up process launcher delegate. launcher_delegate_ = std::make_unique<MockProcessLauncherDelegate>(); - EXPECT_CALL(*launcher_delegate_, Send(_)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::SendToProcess)); EXPECT_CALL(*launcher_delegate_, CloseChannel()) .Times(AnyNumber()) .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::DisconnectServer)); + EXPECT_CALL(*launcher_delegate_, CrashProcess(_)) + .Times(AnyNumber()) + .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::CrashProcess)); EXPECT_CALL(*launcher_delegate_, KillProcess()) .Times(AnyNumber()) .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess)); - - // Set up IPC delegate. - EXPECT_CALL(server_listener_, OnMessageReceived(_)) - .Times(0); -} - -void WorkerProcessLauncherTest::TearDown() { } bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) { - return event_handler_->OnMessageReceived(message); + ADD_FAILURE() << "Unexpected call to OnMessageReceived()"; + return false; } void WorkerProcessLauncherTest::OnChannelConnected(int32_t peer_pid) { @@ -281,6 +293,11 @@ base::Unretained(this))); } +void WorkerProcessLauncherTest::CrashProcess(const base::Location& location) { + worker_process_control_->CrashProcess( + location.function_name(), location.file_name(), location.line_number()); +} + void WorkerProcessLauncherTest::KillProcess() { event_handler_ = nullptr; @@ -305,6 +322,9 @@ channel_client_->GetRemoteAssociatedInterface( &desktop_session_state_handler_); + worker_process_control_.reset(); + channel_server_->GetRemoteAssociatedInterface(&worker_process_control_); + // Pretend that |kLaunchSuccessTimeoutSeconds| passed since launching // the worker process. This will make the backoff algorithm think that this // launch attempt was successful and it will not delay the next launch. @@ -315,8 +335,8 @@ if (channel_client_) { channel_client_->Close(); channel_client_.reset(); - desktop_session_state_handler_.reset(); } + desktop_session_state_handler_.reset(); } void WorkerProcessLauncherTest::DisconnectServer() { @@ -324,15 +344,7 @@ channel_server_->Close(); channel_server_.reset(); } -} - -void WorkerProcessLauncherTest::SendToProcess(IPC::Message* message) { - if (channel_server_) { - channel_server_->Send(message); - return; - } - - delete message; + worker_process_control_.reset(); } void WorkerProcessLauncherTest::SendFakeMessageToLauncher() { @@ -356,7 +368,7 @@ launcher_.reset(); DisconnectClient(); client_channel_handle_.reset(); - channel_server_.reset(); + DisconnectServer(); task_runner_ = nullptr; } @@ -379,12 +391,12 @@ PROCESS_INFORMATION temp_process_info = {}; ASSERT_TRUE(CreateProcess(nullptr, notepad, - nullptr, // default process attributes - nullptr, // default thread attributes - FALSE, // do not inherit handles + nullptr, // default process attributes + nullptr, // default thread attributes + FALSE, // do not inherit handles CREATE_SUSPENDED, - nullptr, // no environment - nullptr, // default current directory + nullptr, // no environment + nullptr, // default current directory &startup_info, &temp_process_info)); base::win::ScopedProcessInformation process_information(temp_process_info); @@ -530,7 +542,7 @@ .WillOnce(InvokeWithoutArgs(this, &WorkerProcessLauncherTest::StopWorker)); - EXPECT_CALL(client_listener_, OnCrash(_, _, _)) + EXPECT_CALL(client_listener_, CrashProcess(_, _, _)) .Times(1) .WillOnce( InvokeWithoutArgs([=]() { TerminateWorker(EXCEPTION_BREAKPOINT); })); @@ -557,7 +569,7 @@ &WorkerProcessLauncherTest::StopWorker)); // Ignore the crash request and try send another message to the launcher. - EXPECT_CALL(client_listener_, OnCrash(_, _, _)) + EXPECT_CALL(client_listener_, CrashProcess(_, _, _)) .Times(1) .WillOnce(InvokeWithoutArgs( this, &WorkerProcessLauncherTest::SendFakeMessageToLauncher));
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc index 9175a87..fc0f656 100644 --- a/remoting/host/win/wts_session_process_delegate.cc +++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -15,6 +15,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" +#include "base/notreached.h" #include "base/process/process_handle.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" @@ -27,6 +28,7 @@ #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/platform/named_platform_channel.h" #include "mojo/public/cpp/platform/platform_channel.h" @@ -36,6 +38,7 @@ #include "remoting/host/base/switches.h" #include "remoting/host/host_main.h" #include "remoting/host/ipc_constants.h" +#include "remoting/host/mojom/desktop_session.mojom.h" #include "remoting/host/win/launch_process_with_token.h" #include "remoting/host/win/security_descriptor.h" #include "remoting/host/win/worker_process_launcher.h" @@ -73,10 +76,10 @@ // Mirrors WorkerProcessLauncher::Delegate. void LaunchProcess(WorkerProcessLauncher* event_handler); - void Send(IPC::Message* message); void GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver); void CloseChannel(); + void CrashProcess(const base::Location& location); void KillProcess(); private: @@ -167,6 +170,8 @@ // The pending process connection for the process being launched. mojo::OutgoingInvitation mojo_invitation_; + + mojo::AssociatedRemote<mojom::WorkerProcessControl> worker_process_control_; }; WtsSessionProcessDelegate::Core::Core( @@ -244,21 +249,10 @@ DoLaunchProcess(); } -void WtsSessionProcessDelegate::Core::Send(IPC::Message* message) { - DCHECK(caller_task_runner_->BelongsToCurrentThread()); - - if (channel_) { - channel_->Send(message); - } else { - delete message; - } -} - void WtsSessionProcessDelegate::Core::GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - // TODO(joedow): Implement this when converting the Daemon->Desktop messages. - NOTIMPLEMENTED(); + channel_->GetRemoteAssociatedInterface(std::move(receiver)); } void WtsSessionProcessDelegate::Core::CloseChannel() { @@ -268,12 +262,22 @@ return; } + worker_process_control_.reset(); channel_.reset(); elevated_server_endpoint_.reset(); elevated_launcher_pid_ = base::kNullProcessId; mojo_invitation_ = {}; } +void WtsSessionProcessDelegate::Core::CrashProcess( + const base::Location& location) { + DCHECK(caller_task_runner_->BelongsToCurrentThread()); + if (worker_process_control_) { + worker_process_control_->CrashProcess( + location.function_name(), location.file_name(), location.line_number()); + } +} + void WtsSessionProcessDelegate::Core::KillProcess() { DCHECK(caller_task_runner_->BelongsToCurrentThread()); @@ -358,13 +362,15 @@ bool WtsSessionProcessDelegate::Core::OnMessageReceived( const IPC::Message& message) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); - - return event_handler_->OnMessageReceived(message); + NOTREACHED() << "Received unexpected IPC type: " << message.type(); + return false; } void WtsSessionProcessDelegate::Core::OnChannelConnected(int32_t peer_pid) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); + channel_->GetRemoteAssociatedInterface(&worker_process_control_); + if (event_handler_) event_handler_->OnChannelConnected(peer_pid); } @@ -621,10 +627,6 @@ core_->LaunchProcess(event_handler); } -void WtsSessionProcessDelegate::Send(IPC::Message* message) { - core_->Send(message); -} - void WtsSessionProcessDelegate::GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) { core_->GetRemoteAssociatedInterface(std::move(receiver)); @@ -634,6 +636,10 @@ core_->CloseChannel(); } +void WtsSessionProcessDelegate::CrashProcess(const base::Location& location) { + core_->CrashProcess(location); +} + void WtsSessionProcessDelegate::KillProcess() { core_->KillProcess(); }
diff --git a/remoting/host/win/wts_session_process_delegate.h b/remoting/host/win/wts_session_process_delegate.h index c2fa5aa8..5612c4d 100644 --- a/remoting/host/win/wts_session_process_delegate.h +++ b/remoting/host/win/wts_session_process_delegate.h
@@ -19,10 +19,6 @@ class SingleThreadTaskRunner; } // namespace base -namespace IPC { -class Message; -} // namespace base - namespace remoting { // Implements logic for launching and monitoring a worker process in a different @@ -46,10 +42,10 @@ // WorkerProcessLauncher::Delegate implementation. void LaunchProcess(WorkerProcessLauncher* event_handler) override; - void Send(IPC::Message* message) override; void GetRemoteAssociatedInterface( mojo::GenericPendingAssociatedReceiver receiver) override; void CloseChannel() override; + void CrashProcess(const base::Location& location) override; void KillProcess() override; private:
diff --git a/remoting/host/worker_process_ipc_delegate.h b/remoting/host/worker_process_ipc_delegate.h index fe15ffa0..0eabcd20 100644 --- a/remoting/host/worker_process_ipc_delegate.h +++ b/remoting/host/worker_process_ipc_delegate.h
@@ -15,10 +15,6 @@ class ScopedInterfaceEndpointHandle; } // namespace mojo -namespace IPC { -class Message; -} // namespace IPC - namespace remoting { // An interface representing the object receiving IPC messages from a worker @@ -30,9 +26,6 @@ // Notifies that a client has been connected to the channel. virtual void OnChannelConnected(int32_t peer_pid) = 0; - // Processes messages sent by the client. - virtual bool OnMessageReceived(const IPC::Message& message) = 0; - // Notifies that a permanent error was encountered. virtual void OnPermanentError(int exit_code) = 0;
diff --git a/remoting/host/x11_crtc_resizer.cc b/remoting/host/x11_crtc_resizer.cc index 50e7d46..9fd6b8e7 100644 --- a/remoting/host/x11_crtc_resizer.cc +++ b/remoting/host/x11_crtc_resizer.cc
@@ -107,52 +107,98 @@ DCHECK(iter != active_crtcs_.end()); iter->mode = mode; + + if (new_size.width() > iter->width) { + // CRTCs beyond the old right edge may need to be pushed out of the way. + // Loop over these CRTCs and find the amount of adjustment needed for each + // CRTC. The final adjustment will be the max of these, and the same amount + // will be applied to every CRTC (beyond the old right edge), to avoid + // introducing any new overlaps. + int16_t old_right_edge = iter->x + iter->width; + int16_t new_right_edge = iter->x + new_size.width(); + int16_t x_adjustment = 0; + for (auto& crtc : active_crtcs_) { + // Only consider CRTCs whose left edges lie between these values. + if (crtc.x >= old_right_edge && crtc.x < new_right_edge) { + int16_t adjustment = new_right_edge - crtc.x; + x_adjustment = std::max(x_adjustment, adjustment); + } + } + if (x_adjustment > 0) { + for (auto& crtc : active_crtcs_) { + if (crtc.x >= old_right_edge) { + crtc.x += x_adjustment; + crtc.changed = true; + } + } + } + } iter->width = new_size.width(); + + if (new_size.height() > iter->height) { + // Apply the same algorithm as above, but using heights and y-offsets. + int16_t old_bottom_edge = iter->y + iter->height; + int16_t new_bottom_edge = iter->y + new_size.height(); + int16_t y_adjustment = 0; + for (auto& crtc : active_crtcs_) { + if (crtc.y >= old_bottom_edge && crtc.y < new_bottom_edge) { + int16_t adjustment = new_bottom_edge - crtc.y; + y_adjustment = std::max(y_adjustment, adjustment); + } + } + if (y_adjustment > 0) { + for (auto& crtc : active_crtcs_) { + if (crtc.y >= old_bottom_edge) { + crtc.y += y_adjustment; + crtc.changed = true; + } + } + } + } iter->height = new_size.height(); // Mark it as changed so that ApplyActiveCrtcs() will apply the new |mode|. // The |width| and |height| are only used for computing the bounding-box, // they are not used by ApplyActiveCrtcs(). iter->changed = true; - - // TODO(crbug.com/1326339): Adjust the xy-offsets to avoid overlaps. } void X11CrtcResizer::DisableChangedCrtcs() { - base::ranges::for_each(active_crtcs_, [this](const CrtcInfo& crtc_info) { + for (const auto& crtc_info : active_crtcs_) { if (crtc_info.changed) { DisableCrtc(crtc_info.crtc); } - }); + } } webrtc::DesktopSize X11CrtcResizer::GetBoundingBox() const { webrtc::DesktopSize result; - base::ranges::for_each(active_crtcs_, [&result](const CrtcInfo& crtc_info) { + for (const auto& crtc_info : active_crtcs_) { int32_t width = crtc_info.x + crtc_info.width; int32_t height = crtc_info.y + crtc_info.height; result.set(std::max(result.width(), width), std::max(result.height(), height)); - }); + } return result; } void X11CrtcResizer::ApplyActiveCrtcs() { - base::ranges::for_each(active_crtcs_, [this](const CrtcInfo& crtc_info) { - if (crtc_info.changed) { - x11::Time config_timestamp = resources_->config_timestamp; - randr_->SetCrtcConfig({ - .crtc = crtc_info.crtc, - .timestamp = x11::Time::CurrentTime, - .config_timestamp = config_timestamp, - .x = crtc_info.x, - .y = crtc_info.y, - .mode = crtc_info.mode, - .rotation = crtc_info.rotation, - .outputs = crtc_info.outputs, - }); - } - }); + for (const auto& crtc_info : active_crtcs_) { + if (!crtc_info.changed) + continue; + + x11::Time config_timestamp = resources_->config_timestamp; + randr_->SetCrtcConfig({ + .crtc = crtc_info.crtc, + .timestamp = x11::Time::CurrentTime, + .config_timestamp = config_timestamp, + .x = crtc_info.x, + .y = crtc_info.y, + .mode = crtc_info.mode, + .rotation = crtc_info.rotation, + .outputs = crtc_info.outputs, + }); + } } } // namespace remoting
diff --git a/rlz/BUILD.gn b/rlz/BUILD.gn index 0743036..3bfdb0cc 100644 --- a/rlz/BUILD.gn +++ b/rlz/BUILD.gn
@@ -201,8 +201,8 @@ ] if (is_chromeos_ash) { deps += [ + "//chromeos/ash/components/dbus:test_support", "//chromeos/ash/components/dbus/debug_daemon", - "//chromeos/dbus:test_support", "//chromeos/system", ] }
diff --git a/services/metrics/public/cpp/ukm_recorder.cc b/services/metrics/public/cpp/ukm_recorder.cc index 4bd1167..e43b59c 100644 --- a/services/metrics/public/cpp/ukm_recorder.cc +++ b/services/metrics/public/cpp/ukm_recorder.cc
@@ -49,7 +49,17 @@ } // static -ukm::SourceId UkmRecorder::GetSourceIdForWebsiteUrl(const GURL& start_url) { +ukm::SourceId UkmRecorder::GetSourceIdForDesktopWebAppStartUrl( + base::PassKey<web_app::DesktopWebAppUkmRecorder>, + const GURL& start_url) { + return UkmRecorder::GetSourceIdFromScopeImpl( + start_url, SourceIdType::DESKTOP_WEB_APP_ID); +} + +// static +ukm::SourceId UkmRecorder::GetSourceIdForWebsiteUrl( + base::PassKey<apps::WebsiteMetrics>, + const GURL& start_url) { return UkmRecorder::GetSourceIdFromScopeImpl( start_url, SourceIdType::DESKTOP_WEB_APP_ID); }
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h index 6b7d8b13..442e9eb 100644 --- a/services/metrics/public/cpp/ukm_recorder.h +++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -89,6 +89,17 @@ base::PassKey<WebApkUkmRecorder>, const GURL& manifest_url); + // Gets new source ID for a desktop web app, using the start_url from the web + // app manifest. This method should only be called by DailyMetricsHelper. + static SourceId GetSourceIdForDesktopWebAppStartUrl( + base::PassKey<web_app::DesktopWebAppUkmRecorder>, + const GURL& start_url); + + // Gets new SourceId for a website Url. This method should only be called by + // WebsiteMetrics. + static SourceId GetSourceIdForWebsiteUrl(base::PassKey<apps::WebsiteMetrics>, + const GURL& start_url); + // Gets new source Id for PAYMENT_APP_ID type and updates the source url to // the scope of the app. This method should only be called by // PaymentAppProviderUtil class when the payment app window is opened. @@ -135,17 +146,6 @@ friend PermissionUmaUtil; friend content::RenderFrameHostImpl; - // WebsiteMetrics and DesktopWebAppUkmRecorder record metrics about - // websites and installed web apps. Instead of using - // the current main frame URL, we want to record the URL which identifies the - // current app: the web app manifest url or start url, respectively. - // Therefore, they need to be friends so that they can access the private - // GetSourceIdForWebsiteUrl() method. - // TODO(crbug.com/1340241): Use PassKeys in UkmRecorder, and remove these - // friend classes. - friend apps::WebsiteMetrics; - friend web_app::DesktopWebAppUkmRecorder; - // Associates the SourceId with a URL. Most UKM recording code should prefer // to use a shared SourceId that is already associated with a URL, rather // than using this API directly. New uses of this API must be audited to @@ -158,9 +158,6 @@ const GURL& url, const AppType app_type) = 0; - // Gets new SourceId for a website Url. - static SourceId GetSourceIdForWebsiteUrl(const GURL& start_url); - // Associates navigation data with the UkmSource keyed by |source_id|. This // should only be called by SourceUrlRecorderWebContentsObserver, for // navigation sources.
diff --git a/services/network/first_party_sets/first_party_sets_manager.cc b/services/network/first_party_sets/first_party_sets_manager.cc index 79d8caf..032f321 100644 --- a/services/network/first_party_sets/first_party_sets_manager.cc +++ b/services/network/first_party_sets/first_party_sets_manager.cc
@@ -165,9 +165,7 @@ if (const auto it = fps_context_config.customizations().find(normalized_site); it != fps_context_config.customizations().end()) { - if (it->second.has_value()) { - entry = it->second.value(); - } + entry = it->second; } else if (const auto it = sets_->find(normalized_site); it != sets_->end()) { entry = it->second;
diff --git a/services/network/public/cpp/optional_trust_token_params_unittest.cc b/services/network/public/cpp/optional_trust_token_params_unittest.cc index d414e7fd..0c1926a8 100644 --- a/services/network/public/cpp/optional_trust_token_params_unittest.cc +++ b/services/network/public/cpp/optional_trust_token_params_unittest.cc
@@ -27,6 +27,7 @@ return mojom::TrustTokenParams( mojom::TrustTokenOperationType::kRedemption, mojom::TrustTokenRefreshPolicy::kRefresh, "custom_key_commitment", + url::Origin::Create(GURL("https://custom-issuer.com")), mojom::TrustTokenSignRequestData::kInclude, /*include_timestamp_header=*/true, std::vector<url::Origin>{url::Origin::Create(GURL("https://issuer.com"))},
diff --git a/services/network/public/mojom/trust_tokens.mojom b/services/network/public/mojom/trust_tokens.mojom index 716db86..6d29b77 100644 --- a/services/network/public/mojom/trust_tokens.mojom +++ b/services/network/public/mojom/trust_tokens.mojom
@@ -127,6 +127,9 @@ // used for this operation if set. string? custom_key_commitment; + // "custom_issuer" specifies what issuer to use for this operation if set. + url.mojom.Origin? custom_issuer; + // The remaining members are used only when "type" is "kSigning": these // parameters specify the manner in which the outgoing request should be // signed, including optionally specifying additional data to add in
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory.cc b/services/network/trust_tokens/trust_token_request_helper_factory.cc index b9b08b4..95a16da 100644 --- a/services/network/trust_tokens/trust_token_request_helper_factory.cc +++ b/services/network/trust_tokens/trust_token_request_helper_factory.cc
@@ -150,7 +150,7 @@ Outcome::kSuccessfullyCreatedAnIssuanceHelper); auto helper = std::make_unique<TrustTokenRequestIssuanceHelper>( std::move(top_frame_origin), store, key_commitment_getter_, - params->custom_key_commitment, + params->custom_key_commitment, params->custom_issuer, std::make_unique<BoringsslTrustTokenIssuanceCryptographer>(), std::make_unique<LocalTrustTokenOperationDelegateImpl>( context_client_provider_), @@ -168,7 +168,7 @@ auto helper = std::make_unique<TrustTokenRequestRedemptionHelper>( std::move(top_frame_origin), params->refresh_policy, store, key_commitment_getter_, params->custom_key_commitment, - std::make_unique<EcdsaP256KeyPairGenerator>(), + params->custom_issuer, std::make_unique<EcdsaP256KeyPairGenerator>(), std::make_unique<BoringsslTrustTokenRedemptionCryptographer>(), std::move(net_log)); std::move(done).Run(TrustTokenStatusOrRequestHelper(
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/services/network/trust_tokens/trust_token_request_issuance_helper.cc index 997a820..7fa73c3 100644 --- a/services/network/trust_tokens/trust_token_request_issuance_helper.cc +++ b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
@@ -94,6 +94,7 @@ TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, absl::optional<std::string> custom_key_commitment, + absl::optional<url::Origin> custom_issuer, std::unique_ptr<Cryptographer> cryptographer, std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate, base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)> @@ -104,6 +105,7 @@ token_store_(token_store), key_commitment_getter_(std::move(key_commitment_getter)), custom_key_commitment_(custom_key_commitment), + custom_issuer_(custom_issuer), cryptographer_(std::move(cryptographer)), local_operation_delegate_(std::move(local_operation_delegate)), is_current_os_callback_(std::move(is_current_os_callback)), @@ -129,7 +131,12 @@ net_log_.BeginEvent( net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_ISSUANCE); - issuer_ = SuitableTrustTokenOrigin::Create(request->url()); + if (custom_issuer_) { + issuer_ = SuitableTrustTokenOrigin::Create(*custom_issuer_); + } else { + issuer_ = SuitableTrustTokenOrigin::Create(request->url()); + } + if (!issuer_) { LogOutcome(net_log_, kBegin, "Unsuitable issuer URL"); std::move(done).Run(mojom::TrustTokenOperationStatus::kInvalidArgument);
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.h b/services/network/trust_tokens/trust_token_request_issuance_helper.h index 8a43500..02577fa 100644 --- a/services/network/trust_tokens/trust_token_request_issuance_helper.h +++ b/services/network/trust_tokens/trust_token_request_issuance_helper.h
@@ -147,6 +147,7 @@ TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, absl::optional<std::string> custom_key_commitment, + absl::optional<url::Origin> custom_issuer, std::unique_ptr<Cryptographer> cryptographer, std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate, @@ -271,7 +272,8 @@ const SuitableTrustTokenOrigin top_level_origin_; const raw_ptr<TrustTokenStore> token_store_; const raw_ptr<const TrustTokenKeyCommitmentGetter> key_commitment_getter_; - absl::optional<std::string> custom_key_commitment_; + const absl::optional<std::string> custom_key_commitment_; + const absl::optional<url::Origin> custom_issuer_; mojom::TrustTokenProtocolVersion protocol_version_;
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc index d4f23492..5a2c183 100644 --- a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc +++ b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
@@ -163,7 +163,7 @@ TrustTokenRequestIssuanceHelper helper( toplevel, store.get(), g_fixed_key_commitment_getter.get(), absl::nullopt, - std::make_unique<MockCryptographer>(), + absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -189,7 +189,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), absl::nullopt, - std::make_unique<MockCryptographer>(), + absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -211,7 +211,7 @@ auto getter = std::make_unique<FixedKeyCommitmentGetter>(issuer, nullptr); TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, + store.get(), getter.get(), absl::nullopt, absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -238,7 +238,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -262,7 +263,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -290,7 +292,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -323,7 +326,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -363,7 +367,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -392,7 +397,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -426,7 +432,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -471,7 +478,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -515,7 +523,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -557,7 +566,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -600,7 +610,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -666,7 +677,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); // request is from issuer1 @@ -735,7 +747,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -802,7 +815,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -860,7 +874,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -892,7 +907,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), absl::nullopt, - std::make_unique<MockCryptographer>(), + absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -908,7 +923,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), g_fixed_key_commitment_getter.get(), absl::nullopt, - std::make_unique<MockCryptographer>(), + absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -937,7 +952,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), store.get(), ReasonableKeyCommitmentGetter(), absl::nullopt, - std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), + absl::nullopt, std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/"); @@ -954,7 +970,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), store.get(), g_fixed_key_commitment_getter.get(), "junk keys", - std::make_unique<MockCryptographer>(), + absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -1002,7 +1018,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), ReasonableKeyCommitmentGetter(), basic_key, + store.get(), ReasonableKeyCommitmentGetter(), basic_key, absl::nullopt, std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); @@ -1031,6 +1047,95 @@ ElementsAre(Property(&TrustToken::body, "a signed, unblinded token"))); } +// Check that attempting to issue with custom key commitments fails if custom +// key commitments are invalid. +TEST_F(TrustTokenRequestIssuanceHelperTest, BadCustomIssuer) { + auto store = TrustTokenStore::CreateForTesting(); + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), + store.get(), g_fixed_key_commitment_getter.get(), "junk keys", + url::Origin::Create(GURL("http://bad-issuer.com")), + std::make_unique<MockCryptographer>(), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); + + auto request = MakeURLRequest("https://issuer.com/"); + + EXPECT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kInvalidArgument); +} + +// Check that a successful end-to-end Begin/Finalize flow with custom key +// commitments stores the obtained trust tokens in the trust token store. +TEST_F(TrustTokenRequestIssuanceHelperTest, CustomIssuerStoresObtainedTokens) { + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + + SuitableTrustTokenOrigin fakeissuer = + *SuitableTrustTokenOrigin::Create(GURL("https://fakeissuer.com/")); + + SuitableTrustTokenOrigin goodissuer = + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")); + + // Have the Trust Tokens issuance conclude by the underlying cryptographic + // library returning one signed, unblinded token associated with the same + // returned from the key commitment. + auto unblinded_tokens = std::make_unique<UnblindedTokens>(); + unblinded_tokens->body_of_verifying_key = + ReasonableKeyCommitmentResult()->keys.front()->body; + unblinded_tokens->tokens.push_back("a signed, unblinded token"); + + auto cryptographer = std::make_unique<MockCryptographer>(); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginIssuance(_)) + .WillOnce( + Return(std::string("this string contains some blinded tokens"))); + EXPECT_CALL(*cryptographer, ConfirmIssuance(_)) + .WillOnce(Return(ByMove(std::move((unblinded_tokens))))); + + base::Time one_minute_from_now = base::Time::Now() + base::Minutes(1); + int64_t one_minute_from_now_in_micros = + (one_minute_from_now - base::Time::UnixEpoch()).InMicroseconds(); + + const std::string basic_key = base::StringPrintf( + R"({ "TrustTokenV3PMB": { + "protocol_version": "TrustTokenV3PMB", "id": 1, "batchsize": 5, + "keys": {"1": { "Y": "akey", "expiry": "%s" }} + }})", + base::NumberToString(one_minute_from_now_in_micros).c_str()); + + TrustTokenRequestIssuanceHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + store.get(), ReasonableKeyCommitmentGetter(), basic_key, + url::Origin::Create(GURL("https://issuer.com")), std::move(cryptographer), + std::make_unique<MockLocalOperationDelegate>(), + base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get()); + + auto request = MakeURLRequest("https://fakeissuer.com/"); + request->set_initiator(fakeissuer); + + ASSERT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kOk); + + auto response_head = mojom::URLResponseHead::New(); + response_head->headers = + net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\r\n"); + response_head->headers->SetHeader( + kTrustTokensSecTrustTokenHeader, + "response from issuer (this value will be ignored, since " + "Cryptographer::ConfirmResponse is mocked out)"); + EXPECT_EQ(ExecuteFinalizeAndWaitForResult(&helper, response_head.get()), + mojom::TrustTokenOperationStatus::kOk); + + // After the operation has successfully finished, the trust tokens parsed from + // the server response should be in the store. + auto match_all_keys = + base::BindRepeating([](const std::string&) { return true; }); + EXPECT_THAT( + store->RetrieveMatchingTokens(goodissuer, std::move(match_all_keys)), + ElementsAre(Property(&TrustToken::body, "a signed, unblinded token"))); +} + class TrustTokenRequestIssuanceHelperTestWithPlatformIssuance : public TrustTokenRequestIssuanceHelperTest { public: @@ -1103,8 +1208,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, std::move(cryptographer), - std::move(local_operation_delegate), + store.get(), getter.get(), absl::nullopt, absl::nullopt, + std::move(cryptographer), std::move(local_operation_delegate), base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) { return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid; }), @@ -1173,8 +1278,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, std::move(cryptographer), - std::move(local_operation_delegate), + store.get(), getter.get(), absl::nullopt, absl::nullopt, + std::move(cryptographer), std::move(local_operation_delegate), base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) { return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid; }), @@ -1209,7 +1314,7 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, + store.get(), getter.get(), absl::nullopt, absl::nullopt, std::make_unique<MockCryptographer>(), std::make_unique<MockLocalOperationDelegate>(), // Fail to match to the current OS... @@ -1254,8 +1359,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, std::move(cryptographer), - std::make_unique<MockLocalOperationDelegate>(), + store.get(), getter.get(), absl::nullopt, absl::nullopt, + std::move(cryptographer), std::make_unique<MockLocalOperationDelegate>(), // Fail to match to the current OS... base::BindLambdaForTesting( [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }), @@ -1321,8 +1426,8 @@ TrustTokenRequestIssuanceHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), - store.get(), getter.get(), absl::nullopt, std::move(cryptographer), - std::move(local_operation_delegate), + store.get(), getter.get(), absl::nullopt, absl::nullopt, + std::move(cryptographer), std::move(local_operation_delegate), base::BindRepeating(&IsCurrentOperatingSystem), metrics_delegate.get()); auto request = MakeURLRequest("https://issuer.com/");
diff --git a/services/network/trust_tokens/trust_token_request_redemption_helper.cc b/services/network/trust_tokens/trust_token_request_redemption_helper.cc index 25de850..978be8c 100644 --- a/services/network/trust_tokens/trust_token_request_redemption_helper.cc +++ b/services/network/trust_tokens/trust_token_request_redemption_helper.cc
@@ -52,6 +52,7 @@ TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, absl::optional<std::string> custom_key_commitment, + absl::optional<url::Origin> custom_issuer, std::unique_ptr<KeyPairGenerator> key_pair_generator, std::unique_ptr<Cryptographer> cryptographer, net::NetLogWithSource net_log) @@ -60,6 +61,7 @@ token_store_(token_store), key_commitment_getter_(std::move(key_commitment_getter)), custom_key_commitment_(custom_key_commitment), + custom_issuer_(custom_issuer), key_pair_generator_(std::move(key_pair_generator)), cryptographer_(std::move(cryptographer)), net_log_(std::move(net_log)) { @@ -80,7 +82,12 @@ net_log_.BeginEvent( net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_REDEMPTION); - issuer_ = SuitableTrustTokenOrigin::Create(request->url()); + if (custom_issuer_) { + issuer_ = SuitableTrustTokenOrigin::Create(*custom_issuer_); + } else { + issuer_ = SuitableTrustTokenOrigin::Create(request->url()); + } + if (!issuer_) { LogOutcome(net_log_, kBegin, "Unsuitable issuer URL (request destination)"); std::move(done).Run(mojom::TrustTokenOperationStatus::kInvalidArgument);
diff --git a/services/network/trust_tokens/trust_token_request_redemption_helper.h b/services/network/trust_tokens/trust_token_request_redemption_helper.h index bf9da7c..6145b1f 100644 --- a/services/network/trust_tokens/trust_token_request_redemption_helper.h +++ b/services/network/trust_tokens/trust_token_request_redemption_helper.h
@@ -130,6 +130,7 @@ TrustTokenStore* token_store, const TrustTokenKeyCommitmentGetter* key_commitment_getter, absl::optional<std::string> custom_key_commitment, + absl::optional<url::Origin> custom_issuer, std::unique_ptr<KeyPairGenerator> key_pair_generator, std::unique_ptr<Cryptographer> cryptographer, net::NetLogWithSource net_log = net::NetLogWithSource()); @@ -215,7 +216,8 @@ const raw_ptr<TrustTokenStore> token_store_; const raw_ptr<const TrustTokenKeyCommitmentGetter> key_commitment_getter_; - absl::optional<std::string> custom_key_commitment_; + const absl::optional<std::string> custom_key_commitment_; + const absl::optional<url::Origin> custom_issuer_; const std::unique_ptr<KeyPairGenerator> key_pair_generator_; const std::unique_ptr<Cryptographer> cryptographer_; net::NetLogWithSource net_log_;
diff --git a/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc index af22594d..a2e606ff 100644 --- a/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc +++ b/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc
@@ -134,7 +134,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), - &*g_fixed_key_commitment_getter, absl::nullopt, + &*g_fixed_key_commitment_getter, absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); @@ -159,7 +159,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); auto request = MakeURLRequest("https://issuer.com/"); @@ -187,7 +187,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); auto request = MakeURLRequest("https://issuer.com/"); @@ -237,7 +237,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -288,7 +288,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -334,7 +334,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FailingKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FailingKeyPairGenerator>(), std::make_unique<MockCryptographer>()); auto request = MakeURLRequest("https://issuer.com/"); @@ -392,7 +392,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); request_ = MakeURLRequest("https://issuer.com/"); @@ -475,7 +475,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -527,7 +527,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -593,7 +593,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -662,7 +662,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -730,7 +730,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), + absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -789,7 +789,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, + absl::nullopt, absl::nullopt, std::make_unique<MockKeyPairGenerator>("signing key", "verification key"), std::move(cryptographer)); @@ -860,7 +860,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, + absl::nullopt, absl::nullopt, std::make_unique<MockKeyPairGenerator>("signing key", "verification key"), std::move(cryptographer)); @@ -932,7 +932,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - absl::nullopt, + absl::nullopt, absl::nullopt, std::make_unique<MockKeyPairGenerator>("signing key", "verification key"), std::move(cryptographer)); @@ -986,7 +986,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), - &*g_fixed_key_commitment_getter, absl::nullopt, + &*g_fixed_key_commitment_getter, absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); @@ -1046,7 +1046,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kRefresh, store.get(), &*getter, - absl::nullopt, + absl::nullopt, absl::nullopt, std::make_unique<MockKeyPairGenerator>("signing key", "verification key"), std::move(cryptographer)); @@ -1090,7 +1090,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), - &*g_fixed_key_commitment_getter, absl::nullopt, + &*g_fixed_key_commitment_getter, absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); @@ -1106,7 +1106,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), - &*g_fixed_key_commitment_getter, absl::nullopt, + &*g_fixed_key_commitment_getter, absl::nullopt, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); @@ -1121,7 +1121,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), - &*g_fixed_key_commitment_getter, "junk keys", + &*g_fixed_key_commitment_getter, "junk keys", absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::make_unique<MockCryptographer>()); @@ -1183,7 +1183,7 @@ TrustTokenRequestRedemptionHelper helper( *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, - basic_key, std::make_unique<FakeKeyPairGenerator>(), + basic_key, absl::nullopt, std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); auto request = MakeURLRequest("https://issuer.com/"); @@ -1213,4 +1213,102 @@ response_head->headers->HasHeader(kTrustTokensSecTrustTokenHeader)); } +TEST_F(TrustTokenRequestRedemptionHelperTest, BadCustomIssuer) { + auto store = TrustTokenStore::CreateForTesting(); + TrustTokenRequestRedemptionHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), + mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), + &*g_fixed_key_commitment_getter, "junk keys", + url::Origin::Create(GURL("http://bad-issuer.com")), + std::make_unique<FakeKeyPairGenerator>(), + std::make_unique<MockCryptographer>()); + + auto request = MakeURLRequest("https://issuer.com/"); + + EXPECT_EQ(ExecuteBeginOperationAndWaitForResult(&helper, request.get()), + mojom::TrustTokenOperationStatus::kInvalidArgument); +} + +// Check that, when preconditions are met and the underlying cryptographic steps +// successfully complete, the begin/finalize methods with custom key commitments +// succeed. +TEST_F(TrustTokenRequestRedemptionHelperTest, CustomIssuerSuccess) { + // Establish the following state: + // * One key commitment returned from the key commitment registry, with one + // key, with body "". + // * One token stored corresponding to the key "" (this will be the token + // that the redemption request redeems; its key needs to match the key + // commitment's key so that it does not get evicted from storage after the key + // commitment is updated to reflect the key commitment result). + std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); + store->AddTokens( + *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/")), + std::vector<std::string>{"a token"}, + /*issuing_key=*/""); + + auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New(); + key_commitment_result->keys.push_back( + mojom::TrustTokenVerificationKey::New()); + key_commitment_result->protocol_version = + mojom::TrustTokenProtocolVersion::kTrustTokenV3Pmb; + key_commitment_result->id = 1; + key_commitment_result->batch_size = + static_cast<int>(kMaximumTrustTokenIssuanceBatchSize); + auto getter = std::make_unique<FixedKeyCommitmentGetter>( + *SuitableTrustTokenOrigin::Create(GURL("https://badissuer.com")), + std::move(key_commitment_result)); + + // Configure the cryptographer to succeed on both the outbound and inbound + // halves of the operation. + auto cryptographer = std::make_unique<MockCryptographer>(); + EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true)); + EXPECT_CALL(*cryptographer, BeginRedemption(_, _, _)) + .WillOnce(Return("well-formed redemption request")); + EXPECT_CALL(*cryptographer, ConfirmRedemption(_)) + .WillOnce(Return("a successfully-extracted RR")); + + base::Time one_minute_from_now = base::Time::Now() + base::Minutes(1); + int64_t one_minute_from_now_in_micros = + (one_minute_from_now - base::Time::UnixEpoch()).InMicroseconds(); + + const std::string basic_key = base::StringPrintf( + R"({ "TrustTokenV3PMB": { + "protocol_version": "TrustTokenV3PMB", "id": 1, "batchsize": 5, + "keys": {"1": { "Y": "", "expiry": "%s" }} + }})", + base::NumberToString(one_minute_from_now_in_micros).c_str()); + + TrustTokenRequestRedemptionHelper helper( + *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")), + mojom::TrustTokenRefreshPolicy::kUseCached, store.get(), &*getter, + basic_key, url::Origin::Create(GURL("https://issuer.com")), + std::make_unique<FakeKeyPairGenerator>(), std::move(cryptographer)); + + auto request = MakeURLRequest("https://badissuer.com/"); + request->set_initiator( + *SuitableTrustTokenOrigin::Create(GURL("https://badissuer.com/"))); + + mojom::TrustTokenOperationStatus result = + ExecuteBeginOperationAndWaitForResult(&helper, request.get()); + + // Since this test is testing the behavior on handling the response after + // successfully constructing a redemption request, sanity check that the setup + // has correctly caused constructing the request so succeed. + ASSERT_EQ(result, mojom::TrustTokenOperationStatus::kOk); + + auto response_head = mojom::URLResponseHead::New(); + response_head->headers = + net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\r\n"); + response_head->headers->SetHeader(kTrustTokensSecTrustTokenHeader, ""); + + // After a successfully constructed request, when the response is well-formed + // and the delegate accepts the response, Finalize should succeed. + EXPECT_EQ(ExecuteFinalizeAndWaitForResult(&helper, response_head.get()), + mojom::TrustTokenOperationStatus::kOk); + + // Processing the response should have stripped the header. + EXPECT_FALSE( + response_head->headers->HasHeader(kTrustTokensSecTrustTokenHeader)); +} + } // namespace network
diff --git a/services/viz/privileged/mojom/gl/gpu_host.mojom b/services/viz/privileged/mojom/gl/gpu_host.mojom index 3068aa0b..ff90550 100644 --- a/services/viz/privileged/mojom/gl/gpu_host.mojom +++ b/services/viz/privileged/mojom/gl/gpu_host.mojom
@@ -4,6 +4,7 @@ module viz.mojom; +import "gpu/ipc/common/gpu_disk_cache_type.mojom"; import "gpu/ipc/common/gpu_feature_info.mojom"; import "gpu/ipc/common/gpu_info.mojom"; import "gpu/ipc/common/surface_handle.mojom"; @@ -61,9 +62,10 @@ SetChildSurface(gpu.mojom.SurfaceHandle parent, gpu.mojom.SurfaceHandle child); - StoreShaderToDisk(int32 client_id, - string key, - mojo_base.mojom.ByteString shader); + // Tells the GPU host to store the blob on the given cache handle. + StoreBlobToDisk(gpu.mojom.GpuDiskCacheHandle cache_handle, + string key, + mojo_base.mojom.ByteString blob); RecordLogMessage(int32 severity, string header, string message); };
diff --git a/services/viz/privileged/mojom/gl/gpu_service.mojom b/services/viz/privileged/mojom/gl/gpu_service.mojom index 12f89ff..d1b3582 100644 --- a/services/viz/privileged/mojom/gl/gpu_service.mojom +++ b/services/viz/privileged/mojom/gl/gpu_service.mojom
@@ -20,6 +20,7 @@ import "components/chromeos_camera/common/jpeg_encode_accelerator.mojom"; import "gpu/ipc/common/device_perf_info.mojom"; import "gpu/ipc/common/dx_diag_node.mojom"; +import "gpu/ipc/common/gpu_disk_cache_type.mojom"; import "gpu/ipc/common/gpu_feature_info.mojom"; import "gpu/ipc/common/gpu_info.mojom"; import "gpu/ipc/common/gpu_peak_memory.mojom"; @@ -49,8 +50,7 @@ [Sync, NoInterrupt] EstablishGpuChannel(int32 client_id, uint64 client_tracing_id, - bool is_gpu_host, - bool cache_shaders_on_disk) + bool is_gpu_host) => (handle<message_pipe>? channel_handle, gpu.mojom.GpuInfo gpu_info, gpu.mojom.GpuFeatureInfo gpu_feature_info); @@ -60,6 +60,11 @@ // `client_id`. SetChannelClientPid(int32 client_id, mojo_base.mojom.ProcessId client_pid); + // Tells the GPU service an assigned cache handle. Note that for each type of + // handle per client only one unique handle is expected. + SetChannelDiskCacheHandle(int32 client_id, + gpu.mojom.GpuDiskCacheHandle cache_handle); + // Tells the GPU process to close the channel identified by |client_id|. // If no channel can be identified, do nothing. CloseChannel(int32 client_id); @@ -157,10 +162,13 @@ [EnableIf=is_win] RequestDXGIInfo() => (gfx.mojom.DXGIInfo dxgi_info); - // Notify GPU that a shader program was loaded from disk. Key is an - // SHA-1 hash, and data a binary blob with serialized program info. - // Note that this method is used only from a trusted process. - LoadedShader(int32 client_id, string key, mojo_base.mojom.ByteString data); + // Notify GPU that a cached blob was loaded from disk for the particular + // handle. The handle is used to map 1:1 to an actual file path on disk in the + // host since multiple clients may be using the same physical disk path. Note + // that this method is used only from a trusted process. + LoadedBlob(gpu.mojom.GpuDiskCacheHandle cache_handle, + string key, + mojo_base.mojom.ByteString data); // Tells GPU to wake up the GPU because we're about to draw. WakeUpGpu();
diff --git a/testing/test.gni b/testing/test.gni index 094d4e8..0ef71de 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -127,8 +127,16 @@ action("${target_name}__rts_filters") { script = "//build/add_rts_filters.py" rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter" - args = [ rebase_path(rts_file, root_build_dir) ] - outputs = [ rts_file ] + inverted_rts_file = + "${root_build_dir}/gen/rts/${invoker.target_name}_inverted.filter" + args = [ + rebase_path(rts_file, root_build_dir), + rebase_path(inverted_rts_file, root_build_dir), + ] + outputs = [ + rts_file, + inverted_rts_file, + ] } } @@ -1034,8 +1042,16 @@ action("${target_name}__rts_filters") { script = "//build/add_rts_filters.py" rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter" - args = [ rebase_path(rts_file, root_build_dir) ] - outputs = [ rts_file ] + inverted_rts_file = + "${root_build_dir}/gen/rts/${invoker.target_name}_inverted.filter" + args = [ + rebase_path(rts_file, root_build_dir), + rebase_path(inverted_rts_file, root_build_dir), + ] + outputs = [ + rts_file, + inverted_rts_file, + ] } }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 4a8622d9..0c79896 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -500,6 +500,27 @@ ] } ], + "ArcEnableTTSCacheSetup": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ArcEnableTTSCacheSetup" + ] + }, + { + "name": "Disabled", + "disable_features": [ + "ArcEnableTTSCacheSetup" + ] + } + ] + } + ], "ArcEnableTTSCaching": [ { "platforms": [ @@ -3635,6 +3656,23 @@ ] } ], + "DesktopSharePreview": [ + { + "platforms": [ + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "DesktopSharePreview" + ] + } + ] + } + ], "DesktopTabGroupsInProductHelp": [ { "platforms": [ @@ -4011,23 +4049,33 @@ "DownloadUXRedesign": [ { "platforms": [ - "windows" + "windows", + "mac", + "chromeos_lacros", + "linux" ], "experiments": [ { - "name": "Enabled_20220616", + "name": "Enabled_New_20220816", "enable_features": [ "DownloadBubble" ] }, { - "name": "Enabled_20220727", + "name": "Enabled_20220816", "enable_features": [ "DownloadBubble" ], "disable_features": [ "DownloadBubbleV2" ] + }, + { + "name": "Enabled_V2_20220816", + "enable_features": [ + "DownloadBubble", + "DownloadBubbleV2" + ] } ] }
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index b48e323f..a776e338 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1506,6 +1506,13 @@ const base::FeatureParam<bool> kDelayAsyncScriptExecutionCrossSiteOnlyParam{ &kDelayAsyncScriptExecution, "cross_site_only", false}; +const base::Feature kLowPriorityAsyncScriptExecution{ + "LowPriorityAsyncScriptExecution", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::FeatureParam<base::TimeDelta> + kTimeoutForLowPriorityAsyncScriptExecution{ + &kLowPriorityAsyncScriptExecution, "timeout", base::Milliseconds(0)}; + const base::Feature kForceDeferScriptIntervention{ "ForceDeferScriptIntervention", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 65cfc79a..9d99245 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -748,6 +748,14 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> kDelayAsyncScriptExecutionCrossSiteOnlyParam; +// If enabled, async scripts will be run on a lower priority task queue. +// See https://crbug.com/1348467. +BLINK_COMMON_EXPORT extern const base::Feature kLowPriorityAsyncScriptExecution; +// The timeout value for kLowPriorityAsyncScriptExecution. Async scripts run on +// lower priority queue until this timeout elapsed. +BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta> + kTimeoutForLowPriorityAsyncScriptExecution; + // If enabled, parser-blocking scripts are force-deferred. // https://crbug.com/1339112 BLINK_COMMON_EXPORT extern const base::Feature kForceDeferScriptIntervention;
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index f8dcfd8..31304e4 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3648,6 +3648,7 @@ kV8PendingPostBeacon_SetData_Method = 4327, kContentVisibilityAutoStateChangedHandlerRegistered = 4328, kReplacedElementPaintedWithLargeOverflow = 4329, + kFlexboxAbsPosJustifyContent = 4330, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/TaskTypes.md b/third_party/blink/public/platform/TaskTypes.md index d76d72c..ce61ee3 100644 --- a/third_party/blink/public/platform/TaskTypes.md +++ b/third_party/blink/public/platform/TaskTypes.md
@@ -14,6 +14,7 @@ | Networking | No | No | Yes | Yes | Yes | No | | NetworkingWithURLLoaderAnnotation | No | No | Yes | Yes | Yes | No | | NetworkingControl | No | No | Yes | Yes | Yes | No | +| LowPriorityScriptExecution | No | No | Yes | Yes | Yes | No | | HistoryTraversal | No | No | Yes | Yes | Yes | Yes | | Embed | No | No | Yes | Yes | Yes | Yes | | MediaElementEvent | No | No | No | Yes | Yes | Yes |
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index 7466cb15..f3e99ff 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -51,6 +51,8 @@ kNetworkingUnfreezable = 75, // This task source is used for control messages between kNetworking tasks. kNetworkingControl = 4, + // Tasks used to run low priority scripts. + kLowPriorityScriptExecution = 81, // This task source is used to queue calls to history.back() and similar APIs. kHistoryTraversal = 5, @@ -292,7 +294,7 @@ kWorkerThreadTaskQueueV8 = 47, kWorkerThreadTaskQueueCompositor = 48, - kMaxValue = kInternalNavigationCancellation, + kMaxValue = kLowPriorityScriptExecution, }; } // namespace blink
diff --git a/third_party/blink/renderer/DEPS b/third_party/blink/renderer/DEPS index c36fa7a..7e180b04 100644 --- a/third_party/blink/renderer/DEPS +++ b/third_party/blink/renderer/DEPS
@@ -53,6 +53,7 @@ "+base/test/gmock_callback_support.h", "+base/test/metrics/histogram_tester.h", "+base/test/mock_callback.h", + "+base/test/null_task_runner.h", "+base/test/scoped_feature_list.h", "+base/test/test_simple_task_runner.h", "+base/thread_annotations.h",
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc index f05d6f8..9437cfb 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
@@ -21,8 +21,8 @@ #include "third_party/blink/renderer/core/css/cssom/css_unit_value.h" #include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h" #include "third_party/blink/renderer/core/css/cssom/css_unsupported_color.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -88,7 +88,7 @@ } protected: - std::unique_ptr<blink::Thread> thread_; + std::unique_ptr<blink::NonMainThread> thread_; }; // Ensure that a CrossThreadUnsupportedValue can be safely passed cross @@ -99,7 +99,7 @@ DCHECK(value); // Use a Thread to emulate worklet thread. - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask( @@ -130,7 +130,7 @@ DCHECK(value); // Use a Thread to emulate worklet thread. - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask( @@ -162,7 +162,7 @@ DCHECK(value); // Use a Thread to emulate worklet thread. - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask( @@ -194,7 +194,7 @@ DCHECK(value); // Use a Thread to emulate worklet thread. - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask( @@ -226,7 +226,7 @@ DCHECK(value); // Use a Thread to emulate worklet thread. - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask(
diff --git a/third_party/blink/renderer/core/css/cssom/css_hsl.cc b/third_party/blink/renderer/core/css/cssom/css_hsl.cc index 7e8e2794..d724ca6 100644 --- a/third_party/blink/renderer/core/css/cssom/css_hsl.cc +++ b/third_party/blink/renderer/core/css/cssom/css_hsl.cc
@@ -108,7 +108,7 @@ } Color CSSHSL::ToColor() const { - // MakeRGBAFromHSLA expects hue in the range [0, 6) + // FromHSLA expects hue in the range [0, 6) return Color::FromHSLA( h_->to(CSSPrimitiveValue::UnitType::kDegrees)->value() / 60, ComponentToColorInput(s_), ComponentToColorInput(l_),
diff --git a/third_party/blink/renderer/core/css/cssom/css_hwb.cc b/third_party/blink/renderer/core/css/cssom/css_hwb.cc index 6a365e55..2f7fc385 100644 --- a/third_party/blink/renderer/core/css/cssom/css_hwb.cc +++ b/third_party/blink/renderer/core/css/cssom/css_hwb.cc
@@ -104,7 +104,7 @@ } Color CSSHWB::ToColor() const { - // MakeRGBAFromHSLA expects hue in the range [0, 6) + // FromHSLA expects hue in the range [0, 6) return Color::FromHWBA( h_->to(CSSPrimitiveValue::UnitType::kDegrees)->value() / 60, ComponentToColorInput(w_), ComponentToColorInput(b_),
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc index 3c3b0f2..f90707b 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -20,8 +20,8 @@ #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -108,7 +108,7 @@ } protected: - std::unique_ptr<blink::Thread> thread_; + std::unique_ptr<blink::NonMainThread> thread_; }; TEST_F(PaintWorkletStylePropertyMapTest, UnregisteredCustomProperty) { @@ -137,7 +137,7 @@ std::move(input_arguments), std::move(property_keys)); ASSERT_TRUE(input); - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask( @@ -185,7 +185,7 @@ std::move(input_arguments), std::move(property_keys)); DCHECK(input); - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true)); base::WaitableEvent waitable_event; PostCrossThreadTask(
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc index dc102386..d72260f 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -611,15 +611,15 @@ } template <typename CharacterType> -static bool FastParseColorInternal(RGBA32& rgb, +static bool FastParseColorInternal(Color& color, const CharacterType* characters, unsigned length, bool quirks_mode) { if (length >= 4 && characters[0] == '#') - return Color::ParseHexColor(characters + 1, length - 1, rgb); + return Color::ParseHexColor(characters + 1, length - 1, color); if (quirks_mode && (length == 3 || length == 6)) { - if (Color::ParseHexColor(characters, length, rgb)) + if (Color::ParseHexColor(characters, length, color)) return true; } @@ -669,11 +669,11 @@ if (should_have_alpha) { if (!ParseAlphaValue(current, end, ')', alpha)) return false; - rgb = MakeRGBA(red, green, blue, alpha); + color = Color::FromRGBA(red, green, blue, alpha); } else { if (current != end) return false; - rgb = MakeRGB(red, green, blue); + color = Color::FromRGB(red, green, blue); } return true; } @@ -706,8 +706,7 @@ return false; } - // We need to convert the hue to the 0..6 scale that MakeRGBAFromHSLA() - // expects. + // We need to convert the hue to the 0..6 scale that FromHSLA() expects. switch (hue_unit) { case CSSPrimitiveValue::UnitType::kNumber: case CSSPrimitiveValue::UnitType::kDegrees: @@ -775,11 +774,12 @@ return false; if (current != end) return false; - rgb = MakeRGBAFromHSLA(hue, saturation, lightness, alpha * (1.0 / 255.0)); + color = + Color::FromHSLA(hue, saturation, lightness, alpha * (1.0 / 255.0)); } else { if (current != end) return false; - rgb = MakeRGBAFromHSLA(hue, saturation, lightness, 1.0); + color = Color::FromHSLA(hue, saturation, lightness, 1.0); } return true; } @@ -801,7 +801,7 @@ return CSSIdentifierValue::Create(value_id); } - RGBA32 color; + Color color; bool quirks_mode = IsQuirksModeBehavior(parser_mode) && ColorPropertyAllowsQuirkyColor(property_id); @@ -812,7 +812,7 @@ }); if (!parse_result) return nullptr; - return cssvalue::CSSColor::Create(Color::FromRGBA32(color)); + return cssvalue::CSSColor::Create(color); } CSSValue* CSSParserFastPaths::ParseColor(const String& string,
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 8e51849c..a94ff4cf 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -1397,7 +1397,7 @@ static bool ParseRGBParameters(CSSParserTokenRange& range, const CSSParserContext& context, - RGBA32& result) { + Color& result) { DCHECK(range.Peek().FunctionId() == CSSValueID::kRgb || range.Peek().FunctionId() == CSSValueID::kRgba); CSSParserTokenRange args = ConsumeFunction(range); @@ -1448,17 +1448,17 @@ // W3 standard stipulates a 2.55 alpha value multiplication factor. int alpha_component = static_cast<int>(lround(ClampTo<double>(alpha, 0.0, 1.0) * 255.0)); - result = MakeRGBA(color_array[0], color_array[1], color_array[2], - alpha_component); + result = Color::FromRGBA(color_array[0], color_array[1], color_array[2], + alpha_component); } else { - result = MakeRGB(color_array[0], color_array[1], color_array[2]); + result = Color::FromRGB(color_array[0], color_array[1], color_array[2]); } return args.AtEnd(); } static bool ParseHSLParameters(CSSParserTokenRange& range, const CSSParserContext& context, - RGBA32& result) { + Color& result) { DCHECK(range.Peek().FunctionId() == CSSValueID::kHsl || range.Peek().FunctionId() == CSSValueID::kHsla); CSSParserTokenRange args = ConsumeFunction(range); @@ -1504,13 +1504,13 @@ alpha = ClampTo<double>(alpha, 0.0, 1.0); } result = - MakeRGBAFromHSLA(color_array[0], color_array[1], color_array[2], alpha); + Color::FromHSLA(color_array[0], color_array[1], color_array[2], alpha); return args.AtEnd(); } static bool ParseHWBParameters(CSSParserTokenRange& range, const CSSParserContext& context, - RGBA32& result) { + Color& result) { DCHECK(range.Peek().FunctionId() == CSSValueID::kHwb); CSSParserTokenRange args = ConsumeFunction(range); // Consume hue, an angle. @@ -1544,12 +1544,12 @@ alpha = ClampTo<double>(alpha, 0.0, 1.0); } - result = MakeRGBAFromHWBA(hue, percentages[0], percentages[1], alpha); + result = Color::FromHWBA(hue, percentages[0], percentages[1], alpha); return args.AtEnd(); } static bool ParseHexColor(CSSParserTokenRange& range, - RGBA32& result, + Color& result, bool accept_quirky_colors) { const CSSParserToken& token = range.Peek(); if (token.GetType() == kHashToken) { @@ -1586,7 +1586,7 @@ static bool ParseColorFunction(CSSParserTokenRange& range, const CSSParserContext& context, - RGBA32& result) { + Color& result) { CSSParserTokenRange color_range = range; switch (range.Peek().FunctionId()) { case CSSValueID::kRgb: @@ -1741,13 +1741,13 @@ CSSIdentifierValue* color = ConsumeIdent(range); return color; } - RGBA32 color = Color::kTransparent.Rgb(); + Color color = Color::kTransparent; if (!ParseHexColor(range, color, accept_quirky_colors) && !ParseColorFunction(range, context, color)) { return ConsumeInternalLightDark(ConsumeColor, range, context, accept_quirky_colors, allowed_keywords); } - return cssvalue::CSSColor::Create(Color::FromRGBA32(color)); + return cssvalue::CSSColor::Create(color); } CSSValue* ConsumeLineWidth(CSSParserTokenRange& range,
diff --git a/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h b/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h index 6968012..fed1039 100644 --- a/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h +++ b/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h
@@ -12,8 +12,8 @@ #include "base/synchronization/waitable_event.h" #include "base/task/single_thread_task_runner.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -53,11 +53,11 @@ // The default for this is 10*100 = 1000 times. template <typename FunctionType, typename... Ps> void RunOnThreads(FunctionType function, Ps&&... parameters) { - Vector<std::unique_ptr<blink::Thread>> threads; + Vector<std::unique_ptr<blink::NonMainThread>> threads; Vector<std::unique_ptr<base::WaitableEvent>> waits; for (int i = 0; i < num_threads_; ++i) { - threads.push_back(blink::Thread::CreateThread( + threads.push_back(blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetSupportsGC(true))); waits.push_back(std::make_unique<base::WaitableEvent>()); }
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc index 181a579b..075c35d 100644 --- a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc +++ b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
@@ -59,6 +59,8 @@ network::mojom::TrustTokenOperationType::kRedemption, network::mojom::TrustTokenRefreshPolicy::kUseCached, /* custom_key_commitment=*/"custom_key_commitment", + /* custom_issuer=*/ + ::blink::SecurityOrigin::CreateFromString("https://ccc.example"), network::mojom::TrustTokenSignRequestData::kInclude, /* include_timestamp_header=*/true, issuers, additional_signed_headers, /* possibly_unsafe_additional_signing_data=*/"ccc");
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 4a95e6f3..d819059c 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -4165,6 +4165,7 @@ } TEST_F(WebFrameTest, DivScrollIntoEditableTest) { + RegisterMockedHttpURLLoad("Ahem.ttf"); RegisterMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html"); const bool kAutoZoomToLegibleScale = true;
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 2d6135a6..deb04b1f 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1634,7 +1634,7 @@ unit); } -static RGBA32 ParseColorStringWithCrazyLegacyRules(const String& color_string) { +static Color ParseColorStringWithCrazyLegacyRules(const String& color_string) { // Per spec, only look at the first 128 digits of the string. const size_t kMaxColorLength = 128; // We'll pad the buffer with two extra 0s later, so reserve two more than the @@ -1658,16 +1658,17 @@ } if (!digit_buffer.size()) - return Color::kBlack.Rgb(); + return Color::kBlack; // Pad the buffer out to at least the next multiple of three in size. digit_buffer.push_back('0'); digit_buffer.push_back('0'); - if (digit_buffer.size() < 6) - return MakeRGB(ToASCIIHexValue(digit_buffer[0]), - ToASCIIHexValue(digit_buffer[1]), - ToASCIIHexValue(digit_buffer[2])); + if (digit_buffer.size() < 6) { + return Color::FromRGB(ToASCIIHexValue(digit_buffer[0]), + ToASCIIHexValue(digit_buffer[1]), + ToASCIIHexValue(digit_buffer[2])); + } // Split the digits into three components, then search the last 8 digits of // each component. @@ -1700,7 +1701,7 @@ ToASCIIHexValue(digit_buffer[green_index], digit_buffer[green_index + 1]); int blue_value = ToASCIIHexValue(digit_buffer[blue_index], digit_buffer[blue_index + 1]); - return MakeRGB(red_value, green_value, blue_value); + return Color::FromRGB(red_value, green_value, blue_value); } // Color parsing that matches HTML's "rules for parsing a legacy color value" @@ -1729,7 +1730,7 @@ if (!success) success = parsed_color.SetNamedColor(color_string); if (!success) { - parsed_color.SetRGB(ParseColorStringWithCrazyLegacyRules(color_string)); + parsed_color = ParseColorStringWithCrazyLegacyRules(color_string); success = true; }
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 91b0386..49befc8 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
@@ -67,8 +67,8 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -128,8 +128,8 @@ // collected objects. This means the thread the scanning runs on must be GC // enabled. DEFINE_STATIC_LOCAL( - std::unique_ptr<Thread>, preload_scanner_thread, - (Thread::CreateThread( + std::unique_ptr<NonMainThread>, preload_scanner_thread, + (NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kPreloadScannerThread) .SetSupportsGC(true)))); return preload_scanner_thread.get();
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set.cc b/third_party/blink/renderer/core/layout/layout_frame_set.cc index 8d9fc162..8c0d0a1 100644 --- a/third_party/blink/renderer/core/layout/layout_frame_set.cc +++ b/third_party/blink/renderer/core/layout/layout_frame_set.cc
@@ -182,8 +182,10 @@ for (int i = 0; i < grid_len; ++i) { if (grid[i].IsRelative()) { grid_layout[i] = - (max(grid[i].Value(), 1.) * remaining_relative) / total_relative; + (ClampTo<int>(max(grid[i].Value(), 1.)) * remaining_relative) / + total_relative; remaining_len -= grid_layout[i]; + DCHECK_GE(remaining_len, 0); last_relative = i; } }
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc index 4e1b2b2..4368776 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -197,24 +197,27 @@ for (LayoutBox* oof_child : oof_children) { NGBlockNode child(oof_child); - // This code block just collects UMA stats. - if (is_column_) { - const ComputedStyle& child_style = oof_child->StyleRef(); - const ComputedStyle& flexbox_style = Style(); + AxisEdge main_axis_edge = MainAxisStaticPositionEdge(Style(), is_column_); + AxisEdge cross_axis_edge = + CrossAxisStaticPositionEdge(Style(), child.Style()); + // This code block just collects UMA stats. + const auto& style = Style(); + const auto& child_style = child.Style(); + const PhysicalToLogical<Length> insets_in_flexbox_writing_mode( + Style().GetWritingDirection(), child_style.Top(), child_style.Right(), + child_style.Bottom(), child_style.Left()); + if (is_column_) { const ItemPosition normalized_alignment = - FlexLayoutAlgorithm::AlignmentForChild(flexbox_style, child_style); + FlexLayoutAlgorithm::AlignmentForChild(style, child_style); const ItemPosition default_justify_self_behavior = child.IsReplaced() ? ItemPosition::kStart : ItemPosition::kStretch; const ItemPosition normalized_justify = FlexLayoutAlgorithm::TranslateItemPosition( - flexbox_style, child_style, + style, child_style, child_style.ResolvedJustifySelf(default_justify_self_behavior) .GetPosition()); - const PhysicalToLogical<Length> insets_in_flexbox_writing_mode( - flexbox_style.GetWritingDirection(), child_style.Top(), - child_style.Right(), child_style.Bottom(), child_style.Left()); const bool are_cross_axis_insets_auto = insets_in_flexbox_writing_mode.InlineStart().IsAuto() && insets_in_flexbox_writing_mode.InlineEnd().IsAuto(); @@ -224,10 +227,17 @@ UseCounter::Count(Node().GetDocument(), WebFeature::kFlexboxNewAbsPos); } } - - AxisEdge main_axis_edge = MainAxisStaticPositionEdge(Style(), is_column_); - AxisEdge cross_axis_edge = - CrossAxisStaticPositionEdge(Style(), child.Style()); + if (main_axis_edge != AxisEdge::kStart) { + const bool are_main_axis_insets_auto = + is_column_ ? insets_in_flexbox_writing_mode.BlockStart().IsAuto() && + insets_in_flexbox_writing_mode.BlockEnd().IsAuto() + : insets_in_flexbox_writing_mode.InlineStart().IsAuto() && + insets_in_flexbox_writing_mode.InlineEnd().IsAuto(); + if (are_main_axis_insets_auto) { + UseCounter::Count(Node().GetDocument(), + WebFeature::kFlexboxAbsPosJustifyContent); + } + } AxisEdge inline_axis_edge = is_column_ ? cross_axis_edge : main_axis_edge; AxisEdge block_axis_edge = is_column_ ? main_axis_edge : cross_axis_edge;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc index 2ea218e..3ef9f367 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.cc
@@ -115,44 +115,73 @@ } } -// Determines whether the track direction, grid container writing mode, and -// grid item writing mode are part of the same alignment context as specified in -// https://www.w3.org/TR/css-align-3/#baseline-sharing-group -// In particular, 'Boxes share an alignment context, along a particular axis, -// and established by a particular box, when they are grid items in the same -// row, along the grid’s row (inline) axis, established by the grid container.' -// -// TODO(kschmi): Some of these conditions are non-intuitive, so investigate -// whether these conditions are correct or if the test expectations are off. -BaselineGroup DetermineBaselineGroup( +// Determines the writing-mode to read a baseline from a fragment. +WritingMode DetermineBaselineWritingMode( const GridTrackSizingDirection track_direction, const WritingMode container_writing_mode, const WritingMode child_writing_mode) { - bool is_major = false; - switch (container_writing_mode) { - case WritingMode::kHorizontalTb: - is_major = (track_direction == kForRows) - ? true - : (child_writing_mode == WritingMode::kVerticalLr || - child_writing_mode == WritingMode::kHorizontalTb); - break; - case WritingMode::kVerticalLr: - is_major = (track_direction == kForRows) - ? (child_writing_mode == WritingMode::kVerticalLr || - child_writing_mode == WritingMode::kHorizontalTb) - : true; - break; - case WritingMode::kVerticalRl: - is_major = (track_direction == kForRows) - ? (child_writing_mode == WritingMode::kVerticalRl || - child_writing_mode == WritingMode::kHorizontalTb) - : true; - break; - default: - is_major = true; - break; + // From: https://drafts.csswg.org/css-align-3/#generate-baselines + // + // kForRows: + // "If the box establishing the alignment context has a block flow + // direction that is orthogonal to the axis of the alignment context, use + // its writing mode." + // + // kForColumns: + // "If the child's writing-mode isn't parallel to the alignment context use + // either "horizontal-tb" or "vertical-lr" whichever is orthogonal." + const auto orthogonal_writing_mode = + (track_direction == kForRows) + ? container_writing_mode + : ((child_writing_mode == WritingMode::kHorizontalTb) + ? WritingMode::kVerticalLr + : WritingMode::kHorizontalTb); + const bool is_parallel = + IsParallelWritingMode(container_writing_mode, child_writing_mode); + + if (track_direction == kForRows) + return is_parallel ? child_writing_mode : orthogonal_writing_mode; + else + return is_parallel ? orthogonal_writing_mode : child_writing_mode; +} + +// There are potentially two different baseline groups for a column/row. +// See: https://www.w3.org/TR/css-align-3/#baseline-sharing-group +// +// We label these "major"/"minor" to separate them. The "major" group should be +// aligned to the appropriate "start" axis. +BaselineGroup DetermineBaselineGroup( + const GridTrackSizingDirection track_direction, + const WritingDirectionMode container_writing_direction, + const WritingMode baseline_writing_mode) { + const auto container_writing_mode = + container_writing_direction.GetWritingMode(); + const bool is_parallel = + IsParallelWritingMode(container_writing_mode, baseline_writing_mode); + if (track_direction == kForRows) { + DCHECK(is_parallel); + return (baseline_writing_mode == container_writing_mode) + ? BaselineGroup::kMajor + : BaselineGroup::kMinor; } - return is_major ? BaselineGroup::kMajor : BaselineGroup::kMinor; + + // kForColumns + DCHECK(!is_parallel); + + // For each writing-mode the "major" group is aligned with the container's + // direction. This is to ensure the inline-start offset (for the grid-item) + // matches the baseline offset we calculate. + const bool is_ltr = container_writing_direction.IsLtr(); + if ((baseline_writing_mode == WritingMode::kHorizontalTb) == is_ltr) + return BaselineGroup::kMajor; + + if ((baseline_writing_mode == WritingMode::kVerticalLr) == is_ltr) + return BaselineGroup::kMajor; + + if ((baseline_writing_mode == WritingMode::kVerticalRl) == !is_ltr) + return BaselineGroup::kMajor; + + return BaselineGroup::kMinor; } } // namespace @@ -184,12 +213,21 @@ container_style, &block_auto_behavior, &is_overflow_safe); is_block_axis_overflow_safe = is_overflow_safe; - const auto container_writing_mode = container_style.GetWritingMode(); + const auto container_writing_direction = + container_style.GetWritingDirection(); const auto item_writing_mode = style.GetWritingMode(); + + column_baseline_writing_mode = DetermineBaselineWritingMode( + kForColumns, container_writing_direction.GetWritingMode(), + item_writing_mode); + row_baseline_writing_mode = DetermineBaselineWritingMode( + kForRows, container_writing_direction.GetWritingMode(), + item_writing_mode); + column_baseline_group = DetermineBaselineGroup( - kForColumns, container_writing_mode, item_writing_mode); - row_baseline_group = DetermineBaselineGroup(kForRows, container_writing_mode, - item_writing_mode); + kForColumns, container_writing_direction, column_baseline_writing_mode); + row_baseline_group = DetermineBaselineGroup( + kForRows, container_writing_direction, row_baseline_writing_mode); } void GridItemData::SetAlignmentFallback(
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h index fa742aef..67cc73f 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_item.h
@@ -73,6 +73,15 @@ : row_baseline_group; } + WritingDirectionMode BaselineWritingDirection( + const GridTrackSizingDirection track_direction) const { + // NOTE: For reading the baseline from a fragment the direction doesn't + // matter - just use the default. + return {(track_direction == kForColumns) ? column_baseline_writing_mode + : row_baseline_writing_mode, + TextDirection::kLtr}; + } + const GridItemIndices& SetIndices( const GridTrackSizingDirection track_direction) const { return (track_direction == kForColumns) ? column_set_indices @@ -185,6 +194,9 @@ enum BaselineGroup column_baseline_group; enum BaselineGroup row_baseline_group; + WritingMode column_baseline_writing_mode; + WritingMode row_baseline_writing_mode; + TrackSpanProperties column_span_properties; TrackSpanProperties row_span_properties;
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 926d075..8e256cf 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
@@ -859,77 +859,18 @@ return node.Layout(constraint_space); } -LayoutUnit GetLogicalBaseline(const NGBoxFragment& fragment, - const GridTrackSizingDirection track_direction, - const WritingMode writing_mode) { - const auto child_writing_mode = - fragment.GetWritingDirection().GetWritingMode(); - const bool is_for_columns = (track_direction == kForColumns); - - // TODO(kschmi): Reconcile this with layout experts to see if this makes - // sense. Some of the entries here are non-intuitive. - switch (writing_mode) { - case WritingMode::kHorizontalTb: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns - ? LayoutUnit() - : fragment.Baseline().value_or(fragment.BlockSize()); - case WritingMode::kVerticalLr: - return is_for_columns ? fragment.Baseline().value_or(LayoutUnit()) - : fragment.InlineSize(); - case WritingMode::kVerticalRl: - return is_for_columns ? (fragment.BlockSize() - - fragment.Baseline().value_or(LayoutUnit())) - : fragment.InlineSize(); - default: - NOTREACHED(); - return LayoutUnit(); - } - case WritingMode::kVerticalLr: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns - ? fragment.Baseline().value_or(fragment.BlockSize()) - : LayoutUnit(); - case WritingMode::kVerticalLr: - return is_for_columns ? fragment.InlineSize() - : fragment.Baseline().value_or(LayoutUnit()); - case WritingMode::kVerticalRl: - return is_for_columns ? fragment.InlineSize() - : (fragment.BlockSize() - - fragment.Baseline().value_or(LayoutUnit())); - default: - NOTREACHED(); - return LayoutUnit(); - } - case WritingMode::kVerticalRl: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns - ? fragment.Baseline().value_or(fragment.BlockSize()) - : fragment.InlineSize(); - case WritingMode::kVerticalLr: - return is_for_columns - ? fragment.InlineSize() - : (fragment.BlockSize() - - fragment.Baseline().value_or(fragment.BlockSize())); - case WritingMode::kVerticalRl: - return is_for_columns - ? fragment.InlineSize() - : fragment.Baseline().value_or(fragment.BlockSize()); - default: - NOTREACHED(); - return LayoutUnit(); - } - default: - NOTREACHED(); - return LayoutUnit(); - } -} - } // namespace +LayoutUnit NGGridLayoutAlgorithm::GetLogicalBaseline( + const NGBoxFragment& baseline_fragment, + BaselineGroup baseline_group) const { + const auto baseline = + baseline_fragment.BaselineOrSynthesize(Style().GetFontBaseline()); + return (baseline_group == BaselineGroup::kMajor) + ? baseline + : baseline_fragment.BlockSize() - baseline; +} + LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem( const NGGridLayoutData& layout_data, const SizingConstraint sizing_constraint, @@ -1012,8 +953,8 @@ result = LayoutGridItemForMeasure(*grid_item, space, sizing_constraint); } - NGBoxFragment fragment( - item_style.GetWritingDirection(), + NGBoxFragment baseline_fragment( + grid_item->BaselineWritingDirection(track_direction), To<NGPhysicalBoxFragment>(result->PhysicalFragment())); if (grid_item->IsBaselineAlignedForDirection(track_direction)) { @@ -1025,9 +966,8 @@ if (track_baseline != LayoutUnit::Min()) { baseline_shim = track_baseline - - GetLogicalBaseline( - fragment, track_direction, - ConstraintSpace().GetWritingDirection().GetWritingMode()); + GetLogicalBaseline(baseline_fragment, + grid_item->BaselineGroup(track_direction)); // Subtract out the start margin so it doesn't get added a second time // at the end of |NGGridLayoutAlgorithm::ContributionSizeForGridItem|. @@ -1035,7 +975,7 @@ is_for_columns ? margins.inline_start : margins.block_start; } } - return fragment.BlockSize() + baseline_shim; + return baseline_fragment.BlockSize() + baseline_shim; }; const LayoutUnit margin_sum = @@ -1379,62 +1319,6 @@ track_collection->FinalizeRanges(); } -namespace { - -bool HasSynthesizedBaseline(const GridTrackSizingDirection track_direction, - const NGBoxFragment& fragment, - const WritingMode writing_mode) { - const auto child_writing_mode = - fragment.GetWritingDirection().GetWritingMode(); - const bool is_for_columns = (track_direction == kForColumns); - - // TODO(kschmi): Reconcile this with layout experts to see if this makes - // sense. Some of the entries here are non-intuitive. - switch (writing_mode) { - case WritingMode::kHorizontalTb: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns ? true : !fragment.Baseline().has_value(); - case WritingMode::kVerticalLr: - return is_for_columns ? !fragment.Baseline().has_value() : true; - case WritingMode::kVerticalRl: - return is_for_columns ? (!fragment.Baseline().has_value()) : true; - default: - NOTREACHED(); - return false; - } - case WritingMode::kVerticalLr: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns ? !fragment.Baseline().has_value() : true; - case WritingMode::kVerticalLr: - return is_for_columns ? true : !fragment.Baseline().has_value(); - case WritingMode::kVerticalRl: - return is_for_columns ? true : !fragment.Baseline().has_value(); - default: - NOTREACHED(); - return false; - } - case WritingMode::kVerticalRl: - switch (child_writing_mode) { - case WritingMode::kHorizontalTb: - return is_for_columns ? !fragment.Baseline().has_value() : true; - case WritingMode::kVerticalLr: - return is_for_columns ? true : !fragment.Baseline().has_value(); - case WritingMode::kVerticalRl: - return is_for_columns ? true : !fragment.Baseline().has_value(); - default: - NOTREACHED(); - return false; - } - default: - NOTREACHED(); - return false; - } -} - -} // namespace - void NGGridLayoutAlgorithm::CalculateAlignmentBaselines( const NGGridLayoutData& layout_data, const SizingConstraint sizing_constraint, @@ -1487,24 +1371,21 @@ const auto* result = LayoutGridItemForMeasure(grid_item, space, sizing_constraint); - NGBoxFragment fragment( - item_style.GetWritingDirection(), + NGBoxFragment baseline_fragment( + grid_item.BaselineWritingDirection(track_direction), To<NGPhysicalBoxFragment>(result->PhysicalFragment())); - const auto& container_space = ConstraintSpace(); - const auto container_writing_mode = - container_space.GetWritingDirection().GetWritingMode(); + grid_item.SetAlignmentFallback(track_direction, Style(), + /* has_synthesized_baseline */ + !baseline_fragment.Baseline().has_value()); - grid_item.SetAlignmentFallback( - track_direction, Style(), - HasSynthesizedBaseline(track_direction, fragment, - container_writing_mode)); - - const auto margins = ComputeMarginsFor(space, item_style, container_space); + const auto margins = + ComputeMarginsFor(space, item_style, ConstraintSpace()); LayoutUnit baseline = ((track_direction == kForColumns) ? margins.inline_start : margins.block_start) + - GetLogicalBaseline(fragment, track_direction, container_writing_mode); + GetLogicalBaseline(baseline_fragment, + grid_item.BaselineGroup(track_direction)); // TODO(kschmi): The IsReplaced() check here is a bit strange, but is // necessary to pass some of the tests. Follow-up to see if there's @@ -3005,17 +2886,17 @@ auto* result = grid_item.node.Layout(space); const auto& physical_fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment()); - NGBoxFragment logical_fragment(item_style.GetWritingDirection(), - physical_fragment); auto BaselineOffset = [&](const GridTrackSizingDirection track_direction) -> LayoutUnit { if (grid_item.IsBaselineAlignedForDirection(track_direction)) { + NGBoxFragment baseline_fragment( + grid_item.BaselineWritingDirection(track_direction), + physical_fragment); // The baseline offset is the difference between the grid item's // baseline and its track baseline. const LayoutUnit item_baseline = GetLogicalBaseline( - logical_fragment, track_direction, - container_space.GetWritingDirection().GetWritingMode()); + baseline_fragment, grid_item.BaselineGroup(track_direction)); const LayoutUnit track_baseline = Baseline(layout_data, grid_item, track_direction);
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h index 109241f..f2da58c 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -21,6 +21,8 @@ namespace blink { +class NGBoxFragment; + // This enum corresponds to each step used to accommodate grid items across // intrinsic tracks according to their min and max track sizing functions, as // defined in https://drafts.csswg.org/css-grid-2/#algo-spanning-items. @@ -74,6 +76,8 @@ LayoutUnit ComputeIntrinsicBlockSizeIgnoringChildren() const; + LayoutUnit GetLogicalBaseline(const NGBoxFragment&, BaselineGroup) const; + // Returns the size that a grid item will distribute across the tracks with an // intrinsic sizing function it spans in the relevant track direction. LayoutUnit ContributionSizeForGridItem(
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc index 9b0685d..a22a730 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -32,6 +32,26 @@ namespace blink { +namespace { + +bool CanUseConstraintSpaceForCaching(const NGLayoutResult* previous_result, + const LayoutBox& box) { + if (!previous_result) + return false; + const auto& space = previous_result->GetConstraintSpaceForCaching(); + if (space.IsFixedInlineSize() && box.HasOverrideLogicalWidth()) { + if (space.AvailableSize().inline_size != box.OverrideLogicalWidth()) + return false; + } + if (space.IsFixedBlockSize() && box.HasOverrideLogicalHeight()) { + if (space.AvailableSize().block_size != box.OverrideLogicalHeight()) + return false; + } + return space.GetWritingMode() == box.StyleRef().GetWritingMode(); +} + +} // namespace + template <typename Base> LayoutNGMixin<Base>::LayoutNGMixin(ContainerNode* node) : Base(node) { Base::CheckIsNotDestroyed(); @@ -413,9 +433,7 @@ // If we are a layout root, use the previous space if available. This will // include any stretched sizes if applicable. NGConstraintSpace constraint_space = - is_layout_root && previous_result && - previous_result->GetConstraintSpaceForCaching() - .GetWritingMode() == Base::StyleRef().GetWritingMode() + is_layout_root && CanUseConstraintSpaceForCaching(previous_result, *this) ? previous_result->GetConstraintSpaceForCaching() : NGConstraintSpace::CreateFromLayoutObject(*this);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc index 6677b223..1dfb80fe 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
@@ -337,7 +337,7 @@ // Anchor names of out-of-flow positioned objects are propagated to their // containing blocks. - EXPECT_NE(AnchorQueryByElementId("middle"), nullptr); + EXPECT_EQ(AnchorQueryByElementId("middle"), nullptr); } // Relative-positioning should shift the rectangles.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h index 14d9be8..b750dd1 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -138,7 +138,10 @@ bool IsContainingBlockNGGrid() const { return box_->ContainingBlock()->IsLayoutNGGrid(); } - + bool IsFrameSet() const { return box_->IsLayoutNGFrameSet(); } + bool IsParentNGFrameSet() const { + return box_->Parent()->IsLayoutNGFrameSet(); + } bool IsParentNGGrid() const { return box_->Parent()->IsLayoutNGGrid(); } // Return true if this block node establishes an inline formatting context.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc index edd83e1..863b82a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -1442,6 +1442,20 @@ bool is_intrinsic) { DCHECK(is_intrinsic || node.CanUseNewLayout()); const ComputedStyle& style = node.Style(); + + if (node.IsFrameSet()) { + if (node.IsParentNGFrameSet()) { + LogicalSize size = constraint_space.AvailableSize(); + DCHECK_NE(size.inline_size, kIndefiniteSize); + DCHECK_NE(size.block_size, kIndefiniteSize); + DCHECK(constraint_space.IsFixedInlineSize()); + DCHECK(constraint_space.IsFixedBlockSize()); + return {size, {}, {}, {}}; + } + PhysicalSize size = node.InitialContainingBlockSize(); + return {size.ConvertToLogical(style.GetWritingMode()), {}, {}, {}}; + } + NGBoxStrut border = ComputeBorders(constraint_space, node); NGBoxStrut padding = ComputePadding(constraint_space, style); NGBoxStrut scrollbar = ComputeScrollbars(constraint_space, node);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h index 0d1e93ff..f73a2cbd 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -176,6 +176,9 @@ bool IsAnonymousBlock() const { return IsCSSBox() && layout_object_->IsAnonymousBlock(); } + bool IsFrameSet() const { + return IsCSSBox() && layout_object_->IsLayoutNGFrameSet(); + } bool IsListMarker() const { return IsCSSBox() && layout_object_->IsLayoutNGOutsideListMarker(); } @@ -635,9 +638,9 @@ return oof_data_ && !oof_data_->anchor_query.IsEmpty(); } const NGPhysicalAnchorQuery* AnchorQuery() const { - if (oof_data_) - return &oof_data_->anchor_query; - return nullptr; + if (!HasAnchorQuery()) + return nullptr; + return &oof_data_->anchor_query; } NGFragmentedOutOfFlowData* FragmentedOutOfFlowData() const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc index cf75261..c5ab6353 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
@@ -147,6 +147,10 @@ if (physical_fragment.IsGridNG()) { container_builder_.TransferGridLayoutData( std::make_unique<NGGridLayoutData>(*result.GridLayoutData())); + } else if (physical_fragment.IsFrameSet()) { + container_builder_.TransferFrameSetLayoutData( + std::make_unique<FrameSetLayoutData>( + *physical_fragment.GetFrameSetLayoutData())); } if (physical_fragment.IsHiddenForPaint())
diff --git a/third_party/blink/renderer/core/paint/build.gni b/third_party/blink/renderer/core/paint/build.gni index ebf2f76..66da401 100644 --- a/third_party/blink/renderer/core/paint/build.gni +++ b/third_party/blink/renderer/core/paint/build.gni
@@ -112,6 +112,8 @@ "ng/ng_fieldset_painter.h", "ng/ng_fragment_painter.cc", "ng/ng_fragment_painter.h", + "ng/ng_frame_set_painter.cc", + "ng/ng_frame_set_painter.h", "ng/ng_highlight_overlay.cc", "ng/ng_highlight_overlay.h", "ng/ng_highlight_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 256e4c6..a791e09 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -33,6 +33,7 @@ #include "third_party/blink/renderer/core/paint/box_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h" +#include "third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_mathml_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_table_painters.h" @@ -622,6 +623,11 @@ bool suppress_box_decoration_background) { const PaintPhase paint_phase = paint_info.phase; const NGPhysicalBoxFragment& fragment = PhysicalFragment(); + if (fragment.IsFrameSet()) { + NGFrameSetPainter(fragment, display_item_client_) + .PaintObject(paint_info, paint_offset); + return; + } const ComputedStyle& style = fragment.Style(); const bool is_visible = IsVisibleToPaint(fragment, style); if (ShouldPaintSelfBlockBackground(paint_phase)) {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.cc new file mode 100644 index 0000000..98ad70c --- /dev/null +++ b/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.cc
@@ -0,0 +1,12 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.h" + +namespace blink { + +void NGFrameSetPainter::PaintObject(const PaintInfo& paint_info, + const PhysicalOffset& paint_offset) {} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.h b/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.h new file mode 100644 index 0000000..ebbf914 --- /dev/null +++ b/third_party/blink/renderer/core/paint/ng/ng_frame_set_painter.h
@@ -0,0 +1,34 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_FRAME_SET_PAINTER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_FRAME_SET_PAINTER_H_ + +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +class DisplayItemClient; +class NGPhysicalBoxFragment; +struct PaintInfo; +struct PhysicalOffset; + +class NGFrameSetPainter { + STACK_ALLOCATED(); + + public: + NGFrameSetPainter(const NGPhysicalBoxFragment& box_fragment, + const DisplayItemClient& display_item_client) + : box_fragment_(box_fragment), + display_item_client_(display_item_client) {} + void PaintObject(const PaintInfo&, const PhysicalOffset&); + + private: + [[maybe_unused]] const NGPhysicalBoxFragment& box_fragment_; + [[maybe_unused]] const DisplayItemClient& display_item_client_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_FRAME_SET_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc b/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc index ac7c3d62..743421d 100644 --- a/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc +++ b/third_party/blink/renderer/core/paint/selection_bounds_recorder_test.cc
@@ -58,10 +58,17 @@ TEST_P(SelectionBoundsRecorderTest, SelectMultiline) { LocalFrame* local_frame = GetDocument().GetFrame(); + LoadAhem(*local_frame); + local_frame->Selection().SetSelectionAndEndTyping( - SelectionSample::SetSelectionText( - GetDocument().body(), - "<div style='white-space:pre'>f^oo\nbar\nb|az</div>")); + SelectionSample::SetSelectionText(GetDocument().body(), + R"HTML( + <style> + div { white-space:pre; font-family: Ahem; } + </style> + <div>f^oo\nbar\nb|az</div> + )HTML")); + local_frame->Selection().SetHandleVisibleForTesting(); local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame); UpdateAllLifecyclePhasesForTest(); @@ -73,13 +80,13 @@ PaintedSelectionBound start = chunks.begin()->layer_selection_data->start.value(); EXPECT_EQ(start.type, gfx::SelectionBound::LEFT); - EXPECT_EQ(start.edge_start, gfx::Point(8, 8)); - EXPECT_EQ(start.edge_end, gfx::Point(8, 9)); + EXPECT_EQ(start.edge_start, gfx::Point(9, 8)); + EXPECT_EQ(start.edge_end, gfx::Point(9, 9)); PaintedSelectionBound end = chunks.begin()->layer_selection_data->end.value(); EXPECT_EQ(end.type, gfx::SelectionBound::RIGHT); - EXPECT_EQ(end.edge_start, gfx::Point(9, 10)); - EXPECT_EQ(end.edge_end, gfx::Point(9, 11)); + EXPECT_EQ(end.edge_start, gfx::Point(19, 8)); + EXPECT_EQ(end.edge_end, gfx::Point(19, 9)); } TEST_P(SelectionBoundsRecorderTest, SelectMultilineEmptyStartEnd) {
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc index 14f0558..8eea6df 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -195,12 +195,16 @@ if (response.IsNull()) return; + ExecutionContext* execution_context = OriginalExecutionContext(); + Document* element_document = OriginalElementDocument(); + if (!execution_context || !element_document) + return; + scoped_refptr<SecurityOrigin> script_origin = SecurityOrigin::Create(response.ResponseUrl()); - const SecurityOrigin* doc_origin = - GetElement()->GetExecutionContext()->GetSecurityOrigin(); + const SecurityOrigin* doc_origin = execution_context->GetSecurityOrigin(); scoped_refptr<const SecurityOrigin> top_frame_origin = - GetElement()->GetDocument().TopFrameOrigin(); + element_document->TopFrameOrigin(); // The use counter is meant to gather data for prerendering: how often do // pages make credentialed requests to third parties from first-party frames, @@ -228,7 +232,7 @@ if (GetSchedulingType() == ScriptSchedulingType::kAsync) return; - GetElement()->GetExecutionContext()->CountUse( + execution_context->CountUse( mojom::blink::WebFeature:: kUndeferrableThirdPartySubresourceRequestWithCookie); } @@ -276,30 +280,39 @@ // See https://crbug.com/500701 for more information. CheckState(); DCHECK(GetResource()); - ScriptElementBase* element = GetElement(); - if (element) { - SubresourceIntegrityHelper::DoReport(*element->GetExecutionContext(), - GetResource()->IntegrityReportInfo()); - // It is possible to get back a script resource with integrity metadata - // for a request with an empty integrity attribute. In that case, the - // integrity check should be skipped, as the integrity may not have been - // "meant" for this specific request. If the resource is being served from - // the preload cache however, we know any associated integrity metadata and - // checks were destined for this request, so we cannot skip the integrity - // check. - if (!options_.GetIntegrityMetadata().IsEmpty() || - GetResource()->IsLinkPreload()) { - integrity_failure_ = GetResource()->IntegrityDisposition() != - ResourceIntegrityDisposition::kPassed; - } + // If the original execution context/element document is gone, consider this + // as network error. Anyway the script wouldn't evaluated / no events are + // fired, so this is not observable. + ExecutionContext* execution_context = OriginalExecutionContext(); + Document* element_document = OriginalElementDocument(); + if (!execution_context || execution_context->IsContextDestroyed() || + !element_document || !element_document->IsActive()) { + AdvanceReadyState(kErrorOccurred); + return; + } + + SubresourceIntegrityHelper::DoReport(*execution_context, + GetResource()->IntegrityReportInfo()); + + // It is possible to get back a script resource with integrity metadata + // for a request with an empty integrity attribute. In that case, the + // integrity check should be skipped, as the integrity may not have been + // "meant" for this specific request. If the resource is being served from + // the preload cache however, we know any associated integrity metadata and + // checks were destined for this request, so we cannot skip the integrity + // check. + if (!options_.GetIntegrityMetadata().IsEmpty() || + GetResource()->IsLinkPreload()) { + integrity_failure_ = GetResource()->IntegrityDisposition() != + ResourceIntegrityDisposition::kPassed; } if (intervened_) { CrossOriginAttributeValue cross_origin = - GetCrossOriginAttributeValue(element->CrossOriginAttributeValue()); - PossiblyFetchBlockedDocWriteScript(resource, element->GetDocument(), - options_, cross_origin); + GetCrossOriginAttributeValue(GetElement()->CrossOriginAttributeValue()); + PossiblyFetchBlockedDocWriteScript(resource, *element_document, options_, + cross_origin); } // <specdef href="https://fetch.spec.whatwg.org/#concept-main-fetch"> @@ -311,7 +324,7 @@ // nosniff</spec> // <spec step="17">then set response and internalResponse to a network // error.</spec> - auto* fetcher = GetElement()->GetExecutionContext()->Fetcher(); + auto* fetcher = execution_context->Fetcher(); const bool mime_type_failure = !AllowedByNosniff::MimeTypeAsScript( fetcher->GetUseCounter(), &fetcher->GetConsoleLogger(), resource->GetResponse(), AllowedByNosniff::MimeTypeCheck::kLaxForElement); @@ -339,25 +352,13 @@ cache_consumer_ = script_resource->TakeCacheConsumer(); if (cache_consumer_) { - ExecutionContext* execution_context = element->GetExecutionContext(); // Only wait for the cache consume if there is an execution context it can // notify us on. - if (execution_context) { - AdvanceReadyState(kWaitingForCacheConsumer); - // TODO(leszeks): Decide whether kNetworking is the right task type here. - cache_consumer_->NotifyClientWaiting( - this, execution_context->GetTaskRunner(TaskType::kNetworking)); - - } else { - // Otherwise (probably when our Document isn't active anymore), - // we can simply drop the cache consumer and let it be cleaned up by the - // GC; no one is waiting on it so it's safe to just drop it without - // needing to cancel or dispose it in any way. - cache_consumer_ = nullptr; - } - } - - if (!cache_consumer_) { + AdvanceReadyState(kWaitingForCacheConsumer); + // TODO(leszeks): Decide whether kNetworking is the right task type here. + cache_consumer_->NotifyClientWaiting( + this, execution_context->GetTaskRunner(TaskType::kNetworking)); + } else { // Either there was never a cache consume, or it was dropped. Either way, we // are ready. AdvanceReadyState(kReady); @@ -451,11 +452,13 @@ // behaviour. We should decide whether it is ok for this parameter to be // used for behavioural changes (and if yes, update its documentation), or // otherwise trigger this behaviour differently. - if (source_location_type_ == ScriptSourceLocationType::kInline) { + Document* element_document = OriginalElementDocument(); + if (source_location_type_ == ScriptSourceLocationType::kInline && + element_document && element_document->IsActive()) { cache_handler = GetInlineCacheHandler(source_text_for_inline_script_, - GetElement()->GetDocument()); + *element_document); streamer = GetInlineScriptStreamer(source_text_for_inline_script_, - GetElement()->GetDocument()); + *element_document); } DCHECK(!GetResource());
diff --git a/third_party/blink/renderer/core/script/pending_script.h b/third_party/blink/renderer/core/script/pending_script.h index ecd28d6..151fc562 100644 --- a/third_party/blink/renderer/core/script/pending_script.h +++ b/third_party/blink/renderer/core/script/pending_script.h
@@ -145,6 +145,13 @@ virtual void CheckState() const = 0; + Document* OriginalElementDocument() const { + return original_element_document_; + } + ExecutionContext* OriginalExecutionContext() const { + return original_execution_context_; + } + private: static void ExecuteScriptBlockInternal( Script*,
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc index 83d9d1ba..304363d 100644 --- a/third_party/blink/renderer/core/script/script_runner.cc +++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -44,11 +44,56 @@ #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/wtf/casting.h" +namespace { + +void PostTaskWithLowPriorityUntilTimeout( + const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta timeout, + scoped_refptr<base::SingleThreadTaskRunner> lower_priority_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> normal_priority_task_runner) { + using RefCountedOnceClosure = base::RefCountedData<base::OnceClosure>; + scoped_refptr<RefCountedOnceClosure> ref_counted_task = + base::MakeRefCounted<RefCountedOnceClosure>(std::move(task)); + + // |run_task_once| runs on both of |lower_priority_task_runner| and + // |normal_priority_task_runner|. |run_task_once| guarantees that the given + // |task| doesn't run more than once. |task| runs on either of + // |lower_priority_task_runner| and |normal_priority_task_runner| whichever + // comes first. + auto run_task_once = + [](scoped_refptr<RefCountedOnceClosure> ref_counted_task) { + if (!ref_counted_task->data.is_null()) + std::move(ref_counted_task->data).Run(); + }; + + lower_priority_task_runner->PostTask( + from_here, WTF::Bind(run_task_once, ref_counted_task)); + + normal_priority_task_runner->PostDelayedTask( + from_here, WTF::Bind(run_task_once, ref_counted_task), timeout); +} + +} // namespace + namespace blink { +void PostTaskWithLowPriorityUntilTimeoutForTesting( + const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta timeout, + scoped_refptr<base::SingleThreadTaskRunner> lower_priority_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> normal_priority_task_runner) { + PostTaskWithLowPriorityUntilTimeout(from_here, std::move(task), timeout, + std::move(lower_priority_task_runner), + std::move(normal_priority_task_runner)); +} + ScriptRunner::ScriptRunner(Document* document) : document_(document), - task_runner_(document->GetTaskRunner(TaskType::kNetworking)) { + task_runner_(document->GetTaskRunner(TaskType::kNetworking)), + low_priority_task_runner_( + document->GetTaskRunner(TaskType::kLowPriorityScriptExecution)) { DCHECK(document); } @@ -133,10 +178,18 @@ // Script is really ready to evaluate. pending_async_scripts_.erase(it); - task_runner_->PostTask( - FROM_HERE, + base::OnceClosure task = WTF::Bind(&ScriptRunner::ExecutePendingScript, WrapWeakPersistent(this), - WrapPersistent(pending_script))); + WrapPersistent(pending_script)); + if (base::FeatureList::IsEnabled( + features::kLowPriorityAsyncScriptExecution)) { + PostTaskWithLowPriorityUntilTimeout( + FROM_HERE, std::move(task), + features::kTimeoutForLowPriorityAsyncScriptExecution.Get(), + low_priority_task_runner_, task_runner_); + } else { + task_runner_->PostTask(FROM_HERE, std::move(task)); + } } void ScriptRunner::ExecuteForceInOrderPendingScript(
diff --git a/third_party/blink/renderer/core/script/script_runner.h b/third_party/blink/renderer/core/script/script_runner.h index 4b024575..843da89 100644 --- a/third_party/blink/renderer/core/script/script_runner.h +++ b/third_party/blink/renderer/core/script/script_runner.h
@@ -129,6 +129,7 @@ wtf_size_t pending_force_in_order_scripts_count_ = 0; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> low_priority_task_runner_; DelayReasons active_delay_reasons_ = 0; }; @@ -152,6 +153,14 @@ bool activated_ = false; }; +// This function is exported for testing purposes only. +void CORE_EXPORT PostTaskWithLowPriorityUntilTimeoutForTesting( + const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta timeout, + scoped_refptr<base::SingleThreadTaskRunner> lower_priority_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> normal_priority_task_runner); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_RUNNER_H_
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc index b906aef..085e380 100644 --- a/third_party/blink/renderer/core/script/script_runner_test.cc +++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -4,7 +4,9 @@ #include "third_party/blink/renderer/core/script/script_runner.h" +#include "base/test/null_task_runner.h" #include "base/test/scoped_feature_list.h" +#include "base/time/time.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h" @@ -552,4 +554,69 @@ platform_->RunUntilIdle(); } +class PostTaskWithLowPriorityUntilTimeoutTest : public testing::Test { + public: + PostTaskWithLowPriorityUntilTimeoutTest() + : task_runner_(platform_->test_task_runner()), + null_task_runner_(base::MakeRefCounted<base::NullTaskRunner>()) {} + + protected: + ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> + platform_; + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; + scoped_refptr<base::NullTaskRunner> null_task_runner_; +}; + +TEST_F(PostTaskWithLowPriorityUntilTimeoutTest, RunTaskOnce) { + int counter = 0; + base::OnceClosure task = + WTF::Bind([](int* counter) { (*counter)++; }, WTF::Unretained(&counter)); + + PostTaskWithLowPriorityUntilTimeoutForTesting( + FROM_HERE, std::move(task), base::Seconds(1), + /*lower_priority_task_runner=*/task_runner_, + /*normal_priority_task_runner=*/task_runner_); + + EXPECT_EQ(0, counter); + EXPECT_EQ(2u, task_runner_->GetPendingTaskCount()); + platform_->SetAutoAdvanceNowToPendingTasks(true); + platform_->RunUntilIdle(); + EXPECT_EQ(1, counter); + EXPECT_EQ(0u, task_runner_->GetPendingTaskCount()); +} + +TEST_F(PostTaskWithLowPriorityUntilTimeoutTest, RunOnLowerPriorityTaskRunner) { + int counter = 0; + base::OnceClosure task = + WTF::Bind([](int* counter) { (*counter)++; }, WTF::Unretained(&counter)); + + PostTaskWithLowPriorityUntilTimeoutForTesting( + FROM_HERE, std::move(task), base::Seconds(1), + /*lower_priority_task_runner=*/task_runner_, + /*normal_priority_task_runner=*/null_task_runner_); + + EXPECT_EQ(0, counter); + EXPECT_EQ(1u, task_runner_->GetPendingTaskCount()); + platform_->RunSingleTask(); + EXPECT_EQ(1, counter); + EXPECT_EQ(0u, task_runner_->GetPendingTaskCount()); +} + +TEST_F(PostTaskWithLowPriorityUntilTimeoutTest, RunOnNormalPriorityTaskRunner) { + int counter = 0; + base::OnceClosure task = + WTF::Bind([](int* counter) { (*counter)++; }, WTF::Unretained(&counter)); + + PostTaskWithLowPriorityUntilTimeoutForTesting( + FROM_HERE, std::move(task), base::Seconds(1), + /*lower_priority_task_runner=*/null_task_runner_, + /*normal_priority_task_runner=*/task_runner_); + + EXPECT_EQ(0, counter); + EXPECT_EQ(1u, task_runner_->GetPendingTaskCount()); + platform_->RunSingleTask(); + EXPECT_EQ(1, counter); + EXPECT_EQ(0u, task_runner_->GetPendingTaskCount()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/data/get_scale_for_zoom_into_editable_test.html b/third_party/blink/renderer/core/testing/data/get_scale_for_zoom_into_editable_test.html index acd519c..a6d11ac 100644 --- a/third_party/blink/renderer/core/testing/data/get_scale_for_zoom_into_editable_test.html +++ b/third_party/blink/renderer/core/testing/data/get_scale_for_zoom_into_editable_test.html
@@ -3,7 +3,7 @@ <style> input { font-size: 13px; - font-family: monospace; + font: Ahem; } </style> </head>
diff --git a/third_party/blink/renderer/core/workers/worker_backing_thread.cc b/third_party/blink/renderer/core/workers/worker_backing_thread.cc index b14a7610..97690a1 100644 --- a/third_party/blink/renderer/core/workers/worker_backing_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_backing_thread.cc
@@ -56,7 +56,7 @@ } WorkerBackingThread::WorkerBackingThread(const ThreadCreationParams& params) - : backing_thread_(blink::Thread::CreateThread( + : backing_thread_(blink::NonMainThread::CreateThread( ThreadCreationParams(params).SetSupportsGC(true))) {} WorkerBackingThread::~WorkerBackingThread() = default;
diff --git a/third_party/blink/renderer/core/workers/worker_backing_thread.h b/third_party/blink/renderer/core/workers/worker_backing_thread.h index 75bef72..e5c640bd 100644 --- a/third_party/blink/renderer/core/workers/worker_backing_thread.h +++ b/third_party/blink/renderer/core/workers/worker_backing_thread.h
@@ -9,7 +9,7 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" @@ -37,7 +37,7 @@ void InitializeOnBackingThread(const WorkerBackingThreadStartupData&); void ShutdownOnBackingThread(); - blink::Thread& BackingThread() { + blink::NonMainThread& BackingThread() { DCHECK(backing_thread_); return *backing_thread_; } @@ -48,7 +48,7 @@ v8::MemoryPressureLevel); private: - std::unique_ptr<blink::Thread> backing_thread_; + std::unique_ptr<blink::NonMainThread> backing_thread_; v8::Isolate* isolate_ = nullptr; };
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index 91fd003f..2497279 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -62,7 +62,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h" #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h" #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h" -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h" @@ -535,10 +535,10 @@ DCHECK(IsCurrentThread()); DCHECK(!worker_scheduler_); - // TODO(hajimehoshi, nhiroki): scheduler::WorkerThread and scheduler:: + // TODO(hajimehoshi, nhiroki): scheduler::NonMainThreadImpl and scheduler:: // WorkerThreadScheduler are not in scheduler/public, then using them is a // layer violation. Fix this. - auto& worker_thread = static_cast<scheduler::WorkerThread&>( + auto& worker_thread = static_cast<scheduler::NonMainThreadImpl&>( GetWorkerBackingThread().BackingThread()); worker_scheduler_ = scheduler::WorkerScheduler::CreateWorkerScheduler( static_cast<scheduler::WorkerThreadScheduler*>(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authenticator_attestation_response.cc b/third_party/blink/renderer/modules/credentialmanagement/authenticator_attestation_response.cc index c62ae80..979fb9e6 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/authenticator_attestation_response.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/authenticator_attestation_response.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/credentialmanagement/authenticator_attestation_response.h" +#include <algorithm> + #include "third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h" namespace blink { @@ -30,6 +32,7 @@ ret.emplace_back(mojo::ConvertTo<String>(transport)); } std::sort(ret.begin(), ret.end(), WTF::CodeUnitCompareLessThan); + ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); return ret; }
diff --git a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc index a2475b8d..cc956898b 100644 --- a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.cc
@@ -14,8 +14,8 @@ #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.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" @@ -61,7 +61,7 @@ std::move(on_encoded_audio_cb), bits_per_second, bitrate_mode)), - encoder_thread_(Thread::CreateThread( + encoder_thread_(NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kAudioEncoderThread))), encoder_task_runner_(encoder_thread_->GetTaskRunner()) { DCHECK(IsMainThread());
diff --git a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h index 5158bc8..480b3dbb 100644 --- a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h +++ b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h
@@ -22,7 +22,7 @@ class AudioTrackEncoder; class MediaStreamComponent; -class Thread; +class NonMainThread; // AudioTrackRecorder is a MediaStreamAudioSink that encodes the audio buses // received from a Stream Audio Track. The class is constructed on a @@ -100,7 +100,7 @@ const scoped_refptr<AudioTrackEncoder> encoder_; // The thread on which |encoder_| works. - std::unique_ptr<Thread> encoder_thread_; + std::unique_ptr<NonMainThread> encoder_thread_; scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc index c2c3449..bdd6e8e 100644 --- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
@@ -12,8 +12,8 @@ #include "media/base/video_frame.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.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" @@ -85,8 +85,9 @@ } // static -void H264Encoder::ShutdownEncoder(std::unique_ptr<Thread> encoding_thread, - ScopedISVCEncoderPtr encoder) { +void H264Encoder::ShutdownEncoder( + std::unique_ptr<NonMainThread> encoding_thread, + ScopedISVCEncoderPtr encoder) { DCHECK(encoding_thread); // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope. }
diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.h b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.h index b866a62..af32ea77 100644 --- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.h +++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.h
@@ -26,7 +26,7 @@ }; typedef std::unique_ptr<ISVCEncoder, ISVCEncoderDeleter> ScopedISVCEncoderPtr; - static void ShutdownEncoder(std::unique_ptr<Thread> encoding_thread, + static void ShutdownEncoder(std::unique_ptr<NonMainThread> encoding_thread, ScopedISVCEncoderPtr encoder); H264Encoder(const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb,
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc index 62c33df..02a05f0 100644 --- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -26,8 +26,8 @@ #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_util.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/libyuv/include/libyuv.h" @@ -320,7 +320,7 @@ if (encoding_task_runner_) return; - encoding_thread_ = Thread::CreateThread( + encoding_thread_ = NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kVideoEncoderThread)); encoding_task_runner_ = encoding_thread_->GetTaskRunner();
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h index 08039e3f..13f8d48 100644 --- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h +++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
@@ -29,10 +29,6 @@ #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" #include "third_party/skia/include/core/SkBitmap.h" -namespace base { -class Thread; -} // namespace base - namespace cc { class PaintCanvas; } // namespace cc @@ -66,7 +62,7 @@ namespace blink { class MediaStreamVideoTrack; -class Thread; +class NonMainThread; class WebGraphicsContext3DProvider; // Base class serving as interface for eventually saving encoded frames stemming @@ -221,7 +217,7 @@ SEQUENCE_CHECKER(encoding_sequence_checker_); // Optional thread for encoding. Active for the lifetime of VpxEncoder. - std::unique_ptr<Thread> encoding_thread_; + std::unique_ptr<NonMainThread> encoding_thread_; // While |paused_|, frames are not encoded. Used only from // |encoding_thread_|.
diff --git a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc index 4c5b802..9f871416 100644 --- a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
@@ -12,8 +12,8 @@ #include "media/base/video_frame.h" #include "media/base/video_util.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.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" @@ -41,7 +41,7 @@ } // static -void VpxEncoder::ShutdownEncoder(std::unique_ptr<Thread> encoding_thread, +void VpxEncoder::ShutdownEncoder(std::unique_ptr<NonMainThread> encoding_thread, ScopedVpxCodecCtxPtr encoder) { DCHECK(encoding_thread); // Both |encoding_thread| and |encoder| will be destroyed at end-of-scope.
diff --git a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.h b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.h index 73cfe54..5b815b3 100644 --- a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.h +++ b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.h
@@ -25,7 +25,7 @@ typedef std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodecCtxPtr; - static void ShutdownEncoder(std::unique_ptr<Thread> encoding_thread, + static void ShutdownEncoder(std::unique_ptr<NonMainThread> encoding_thread, ScopedVpxCodecCtxPtr encoder); VpxEncoder(bool use_vp9,
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index e7d6b9c0..f8833462 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -383,6 +383,9 @@ DCHECK(!did_evaluate_script_); did_evaluate_script_ = true; + base::UmaHistogramCounts1000( + "ServiceWorker.NumberOfRegisteredFetchHandlers", + NumberOfEventListeners(event_type_names::kFetch)); event_queue_->Start(); }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc index 2ee4802b..05ace94 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc
@@ -14,8 +14,8 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/web/web_embedded_worker.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -129,12 +129,12 @@ class ServiceWorkerInstalledScriptsManagerTest : public testing::Test { public: ServiceWorkerInstalledScriptsManagerTest() - : io_thread_( - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("io thread"))), - worker_thread_( - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("worker thread"))), + : io_thread_(NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("io thread"))), + worker_thread_(NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("worker thread"))), worker_waiter_(std::make_unique<base::WaitableEvent>( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED)) {} @@ -200,8 +200,8 @@ waiter->Signal(); } - std::unique_ptr<Thread> io_thread_; - std::unique_ptr<Thread> worker_thread_; + std::unique_ptr<NonMainThread> io_thread_; + std::unique_ptr<NonMainThread> worker_thread_; std::unique_ptr<base::WaitableEvent> worker_waiter_;
diff --git a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc index e4157a5..023ba42 100644 --- a/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc +++ b/third_party/blink/renderer/modules/service_worker/thread_safe_script_container_test.cc
@@ -8,8 +8,8 @@ #include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -23,12 +23,12 @@ class ThreadSafeScriptContainerTest : public ::testing::Test { public: ThreadSafeScriptContainerTest() - : writer_thread_( - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("writer_thread"))), - reader_thread_( - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("reader_thread"))), + : writer_thread_(NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("writer_thread"))), + reader_thread_(NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("reader_thread"))), writer_waiter_(std::make_unique<base::WaitableEvent>( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED)), @@ -119,8 +119,8 @@ } private: - std::unique_ptr<Thread> writer_thread_; - std::unique_ptr<Thread> reader_thread_; + std::unique_ptr<NonMainThread> writer_thread_; + std::unique_ptr<NonMainThread> reader_thread_; std::unique_ptr<base::WaitableEvent> writer_waiter_; std::unique_ptr<base::WaitableEvent> reader_waiter_;
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.cc index f9a076a2..2f63846 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.cc
@@ -17,7 +17,7 @@ #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/audio/denormal_disabler.h" #include "third_party/blink/renderer/platform/audio/hrtf_database_loader.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -339,7 +339,7 @@ } else { if (!render_thread_) { // The context started from the non-AudioWorklet mode. - render_thread_ = Thread::CreateThread( + render_thread_ = NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kOfflineAudioRenderThread)); render_thread_task_runner_ = render_thread_->GetTaskRunner(); }
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h index b2afe1b..e9d9290 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h
@@ -12,7 +12,7 @@ #include "third_party/blink/renderer/modules/webaudio/audio_buffer.h" #include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h" #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" namespace blink { @@ -132,7 +132,7 @@ // The rendering thread for the non-AudioWorklet mode. For the AudioWorklet // node, AudioWorkletThread will drive the rendering. - std::unique_ptr<Thread> render_thread_; + std::unique_ptr<NonMainThread> render_thread_; scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
diff --git a/third_party/blink/renderer/modules/webdatabase/database_thread.cc b/third_party/blink/renderer/modules/webdatabase/database_thread.cc index 72f0d01..f9f6df6 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_thread.cc +++ b/third_party/blink/renderer/modules/webdatabase/database_thread.cc
@@ -60,7 +60,7 @@ DCHECK(IsMainThread()); if (thread_) return; - thread_ = blink::Thread::CreateThread( + thread_ = blink::NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kDatabaseThread).SetSupportsGC(true)); PostCrossThreadTask(*thread_->GetTaskRunner(), FROM_HERE, CrossThreadBindOnce(&DatabaseThread::SetupDatabaseThread,
diff --git a/third_party/blink/renderer/modules/webdatabase/database_thread.h b/third_party/blink/renderer/modules/webdatabase/database_thread.h index 5740847..35bc600 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_thread.h +++ b/third_party/blink/renderer/modules/webdatabase/database_thread.h
@@ -34,7 +34,7 @@ #include "base/thread_annotations.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { @@ -75,7 +75,7 @@ void CleanupDatabaseThread(); void CleanupDatabaseThreadCompleted(); - std::unique_ptr<blink::Thread> thread_; + std::unique_ptr<blink::NonMainThread> thread_; // This set keeps track of the open databases that have been used on this // thread. This must be updated in the database thread though it is
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc index af74333..4b82bbee 100644 --- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc +++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
@@ -98,7 +98,7 @@ DCHECK(!thread_); // Start the asynchronous database loading process. - thread_ = Thread::CreateThread( + thread_ = NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kHRTFDatabaseLoaderThread)); // TODO(alexclarke): Should this be posted as a loading task? PostCrossThreadTask(*thread_->GetTaskRunner(), FROM_HERE,
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h index 8c897323..422888c 100644 --- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h +++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
@@ -35,7 +35,7 @@ #include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/platform/audio/hrtf_database.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" @@ -93,7 +93,7 @@ // it can be accessed by multiple threads (e.g multiple AudioContexts). base::Lock lock_; std::unique_ptr<HRTFDatabase> hrtf_database_ GUARDED_BY(lock_); - std::unique_ptr<Thread> thread_ GUARDED_BY(lock_); + std::unique_ptr<NonMainThread> thread_ GUARDED_BY(lock_); float database_sample_rate_; };
diff --git a/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc b/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc index a9d0715..e12b0a3 100644 --- a/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc +++ b/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc
@@ -10,8 +10,8 @@ #include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -33,7 +33,7 @@ : fifo_(fifo), bus_(AudioBus::Create(fifo->GetStateForTest().number_of_channels, bus_length)), - client_thread_(Thread::CreateThread( + client_thread_(NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread) .SetThreadNameForTest("FIFOClientThread"))), done_event_(std::make_unique<base::WaitableEvent>( @@ -83,7 +83,7 @@ PushPullFIFO* fifo_; scoped_refptr<AudioBus> bus_; - std::unique_ptr<Thread> client_thread_; + std::unique_ptr<NonMainThread> client_thread_; std::unique_ptr<base::WaitableEvent> done_event_; // Test duration.
diff --git a/third_party/blink/renderer/platform/audio/reverb_convolver.cc b/third_party/blink/renderer/platform/audio/reverb_convolver.cc index df73ab1..3c22ec8 100644 --- a/third_party/blink/renderer/platform/audio/reverb_convolver.cc +++ b/third_party/blink/renderer/platform/audio/reverb_convolver.cc
@@ -35,7 +35,6 @@ #include "third_party/blink/renderer/platform/audio/audio_bus.h" #include "third_party/blink/renderer/platform/audio/vector_math.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { @@ -140,7 +139,7 @@ // FIXME: would be better to up the thread priority here. It doesn't need to // be real-time, but higher than the default... if (use_background_threads && background_stages_.size() > 0) { - background_thread_ = Thread::CreateThread( + background_thread_ = NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kReverbConvolutionBackgroundThread)); } }
diff --git a/third_party/blink/renderer/platform/audio/reverb_convolver.h b/third_party/blink/renderer/platform/audio/reverb_convolver.h index 3076bc4..0d1a9af 100644 --- a/third_party/blink/renderer/platform/audio/reverb_convolver.h +++ b/third_party/blink/renderer/platform/audio/reverb_convolver.h
@@ -37,7 +37,7 @@ #include "third_party/blink/renderer/platform/audio/reverb_convolver_stage.h" #include "third_party/blink/renderer/platform/audio/reverb_input_buffer.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -96,7 +96,7 @@ unsigned max_realtime_fft_size_; // Background thread and synchronization - std::unique_ptr<Thread> background_thread_; + std::unique_ptr<NonMainThread> background_thread_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc index 413e618..36eb029b 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
@@ -14,8 +14,8 @@ #include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/persistent.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_type.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -36,8 +36,8 @@ namespace blink { namespace { -std::unique_ptr<Thread> CreateThread(const char* name) { - return Thread::CreateThread( +std::unique_ptr<NonMainThread> CreateThread(const char* name) { + return NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetThreadNameForTest(name)); } @@ -134,7 +134,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, RegisteredAnimatorShouldOnlyReceiveInputForItself) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -154,7 +154,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, RegisteredAnimatorShouldNotBeMutatedWhenNoInput) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -188,7 +188,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, MutationUpdateIsNotInvokedWithNullOutput) { // Create a thread to run mutator tasks. - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -207,7 +208,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) { // Create a thread to run mutator tasks. - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -240,7 +242,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -272,12 +275,14 @@ TEST_F( AnimationWorkletMutatorDispatcherImplTest, MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread"); + std::unique_ptr<NonMainThread> second_thread = + CreateThread("SecondAnimationThread"); MockAnimationWorkletMutator* second_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( second_thread->GetTaskRunner()); @@ -328,7 +333,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplTest, DispatcherShouldNotHangWhenMutatorGoesAway) { // Create a thread to run mutator tasks. - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -411,7 +417,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, RegisteredAnimatorShouldOnlyReceiveInputForItself) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -435,7 +441,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, RegisteredAnimatorShouldNotBeMutatedWhenNoInput) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -469,7 +475,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateIsNotInvokedWithNullOutput) { // Create a thread to run mutator tasks. - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -493,7 +500,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) { // Create a thread to run mutator tasks. - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -528,7 +536,8 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -564,12 +573,14 @@ TEST_F( AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread"); + std::unique_ptr<NonMainThread> first_thread = + CreateThread("FirstAnimationThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); - std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread"); + std::unique_ptr<NonMainThread> second_thread = + CreateThread("SecondAnimationThread"); MockAnimationWorkletMutator* second_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( second_thread->GetTaskRunner()); @@ -602,7 +613,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateDroppedWhenBusy) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( first_thread->GetTaskRunner()); @@ -635,7 +646,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateQueuedWhenBusy) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( @@ -671,7 +682,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateQueueWithReplacementWhenBusy) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( @@ -712,7 +723,7 @@ TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, MutationUpdateMultipleQueuesWhenBusy) { - std::unique_ptr<Thread> first_thread = CreateThread("FirstThread"); + std::unique_ptr<NonMainThread> first_thread = CreateThread("FirstThread"); MockAnimationWorkletMutator* first_mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( @@ -764,7 +775,7 @@ static_cast<base::SimpleTestTickClock*>(mock_clock.get()); mutator_->SetClockForTesting(std::move(mock_clock)); - std::unique_ptr<Thread> thread = CreateThread("MyThread"); + std::unique_ptr<NonMainThread> thread = CreateThread("MyThread"); MockAnimationWorkletMutator* mutator = MakeGarbageCollected<MockAnimationWorkletMutator>( thread->GetTaskRunner());
diff --git a/third_party/blink/renderer/platform/graphics/color.cc b/third_party/blink/renderer/platform/graphics/color.cc index afaa9c0c1..73c83fc0 100644 --- a/third_party/blink/renderer/platform/graphics/color.cc +++ b/third_party/blink/renderer/platform/graphics/color.cc
@@ -68,7 +68,7 @@ template <typename CharacterType> inline bool ParseHexColorInternal(const CharacterType* name, unsigned length, - RGBA32& rgb) { + Color& color) { if (length != 3 && length != 4 && length != 6 && length != 8) return false; if ((length == 8 || length == 4) && @@ -82,26 +82,28 @@ value |= ToASCIIHexValue(name[i]); } if (length == 6) { - rgb = 0xFF000000 | value; + color = Color::FromRGBA32(0xFF000000 | value); return true; } if (length == 8) { // We parsed the values into RGBA order, but the RGBA32 type // expects them to be in ARGB order, so we right rotate eight bits. - rgb = value << 24 | value >> 8; + color = Color::FromRGBA32(value << 24 | value >> 8); return true; } if (length == 4) { // #abcd converts to ddaabbcc in RGBA32. - rgb = (value & 0xF) << 28 | (value & 0xF) << 24 | (value & 0xF000) << 8 | - (value & 0xF000) << 4 | (value & 0xF00) << 4 | (value & 0xF00) | - (value & 0xF0) | (value & 0xF0) >> 4; + color = Color::FromRGBA32((value & 0xF) << 28 | (value & 0xF) << 24 | + (value & 0xF000) << 8 | (value & 0xF000) << 4 | + (value & 0xF00) << 4 | (value & 0xF00) | + (value & 0xF0) | (value & 0xF0) >> 4); return true; } // #abc converts to #aabbcc - rgb = 0xFF000000 | (value & 0xF00) << 12 | (value & 0xF00) << 8 | - (value & 0xF0) << 8 | (value & 0xF0) << 4 | (value & 0xF) << 4 | - (value & 0xF); + color = Color::FromRGBA32(0xFF000000 | (value & 0xF00) << 12 | + (value & 0xF00) << 8 | (value & 0xF0) << 8 | + (value & 0xF0) << 4 | (value & 0xF) << 4 | + (value & 0xF)); return true; } @@ -141,20 +143,20 @@ return MakeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a)); } -bool Color::ParseHexColor(const LChar* name, unsigned length, RGBA32& rgb) { - return ParseHexColorInternal(name, length, rgb); +bool Color::ParseHexColor(const LChar* name, unsigned length, Color& color) { + return ParseHexColorInternal(name, length, color); } -bool Color::ParseHexColor(const UChar* name, unsigned length, RGBA32& rgb) { - return ParseHexColorInternal(name, length, rgb); +bool Color::ParseHexColor(const UChar* name, unsigned length, Color& color) { + return ParseHexColorInternal(name, length, color); } -bool Color::ParseHexColor(const StringView& name, RGBA32& rgb) { +bool Color::ParseHexColor(const StringView& name, Color& color) { if (name.IsEmpty()) return false; if (name.Is8Bit()) - return ParseHexColor(name.Characters8(), name.length(), rgb); - return ParseHexColor(name.Characters16(), name.length(), rgb); + return ParseHexColor(name.Characters8(), name.length(), color); + return ParseHexColor(name.Characters16(), name.length(), color); } int DifferenceSquared(const Color& c1, const Color& c2) { @@ -168,8 +170,8 @@ if (name[0] != '#') return SetNamedColor(name); if (name.Is8Bit()) - return ParseHexColor(name.Characters8() + 1, name.length() - 1, color_); - return ParseHexColor(name.Characters16() + 1, name.length() - 1, color_); + return ParseHexColor(name.Characters8() + 1, name.length() - 1, *this); + return ParseHexColor(name.Characters16() + 1, name.length() - 1, *this); } String Color::Serialized() const {
diff --git a/third_party/blink/renderer/platform/graphics/color.h b/third_party/blink/renderer/platform/graphics/color.h index 0b877c3..e7f6ed54 100644 --- a/third_party/blink/renderer/platform/graphics/color.h +++ b/third_party/blink/renderer/platform/graphics/color.h
@@ -265,9 +265,9 @@ Color Blend(const Color&) const; Color BlendWithWhite() const; - static bool ParseHexColor(const StringView&, RGBA32&); - static bool ParseHexColor(const LChar*, unsigned, RGBA32&); - static bool ParseHexColor(const UChar*, unsigned, RGBA32&); + static bool ParseHexColor(const StringView&, Color&); + static bool ParseHexColor(const LChar*, unsigned, Color&); + static bool ParseHexColor(const UChar*, unsigned, Color&); static const Color kBlack; static const Color kWhite;
diff --git a/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc b/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc index fde1873..985a63c 100644 --- a/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc +++ b/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
@@ -38,8 +38,8 @@ #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h" #include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_skia.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/shared_buffer.h" @@ -269,9 +269,9 @@ EXPECT_EQ(0, decode_request_count_); // Create a thread to rasterize PaintRecord. - std::unique_ptr<Thread> thread = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("RasterThread")); + std::unique_ptr<NonMainThread> thread = + NonMainThread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("RasterThread")); PostCrossThreadTask( *thread->GetTaskRunner(), FROM_HERE, CrossThreadBindOnce(&RasterizeMain, CrossThreadUnretained(canvas_.get()),
diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc b/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc index b8ea40a..d3d6aa4 100644 --- a/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc +++ b/third_party/blink/renderer/platform/graphics/image_frame_generator_test.cc
@@ -33,8 +33,8 @@ #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h" #include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h" #include "third_party/blink/renderer/platform/image-decoders/segment_reader.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/shared_buffer.h" @@ -306,9 +306,9 @@ // LocalFrame can now be decoded completely. SetFrameStatus(ImageFrame::kFrameComplete); AddNewData(); - std::unique_ptr<Thread> thread = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("DecodeThread")); + std::unique_ptr<NonMainThread> thread = + NonMainThread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("DecodeThread")); PostCrossThreadTask( *thread->GetTaskRunner(), FROM_HERE, CrossThreadBindOnce(&DecodeThreadMain, WTF::RetainedRef(generator_),
diff --git a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc index c907610..1b8e55c1 100644 --- a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc +++ b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc
@@ -9,7 +9,7 @@ #include "cc/paint/paint_worklet_job.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_type.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -20,8 +20,8 @@ namespace blink { namespace { // We need a thread (or multiple threads) for the (mock) worklets to run on. -std::unique_ptr<Thread> CreateTestThread(const char* name) { - return Thread::CreateThread( +std::unique_ptr<NonMainThread> CreateTestThread(const char* name) { + return NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread).SetThreadNameForTest(name)); } @@ -96,7 +96,8 @@ const int worklet_id = 4; MockPaintWorkletPainter* mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(worklet_id); - std::unique_ptr<Thread> worklet_thread = CreateTestThread("WorkletThread"); + std::unique_ptr<NonMainThread> worklet_thread = + CreateTestThread("WorkletThread"); dispatcher->RegisterPaintWorkletPainter(mock_painter, worklet_thread->GetTaskRunner()); @@ -138,7 +139,8 @@ const int worklet_id = 4; auto* mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(worklet_id); - std::unique_ptr<Thread> worklet_thread = CreateTestThread("WorkletThread"); + std::unique_ptr<NonMainThread> worklet_thread = + CreateTestThread("WorkletThread"); dispatcher->RegisterPaintWorkletPainter(mock_painter, worklet_thread->GetTaskRunner()); @@ -158,7 +160,8 @@ const int first_worklet_id = 2; auto* first_mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(first_worklet_id); - std::unique_ptr<Thread> first_thread = CreateTestThread("WorkletThread1"); + std::unique_ptr<NonMainThread> first_thread = + CreateTestThread("WorkletThread1"); dispatcher->RegisterPaintWorkletPainter(first_mock_painter, first_thread->GetTaskRunner()); @@ -166,7 +169,8 @@ auto* second_mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>( second_worklet_id); - std::unique_ptr<Thread> second_thread = CreateTestThread("WorkletThread2"); + std::unique_ptr<NonMainThread> second_thread = + CreateTestThread("WorkletThread2"); dispatcher->RegisterPaintWorkletPainter(second_mock_painter, second_thread->GetTaskRunner()); @@ -192,7 +196,8 @@ const int worklet_id = 2; auto* mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(worklet_id); - std::unique_ptr<Thread> worklet_thread = CreateTestThread("WorkletThread"); + std::unique_ptr<NonMainThread> worklet_thread = + CreateTestThread("WorkletThread"); dispatcher->RegisterPaintWorkletPainter(mock_painter, worklet_thread->GetTaskRunner()); @@ -217,7 +222,8 @@ const int first_worklet_id = 5; auto* first_mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(first_worklet_id); - std::unique_ptr<Thread> first_thread = CreateTestThread("WorkletThread1"); + std::unique_ptr<NonMainThread> first_thread = + CreateTestThread("WorkletThread1"); dispatcher->RegisterPaintWorkletPainter(first_mock_painter, first_thread->GetTaskRunner()); @@ -225,7 +231,8 @@ auto* second_mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>( second_worklet_id); - std::unique_ptr<Thread> second_thread = CreateTestThread("WorkletThread2"); + std::unique_ptr<NonMainThread> second_thread = + CreateTestThread("WorkletThread2"); dispatcher->RegisterPaintWorkletPainter(second_mock_painter, second_thread->GetTaskRunner()); @@ -250,7 +257,8 @@ const int first_worklet_id = 2; auto* first_mock_painter = MakeGarbageCollected<NiceMock<MockPaintWorkletPainter>>(first_worklet_id); - std::unique_ptr<Thread> first_thread = CreateTestThread("WorkletThread1"); + std::unique_ptr<NonMainThread> first_thread = + CreateTestThread("WorkletThread1"); dispatcher->RegisterPaintWorkletPainter(first_mock_painter, first_thread->GetTaskRunner());
diff --git a/third_party/blink/renderer/platform/heap/test/heap_test.cc b/third_party/blink/renderer/platform/heap/test/heap_test.cc index 909b2a0..eb6892e 100644 --- a/third_party/blink/renderer/platform/heap/test/heap_test.cc +++ b/third_party/blink/renderer/platform/heap/test/heap_test.cc
@@ -47,8 +47,8 @@ #include "third_party/blink/renderer/platform/heap/prefinalizer.h" #include "third_party/blink/renderer/platform/heap/self_keep_alive.h" #include "third_party/blink/renderer/platform/heap/visitor.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" @@ -332,9 +332,9 @@ protected: static void Test(ThreadedTesterBase* tester) { HeapTestingPlatformAdapter platform_for_threads(gin::V8Platform::Get()); - std::unique_ptr<Thread> threads[kNumberOfThreads]; + std::unique_ptr<NonMainThread> threads[kNumberOfThreads]; for (auto& thread : threads) { - thread = Thread::CreateThread( + thread = NonMainThread::CreateThread( ThreadCreationParams(ThreadType::kTestThread) .SetThreadNameForTest("blink gc testing thread")); PostCrossThreadTask(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc index 8620f2d..013906e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response_test.cc
@@ -6,8 +6,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" @@ -52,9 +52,9 @@ ResourceResponse response(CreateTestResponse()); RunHeaderRelatedTest(response); - std::unique_ptr<Thread> thread = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("WorkerThread")); + std::unique_ptr<NonMainThread> thread = + NonMainThread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("WorkerThread")); PostCrossThreadTask(*thread->GetTaskRunner(), FROM_HERE, CrossThreadBindOnce(&RunInThread)); thread.reset();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 61792d1..ba30c453 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1079,6 +1079,9 @@ // a Chromium level feature. }, { + // TODO(crbug.com/1231644): This flag is being kept (even though the + // feature has shipped) until there are settings to allow users to + // customize the feature. name: "ForcedColors", status: "stable", },
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn index d5c1fb0d..5bda028 100644 --- a/third_party/blink/renderer/platform/scheduler/BUILD.gn +++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -124,6 +124,7 @@ "public/frame_scheduler.h", "public/frame_status.h", "public/main_thread_scheduler.h", + "public/non_main_thread.h", "public/page_lifecycle_state.h", "public/page_scheduler.h", "public/post_cancellable_task.h", @@ -148,6 +149,8 @@ "worker/compositor_thread.h", "worker/compositor_thread_scheduler_impl.cc", "worker/compositor_thread_scheduler_impl.h", + "worker/non_main_thread_impl.cc", + "worker/non_main_thread_impl.h", "worker/non_main_thread_scheduler_base.cc", "worker/non_main_thread_scheduler_base.h", "worker/non_main_thread_scheduler_helper.cc", @@ -162,8 +165,6 @@ "worker/worker_scheduler_impl.h", "worker/worker_scheduler_proxy.cc", "worker/worker_scheduler_proxy.h", - "worker/worker_thread.cc", - "worker/worker_thread.h", "worker/worker_thread_scheduler.cc", "worker/worker_thread_scheduler.h", ] @@ -251,10 +252,10 @@ "main_thread/pending_user_input_unittest.cc", "main_thread/render_widget_signals_unittest.cc", "main_thread/user_model_unittest.cc", + "worker/non_main_thread_impl_unittest.cc", "worker/worker_scheduler_impl_unittest.cc", "worker/worker_scheduler_proxy_unittest.cc", "worker/worker_thread_scheduler_unittest.cc", - "worker/worker_thread_unittest.cc", ] deps = [
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc index c6e139cb..72b4c3a 100644 --- a/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
@@ -22,8 +22,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h" #include "third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.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" @@ -1104,9 +1104,9 @@ } void PostDelayedIdleTaskFromNewThread(base::TimeDelta delay, int* run_count) { - std::unique_ptr<Thread> thread = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("TestBackgroundThread")); + std::unique_ptr<NonMainThread> thread = NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread) + .SetThreadNameForTest("TestBackgroundThread")); PostCrossThreadTask( *thread->GetTaskRunner(), FROM_HERE, CrossThreadBindOnce(&PostIdleTaskFromBackgroundThread,
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread.cc b/third_party/blink/renderer/platform/scheduler/common/thread.cc index b684bd3a..576ead9 100644 --- a/third_party/blink/renderer/platform/scheduler/common/thread.cc +++ b/third_party/blink/renderer/platform/scheduler/common/thread.cc
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h" #include "third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_impl.h" -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/thread_specific.h" @@ -77,16 +76,6 @@ return *this; } -std::unique_ptr<Thread> Thread::CreateThread( - const ThreadCreationParams& params) { -#if DCHECK_IS_ON() - WTF::WillCreateThread(); -#endif - auto thread = std::make_unique<scheduler::WorkerThread>(params); - thread->Init(); - return std::move(thread); -} - void Thread::CreateAndSetCompositorThread() { DCHECK(!GetCompositorThread());
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/thread_unittest.cc index 009e9dc..3f6857f3 100644 --- a/third_party/blink/renderer/platform/scheduler/common/thread_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/thread_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,7 +17,7 @@ EXPECT_TRUE(WTF::IsBeforeThreadCreated()); ThreadCreationParams params(ThreadType::kTestThread); - std::unique_ptr<Thread> thread = Thread::CreateThread(params); + std::unique_ptr<NonMainThread> thread = NonMainThread::CreateThread(params); thread.reset(); EXPECT_FALSE(WTF::IsBeforeThreadCreated());
diff --git a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.cc b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.cc index bdf443f0..7340d7a 100644 --- a/third_party/blink/renderer/platform/scheduler/common/tracing_helper.cc +++ b/third_party/blink/renderer/platform/scheduler/common/tracing_helper.cc
@@ -35,6 +35,9 @@ return RendererMainThreadTaskExecution::TASK_TYPE_NETWORKING; case TaskType::kNetworkingControl: return RendererMainThreadTaskExecution::TASK_TYPE_NETWORKING_CONTROL; + case TaskType::kLowPriorityScriptExecution: + return RendererMainThreadTaskExecution:: + TASK_TYPE_LOW_PRIORITY_SCRIPT_EXECUTION; case TaskType::kHistoryTraversal: return RendererMainThreadTaskExecution::TASK_TYPE_HISTORY_TRAVERSAL; case TaskType::kEmbed:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index bde63b1..cb77db1c 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -396,6 +396,9 @@ : LoadingTaskQueueTraits(); case TaskType::kNetworkingControl: return LoadingControlTaskQueueTraits(); + case TaskType::kLowPriorityScriptExecution: + return LoadingTaskQueueTraits().SetPrioritisationType( + QueueTraits::PrioritisationType::kBestEffort); // Throttling following tasks may break existing web pages, so tentatively // these are unthrottled. // TODO(nhiroki): Throttle them again after we're convinced that it's safe
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc index 42ea45b..b360c2e 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -110,6 +110,7 @@ TaskType::kNetworking, TaskType::kNetworkingUnfreezable, TaskType::kNetworkingControl, + TaskType::kLowPriorityScriptExecution, TaskType::kDOMManipulation, TaskType::kHistoryTraversal, TaskType::kEmbed, @@ -158,7 +159,7 @@ TaskType::kInternalNavigationCancellation}; static_assert( - static_cast<int>(TaskType::kMaxValue) == 80, + static_cast<int>(TaskType::kMaxValue) == 81, "When adding a TaskType, make sure that kAllFrameTaskTypes is updated."); void AppendToVectorTestTask(Vector<String>* vector, String value) { @@ -2495,6 +2496,14 @@ frame_scheduler_->ComputePriority(task_queue.get()); } +TEST_F(FrameSchedulerImplTest, + LowPriorityScriptExecutionHasBestEffortPriority) { + auto task_queue = GetTaskQueue(TaskType::kLowPriorityScriptExecution); + + EXPECT_EQ(TaskQueue::QueuePriority::kBestEffortPriority, + task_queue->GetQueuePriority()); +} + namespace { // Mask is a preferred way of plumbing the list of features, but a list
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index 52f0dfc..1911a54 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -25,6 +25,8 @@ return "NetworkingUnfreezable"; case TaskType::kNetworkingControl: return "NetworkingControl"; + case TaskType::kLowPriorityScriptExecution: + return "LowPriorityScriptExecution"; case TaskType::kHistoryTraversal: return "HistoryTraversal"; case TaskType::kEmbed:
diff --git a/third_party/blink/renderer/platform/scheduler/public/non_main_thread.h b/third_party/blink/renderer/platform/scheduler/public/non_main_thread.h new file mode 100644 index 0000000..496f837 --- /dev/null +++ b/third_party/blink/renderer/platform/scheduler/public/non_main_thread.h
@@ -0,0 +1,32 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_H_ + +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" + +namespace blink { + +// The interface of a non-main thread in Blink. +// +// This class will have an unrestricted GetTaskRunner method, anyone can use +// it. For main thread a frame based task runner should likely be used, +// so `Thread::GetTaskRunner` will eventually be removed or restricted via a +// pass key. +// +class PLATFORM_EXPORT NonMainThread : public Thread { + public: + // Creates a new non-main thread. This may be called from a non-main thread + // (e.g. nested Web workers). + static std::unique_ptr<NonMainThread> CreateThread( + const ThreadCreationParams&); + + // TODO(dtapuska): Add GetTaskRunner here and rename Thread::GetTaskRunner + // to Thread::GetTaskRunnerDeprecated. +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_H_
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread.h b/third_party/blink/renderer/platform/scheduler/public/thread.h index 9daff89..933fa13 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -90,10 +90,6 @@ // TaskObserver is an observer fired before and after a task is executed. using TaskObserver = base::TaskObserver; - // Creates a new thread. This may be called from a non-main thread (e.g. - // nested Web workers). - static std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&); - // Create and save (as a global variable) the compositor thread. The thread // will be accessible through CompositorThread(). static void CreateAndSetCompositorThread();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/DEPS b/third_party/blink/renderer/platform/scheduler/worker/DEPS index f20f940..f47031c 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/DEPS +++ b/third_party/blink/renderer/platform/scheduler/worker/DEPS
@@ -2,11 +2,11 @@ "non_main_thread_task_queue.h": [ "+base/task/sequence_manager/task_queue_impl.h", ], - "worker_thread.h": [ + "non_main_thread_impl.h": [ "+base/threading/simple_thread.h", "+third_party/blink/renderer/platform/heap/gc_task_runner.h", ], - "worker_thread.cc": [ + "non_main_thread_impl.cc": [ "+base/message_loop/message_pump_type.h", "+third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h", "+third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h",
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.cc b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.cc index e389c45..abb54aaa 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.cc
@@ -11,7 +11,7 @@ namespace scheduler { CompositorThread::CompositorThread(const ThreadCreationParams& params) - : WorkerThread(params) {} + : NonMainThreadImpl(params) {} CompositorThread::~CompositorThread() = default;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h index 178d404d..67b0350 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h +++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h
@@ -5,12 +5,12 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_ -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h" namespace blink { namespace scheduler { -class PLATFORM_EXPORT CompositorThread : public WorkerThread { +class PLATFORM_EXPORT CompositorThread : public NonMainThreadImpl { public: explicit CompositorThread(const ThreadCreationParams& params); CompositorThread(const CompositorThread&) = delete;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.cc similarity index 78% rename from third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc rename to third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.cc index 4343ad6..949e6f4 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h" #include <memory> #include "base/bind.h" @@ -26,9 +26,20 @@ #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" namespace blink { + +std::unique_ptr<NonMainThread> NonMainThread::CreateThread( + const ThreadCreationParams& params) { +#if DCHECK_IS_ON() + WTF::WillCreateThread(); +#endif + auto thread = std::make_unique<scheduler::NonMainThreadImpl>(params); + thread->Init(); + return std::move(thread); +} + namespace scheduler { -WorkerThread::WorkerThread(const ThreadCreationParams& params) +NonMainThreadImpl::NonMainThreadImpl(const ThreadCreationParams& params) : thread_type_(params.thread_type), worker_scheduler_proxy_(params.frame_or_worker_scheduler ? std::make_unique<WorkerSchedulerProxy>( @@ -39,55 +50,55 @@ options.thread_type = params.base_thread_type; thread_ = std::make_unique<SimpleThreadImpl>( params.name ? params.name : String(), options, supports_gc_, - const_cast<scheduler::WorkerThread*>(this)); + const_cast<scheduler::NonMainThreadImpl*>(this)); if (supports_gc_) { MemoryPressureListenerRegistry::Instance().RegisterThread( - const_cast<scheduler::WorkerThread*>(this)); + const_cast<scheduler::NonMainThreadImpl*>(this)); } } -WorkerThread::~WorkerThread() { +NonMainThreadImpl::~NonMainThreadImpl() { if (supports_gc_) { MemoryPressureListenerRegistry::Instance().UnregisterThread( - const_cast<scheduler::WorkerThread*>(this)); + const_cast<scheduler::NonMainThreadImpl*>(this)); } thread_->Quit(); base::ScopedAllowBaseSyncPrimitives allow_wait; thread_->Join(); } -void WorkerThread::Init() { +void NonMainThreadImpl::Init() { thread_->CreateScheduler(); thread_->StartAsync(); } std::unique_ptr<NonMainThreadSchedulerBase> -WorkerThread::CreateNonMainThreadScheduler( +NonMainThreadImpl::CreateNonMainThreadScheduler( base::sequence_manager::SequenceManager* sequence_manager) { return std::make_unique<WorkerThreadScheduler>(thread_type_, sequence_manager, worker_scheduler_proxy_.get()); } -blink::ThreadScheduler* WorkerThread::Scheduler() { +blink::ThreadScheduler* NonMainThreadImpl::Scheduler() { return static_cast<WorkerThreadScheduler*>( thread_->GetNonMainThreadScheduler()); } -scoped_refptr<base::SingleThreadTaskRunner> WorkerThread::GetTaskRunner() +scoped_refptr<base::SingleThreadTaskRunner> NonMainThreadImpl::GetTaskRunner() const { return thread_->GetDefaultTaskRunner(); } -void WorkerThread::ShutdownOnThread() { +void NonMainThreadImpl::ShutdownOnThread() { thread_->ShutdownOnThread(); Scheduler()->Shutdown(); } -WorkerThread::SimpleThreadImpl::SimpleThreadImpl( +NonMainThreadImpl::SimpleThreadImpl::SimpleThreadImpl( const WTF::String& name_prefix, const base::SimpleThread ::Options& options, bool supports_gc, - WorkerThread* worker_thread) + NonMainThreadImpl* worker_thread) : SimpleThread(name_prefix.Utf8(), options), thread_(worker_thread), supports_gc_(supports_gc) { @@ -104,7 +115,7 @@ base::sequence_manager::kTaskTypeNone); } -void WorkerThread::SimpleThreadImpl::CreateScheduler() { +void NonMainThreadImpl::SimpleThreadImpl::CreateScheduler() { DCHECK(!non_main_thread_scheduler_); DCHECK(!default_task_runner_); DCHECK(sequence_manager_); @@ -117,7 +128,7 @@ TaskType::kWorkerThreadTaskQueueDefault); } -WorkerThread::GCSupport::GCSupport(WorkerThread* thread) { +NonMainThreadImpl::GCSupport::GCSupport(NonMainThreadImpl* thread) { ThreadState* thread_state = ThreadState::AttachCurrentThread(); gc_task_runner_ = std::make_unique<GCTaskRunner>(thread); blink_gc_memory_dump_provider_ = std::make_unique<BlinkGCMemoryDumpProvider>( @@ -125,7 +136,7 @@ BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread); } -WorkerThread::GCSupport::~GCSupport() { +NonMainThreadImpl::GCSupport::~GCSupport() { // Ensure no posted tasks will run from this point on. gc_task_runner_.reset(); blink_gc_memory_dump_provider_.reset(); @@ -133,11 +144,11 @@ ThreadState::DetachCurrentThread(); } -void WorkerThread::SimpleThreadImpl::ShutdownOnThread() { +void NonMainThreadImpl::SimpleThreadImpl::ShutdownOnThread() { gc_support_.reset(); } -void WorkerThread::SimpleThreadImpl::Run() { +void NonMainThreadImpl::SimpleThreadImpl::Run() { DCHECK(non_main_thread_scheduler_) << "CreateScheduler() should be called before starting the thread."; non_main_thread_scheduler_->AttachToCurrentThread(); @@ -160,10 +171,10 @@ run_loop_ = nullptr; } -void WorkerThread::SimpleThreadImpl::Quit() { +void NonMainThreadImpl::SimpleThreadImpl::Quit() { if (!internal_task_runner_->RunsTasksInCurrentSequence()) { internal_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&WorkerThread::SimpleThreadImpl::Quit, + FROM_HERE, base::BindOnce(&NonMainThreadImpl::SimpleThreadImpl::Quit, base::Unretained(this))); return; }
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h similarity index 86% rename from third_party/blink/renderer/platform/scheduler/worker/worker_thread.h rename to third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h index c715944..401b0a9 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h +++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_IMPL_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_IMPL_H_ #include "base/callback_forward.h" #include "base/run_loop.h" @@ -13,13 +13,13 @@ #include "base/threading/simple_thread.h" #include "third_party/blink/public/platform/web_private_ptr.h" #include "third_party/blink/renderer/platform/heap/gc_task_runner.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { class BlinkGCMemoryDumpProvider; class ThreadScheduler; -} +} // namespace blink namespace blink { namespace scheduler { @@ -31,12 +31,10 @@ // "worker", the thread represented by this class is used not only for Web // Workers but for many other use cases, like for WebAudio, Web Database, etc. // -// TODO(yutak): This could be a misnomer, as we already have WorkerThread in -// core/ (though this is under blink::scheduler namespace). -class PLATFORM_EXPORT WorkerThread : public Thread { +class PLATFORM_EXPORT NonMainThreadImpl : public NonMainThread { public: - explicit WorkerThread(const ThreadCreationParams& params); - ~WorkerThread() override; + explicit NonMainThreadImpl(const ThreadCreationParams& params); + ~NonMainThreadImpl() override; // Thread implementation. void Init() override; @@ -72,7 +70,7 @@ explicit SimpleThreadImpl(const WTF::String& name_prefix, const base::SimpleThread::Options& options, bool supports_gc, - WorkerThread* worker_thread); + NonMainThreadImpl* worker_thread); // Creates the thread's scheduler. Must be invoked before starting the // thread or accessing the default TaskRunner. @@ -92,7 +90,7 @@ // SimpleThreadImpl automatically calls this after exiting the Run() but // there are some use cases in which clients must call it before. See - // WorkerThread::ShutdownOnThread(). + // NonMainThreadImpl::ShutdownOnThread(). void ShutdownOnThread(); // Makes sure that Run will eventually finish and thus the thread can be @@ -109,7 +107,7 @@ // loop. scoped_refptr<base::SingleThreadTaskRunner> internal_task_runner_; - WorkerThread* thread_; + NonMainThreadImpl* thread_; // The following variables are "owned" by the worker thread std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_; @@ -124,7 +122,7 @@ class GCSupport final { public: - explicit GCSupport(WorkerThread* thread); + explicit GCSupport(NonMainThreadImpl* thread); ~GCSupport(); private: @@ -141,4 +139,4 @@ } // namespace scheduler } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_IMPL_H_
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl_unittest.cc similarity index 86% rename from third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc rename to third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl_unittest.cc index c238eb8c..0900074 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h" #include "base/bind.h" #include "base/location.h" @@ -68,17 +68,17 @@ thread->Scheduler()->Shutdown(); } -class WorkerThreadTest : public testing::Test { +class NonMainThreadImplTest : public testing::Test { public: - WorkerThreadTest() = default; - WorkerThreadTest(const WorkerThreadTest&) = delete; - WorkerThreadTest& operator=(const WorkerThreadTest&) = delete; + NonMainThreadImplTest() = default; + NonMainThreadImplTest(const NonMainThreadImplTest&) = delete; + NonMainThreadImplTest& operator=(const NonMainThreadImplTest&) = delete; - ~WorkerThreadTest() override = default; + ~NonMainThreadImplTest() override = default; void SetUp() override { - thread_ = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread)); + thread_ = NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread)); } void RunOnWorkerThread(const base::Location& from_here, @@ -88,7 +88,7 @@ base::WaitableEvent::InitialState::NOT_SIGNALED); thread_->GetTaskRunner()->PostTask( from_here, - base::BindOnce(&WorkerThreadTest::RunOnWorkerThreadTask, + base::BindOnce(&NonMainThreadImplTest::RunOnWorkerThreadTask, base::Unretained(this), std::move(task), &completion)); completion.Wait(); } @@ -100,10 +100,10 @@ completion->Signal(); } - std::unique_ptr<Thread> thread_; + std::unique_ptr<NonMainThread> thread_; }; -TEST_F(WorkerThreadTest, TestDefaultTask) { +TEST_F(NonMainThreadImplTest, TestDefaultTask) { MockTask task; base::WaitableEvent completion( base::WaitableEvent::ResetPolicy::AUTOMATIC, @@ -120,7 +120,7 @@ completion.Wait(); } -TEST_F(WorkerThreadTest, TestTaskObserver) { +TEST_F(NonMainThreadImplTest, TestTaskObserver) { StringBuilder calls; TestObserver observer(&calls); @@ -141,7 +141,7 @@ testing::HasSubstr("willProcessTask run didProcessTask")); } -TEST_F(WorkerThreadTest, TestShutdown) { +TEST_F(NonMainThreadImplTest, TestShutdown) { MockTask task; MockTask delayed_task;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl.cc index 2d5a6e9..7322455 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl.cc
@@ -156,6 +156,7 @@ case TaskType::kUserInteraction: case TaskType::kNetworking: case TaskType::kNetworkingControl: + case TaskType::kLowPriorityScriptExecution: case TaskType::kHistoryTraversal: case TaskType::kEmbed: case TaskType::kMediaElementEvent:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc index e7f69d8..1935869 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
@@ -15,8 +15,8 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_impl.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_impl.h" -#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" namespace blink { @@ -45,12 +45,12 @@ base::WaitableEvent* throtting_state_changed_; }; -class WorkerThreadForTest : public WorkerThread { +class WorkerThreadForTest : public NonMainThreadImpl { public: WorkerThreadForTest(FrameScheduler* frame_scheduler, base::WaitableEvent* throtting_state_changed) - : WorkerThread(ThreadCreationParams(ThreadType::kTestThread) - .SetFrameOrWorkerScheduler(frame_scheduler)), + : NonMainThreadImpl(ThreadCreationParams(ThreadType::kTestThread) + .SetFrameOrWorkerScheduler(frame_scheduler)), throtting_state_changed_(throtting_state_changed) {} ~WorkerThreadForTest() override {
diff --git a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc index 709d268..44b7008 100644 --- a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc +++ b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc
@@ -9,9 +9,8 @@ namespace blink { IOTaskRunnerTestingPlatformSupport::IOTaskRunnerTestingPlatformSupport() - : io_thread_( - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread))) { -} + : io_thread_(NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread))) {} scoped_refptr<base::SingleThreadTaskRunner> IOTaskRunnerTestingPlatformSupport::GetIOTaskRunner() const {
diff --git a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h index 21a288f..aad01d4 100644 --- a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h +++ b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h
@@ -8,7 +8,7 @@ #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "base/memory/scoped_refptr.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" namespace base { class SingleThreadTaskRunner; @@ -23,7 +23,7 @@ scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() const override; private: - std::unique_ptr<Thread> io_thread_; + std::unique_ptr<NonMainThread> io_thread_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/weborigin/DEPS b/third_party/blink/renderer/platform/weborigin/DEPS index ee4bd6c..42a95cf 100644 --- a/third_party/blink/renderer/platform/weborigin/DEPS +++ b/third_party/blink/renderer/platform/weborigin/DEPS
@@ -20,5 +20,5 @@ ] specific_include_rules = { - "kurl_test.cc": [ "+third_party/blink/renderer/platform/scheduler/public/thread.h" ], + "kurl_test.cc": [ "+third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" ], } \ No newline at end of file
diff --git a/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/third_party/blink/renderer/platform/weborigin/kurl_test.cc index a7a9e4e..78fe0ca 100644 --- a/third_party/blink/renderer/platform/weborigin/kurl_test.cc +++ b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -36,7 +36,7 @@ #include <stdint.h> #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h" #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -924,8 +924,8 @@ KURL null_url = NullURL(); EXPECT_TRUE(null_url.IsNull()); - auto thread = - Thread::CreateThread(ThreadCreationParams(ThreadType::kTestThread)); + auto thread = NonMainThread::CreateThread( + ThreadCreationParams(ThreadType::kTestThread)); thread->GetTaskRunner()->PostTask(FROM_HERE, base::BindOnce([]() { // Reference each of the static KURLs // again, from the background thread,
diff --git a/third_party/blink/tools/blinkpy/common/net/rpc.py b/third_party/blink/tools/blinkpy/common/net/rpc.py index d5cc65b..421672b 100644 --- a/third_party/blink/tools/blinkpy/common/net/rpc.py +++ b/third_party/blink/tools/blinkpy/common/net/rpc.py
@@ -56,14 +56,14 @@ class RPCError(Exception): """Base type for all pRPC errors.""" - def __init__(self, message, method, request=None, code=None): + def __init__(self, message, method, request_body=None, code=None): message = '%s: %s' % (method, message) if code: message += ' (code: %d)' % code super().__init__(message) self.method = method self.code = code - self.request = request + self.request_body = request_body class BaseRPC: @@ -254,12 +254,12 @@ if not self._batch_requests: return batch_requests, self._batch_requests = self._batch_requests, [] - request = { + batch_request_body = { 'requests': [{ method: body } for method, body, _, _ in batch_requests] } - batch_response = self._luci_rpc('Batch', request) or {} + batch_response = self._luci_rpc('Batch', batch_request_body) or {} responses = batch_response.get('responses') or [] for request, response_body in zip(batch_requests, responses): method, request_body, field, count = request @@ -269,7 +269,7 @@ # Avoid the built-in `str.capitalize`, since it lowercases the # remaining letters. raise RPCError(message, method[0].upper() + method[1:], - request, error.get('code')) + request_body, error.get('code')) unwrapped_response = response_body[method] if field: yield from unwrapped_response[field][:count]
diff --git a/third_party/blink/tools/blinkpy/tool/blink_tool.py b/third_party/blink/tools/blinkpy/tool/blink_tool.py index 9bff59b4..82e2714d 100644 --- a/third_party/blink/tools/blinkpy/tool/blink_tool.py +++ b/third_party/blink/tools/blinkpy/tool/blink_tool.py
@@ -50,6 +50,7 @@ from blinkpy.tool.commands.rebaseline import Rebaseline from blinkpy.tool.commands.rebaseline_cl import RebaselineCL from blinkpy.tool.commands.rebaseline_test import RebaselineTest +from blinkpy.tool.commands.update_metadata import UpdateMetadata _log = logging.getLogger(__name__) @@ -83,6 +84,7 @@ Rebaseline(), RebaselineCL(), RebaselineTest(), + UpdateMetadata(self), ] self.help_command = HelpCommand(tool=self) self.commands.append(self.help_command)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py index b2b45de..73ad10ea 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -71,8 +71,8 @@ '--dry-run', action='store_true', default=False, - help=('Dry run mode; list actions that would be performed ' - 'but do not actually download any new baselines.')) + help=('Dry run mode. List actions that would be performed ' + 'but do not actually write to disk.')) results_directory_option = optparse.make_option( '--results-directory', action='callback',
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py index f83243f..55ba3476 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
@@ -38,19 +38,34 @@ show_in_main_help = True argument_names = '[testname,...]' + only_changed_tests_option = optparse.make_option( + '--only-changed-tests', + action='store_true', + default=False, + help='Only update files for tests directly modified in the CL.') + no_trigger_jobs_option = optparse.make_option( + '--no-trigger-jobs', + dest='trigger_jobs', + action='store_false', + default=True, + help='Do not trigger any try jobs.') + test_name_file_option = optparse.make_option( + '--test-name-file', + action='callback', + callback=check_file_option, + type='string', + help=('Read names of tests to update from this file, ' + 'one test per line.')) + patchset_option = optparse.make_option( + '--patchset', + default=None, + type='int', + help='Patchset number to fetch results from.') + def __init__(self): super(RebaselineCL, self).__init__(options=[ - optparse.make_option( - '--only-changed-tests', - action='store_true', - default=False, - help='Only download new baselines for tests that are directly ' - 'modified in the CL.'), - optparse.make_option('--no-trigger-jobs', - dest='trigger_jobs', - action='store_false', - default=True, - help='Do not trigger any try jobs.'), + self.only_changed_tests_option, + self.no_trigger_jobs_option, optparse.make_option( '--fill-missing', dest='fill_missing', @@ -69,14 +84,7 @@ help='Use only the try jobs results for rebaselining. ' 'Default behavior is to use results from both CQ builders ' 'and try bots.'), - optparse.make_option( - '--test-name-file', - dest='test_name_file', - action='callback', - callback=check_file_option, - type='string', - help='Read names of tests to rebaseline from this file, one ' - 'test per line.'), + self.test_name_file_option, optparse.make_option( '--builders', default=None, @@ -97,10 +105,7 @@ 'FlagSpecificConfig. This option will rebaseline ' 'results for the given FlagSpecificConfig while ' 'ignoring results from other builders.')), - optparse.make_option( - '--patchset', - default=None, - help='Patchset number to fetch new baselines from.'), + self.patchset_option, optparse.make_option('--resultDB', dest='resultDB', default=False, @@ -156,8 +161,8 @@ jobs = build_resolver.resolve_builds(builds, options.patchset) except RPCError as error: _log.error('%s', error) - _, payload, _, _ = error.request - _log.error('Request payload: %s', json.dumps(payload, indent=2)) + _log.error('Request payload: %s', + json.dumps(error.request_body, indent=2)) return 1 except UnresolvedBuildException as error: _log.error('%s', error)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py new file mode 100644 index 0000000..9b440ad --- /dev/null +++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py
@@ -0,0 +1,150 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Update WPT metadata from builder results.""" + +import json +import logging +import optparse +import re +from typing import List, Optional + +from blinkpy.common.host import Host +from blinkpy.common.net.git_cl import GitCL +from blinkpy.common.net.rpc import Build, RPCError +from blinkpy.tool.commands.build_resolver import ( + BuildResolver, + UnresolvedBuildException, +) +from blinkpy.tool.commands.command import Command, check_file_option +from blinkpy.tool.commands.rebaseline_cl import RebaselineCL + +_log = logging.getLogger(__name__) + + +class UpdateMetadata(Command): + name = 'update-metadata' + show_in_main_help = False # TODO(crbug.com/1299650): To be switched on. + help_text = 'Update WPT metadata from builder results.' + argument_names = '[<test>,...]' + long_help = __doc__ + + def __init__(self, tool: Host, git_cl: Optional[GitCL] = None): + super().__init__(options=[ + optparse.make_option( + '--build', + dest='builds', + metavar='<builder>[:<buildnum>],...', + action='callback', + callback=_parse_build_specifiers, + type='string', + help=('Comma-separated list of builds to download results for ' + '(e.g., "Linux Tests:100,linux-rel"). ' + 'May specify multiple times.')), + optparse.make_option( + '-b', + '--bug', + action='callback', + callback=_coerce_bug_number, + type='string', + help='Bug number to include for updated tests.'), + optparse.make_option( + '--overwrite-conditions', + default='fill', + metavar='{yes,no,auto,fill}', + choices=['yes', 'no', 'auto', 'fill'], + help=( + 'Specify whether to reformat conditional statuses. ' + '"auto" will reformat conditions if every platform ' + 'a test is enabled for has results. ' + '"fill" will reformat conditions using existing statuses ' + 'for platforms without results. (default: "fill")')), + # TODO(crbug.com/1299650): This reason should be optional, but + # nargs='?' is only supported by argparse, which we should + # eventually migrate to. + optparse.make_option( + '--disable-intermittent', + metavar='REASON', + help=('Disable tests that have inconsistent results ' + 'with the given reason.')), + optparse.make_option('--keep-statuses', + action='store_true', + help='Keep all existing statuses.'), + optparse.make_option( + '--run-log', + dest='run_logs', + action='callback', + callback=self._append_run_logs, + type='string', + help=('Path to a wptrunner log file (or directory of ' + 'log files) to use in the update. Logs may use either ' + 'the raw mozlog format or the wptreport format. ' + 'May specify multiple times.')), + RebaselineCL.patchset_option, + RebaselineCL.test_name_file_option, + RebaselineCL.only_changed_tests_option, + RebaselineCL.no_trigger_jobs_option, + RebaselineCL.dry_run_option, + ]) + self._tool = tool + self.git_cl = git_cl or GitCL(self._tool) + + def execute(self, options: optparse.Values, args: List[str], + _tool: Host) -> Optional[int]: + if not options.builds: + builders = self._tool.builders.all_try_builder_names() + options.builds = [Build(builder) for builder in builders] + build_resolver = BuildResolver( + self._tool.builders, + self.git_cl, + can_trigger_jobs=(options.trigger_jobs and not options.dry_run)) + try: + build_statuses = build_resolver.resolve_builds( + options.builds, options.patchset) + except RPCError as error: + _log.error('%s', error) + _log.error('Request payload: %s', + json.dumps(error.request_body, indent=2)) + return 1 + except UnresolvedBuildException as error: + _log.error('%s', error) + return 1 + + def _append_run_logs(self, option: optparse.Option, _opt_str: str, + value: str, parser: optparse.OptionParser): + run_logs = getattr(parser.values, option.dest, None) or [] + fs = self._tool.filesystem + path = fs.expanduser(value) + if fs.isfile(path): + run_logs.append(path) + elif fs.isdir(path): + for filename in fs.listdir(path): + child_path = fs.join(path, filename) + if fs.isfile(child_path): + run_logs.append(child_path) + else: + raise optparse.OptionValueError( + '%r is neither a regular file nor a directory' % value) + setattr(parser.values, option.dest, run_logs) + + +def _parse_build_specifiers(option: optparse.Option, _opt_str: str, value: str, + parser: optparse.OptionParser): + builds = getattr(parser.values, option.dest, None) or [] + for build_specifier in value.split(','): + builder, sep, maybe_num = build_specifier.partition(':') + try: + build_num = int(maybe_num) if sep else None + builds.append(Build(builder, build_num)) + except ValueError: + raise optparse.OptionValueError('invalid build number for %r' % + builder) + setattr(parser.values, option.dest, builds) + + +def _coerce_bug_number(option: optparse.Option, _opt_str: str, value: str, + parser: optparse.OptionParser): + bug_match = re.fullmatch(r'(crbug(\.com)?/)?(?P<bug>\d+)', value) + if not bug_match: + raise optparse.OptionValueError('invalid bug number or URL %r' % value) + setattr(parser.values, option.dest, int(bug_match['bug']))
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py new file mode 100644 index 0000000..4e2fbae0 --- /dev/null +++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py
@@ -0,0 +1,175 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import contextlib +import io +import optparse +import unittest +from unittest.mock import patch + +from blinkpy.common.net.git_cl import TryJobStatus +from blinkpy.common.net.git_cl_mock import MockGitCL +from blinkpy.common.net.rpc import Build, RPCError +from blinkpy.common.system.log_testing import LoggingTestCase +from blinkpy.tool.mock_tool import MockBlinkTool +from blinkpy.tool.commands.update_metadata import UpdateMetadata +from blinkpy.web_tests.builder_list import BuilderList + + +class UpdateMetadataTest(LoggingTestCase): + def setUp(self): + super().setUp() + self.maxDiff = None + self.tool = MockBlinkTool() + self.tool.builders = BuilderList({ + 'test-linux-rel': { + 'port_name': 'test-linux-trusty', + 'specifiers': ['Trusty', 'Release'], + 'is_try_builder': True, + }, + 'test-mac-rel': { + 'port_name': 'test-mac-mac12', + 'specifiers': ['Mac12', 'Release'], + 'is_try_builder': True, + }, + 'Test Linux Tests': { + 'port_name': 'test-linux-trusty', + 'specifiers': ['Trusty', 'Release'], + }, + }) + git_cl = MockGitCL( + self.tool, { + Build('test-linux-rel', 1000, '1000'): + TryJobStatus.from_bb_status('FAILURE'), + Build('test-mac-rel', 2000, '2000'): + TryJobStatus.from_bb_status('SUCCESS'), + }) + self.command = UpdateMetadata(self.tool, git_cl) + + def test_execute_basic(self): + exit_code = self.command.main([]) + self.assertEqual(exit_code, 0) + self.assertLog([ + 'INFO: All builds finished.\n', + ]) + + def test_execute_with_no_issue_number_aborts(self): + self.command.git_cl = MockGitCL(self.tool, issue_number='None') + exit_code = self.command.main([]) + self.assertEqual(exit_code, 1) + self.assertLog(['ERROR: No issue number for current branch.\n']) + + def test_execute_trigger_jobs(self): + self.command.git_cl = MockGitCL( + self.tool, { + Build('test-linux-rel', 1000, '1000'): + TryJobStatus.from_bb_status('STARTED'), + }) + exit_code = self.command.main([]) + self.assertEqual(exit_code, 1) + self.assertLog([ + 'INFO: No finished builds.\n', + 'INFO: Scheduled or started builds:\n', + 'INFO: BUILDER NUMBER STATUS BUCKET\n', + 'INFO: test-linux-rel 1000 STARTED try \n', + 'INFO: test-mac-rel -- TRIGGERED try \n', + 'ERROR: Once all pending try jobs have finished, ' + 'please re-run the tool to fetch new results.\n', + ]) + + def test_execute_with_rpc_error(self): + error = RPCError('mock error', 'getBuild', {'id': '123'}, 400) + with patch.object(self.command.git_cl.bb_client, + 'execute_batch', + side_effect=error): + exit_code = self.command.main(['--build=Test Linux Tests']) + self.assertEqual(exit_code, 1) + self.assertLog([ + 'ERROR: getBuild: mock error (code: 400)\n', + 'ERROR: Request payload: {\n' + ' "id": "123"\n' + '}\n', + ]) + + def test_execute_no_trigger_jobs(self): + self.command.git_cl = MockGitCL(self.tool, {}) + exit_code = self.command.main(['--no-trigger-jobs']) + self.assertEqual(exit_code, 1) + self.assertLog([ + "ERROR: Aborted: no try jobs and '--no-trigger-jobs' or " + "'--dry-run' passed.\n", + ]) + exit_code = self.command.main(['--dry-run']) + self.assertEqual(exit_code, 1) + self.assertLog([ + "ERROR: Aborted: no try jobs and '--no-trigger-jobs' or " + "'--dry-run' passed.\n", + ]) + self.assertEqual(self.command.git_cl.calls, []) + + +class UpdateMetadataArgumentParsingTest(unittest.TestCase): + def setUp(self): + self.tool = MockBlinkTool() + self.command = UpdateMetadata(self.tool) + + @contextlib.contextmanager + def assert_parse_error(self, expected_pattern): + buf = io.StringIO() + with contextlib.redirect_stderr(buf): + with self.assertRaises(SystemExit): + yield + self.assertRegex(buf.getvalue(), expected_pattern) + + def test_build_syntax(self): + options, _args = self.command.parse_args([ + '--build=Linux Tests:100,linux-rel', '--build=mac-rel:200', + '--build=Mac12 Tests' + ]) + self.assertEqual(options.builds, [ + Build('Linux Tests', 100), + Build('linux-rel'), + Build('mac-rel', 200), + Build('Mac12 Tests'), + ]) + with self.assert_parse_error('invalid build number'): + self.command.parse_args(['--build=linux-rel:']) + with self.assert_parse_error('invalid build number'): + self.command.parse_args(['--build=linux-rel:nan']) + + def test_bug_number_patterns(self): + options, _args = self.command.parse_args(['-b', '123']) + self.assertEqual(options.bug, 123) + options, _args = self.command.parse_args(['-b', 'crbug/123']) + self.assertEqual(options.bug, 123) + options, _args = self.command.parse_args(['--bug=crbug.com/123']) + self.assertEqual(options.bug, 123) + with self.assert_parse_error('invalid bug number or URL'): + self.command.parse_args(['--bug=crbug.com/123a']) + with self.assert_parse_error('invalid bug number or URL'): + self.command.parse_args(['-b', 'cbug.com/123']) + + def test_run_log_files(self): + self.tool.filesystem.write_text_file('path/to/a.log', 'a') + self.tool.filesystem.write_text_file('path/to/b.log', 'b') + options, _args = self.command.parse_args( + ['--run-log=path/to/a.log', '--run-log=path/to/b.log']) + self.assertEqual(options.run_logs, ['path/to/a.log', 'path/to/b.log']) + + def test_run_log_dir(self): + self.tool.filesystem.write_text_file('path/to/logs/a.log', 'a') + self.tool.filesystem.write_text_file('path/to/logs/b.log', 'b') + # Do not recursively traverse, since it can be slow. + self.tool.filesystem.write_text_file('path/to/logs/skip/nested/c.log', + 'c') + options, _args = self.command.parse_args(['--run-log=path/to/logs']) + self.assertEqual(options.run_logs, [ + 'path/to/logs/a.log', + 'path/to/logs/b.log', + ]) + + def test_run_log_does_not_exist(self): + with self.assert_parse_error('is neither a regular file ' + 'nor a directory'): + self.command.parse_args(['--run-log=does/not/exist'])
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index ba1f4015..1d71f855 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -482,6 +482,8 @@ crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-031.html [ Failure ] crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-035.html [ Failure ] crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-036.html [ Failure ] +crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-style-changes-003.html [ Failure ] +crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-style-changes-004.html [ Failure ] crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-baseline-004.html [ Failure ] crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-content-alignment-overflow-002.html [ Failure ] crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-content-alignment-with-abspos-001.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7668c943..076acaf7 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1779,20 +1779,20 @@ # ====== Style team owned tests from here ====== -crbug.com/753671 [ Linux ] external/wpt/css/css-content/quotes-001.html [ Failure ] -crbug.com/753671 [ Mac ] external/wpt/css/css-content/quotes-006.html [ Failure ] +crbug.com/1353560 [ Linux ] external/wpt/css/css-content/quotes-001.html [ Failure ] +crbug.com/1353560 [ Mac ] external/wpt/css/css-content/quotes-006.html [ Failure ] crbug.com/1341208 [ Mac ] external/wpt/css/css-content/quotes-007.html [ Skip ] -crbug.com/753671 [ Mac ] external/wpt/css/css-content/quotes-009.html [ Failure ] -crbug.com/753671 [ Mac10.13 ] external/wpt/css/css-content/quotes-012.html [ Failure ] -crbug.com/753671 [ Mac10.14 ] external/wpt/css/css-content/quotes-012.html [ Failure ] -crbug.com/753671 external/wpt/css/css-content/quotes-013.html [ Failure ] -crbug.com/753671 [ Mac ] external/wpt/css/css-content/quotes-014.html [ Failure ] -crbug.com/753671 [ Mac10.15 ] external/wpt/css/css-content/quotes-020.html [ Failure ] -crbug.com/753671 [ Mac11 ] external/wpt/css/css-content/quotes-020.html [ Failure ] -crbug.com/753671 [ Mac11-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ] -crbug.com/753671 [ Mac12 ] external/wpt/css/css-content/quotes-020.html [ Failure ] -crbug.com/753671 [ Mac12-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ] -crbug.com/753671 [ Win ] external/wpt/css/css-content/quotes-030.html [ Failure ] +crbug.com/1353560 [ Mac ] external/wpt/css/css-content/quotes-009.html [ Failure ] +crbug.com/1353560 [ Mac10.13 ] external/wpt/css/css-content/quotes-012.html [ Failure ] +crbug.com/1353560 [ Mac10.14 ] external/wpt/css/css-content/quotes-012.html [ Failure ] +crbug.com/1353560 external/wpt/css/css-content/quotes-013.html [ Failure ] +crbug.com/1353560 [ Mac ] external/wpt/css/css-content/quotes-014.html [ Failure ] +crbug.com/1353560 [ Mac10.15 ] external/wpt/css/css-content/quotes-020.html [ Failure ] +crbug.com/1353560 [ Mac11 ] external/wpt/css/css-content/quotes-020.html [ Failure ] +crbug.com/1353560 [ Mac11-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ] +crbug.com/1353560 [ Mac12 ] external/wpt/css/css-content/quotes-020.html [ Failure ] +crbug.com/1353560 [ Mac12-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ] +crbug.com/1353560 [ Win ] external/wpt/css/css-content/quotes-030.html [ Failure ] crbug.com/1067277 external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ] crbug.com/1335893 external/wpt/css/css-content/content-none-root-columns.html [ Failure ] @@ -3270,8 +3270,8 @@ # ====== Test expectations added to unblock wpt-importer ====== crbug.com/626703 external/wpt/fetch/metadata/generated/worker-dedicated-constructor.sub.html [ Failure ] crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/fetch/metadata/generated/worker-dedicated-constructor.sub.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html [ Failure ] crbug.com/626703 virtual/threaded/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html [ Failure ] crbug.com/626703 external/wpt/service-workers/service-worker/navigation-timing-extended.https.html [ Failure ] crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https.html [ Failure ] @@ -3282,6 +3282,7 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/cross-partition.https.tentative.html [ Skip Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html [ Timeout ] crbug.com/626703 external/wpt/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html [ Timeout ] crbug.com/626703 external/wpt/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-xml-parser.xhtml [ Crash ] @@ -6742,7 +6743,7 @@ crbug.com/1319320 rootscroller/root-scroller-apply-filter-to-parent.html [ Failure Pass ] # Sheriff 2022-04-25 -crbug.com/1319808 virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Skip ] +crbug.com/1319808 virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html [ Skip ] # Sheriff 2022-04-26 crbug.com/1320140 [ Win ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/disallowed-navigations.https.html [ Pass Timeout ] @@ -6820,7 +6821,7 @@ crbug.com/1277696 fast/loader/reload-zero-byte-plugin.html [ Failure Pass ] # Flaky on Windows -crbug.com/1316343 [ Win ] external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Failure ] +crbug.com/1316343 [ Win ] external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html [ Failure ] # Manual test fails when run under automation due to lack of pop-up blocking. https://github.com/web-platform-tests/wpt/issues/3867 crbug.com/1337125 external/wpt/window-placement/fullscreen-companion-window-manual.tentative.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 2be48ae..043e735 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: bcdff15b0e933ac8e785aad2c7a5f6a4ca85fd1f +Version: d0f7a13135f336290c1b3ebe13056c4fd5f38409
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index bdb1b66..23c1d0a 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -32,7 +32,7 @@ ] ], "aria-owns-fallback-content.html": [ - "e0492ef547733c7d313f2938e3d316670b9d0079", + "8a7c9ab6d0b2dcade77af9b6b7a4a1272fa08e26", [ null, {} @@ -95,7 +95,7 @@ ] ], "delayed-ignored-change.html": [ - "1fc98a10805a58dcd9e73c1bab2a472cf06f69f0", + "226af19b5fe3357d7735f095d5be2b42de625741", [ null, {} @@ -87315,6 +87315,19 @@ ] ], "table": { + "border-spacing-at-breaks.tentative.html": [ + "67588f28b02e258539c456d55af2f421cb6ba96a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "break-after-table-cell-child.html": [ "60e09248923e633610555d533961b4f557f420b2", [ @@ -87575,6 +87588,19 @@ {} ] ], + "final-border-spacing-at-fragmentainer-boundary.html": [ + "2e0540d7458dbd696ef601f04f354a2f2faf9acc", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "repeated-section": { "abspos-in-monolithic.tentative.html": [ "6ec70d030d233a8183bbf281503235e2cb005b66", @@ -87757,6 +87783,19 @@ ], {} ] + ], + "repeated-header-border-spacing.tentative.html": [ + "7471c342a90f118ef7a33ac42a1fc9921617729e", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] ] }, "section-with-overflow-000.html": [ @@ -110781,7 +110820,7 @@ ] ], "flexbox_direction-row-reverse.html": [ - "8cc1ab1dec8e8e0b129eb3e49c5d68f6a6fe5817", + "501cd0d514523e5421f1a1ae94c2340f2077a2f5", [ null, [ @@ -136560,6 +136599,32 @@ } ] ], + "clip-path-animation-missing-0-percent.html": [ + "4d4fee1b5b6b11ea0e3efd91dc0028dd3df78d7d", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-missing-0-percent-ref.html", + "==" + ] + ], + {} + ] + ], + "clip-path-animation-none.html": [ + "73b8a473354cde40b3f9542c1616859d0412e8bd", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-none-ref.html", + "==" + ] + ], + {} + ] + ], "clip-path-animation-overflow.html": [ "09a44fb3aac327aef0d51636edfb92dcdd355942", [ @@ -136656,6 +136721,45 @@ ], {} ] + ], + "two-clip-path-animation-diff-length1.html": [ + "d6d04858b5a808aad9d366b3eae26bd75dc80127", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/two-clip-path-animation-diff-length1-ref.html", + "==" + ] + ], + {} + ] + ], + "two-clip-path-animation-diff-length2.html": [ + "0d86120ef35db999dd91b3c2cdd709429e907746", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/two-clip-path-animation-diff-length2-ref.html", + "==" + ] + ], + {} + ] + ], + "two-clip-path-animation-diff-length3.html": [ + "3c8141ad2defe3cd50bf08942819f9b27481ee36", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/two-clip-path-animation-diff-length3-ref.html", + "==" + ] + ], + {} + ] ] }, "clip-path-blending-offset.html": [ @@ -152463,7 +152567,7 @@ ] ], "highlight-currentcolor-painting-properties-001.html": [ - "94e7e9b8f1143ebd65dcb10d02083c5885a9bc46", + "8f347f119e5a3105c7c80df831d927f32d3cf24c", [ null, [ @@ -152476,7 +152580,7 @@ ] ], "highlight-currentcolor-painting-properties-002.html": [ - "7dbc62415b8080c2fea5d5e19103c3d16a2e9e3f", + "bd5d5f4abb8c44a6db5d32975c347ab52d1cfb3b", [ null, [ @@ -152488,6 +152592,32 @@ {} ] ], + "highlight-currentcolor-painting-text-shadow-001.html": [ + "141556f935b8e38f0352fd0a0c32212f2c62debf", + [ + null, + [ + [ + "/css/css-pseudo/highlight-currentcolor-painting-text-shadow-001-ref.html", + "==" + ] + ], + {} + ] + ], + "highlight-currentcolor-painting-text-shadow-002.html": [ + "77858729afaf8c55b435094baceb5959b67d3d46", + [ + null, + [ + [ + "/css/css-pseudo/highlight-currentcolor-painting-text-shadow-002-ref.html", + "==" + ] + ], + {} + ] + ], "highlight-currentcolor-root-explicit-default-001.html": [ "a1512f014df4a38b81ac4c60cb1e2383542a60bd", [ @@ -152567,7 +152697,7 @@ ] ], "highlight-painting-003.html": [ - "e4f061f0b5d1fba48ceb99dd6078a9010293c0d2", + "b09ef52dd7363424c9ce958b9e4cee58279e50d7", [ null, [ @@ -236798,19 +236928,6 @@ {} ] ], - "large-cols-relsize.html": [ - "1bfb2b5404d542f59808826233875977ae9b4f81", - [ - null, - [ - [ - "/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/reference/green-ref.html", - "==" - ] - ], - {} - ] - ], "large-rows-abssize.html": [ "7cd86b94554b9268f30b220ddf8c45021eabf963", [ @@ -236836,19 +236953,6 @@ ], {} ] - ], - "large-rows-relsize.html": [ - "7fd29f6a9e7538f5ce37a914827bf1b03e5cd346", - [ - null, - [ - [ - "/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/reference/green-ref.html", - "==" - ] - ], - {} - ] ] }, "the-hr-element-0": { @@ -269492,7 +269596,7 @@ [] ], "flexbox_direction-row-reverse-ref.html": [ - "d4fbbfcfbe7132a1fb829b9db804aff33e9aac90", + "5ea38fd09e5fa53d56dcaff22b2cf6ef87771de9", [] ], "flexbox_display-ref.html": [ @@ -281291,6 +281395,14 @@ "6cd7e76774bdfada51ae9fc3058db5f65f5fb2f8", [] ], + "clip-path-animation-missing-0-percent-ref.html": [ + "200edcd03821ba2899e43fd560c475b23e7678f3", + [] + ], + "clip-path-animation-none-ref.html": [ + "f47e9f31b07c993aac8e065a699d5db2bc3cd9a0", + [] + ], "clip-path-animation-overflow-ref.html": [ "154a56d5f07832fc7ef08b4db40acbb50faf8348", [] @@ -281310,6 +281422,18 @@ "clip-path-transition-ref.html": [ "af164c30f06808c3394cf3210ca13bc41792d53c", [] + ], + "two-clip-path-animation-diff-length1-ref.html": [ + "0feacb50bae46f131931212122f2b5b0e96d9701", + [] + ], + "two-clip-path-animation-diff-length2-ref.html": [ + "0feacb50bae46f131931212122f2b5b0e96d9701", + [] + ], + "two-clip-path-animation-diff-length3-ref.html": [ + "853f47f9ba31d75417221515965ded69a2b159af", + [] ] }, "clip-path-blending-offset-ref.html": [ @@ -284408,11 +284532,19 @@ [] ], "highlight-currentcolor-painting-properties-001-ref.html": [ - "47a028038b8a3fcd1b6a50d712f115c3c409e1b7", + "93e2002f4aa2bde2c0d1adbb13e0dfd2abf82421", [] ], "highlight-currentcolor-painting-properties-002-ref.html": [ - "19556f6e872a9da2e9ebe6c6e96f831b73fbfd4b", + "11ca501065e5567345ef6ac0541515d45ff20184", + [] + ], + "highlight-currentcolor-painting-text-shadow-001-ref.html": [ + "d6ee33cda749a55a89b28c5f253d2d956d8081e8", + [] + ], + "highlight-currentcolor-painting-text-shadow-002-ref.html": [ + "fb2696a55a1da63de8bc7962ddf7d20a4f31a861", [] ], "highlight-currentcolor-root-explicit-default-001-ref.html": [ @@ -377311,7 +377443,7 @@ ] ], "at-container-parsing.html": [ - "3cf7f3a0251d8d8dccc57f729f6c6ccff6a7c093", + "58e2b26bcf3b70ae8ba991f921996c407bf5eaa3", [ null, {} @@ -377612,7 +377744,7 @@ ] ], "custom-property-style-queries.html": [ - "aec3f9a344cb7a5156f5287aef43c968f4eb9adb", + "35110daea7de7a16e165e36c6a49b3065dd98857", [ null, {} @@ -382362,14 +382494,14 @@ ] ], "grid-alignment-style-changes-003.html": [ - "bca78d76569efb1b12cc3570cde394233db18345", + "5c63fd82b8ee76b081f9581ef0beb983cbdea618", [ null, {} ] ], "grid-alignment-style-changes-004.html": [ - "3064f42396f6da1e3c111a3979da839f43733711", + "c7d004657ee8a68e8ecf7acc77976c3469af737e", [ null, {} @@ -472648,6 +472780,22 @@ ] ] }, + "the-frameset-and-frame-elements": { + "large-cols-relsize.html": [ + "16cf9a416ba405de3f3d31ad91f60d0fea30a850", + [ + null, + {} + ] + ], + "large-rows-relsize.html": [ + "24f34f51c12bf7a73f7f75a4e011c53cf05d3bd2", + [ + null, + {} + ] + ] + }, "the-hr-element-0": { "hr.html": [ "e85221649459eb10243773e07adb8586fb0b283b", @@ -486545,6 +486693,13 @@ {} ] ], + "inhead-noscript-head.html": [ + "bcf42d4793b9a713bcab2e50dc8e780c3cb7ec14", + [ + null, + {} + ] + ], "math-parse01.html": [ "3aff716d9f7cfa6fb6c26992920b137b63f195e4", [
diff --git a/third_party/blink/web_tests/external/wpt/accessibility/crashtests/aria-owns-fallback-content.html b/third_party/blink/web_tests/external/wpt/accessibility/crashtests/aria-owns-fallback-content.html index e0492ef..8a7c9ab 100644 --- a/third_party/blink/web_tests/external/wpt/accessibility/crashtests/aria-owns-fallback-content.html +++ b/third_party/blink/web_tests/external/wpt/accessibility/crashtests/aria-owns-fallback-content.html
@@ -8,8 +8,12 @@ </video> </body> <script> -window.requestIdleCallback(() => { - document.documentElement.style.display = 'none'; - document.documentElement.className = ''; -}); +window.onload = () => { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + document.documentElement.style.display = 'none'; + document.documentElement.className = ''; + }); + }); +} </script>
diff --git a/third_party/blink/web_tests/external/wpt/accessibility/crashtests/delayed-ignored-change.html b/third_party/blink/web_tests/external/wpt/accessibility/crashtests/delayed-ignored-change.html index 1fc98a1..226af19b 100644 --- a/third_party/blink/web_tests/external/wpt/accessibility/crashtests/delayed-ignored-change.html +++ b/third_party/blink/web_tests/external/wpt/accessibility/crashtests/delayed-ignored-change.html
@@ -8,9 +8,11 @@ </rb> <script> document.addEventListener('load', () => { - window.requestIdleCallback(() => { - document.querySelector('style').remove(); - document.documentElement.className = ''; + window.requestAnimationFrame(() => { + window.requestAnimationFrame(() => { + document.querySelector('style').remove(); + document.documentElement.className = ''; + }); }); }, true); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse-ref.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse-ref.html index d4fbbfc..5ea38fd 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse-ref.html
@@ -1,25 +1,19 @@ <!DOCTYPE html> <title>flexbox | flex-direction: row-reverse</title> <link rel="author" href="http://opera.com" title="Opera Software"> +<link rel="stylesheet" href="/fonts/ahem.css"> <style> -* {font-family: monospace;} -body { - width: 10em; -} -ul { - background: blue; - padding: 0; - margin: 0; +#container { + width: 13em; + font: 40px "Ahem"; + background: black; list-style: none; -} -li { - color: white; - margin: 0; - width: 3.3333em; - display: inline-block; + text-align: right; } </style> - +This test makes sure that the flex-direction: row-reverse CSS property correctly orders items. +<div id="container"> <ul> - <li>EFGH</li><li>ABCD</li><li>IJKL</li> +<span style="color: red;">E</span><span style="color: purple;">F</span><span style="color: grey;">G</span><span style="color: bisque;">H</span><span style="color: lightblue;">A</span><span style="color: turquoise;">B</span><span style="color: coral;">C</span><span style="color: violet;">D</span><span style="color: green;">I</span><span style="color: blue;">J</span><span style="color: cyan;">K</span><span style="color: magenta;">L</span> </ul> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse.html index 8cc1ab1..501cd0d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse.html +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox_direction-row-reverse.html
@@ -1,32 +1,29 @@ <!DOCTYPE html> <title>flexbox | flex-direction: row-reverse</title> <link rel="author" href="http://opera.com" title="Opera Software"> -<link rel="help" - href="http://www.w3.org/TR/css-flexbox-1/#flex-direction-property"> +<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-direction-property"> <link rel="match" href="flexbox_direction-row-reverse-ref.html"> +<link rel="stylesheet" href="/fonts/ahem.css"> <style> -* {font-family: monospace;} -body { - width: 10em; +#container { + font: 40px "Ahem"; + width: 13em; } ul { - background: blue; - padding: 0; - margin: 0; + background: black; list-style: none; display: flex; flex-direction: row-reverse; } li { - color: white; margin: 0; - width: 10em; + width: 4em; } </style> - -<ul> - <li>IJKL</li> - <li>ABCD</li> - <li>EFGH</li> -</ul> +This test makes sure that the flex-direction: row-reverse CSS property correctly orders items. +<div id="container"><ul> + <li><span style="color: green;">I</span><span style="color: blue;">J</span><span style="color: cyan;">K</span><span style="color: magenta;">L</span></li> + <li><span style="color: lightblue;">A</span><span style="color: turquoise;">B</span><span style="color: coral;">C</span><span style="color: violet;">D</span></li> + <li><span style="color: red;">E</span><span style="color: purple;">F</span><span style="color: grey;">G</span><span style="color: bisque;">H</span></li> +</ul></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-003.html index bca78d7..5c63fd82 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-003.html
@@ -22,6 +22,7 @@ } #item2 { width: 50px; + margin: 0 10px; background: green; } #item3 { @@ -36,14 +37,14 @@ <script> function runTest() { let before = { - item1: {"data-offset-x": 30 }, - item2: {"data-offset-x": 0 }, - item3: {"data-offset-x": 20 } + item1: {"data-offset-x": 10 }, + item2: {"data-offset-x": 10 }, + item3: {"data-offset-x": 10 } }; let after = { - item1: {"data-offset-x": 10 }, - item2: {"data-offset-x": 50 }, + item1: {"data-offset-x": 0 }, + item2: {"data-offset-x": 40 }, item3: {"data-offset-x": 0 } };
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-004.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-004.html index 3064f42..c7d0046 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-alignment-style-changes-004.html
@@ -22,6 +22,7 @@ } #item2 { width: 50px; + margin: 0 10px; background: green; justify-self: center; } @@ -37,15 +38,15 @@ <script> function runTest() { let before = { - item1: {"data-offset-x": 10 }, + item1: {"data-offset-x": 0 }, item2: {"data-offset-x": 25 }, - item3: {"data-offset-x": 0 } + item3: {"data-offset-x": 0 } }; let after = { - item1: {"data-offset-x": 30 }, - item2: {"data-offset-x": 0 }, - item3: {"data-offset-x": 20 } + item1: {"data-offset-x": 10 }, + item2: {"data-offset-x": 10 }, + item3: {"data-offset-x": 10 } }; evaluateStyleChangeMultiple("before", before);
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-cols-relsize.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-cols-relsize.html index 1bfb2b5..16cf9a4 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-cols-relsize.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-cols-relsize.html
@@ -1,8 +1,21 @@ <!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> <link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#frames-and-framesets"> <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1116832"> -<link rel="match" href="reference/green-ref.html"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1353277"> +<script> +window.onload = () => { + test(() => { + const frameSet = document.querySelector('frameset'); + const frames = document.querySelectorAll('frame'); + assert_less_than(frames[0].offsetWidth, frameSet.offsetWidth); + assert_greater_than_equal(frames[0].offsetWidth, 0); + assert_greater_than_equal(frames[1].offsetWidth, 0); + }, 'A large relative value should not produce weird sizes.'); +}; +</script> <frameset cols="4294967227*,*" frameborder="0"> <frame src="resources/green.html"> <frame src="resources/red.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-rows-relsize.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-rows-relsize.html index 7fd29f6..24f34f5 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-rows-relsize.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-frameset-and-frame-elements/large-rows-relsize.html
@@ -1,8 +1,21 @@ <!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> <link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#frames-and-framesets"> <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1116832"> -<link rel="match" href="reference/green-ref.html"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1353277"> +<script> +window.onload = () => { + test(() => { + const frameSet = document.querySelector('frameset'); + const frames = document.querySelectorAll('frame'); + assert_less_than(frames[0].offsetHeight, frameSet.offsetHeight); + assert_greater_than_equal(frames[0].offsetHeight, 0); + assert_greater_than_equal(frames[1].offsetHeight, 0); + }, 'A large relative value should not produce weird sizes.'); +}; +</script> <frameset rows="4294967227*,*" frameborder="0"> <frame src="resources/green.html"> <frame src="resources/red.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/syntax/parsing/inhead-noscript-head.html b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/inhead-noscript-head.html new file mode 100644 index 0000000..bcf42d4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/inhead-noscript-head.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test that when the scripting flag is disabled, a head start tag in "in head noscript" mode is ignored</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<body> +<script> +promise_test(async function(t) { + let iframe = document.createElement("iframe"); + iframe.srcdoc = "<!DOCTYPE html><head><noscript><head><style></style>"; + iframe.sandbox = "allow-same-origin"; + let loaded = new Promise(resolve => iframe.onload = resolve); + document.body.append(iframe); + await loaded; + assert_equals(String(iframe.contentDocument.querySelector("noscript").firstChild), "[object HTMLStyleElement]"); +}, "When the scripting flag is disabled, a head start tag in \"in head noscript\" mode should be ignored"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-accept-header.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/accept-header.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-accept-header.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/accept-header.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-coep.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/coep.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-coep.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/coep.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-coep.https.tentative.html.headers b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/coep.https.tentative.html.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-coep.https.tentative.html.headers rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/coep.https.tentative.html.headers
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-corp.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/corp.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-corp.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/corp.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-credentials.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/credentials.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-credentials.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/credentials.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-allowed.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-allowed.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-allowed.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-allowed.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-blocked.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-blocked.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-blocked.https.tentative.html.sub.headers b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative.html.sub.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-csp-blocked.https.tentative.html.sub.headers rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative.html.sub.headers
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-element-removal.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/element-removal.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-element-removal.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/element-removal.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-invalid-json.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/invalid-json.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-invalid-json.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/invalid-json.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-nested-bundle.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/nested-bundle.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-nested-bundle.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/nested-bundle.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-network-error.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/network-error.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-network-error.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/network-error.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-not-found.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/not-found.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-not-found.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/not-found.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-path-restriction.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/path-restriction.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-path-restriction.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/path-restriction.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-in-web-bundle-cors.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-in-web-bundle-cors.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-in-web-bundle-cors.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-in-web-bundle-cors.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-in-web-bundle.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-in-web-bundle.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-in-web-bundle.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-in-web-bundle.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-resources.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-resources.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-resources.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-resources.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-scopes.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-scopes.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-scopes.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-scopes.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-static-element.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-static-element.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-static-element.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-static-element.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-with-base.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-with-base.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-relative-url-with-base.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/relative-url-with-base.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/request-destination.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/request-destination.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-resource-timing-attributes-consistent.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/resource-timing-attributes-consistent.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-resource-timing-attributes-consistent.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/resource-timing-attributes-consistent.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-resource-timing.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/resource-timing.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-resource-timing.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/resource-timing.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-service-worker-controlled.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/service-worker-controlled.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-service-worker-controlled.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/service-worker-controlled.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-static-element-with-base.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/static-element-with-base.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-static-element-with-base.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/static-element-with-base.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-static-element.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/static-element.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-static-element.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/static-element.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-subframe-from-web-bundle.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/subframe-from-web-bundle.https.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-subframe-from-web-bundle.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/subframe-from-web-bundle.https.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-subresource-load.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/subresource-load.https.tentative.sub.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-subresource-load.https.tentative.sub.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/subresource-load.https.tentative.sub.html
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-supports-webbundle.https.tentative.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/supports-webbundle.https.tentative.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-supports-webbundle.https.tentative.html rename to third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/supports-webbundle.https.tentative.html index b211a66..9beae28 100644 --- a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-supports-webbundle.https.tentative.html +++ b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/supports-webbundle.https.tentative.html
@@ -1,5 +1,4 @@ -<DOCTYPE html> -<html> +<!DOCTYPE html> <title>HTMLScriptElement.supports webbundle</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/syntax/parsing/inhead-noscript-head-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/syntax/parsing/inhead-noscript-head-expected.txt new file mode 100644 index 0000000..06b6ec1 --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/syntax/parsing/inhead-noscript-head-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL When the scripting flag is disabled, a head start tag in "in head noscript" mode should be ignored assert_equals: expected "[object HTMLStyleElement]" but got "null" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-apply-to-cross-site-only/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-apply-to-cross-site-only/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt index 62844562b3..975d361 100644 --- a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-apply-to-cross-site-only/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt +++ b/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-apply-to-cross-site-only/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL Async Script Execution Order Uncaught Error: assert_equals: expected "async_preload;async_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded" but got "async_preload;async_blocking_render;async;inline1;external;inline2;defer;DOMContentLoaded;async" +FAIL Async Script Execution Order Uncaught Error: assert_equals: expected "async_preload_or_blocking_render;async_preload_or_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded" but got "async_preload_or_blocking_render;async_preload_or_blocking_render;async;inline1;external;inline2;defer;DOMContentLoaded;async" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt index 16feb391..94ead63 100644 --- a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt +++ b/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL Async Script Execution Order Uncaught Error: assert_equals: expected "async_preload;async_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded" but got "async_preload;async_blocking_render;inline1;external;inline2;defer;DOMContentLoaded;async;async" +FAIL Async Script Execution Order Uncaught Error: assert_equals: expected "async_preload_or_blocking_render;async_preload_or_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded" but got "async_preload_or_blocking_render;async_preload_or_blocking_render;inline1;external;inline2;defer;DOMContentLoaded;async;async" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-first-paint-or-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-first-paint-or-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt deleted file mode 100644 index 16feb391..0000000 --- a/third_party/blink/web_tests/platform/generic/virtual/async-script-scheduling-first-paint-or-finished-parsing/wpt_internal/async-script-scheduling/execution-order.sub-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Async Script Execution Order Uncaught Error: assert_equals: expected "async_preload;async_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded" but got "async_preload;async_blocking_render;inline1;external;inline2;defer;DOMContentLoaded;async;async" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative-expected.txt rename to third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/wbn-from-network/external/wpt/web-bundle/subresource-loading/reuse-web-bundle-resource.https.tentative-expected.txt
diff --git a/third_party/blink/web_tests/svg/foreignObject/dynamic-height.html b/third_party/blink/web_tests/svg/foreignObject/dynamic-height.html new file mode 100644 index 0000000..fa4a7bbb --- /dev/null +++ b/third_party/blink/web_tests/svg/foreignObject/dynamic-height.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<meta charset='utf-8'> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<body> +<svg xmlns="http://www.w3.org/2000/svg" width="800" height="480"> +<foreignObject x="0" y="0" width="300"> +<div xmlns="http://www.w3.org/1999/xhtml"> +Lorem ipsum dolor sit amet, consectetur adipiscing elit, +sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +</div> +</foreignObject> +</svg> +<script> +test(() => { + const foreign = document.querySelector('foreignObject'); + const previousHeight = foreign.clientHeight; + foreign.setAttribute('height', 100); + assert_not_equals(foreign.clientHeight, previousHeight); +}, 'crbug.com/1352482; foreignObject should have the correct height after a dynamic change of height attribute.'); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/async-script-scheduling/execution-order.sub.html b/third_party/blink/web_tests/wpt_internal/async-script-scheduling/execution-order.sub.html index c630de3..62c7c38 100644 --- a/third_party/blink/web_tests/wpt_internal/async-script-scheduling/execution-order.sub.html +++ b/third_party/blink/web_tests/wpt_internal/async-script-scheduling/execution-order.sub.html
@@ -3,10 +3,15 @@ <title>Async Script Execution Order</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> - <link rel="preload" as="script" href="resources/script.sub.js?label=async_preload"> - <script async blocking=render src="resources/script.sub.js?pipe=trickle(d1)&label=async_blocking_render"></script> + <!-- Note: The following two async scripts are named as "label=async_preload_or_blocking_render". + These are intentionally named with the same name because the ordering of these two scripts are not guaranteed. --> + <link rel="preload" as="script" href="resources/script.sub.js?pipe=trickle(d1)&label=async_preload_or_blocking_render&1"> + <script async blocking=render src="resources/script.sub.js?pipe=trickle(d1)&label=async_preload_or_blocking_render&2"></script> </head> <body> + <h1> + This is the first (contentful) paint. + </h1> <!-- Note: This test serves mainly to document the current scheduling behavior of async scripts with respect to other scripts and events in the loading pipeline. It does not represent the "ideal" or "desired" behavior, so @@ -20,22 +25,19 @@ } window.onload = e => { const actualOrder = logs.join(";"); - const expectedOrder = "async_preload;async_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded"; + const expectedOrder = "async_preload_or_blocking_render;async_preload_or_blocking_render;async;async;inline1;external;inline2;defer;DOMContentLoaded"; assert_equals(actualOrder, expectedOrder); done(); }; document.addEventListener('DOMContentLoaded', e => { logScript('DOMContentLoaded'); }); </script> - <script defer src="resources/script.sub.js?label=defer"></script> - <!-- Note: The following two async scripts are named as - "label=async". These are intentionally named with the same name - because the ordering of these two scripts are not guaranteed even - if different trickle values are specified. --> + <!-- Note: The following two async scripts are named as "label=async". These are intentionally named with the same name + because the ordering of these two scripts are not guaranteed even if different trickle values are specified. --> <script async src="resources/script.sub.js?pipe=trickle(d2)&label=async"></script> <!-- cross site async script --> <script async src="http://{{hosts[alt][]}}:{{ports[http][0]}}/wpt_internal/async-script-scheduling/resources/script.sub.js?pipe=trickle(d2)&label=async"></script> - <script async src="resources/script.sub.js?label=async_preload"></script> + <script async src="resources/script.sub.js?pipe=trickle(d1)&label=async_preload_or_blocking_render&1"></script> <link rel=stylesheet href=resources/main.css?pipe=trickle(d3)> <script> logScript('inline1'); @@ -45,7 +47,4 @@ <script> logScript('inline2'); </script> - <h1> - This is the first (contentful) paint. - </h1> </body>
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 6b5b4f2..8aab7973 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: e5c24b8b8ac4b093ccf741d1af8e3ecd896a1eda +Version: 0849bc7598e56dc68a6ee67976ad8250f5e87e40 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn index e803491..fb53eb2 100644 --- a/third_party/protobuf/BUILD.gn +++ b/third_party/protobuf/BUILD.gn
@@ -202,7 +202,7 @@ "//third_party/cast_core/public/src/build/chromium:cast_core_grpc_generator", # Used for testing protobuf generation. - "//components/services/screen_ai:unit_tests", + "//components/services/screen_ai:test_support", ] # TODO(crbug.com/1338164): This ends up linking two copies of
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.h b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.h index a047265..0ac89e1 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.h +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.h
@@ -198,6 +198,12 @@ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_extraCode1( /* [retval][out] */ LONG *__MIDL__IUpdateState0008) = 0; + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerText( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerCommandLine( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010) = 0; + }; @@ -267,6 +273,16 @@ IUpdateState * This, /* [retval][out] */ LONG *__MIDL__IUpdateState0008); + DECLSPEC_XFGVIRT(IUpdateState, get_installerText) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerText )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009); + + DECLSPEC_XFGVIRT(IUpdateState, get_installerCommandLine) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerCommandLine )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010); + END_INTERFACE } IUpdateStateVtbl; @@ -317,6 +333,12 @@ #define IUpdateState_get_extraCode1(This,__MIDL__IUpdateState0008) \ ( (This)->lpVtbl -> get_extraCode1(This,__MIDL__IUpdateState0008) ) +#define IUpdateState_get_installerText(This,__MIDL__IUpdateState0009) \ + ( (This)->lpVtbl -> get_installerText(This,__MIDL__IUpdateState0009) ) + +#define IUpdateState_get_installerCommandLine(This,__MIDL__IUpdateState0010) \ + ( (This)->lpVtbl -> get_installerCommandLine(This,__MIDL__IUpdateState0010) ) + #endif /* COBJMACROS */
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.tlb b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.tlb index 3455bbf..feff6f8 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.tlb +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl.tlb Binary files differ
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl_p.c b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl_p.c index 1cbb4c1..8315fcf1 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl_p.c +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/arm64/updater_idl_p.c
@@ -47,7 +47,7 @@ #include "updater_idl.h" #define TYPE_FORMAT_STRING_SIZE 145 -#define PROC_FORMAT_STRING_SIZE 1043 +#define PROC_FORMAT_STRING_SIZE 1127 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 1 @@ -525,23 +525,20 @@ /* 376 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure Run */ - - - /* Procedure Run */ + /* Procedure get_installerText */ /* 378 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 380 */ NdrFcLong( 0x0 ), /* 0 */ -/* 384 */ NdrFcShort( 0x3 ), /* 3 */ +/* 384 */ NdrFcShort( 0xc ), /* 12 */ /* 386 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 388 */ NdrFcShort( 0x8 ), /* 8 */ +/* 388 */ NdrFcShort( 0x0 ), /* 0 */ /* 390 */ NdrFcShort( 0x8 ), /* 8 */ -/* 392 */ 0x44, /* Oi2 Flags: has return, has ext, */ +/* 392 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 394 */ 0xe, /* 14 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 396 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 396 */ NdrFcShort( 0x1 ), /* 1 */ /* 398 */ NdrFcShort( 0x0 ), /* 0 */ /* 400 */ NdrFcShort( 0x0 ), /* 0 */ /* 402 */ NdrFcShort( 0x2 ), /* 2 */ @@ -550,18 +547,11 @@ /* 406 */ 0x81, /* 129 */ 0x0, /* 0 */ - /* Parameter result */ + /* Parameter __MIDL__IUpdateState0009 */ - - /* Parameter status_code */ - -/* 408 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 408 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 410 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 412 */ 0x8, /* FC_LONG */ - 0x0, /* 0 */ - - /* Return value */ - +/* 412 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -570,20 +560,20 @@ /* 418 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnStateChange */ + /* Procedure get_installerCommandLine */ /* 420 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 422 */ NdrFcLong( 0x0 ), /* 0 */ -/* 426 */ NdrFcShort( 0x3 ), /* 3 */ +/* 426 */ NdrFcShort( 0xd ), /* 13 */ /* 428 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ /* 430 */ NdrFcShort( 0x0 ), /* 0 */ /* 432 */ NdrFcShort( 0x8 ), /* 8 */ -/* 434 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 434 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 436 */ 0xe, /* 14 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 438 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 438 */ NdrFcShort( 0x1 ), /* 1 */ /* 440 */ NdrFcShort( 0x0 ), /* 0 */ /* 442 */ NdrFcShort( 0x0 ), /* 0 */ /* 444 */ NdrFcShort( 0x2 ), /* 2 */ @@ -592,11 +582,11 @@ /* 448 */ 0x81, /* 129 */ 0x0, /* 0 */ - /* Parameter update_state */ + /* Parameter __MIDL__IUpdateState0010 */ -/* 450 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 450 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 452 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 454 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ +/* 454 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -605,16 +595,19 @@ /* 460 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnComplete */ + /* Procedure Run */ + + + /* Procedure Run */ /* 462 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 464 */ NdrFcLong( 0x0 ), /* 0 */ -/* 468 */ NdrFcShort( 0x4 ), /* 4 */ +/* 468 */ NdrFcShort( 0x3 ), /* 3 */ /* 470 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 472 */ NdrFcShort( 0x0 ), /* 0 */ +/* 472 */ NdrFcShort( 0x8 ), /* 8 */ /* 474 */ NdrFcShort( 0x8 ), /* 8 */ -/* 476 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 476 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x2, /* 2 */ /* 478 */ 0xe, /* 14 */ 0x1, /* Ext Flags: new corr desc, */ @@ -627,11 +620,18 @@ /* 490 */ 0x81, /* 129 */ 0x0, /* 0 */ - /* Parameter status */ + /* Parameter result */ -/* 492 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ + + /* Parameter status_code */ + +/* 492 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ /* 494 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 496 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ +/* 496 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + /* Return value */ @@ -640,7 +640,7 @@ /* 502 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure GetVersion */ + /* Procedure OnStateChange */ /* 504 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -649,11 +649,11 @@ /* 512 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ /* 514 */ NdrFcShort( 0x0 ), /* 0 */ /* 516 */ NdrFcShort( 0x8 ), /* 8 */ -/* 518 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ +/* 518 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ /* 520 */ 0xe, /* 14 */ - 0x3, /* Ext Flags: new corr desc, clt corr check, */ -/* 522 */ NdrFcShort( 0x1 ), /* 1 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 522 */ NdrFcShort( 0x0 ), /* 0 */ /* 524 */ NdrFcShort( 0x0 ), /* 0 */ /* 526 */ NdrFcShort( 0x0 ), /* 0 */ /* 528 */ NdrFcShort( 0x2 ), /* 2 */ @@ -662,11 +662,11 @@ /* 532 */ 0x81, /* 129 */ 0x0, /* 0 */ - /* Parameter version */ + /* Parameter update_state */ -/* 534 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 534 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 536 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 538 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ +/* 538 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ /* Return value */ @@ -675,7 +675,7 @@ /* 544 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure CheckForUpdate */ + /* Procedure OnComplete */ /* 546 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -697,11 +697,11 @@ /* 574 */ 0x81, /* 129 */ 0x0, /* 0 */ - /* Parameter app_id */ + /* Parameter status */ -/* 576 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 576 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 578 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 580 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 580 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Return value */ @@ -710,412 +710,482 @@ /* 586 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure RegisterApp */ + /* Procedure GetVersion */ /* 588 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 590 */ NdrFcLong( 0x0 ), /* 0 */ -/* 594 */ NdrFcShort( 0x5 ), /* 5 */ -/* 596 */ NdrFcShort( 0x48 ), /* ARM64 Stack size/offset = 72 */ +/* 594 */ NdrFcShort( 0x3 ), /* 3 */ +/* 596 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ /* 598 */ NdrFcShort( 0x0 ), /* 0 */ /* 600 */ NdrFcShort( 0x8 ), /* 8 */ -/* 602 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x8, /* 8 */ -/* 604 */ 0x14, /* 20 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 606 */ NdrFcShort( 0x0 ), /* 0 */ +/* 602 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 604 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 606 */ NdrFcShort( 0x1 ), /* 1 */ /* 608 */ NdrFcShort( 0x0 ), /* 0 */ /* 610 */ NdrFcShort( 0x0 ), /* 0 */ -/* 612 */ NdrFcShort( 0x8 ), /* 8 */ -/* 614 */ 0x8, /* 8 */ +/* 612 */ NdrFcShort( 0x2 ), /* 2 */ +/* 614 */ 0x2, /* 2 */ 0x80, /* 128 */ /* 616 */ 0x81, /* 129 */ - 0x82, /* 130 */ -/* 618 */ 0x83, /* 131 */ - 0x84, /* 132 */ -/* 620 */ 0x85, /* 133 */ - 0x86, /* 134 */ -/* 622 */ 0x87, /* 135 */ + 0x0, /* 0 */ + + /* Parameter version */ + +/* 618 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 620 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 622 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ + + /* Return value */ + +/* 624 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 626 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 628 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure CheckForUpdate */ + +/* 630 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 632 */ NdrFcLong( 0x0 ), /* 0 */ +/* 636 */ NdrFcShort( 0x4 ), /* 4 */ +/* 638 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 640 */ NdrFcShort( 0x0 ), /* 0 */ +/* 642 */ NdrFcShort( 0x8 ), /* 8 */ +/* 644 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 646 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 648 */ NdrFcShort( 0x0 ), /* 0 */ +/* 650 */ NdrFcShort( 0x0 ), /* 0 */ +/* 652 */ NdrFcShort( 0x0 ), /* 0 */ +/* 654 */ NdrFcShort( 0x2 ), /* 2 */ +/* 656 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 658 */ 0x81, /* 129 */ 0x0, /* 0 */ /* Parameter app_id */ -/* 624 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 626 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 628 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_code */ - -/* 630 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 632 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 634 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_path */ - -/* 636 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 638 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 640 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter tag */ - -/* 642 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 644 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ -/* 646 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter version */ - -/* 648 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 650 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ -/* 652 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter existence_checker_path */ - -/* 654 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 656 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ -/* 658 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter callback */ - -/* 660 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 662 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ -/* 664 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ +/* 660 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 662 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 664 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Return value */ /* 666 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 668 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ +/* 668 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ /* 670 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure RunPeriodicTasks */ + /* Procedure RegisterApp */ /* 672 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 674 */ NdrFcLong( 0x0 ), /* 0 */ -/* 678 */ NdrFcShort( 0x6 ), /* 6 */ -/* 680 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 678 */ NdrFcShort( 0x5 ), /* 5 */ +/* 680 */ NdrFcShort( 0x48 ), /* ARM64 Stack size/offset = 72 */ /* 682 */ NdrFcShort( 0x0 ), /* 0 */ /* 684 */ NdrFcShort( 0x8 ), /* 8 */ /* 686 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x2, /* 2 */ -/* 688 */ 0xe, /* 14 */ + 0x8, /* 8 */ +/* 688 */ 0x14, /* 20 */ 0x1, /* Ext Flags: new corr desc, */ /* 690 */ NdrFcShort( 0x0 ), /* 0 */ /* 692 */ NdrFcShort( 0x0 ), /* 0 */ /* 694 */ NdrFcShort( 0x0 ), /* 0 */ -/* 696 */ NdrFcShort( 0x2 ), /* 2 */ -/* 698 */ 0x2, /* 2 */ +/* 696 */ NdrFcShort( 0x8 ), /* 8 */ +/* 698 */ 0x8, /* 8 */ 0x80, /* 128 */ /* 700 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 702 */ 0x83, /* 131 */ + 0x84, /* 132 */ +/* 704 */ 0x85, /* 133 */ + 0x86, /* 134 */ +/* 706 */ 0x87, /* 135 */ + 0x0, /* 0 */ + + /* Parameter app_id */ + +/* 708 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 710 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 712 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_code */ + +/* 714 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 716 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 718 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_path */ + +/* 720 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 722 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 724 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter tag */ + +/* 726 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 728 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ +/* 730 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter version */ + +/* 732 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 734 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ +/* 736 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter existence_checker_path */ + +/* 738 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 740 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ +/* 742 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter callback */ + +/* 744 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 746 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ +/* 748 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 750 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 752 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ +/* 754 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure RunPeriodicTasks */ + +/* 756 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 758 */ NdrFcLong( 0x0 ), /* 0 */ +/* 762 */ NdrFcShort( 0x6 ), /* 6 */ +/* 764 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 766 */ NdrFcShort( 0x0 ), /* 0 */ +/* 768 */ NdrFcShort( 0x8 ), /* 8 */ +/* 770 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 772 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 774 */ NdrFcShort( 0x0 ), /* 0 */ +/* 776 */ NdrFcShort( 0x0 ), /* 0 */ +/* 778 */ NdrFcShort( 0x0 ), /* 0 */ +/* 780 */ NdrFcShort( 0x2 ), /* 2 */ +/* 782 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 784 */ 0x81, /* 129 */ 0x0, /* 0 */ /* Parameter callback */ -/* 702 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 704 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 706 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ +/* 786 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 788 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 790 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ /* Return value */ -/* 708 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 710 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 712 */ 0x8, /* FC_LONG */ +/* 792 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 794 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 796 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Update */ -/* 714 */ 0x33, /* FC_AUTO_HANDLE */ +/* 798 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 716 */ NdrFcLong( 0x0 ), /* 0 */ -/* 720 */ NdrFcShort( 0x7 ), /* 7 */ -/* 722 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ -/* 724 */ NdrFcShort( 0x10 ), /* 16 */ -/* 726 */ NdrFcShort( 0x8 ), /* 8 */ -/* 728 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 800 */ NdrFcLong( 0x0 ), /* 0 */ +/* 804 */ NdrFcShort( 0x7 ), /* 7 */ +/* 806 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ +/* 808 */ NdrFcShort( 0x10 ), /* 16 */ +/* 810 */ NdrFcShort( 0x8 ), /* 8 */ +/* 812 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x6, /* 6 */ -/* 730 */ 0x12, /* 18 */ +/* 814 */ 0x12, /* 18 */ 0x1, /* Ext Flags: new corr desc, */ -/* 732 */ NdrFcShort( 0x0 ), /* 0 */ -/* 734 */ NdrFcShort( 0x0 ), /* 0 */ -/* 736 */ NdrFcShort( 0x0 ), /* 0 */ -/* 738 */ NdrFcShort( 0x6 ), /* 6 */ -/* 740 */ 0x6, /* 6 */ +/* 816 */ NdrFcShort( 0x0 ), /* 0 */ +/* 818 */ NdrFcShort( 0x0 ), /* 0 */ +/* 820 */ NdrFcShort( 0x0 ), /* 0 */ +/* 822 */ NdrFcShort( 0x6 ), /* 6 */ +/* 824 */ 0x6, /* 6 */ 0x80, /* 128 */ -/* 742 */ 0x81, /* 129 */ +/* 826 */ 0x81, /* 129 */ 0x82, /* 130 */ -/* 744 */ 0x83, /* 131 */ +/* 828 */ 0x83, /* 131 */ 0x84, /* 132 */ -/* 746 */ 0x85, /* 133 */ +/* 830 */ 0x85, /* 133 */ 0x0, /* 0 */ /* Parameter app_id */ -/* 748 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 750 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 752 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 832 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 834 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 836 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 754 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 756 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 758 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 838 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 840 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 842 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 760 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 762 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 764 */ 0x8, /* FC_LONG */ +/* 844 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 846 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 848 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter same_version_update_allowed */ -/* 766 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 768 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ -/* 770 */ 0x8, /* FC_LONG */ +/* 850 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 852 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ +/* 854 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 772 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 774 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ -/* 776 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 856 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 858 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ +/* 860 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 778 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 780 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ -/* 782 */ 0x8, /* FC_LONG */ +/* 862 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 864 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ +/* 866 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure UpdateAll */ -/* 784 */ 0x33, /* FC_AUTO_HANDLE */ +/* 868 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 786 */ NdrFcLong( 0x0 ), /* 0 */ -/* 790 */ NdrFcShort( 0x8 ), /* 8 */ -/* 792 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 794 */ NdrFcShort( 0x0 ), /* 0 */ -/* 796 */ NdrFcShort( 0x8 ), /* 8 */ -/* 798 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 870 */ NdrFcLong( 0x0 ), /* 0 */ +/* 874 */ NdrFcShort( 0x8 ), /* 8 */ +/* 876 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 878 */ NdrFcShort( 0x0 ), /* 0 */ +/* 880 */ NdrFcShort( 0x8 ), /* 8 */ +/* 882 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 800 */ 0xe, /* 14 */ +/* 884 */ 0xe, /* 14 */ 0x1, /* Ext Flags: new corr desc, */ -/* 802 */ NdrFcShort( 0x0 ), /* 0 */ -/* 804 */ NdrFcShort( 0x0 ), /* 0 */ -/* 806 */ NdrFcShort( 0x0 ), /* 0 */ -/* 808 */ NdrFcShort( 0x2 ), /* 2 */ -/* 810 */ 0x2, /* 2 */ +/* 886 */ NdrFcShort( 0x0 ), /* 0 */ +/* 888 */ NdrFcShort( 0x0 ), /* 0 */ +/* 890 */ NdrFcShort( 0x0 ), /* 0 */ +/* 892 */ NdrFcShort( 0x2 ), /* 2 */ +/* 894 */ 0x2, /* 2 */ 0x80, /* 128 */ -/* 812 */ 0x81, /* 129 */ +/* 896 */ 0x81, /* 129 */ 0x0, /* 0 */ /* Parameter observer */ -/* 814 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 816 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 818 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 898 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 900 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 902 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 820 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 822 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 824 */ 0x8, /* FC_LONG */ +/* 904 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 906 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 908 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Install */ -/* 826 */ 0x33, /* FC_AUTO_HANDLE */ +/* 910 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 828 */ NdrFcLong( 0x0 ), /* 0 */ -/* 832 */ NdrFcShort( 0x9 ), /* 9 */ -/* 834 */ NdrFcShort( 0x58 ), /* ARM64 Stack size/offset = 88 */ -/* 836 */ NdrFcShort( 0x8 ), /* 8 */ -/* 838 */ NdrFcShort( 0x8 ), /* 8 */ -/* 840 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 912 */ NdrFcLong( 0x0 ), /* 0 */ +/* 916 */ NdrFcShort( 0x9 ), /* 9 */ +/* 918 */ NdrFcShort( 0x58 ), /* ARM64 Stack size/offset = 88 */ +/* 920 */ NdrFcShort( 0x8 ), /* 8 */ +/* 922 */ NdrFcShort( 0x8 ), /* 8 */ +/* 924 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0xa, /* 10 */ -/* 842 */ 0x16, /* 22 */ +/* 926 */ 0x16, /* 22 */ 0x1, /* Ext Flags: new corr desc, */ -/* 844 */ NdrFcShort( 0x0 ), /* 0 */ -/* 846 */ NdrFcShort( 0x0 ), /* 0 */ -/* 848 */ NdrFcShort( 0x0 ), /* 0 */ -/* 850 */ NdrFcShort( 0xa ), /* 10 */ -/* 852 */ 0xa, /* 10 */ +/* 928 */ NdrFcShort( 0x0 ), /* 0 */ +/* 930 */ NdrFcShort( 0x0 ), /* 0 */ +/* 932 */ NdrFcShort( 0x0 ), /* 0 */ +/* 934 */ NdrFcShort( 0xa ), /* 10 */ +/* 936 */ 0xa, /* 10 */ 0x80, /* 128 */ -/* 854 */ 0x81, /* 129 */ +/* 938 */ 0x81, /* 129 */ 0x82, /* 130 */ -/* 856 */ 0x83, /* 131 */ +/* 940 */ 0x83, /* 131 */ 0x84, /* 132 */ -/* 858 */ 0x85, /* 133 */ +/* 942 */ 0x85, /* 133 */ 0x86, /* 134 */ -/* 860 */ 0x87, /* 135 */ +/* 944 */ 0x87, /* 135 */ 0xf8, /* 248 */ -/* 862 */ 0xf8, /* 248 */ +/* 946 */ 0xf8, /* 248 */ 0x0, /* 0 */ /* Parameter app_id */ -/* 864 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 866 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 868 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 948 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 950 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 952 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_code */ -/* 870 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 872 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 874 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 954 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 956 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 958 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_path */ -/* 876 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 878 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 880 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 960 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 962 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 964 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter tag */ -/* 882 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 884 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ -/* 886 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 966 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 968 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ +/* 970 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter version */ -/* 888 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 890 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ -/* 892 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 972 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 974 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ +/* 976 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter existence_checker_path */ -/* 894 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 896 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ -/* 898 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 978 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 980 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ +/* 982 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 900 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 902 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ -/* 904 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 984 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 986 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ +/* 988 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 906 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 908 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ -/* 910 */ 0x8, /* FC_LONG */ +/* 990 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 992 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ +/* 994 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 912 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 914 */ NdrFcShort( 0x48 ), /* ARM64 Stack size/offset = 72 */ -/* 916 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 996 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 998 */ NdrFcShort( 0x48 ), /* ARM64 Stack size/offset = 72 */ +/* 1000 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 918 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 920 */ NdrFcShort( 0x50 ), /* ARM64 Stack size/offset = 80 */ -/* 922 */ 0x8, /* FC_LONG */ +/* 1002 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1004 */ NdrFcShort( 0x50 ), /* ARM64 Stack size/offset = 80 */ +/* 1006 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure CancelInstalls */ -/* 924 */ 0x33, /* FC_AUTO_HANDLE */ +/* 1008 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 926 */ NdrFcLong( 0x0 ), /* 0 */ -/* 930 */ NdrFcShort( 0xa ), /* 10 */ -/* 932 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 934 */ NdrFcShort( 0x0 ), /* 0 */ -/* 936 */ NdrFcShort( 0x8 ), /* 8 */ -/* 938 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 1010 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1014 */ NdrFcShort( 0xa ), /* 10 */ +/* 1016 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 1018 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1020 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1022 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 940 */ 0xe, /* 14 */ +/* 1024 */ 0xe, /* 14 */ 0x1, /* Ext Flags: new corr desc, */ -/* 942 */ NdrFcShort( 0x0 ), /* 0 */ -/* 944 */ NdrFcShort( 0x0 ), /* 0 */ -/* 946 */ NdrFcShort( 0x0 ), /* 0 */ -/* 948 */ NdrFcShort( 0x2 ), /* 2 */ -/* 950 */ 0x2, /* 2 */ +/* 1026 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1028 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1030 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1032 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1034 */ 0x2, /* 2 */ 0x80, /* 128 */ -/* 952 */ 0x81, /* 129 */ +/* 1036 */ 0x81, /* 129 */ 0x0, /* 0 */ /* Parameter app_id */ -/* 954 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 956 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 958 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1038 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1040 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 1042 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Return value */ -/* 960 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 962 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 964 */ 0x8, /* FC_LONG */ +/* 1044 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1046 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 1048 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure RunInstaller */ -/* 966 */ 0x33, /* FC_AUTO_HANDLE */ +/* 1050 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 968 */ NdrFcLong( 0x0 ), /* 0 */ -/* 972 */ NdrFcShort( 0xb ), /* 11 */ -/* 974 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ -/* 976 */ NdrFcShort( 0x0 ), /* 0 */ -/* 978 */ NdrFcShort( 0x8 ), /* 8 */ -/* 980 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 1052 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1056 */ NdrFcShort( 0xb ), /* 11 */ +/* 1058 */ NdrFcShort( 0x40 ), /* ARM64 Stack size/offset = 64 */ +/* 1060 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1062 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1064 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x7, /* 7 */ -/* 982 */ 0x12, /* 18 */ +/* 1066 */ 0x12, /* 18 */ 0x1, /* Ext Flags: new corr desc, */ -/* 984 */ NdrFcShort( 0x0 ), /* 0 */ -/* 986 */ NdrFcShort( 0x0 ), /* 0 */ -/* 988 */ NdrFcShort( 0x0 ), /* 0 */ -/* 990 */ NdrFcShort( 0x7 ), /* 7 */ -/* 992 */ 0x7, /* 7 */ +/* 1068 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1070 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1072 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1074 */ NdrFcShort( 0x7 ), /* 7 */ +/* 1076 */ 0x7, /* 7 */ 0x80, /* 128 */ -/* 994 */ 0x81, /* 129 */ +/* 1078 */ 0x81, /* 129 */ 0x82, /* 130 */ -/* 996 */ 0x83, /* 131 */ +/* 1080 */ 0x83, /* 131 */ 0x84, /* 132 */ -/* 998 */ 0x85, /* 133 */ +/* 1082 */ 0x85, /* 133 */ 0x86, /* 134 */ /* Parameter app_id */ -/* 1000 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 1002 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ -/* 1004 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1084 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1086 */ NdrFcShort( 0x8 ), /* ARM64 Stack size/offset = 8 */ +/* 1088 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter installer_path */ -/* 1006 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 1008 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ -/* 1010 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1090 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1092 */ NdrFcShort( 0x10 ), /* ARM64 Stack size/offset = 16 */ +/* 1094 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_args */ -/* 1012 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 1014 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ -/* 1016 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1096 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1098 */ NdrFcShort( 0x18 ), /* ARM64 Stack size/offset = 24 */ +/* 1100 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data */ -/* 1018 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 1020 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ -/* 1022 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1102 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1104 */ NdrFcShort( 0x20 ), /* ARM64 Stack size/offset = 32 */ +/* 1106 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_settings */ -/* 1024 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 1026 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ -/* 1028 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 1108 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1110 */ NdrFcShort( 0x28 ), /* ARM64 Stack size/offset = 40 */ +/* 1112 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter observer */ -/* 1030 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 1032 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ -/* 1034 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 1114 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 1116 */ NdrFcShort( 0x30 ), /* ARM64 Stack size/offset = 48 */ +/* 1118 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 1036 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 1038 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ -/* 1040 */ 0x8, /* FC_LONG */ +/* 1120 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1122 */ NdrFcShort( 0x38 ), /* ARM64 Stack size/offset = 56 */ +/* 1124 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 @@ -1282,7 +1352,9 @@ 210, 252, 294, - 336 + 336, + 378, + 420 }; static const MIDL_STUBLESS_PROXY_INFO IUpdateState_ProxyInfo = @@ -1306,7 +1378,7 @@ 0, 0, 0}; -CINTERFACE_PROXY_VTABLE(12) _IUpdateStateProxyVtbl = +CINTERFACE_PROXY_VTABLE(14) _IUpdateStateProxyVtbl = { &IUpdateState_ProxyInfo, &IID_IUpdateState, @@ -1321,14 +1393,16 @@ (void *) (INT_PTR) -1 /* IUpdateState::get_installProgress */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCategory */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCode */ , - (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ + (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerText */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerCommandLine */ }; const CInterfaceStubVtbl _IUpdateStateStubVtbl = { &IID_IUpdateState, &IUpdateState_ServerInfo, - 12, + 14, 0, /* pure interpreted */ CStdStubBuffer_METHODS }; @@ -1340,7 +1414,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterRegisterAppCallback_FormatStringOffsetTable[] = { - 378 + 462 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterRegisterAppCallback_ProxyInfo = @@ -1442,8 +1516,8 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterObserver_FormatStringOffsetTable[] = { - 420, - 462 + 504, + 546 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterObserver_ProxyInfo = @@ -1494,7 +1568,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterCallback_FormatStringOffsetTable[] = { - 378 + 462 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterCallback_ProxyInfo = @@ -1544,15 +1618,15 @@ #pragma code_seg(".orpc") static const unsigned short IUpdater_FormatStringOffsetTable[] = { - 504, - 546, 588, + 630, 672, - 714, - 784, - 826, - 924, - 966 + 756, + 798, + 868, + 910, + 1008, + 1050 }; static const MIDL_STUBLESS_PROXY_INFO IUpdater_ProxyInfo =
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.h b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.h index ccb1dce2..72f2a7c 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.h +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.h
@@ -198,6 +198,12 @@ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_extraCode1( /* [retval][out] */ LONG *__MIDL__IUpdateState0008) = 0; + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerText( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerCommandLine( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010) = 0; + }; @@ -267,6 +273,16 @@ IUpdateState * This, /* [retval][out] */ LONG *__MIDL__IUpdateState0008); + DECLSPEC_XFGVIRT(IUpdateState, get_installerText) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerText )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009); + + DECLSPEC_XFGVIRT(IUpdateState, get_installerCommandLine) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerCommandLine )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010); + END_INTERFACE } IUpdateStateVtbl; @@ -317,6 +333,12 @@ #define IUpdateState_get_extraCode1(This,__MIDL__IUpdateState0008) \ ( (This)->lpVtbl -> get_extraCode1(This,__MIDL__IUpdateState0008) ) +#define IUpdateState_get_installerText(This,__MIDL__IUpdateState0009) \ + ( (This)->lpVtbl -> get_installerText(This,__MIDL__IUpdateState0009) ) + +#define IUpdateState_get_installerCommandLine(This,__MIDL__IUpdateState0010) \ + ( (This)->lpVtbl -> get_installerCommandLine(This,__MIDL__IUpdateState0010) ) + #endif /* COBJMACROS */
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.tlb b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.tlb index 3455bbf..feff6f8 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.tlb +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl.tlb Binary files differ
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl_p.c b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl_p.c index 7c03de9..03f2a3cb 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl_p.c +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x64/updater_idl_p.c
@@ -47,7 +47,7 @@ #include "updater_idl.h" #define TYPE_FORMAT_STRING_SIZE 145 -#define PROC_FORMAT_STRING_SIZE 937 +#define PROC_FORMAT_STRING_SIZE 1013 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 1 @@ -489,39 +489,29 @@ /* 340 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure Run */ - - - /* Procedure Run */ + /* Procedure get_installerText */ /* 342 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 344 */ NdrFcLong( 0x0 ), /* 0 */ -/* 348 */ NdrFcShort( 0x3 ), /* 3 */ +/* 348 */ NdrFcShort( 0xc ), /* 12 */ /* 350 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 352 */ NdrFcShort( 0x8 ), /* 8 */ +/* 352 */ NdrFcShort( 0x0 ), /* 0 */ /* 354 */ NdrFcShort( 0x8 ), /* 8 */ -/* 356 */ 0x44, /* Oi2 Flags: has return, has ext, */ +/* 356 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 358 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 360 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 360 */ NdrFcShort( 0x1 ), /* 1 */ /* 362 */ NdrFcShort( 0x0 ), /* 0 */ /* 364 */ NdrFcShort( 0x0 ), /* 0 */ /* 366 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter result */ + /* Parameter __MIDL__IUpdateState0009 */ - - /* Parameter status_code */ - -/* 368 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 368 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 370 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 372 */ 0x8, /* FC_LONG */ - 0x0, /* 0 */ - - /* Return value */ - +/* 372 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -530,29 +520,29 @@ /* 378 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnStateChange */ + /* Procedure get_installerCommandLine */ /* 380 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 382 */ NdrFcLong( 0x0 ), /* 0 */ -/* 386 */ NdrFcShort( 0x3 ), /* 3 */ +/* 386 */ NdrFcShort( 0xd ), /* 13 */ /* 388 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ /* 390 */ NdrFcShort( 0x0 ), /* 0 */ /* 392 */ NdrFcShort( 0x8 ), /* 8 */ -/* 394 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 394 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 396 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 398 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 398 */ NdrFcShort( 0x1 ), /* 1 */ /* 400 */ NdrFcShort( 0x0 ), /* 0 */ /* 402 */ NdrFcShort( 0x0 ), /* 0 */ /* 404 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter update_state */ + /* Parameter __MIDL__IUpdateState0010 */ -/* 406 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 406 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 408 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 410 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ +/* 410 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -561,16 +551,19 @@ /* 416 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnComplete */ + /* Procedure Run */ + + + /* Procedure Run */ /* 418 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 420 */ NdrFcLong( 0x0 ), /* 0 */ -/* 424 */ NdrFcShort( 0x4 ), /* 4 */ +/* 424 */ NdrFcShort( 0x3 ), /* 3 */ /* 426 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 428 */ NdrFcShort( 0x0 ), /* 0 */ +/* 428 */ NdrFcShort( 0x8 ), /* 8 */ /* 430 */ NdrFcShort( 0x8 ), /* 8 */ -/* 432 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 432 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x2, /* 2 */ /* 434 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ @@ -579,11 +572,18 @@ /* 440 */ NdrFcShort( 0x0 ), /* 0 */ /* 442 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter status */ + /* Parameter result */ -/* 444 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ + + /* Parameter status_code */ + +/* 444 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ /* 446 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 448 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ +/* 448 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + /* Return value */ @@ -592,7 +592,7 @@ /* 454 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure GetVersion */ + /* Procedure OnStateChange */ /* 456 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -601,20 +601,20 @@ /* 464 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ /* 466 */ NdrFcShort( 0x0 ), /* 0 */ /* 468 */ NdrFcShort( 0x8 ), /* 8 */ -/* 470 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ +/* 470 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ /* 472 */ 0xa, /* 10 */ - 0x3, /* Ext Flags: new corr desc, clt corr check, */ -/* 474 */ NdrFcShort( 0x1 ), /* 1 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 474 */ NdrFcShort( 0x0 ), /* 0 */ /* 476 */ NdrFcShort( 0x0 ), /* 0 */ /* 478 */ NdrFcShort( 0x0 ), /* 0 */ /* 480 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter version */ + /* Parameter update_state */ -/* 482 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 482 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 484 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 486 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ +/* 486 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ /* Return value */ @@ -623,7 +623,7 @@ /* 492 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure CheckForUpdate */ + /* Procedure OnComplete */ /* 494 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -641,11 +641,11 @@ /* 516 */ NdrFcShort( 0x0 ), /* 0 */ /* 518 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter app_id */ + /* Parameter status */ -/* 520 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 520 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 522 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 524 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 524 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Return value */ @@ -654,362 +654,424 @@ /* 530 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure RegisterApp */ + /* Procedure GetVersion */ /* 532 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 534 */ NdrFcLong( 0x0 ), /* 0 */ -/* 538 */ NdrFcShort( 0x5 ), /* 5 */ -/* 540 */ NdrFcShort( 0x48 ), /* X64 Stack size/offset = 72 */ +/* 538 */ NdrFcShort( 0x3 ), /* 3 */ +/* 540 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ /* 542 */ NdrFcShort( 0x0 ), /* 0 */ /* 544 */ NdrFcShort( 0x8 ), /* 8 */ -/* 546 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x8, /* 8 */ +/* 546 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ /* 548 */ 0xa, /* 10 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 550 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 550 */ NdrFcShort( 0x1 ), /* 1 */ /* 552 */ NdrFcShort( 0x0 ), /* 0 */ /* 554 */ NdrFcShort( 0x0 ), /* 0 */ /* 556 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter app_id */ - -/* 558 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 560 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 562 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_code */ - -/* 564 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 566 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 568 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_path */ - -/* 570 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 572 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 574 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter tag */ - -/* 576 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 578 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ -/* 580 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - /* Parameter version */ -/* 582 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 584 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ -/* 586 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter existence_checker_path */ - -/* 588 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 590 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ -/* 592 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter callback */ - -/* 594 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 596 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ -/* 598 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ +/* 558 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 560 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 562 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ -/* 600 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 602 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ -/* 604 */ 0x8, /* FC_LONG */ +/* 564 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 566 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 568 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure CheckForUpdate */ + +/* 570 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 572 */ NdrFcLong( 0x0 ), /* 0 */ +/* 576 */ NdrFcShort( 0x4 ), /* 4 */ +/* 578 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 580 */ NdrFcShort( 0x0 ), /* 0 */ +/* 582 */ NdrFcShort( 0x8 ), /* 8 */ +/* 584 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 586 */ 0xa, /* 10 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 588 */ NdrFcShort( 0x0 ), /* 0 */ +/* 590 */ NdrFcShort( 0x0 ), /* 0 */ +/* 592 */ NdrFcShort( 0x0 ), /* 0 */ +/* 594 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter app_id */ + +/* 596 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 598 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 600 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Return value */ + +/* 602 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 604 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 606 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure RegisterApp */ + +/* 608 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 610 */ NdrFcLong( 0x0 ), /* 0 */ +/* 614 */ NdrFcShort( 0x5 ), /* 5 */ +/* 616 */ NdrFcShort( 0x48 ), /* X64 Stack size/offset = 72 */ +/* 618 */ NdrFcShort( 0x0 ), /* 0 */ +/* 620 */ NdrFcShort( 0x8 ), /* 8 */ +/* 622 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x8, /* 8 */ +/* 624 */ 0xa, /* 10 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 626 */ NdrFcShort( 0x0 ), /* 0 */ +/* 628 */ NdrFcShort( 0x0 ), /* 0 */ +/* 630 */ NdrFcShort( 0x0 ), /* 0 */ +/* 632 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter app_id */ + +/* 634 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 636 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 638 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_code */ + +/* 640 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 642 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 644 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_path */ + +/* 646 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 648 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 650 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter tag */ + +/* 652 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 654 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ +/* 656 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter version */ + +/* 658 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 660 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ +/* 662 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter existence_checker_path */ + +/* 664 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 666 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ +/* 668 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter callback */ + +/* 670 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 672 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ +/* 674 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 676 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 678 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ +/* 680 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure RunPeriodicTasks */ -/* 606 */ 0x33, /* FC_AUTO_HANDLE */ +/* 682 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 608 */ NdrFcLong( 0x0 ), /* 0 */ -/* 612 */ NdrFcShort( 0x6 ), /* 6 */ -/* 614 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 616 */ NdrFcShort( 0x0 ), /* 0 */ -/* 618 */ NdrFcShort( 0x8 ), /* 8 */ -/* 620 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 684 */ NdrFcLong( 0x0 ), /* 0 */ +/* 688 */ NdrFcShort( 0x6 ), /* 6 */ +/* 690 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 692 */ NdrFcShort( 0x0 ), /* 0 */ +/* 694 */ NdrFcShort( 0x8 ), /* 8 */ +/* 696 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 622 */ 0xa, /* 10 */ +/* 698 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 624 */ NdrFcShort( 0x0 ), /* 0 */ -/* 626 */ NdrFcShort( 0x0 ), /* 0 */ -/* 628 */ NdrFcShort( 0x0 ), /* 0 */ -/* 630 */ NdrFcShort( 0x0 ), /* 0 */ +/* 700 */ NdrFcShort( 0x0 ), /* 0 */ +/* 702 */ NdrFcShort( 0x0 ), /* 0 */ +/* 704 */ NdrFcShort( 0x0 ), /* 0 */ +/* 706 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter callback */ -/* 632 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 634 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 636 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ +/* 708 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 710 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 712 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ /* Return value */ -/* 638 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 640 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 642 */ 0x8, /* FC_LONG */ +/* 714 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 716 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 718 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Update */ -/* 644 */ 0x33, /* FC_AUTO_HANDLE */ +/* 720 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 646 */ NdrFcLong( 0x0 ), /* 0 */ -/* 650 */ NdrFcShort( 0x7 ), /* 7 */ -/* 652 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ -/* 654 */ NdrFcShort( 0x10 ), /* 16 */ -/* 656 */ NdrFcShort( 0x8 ), /* 8 */ -/* 658 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 722 */ NdrFcLong( 0x0 ), /* 0 */ +/* 726 */ NdrFcShort( 0x7 ), /* 7 */ +/* 728 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ +/* 730 */ NdrFcShort( 0x10 ), /* 16 */ +/* 732 */ NdrFcShort( 0x8 ), /* 8 */ +/* 734 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x6, /* 6 */ -/* 660 */ 0xa, /* 10 */ +/* 736 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 662 */ NdrFcShort( 0x0 ), /* 0 */ -/* 664 */ NdrFcShort( 0x0 ), /* 0 */ -/* 666 */ NdrFcShort( 0x0 ), /* 0 */ -/* 668 */ NdrFcShort( 0x0 ), /* 0 */ +/* 738 */ NdrFcShort( 0x0 ), /* 0 */ +/* 740 */ NdrFcShort( 0x0 ), /* 0 */ +/* 742 */ NdrFcShort( 0x0 ), /* 0 */ +/* 744 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 670 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 672 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 674 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 746 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 748 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 750 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 676 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 678 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 680 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 752 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 754 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 756 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 682 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 684 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 686 */ 0x8, /* FC_LONG */ +/* 758 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 760 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 762 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter same_version_update_allowed */ -/* 688 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 690 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ -/* 692 */ 0x8, /* FC_LONG */ +/* 764 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 766 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ +/* 768 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 694 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 696 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ -/* 698 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 770 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 772 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ +/* 774 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 700 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 702 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ -/* 704 */ 0x8, /* FC_LONG */ +/* 776 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 778 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ +/* 780 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure UpdateAll */ -/* 706 */ 0x33, /* FC_AUTO_HANDLE */ +/* 782 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 708 */ NdrFcLong( 0x0 ), /* 0 */ -/* 712 */ NdrFcShort( 0x8 ), /* 8 */ -/* 714 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 716 */ NdrFcShort( 0x0 ), /* 0 */ -/* 718 */ NdrFcShort( 0x8 ), /* 8 */ -/* 720 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 784 */ NdrFcLong( 0x0 ), /* 0 */ +/* 788 */ NdrFcShort( 0x8 ), /* 8 */ +/* 790 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 792 */ NdrFcShort( 0x0 ), /* 0 */ +/* 794 */ NdrFcShort( 0x8 ), /* 8 */ +/* 796 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 722 */ 0xa, /* 10 */ +/* 798 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 724 */ NdrFcShort( 0x0 ), /* 0 */ -/* 726 */ NdrFcShort( 0x0 ), /* 0 */ -/* 728 */ NdrFcShort( 0x0 ), /* 0 */ -/* 730 */ NdrFcShort( 0x0 ), /* 0 */ +/* 800 */ NdrFcShort( 0x0 ), /* 0 */ +/* 802 */ NdrFcShort( 0x0 ), /* 0 */ +/* 804 */ NdrFcShort( 0x0 ), /* 0 */ +/* 806 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter observer */ -/* 732 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 734 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 736 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 808 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 810 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 812 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 738 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 740 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 742 */ 0x8, /* FC_LONG */ +/* 814 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 816 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 818 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Install */ -/* 744 */ 0x33, /* FC_AUTO_HANDLE */ +/* 820 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 746 */ NdrFcLong( 0x0 ), /* 0 */ -/* 750 */ NdrFcShort( 0x9 ), /* 9 */ -/* 752 */ NdrFcShort( 0x58 ), /* X64 Stack size/offset = 88 */ -/* 754 */ NdrFcShort( 0x8 ), /* 8 */ -/* 756 */ NdrFcShort( 0x8 ), /* 8 */ -/* 758 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 822 */ NdrFcLong( 0x0 ), /* 0 */ +/* 826 */ NdrFcShort( 0x9 ), /* 9 */ +/* 828 */ NdrFcShort( 0x58 ), /* X64 Stack size/offset = 88 */ +/* 830 */ NdrFcShort( 0x8 ), /* 8 */ +/* 832 */ NdrFcShort( 0x8 ), /* 8 */ +/* 834 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0xa, /* 10 */ -/* 760 */ 0xa, /* 10 */ +/* 836 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 762 */ NdrFcShort( 0x0 ), /* 0 */ -/* 764 */ NdrFcShort( 0x0 ), /* 0 */ -/* 766 */ NdrFcShort( 0x0 ), /* 0 */ -/* 768 */ NdrFcShort( 0x0 ), /* 0 */ +/* 838 */ NdrFcShort( 0x0 ), /* 0 */ +/* 840 */ NdrFcShort( 0x0 ), /* 0 */ +/* 842 */ NdrFcShort( 0x0 ), /* 0 */ +/* 844 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 770 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 772 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 774 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 846 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 848 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 850 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_code */ -/* 776 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 778 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 780 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 852 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 854 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 856 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_path */ -/* 782 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 784 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 786 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 858 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 860 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 862 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter tag */ -/* 788 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 790 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ -/* 792 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 864 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 866 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ +/* 868 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter version */ -/* 794 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 796 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ -/* 798 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 870 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 872 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ +/* 874 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter existence_checker_path */ -/* 800 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 802 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ -/* 804 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 876 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 878 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ +/* 880 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 806 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 808 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ -/* 810 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 882 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 884 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ +/* 886 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 812 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 814 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ -/* 816 */ 0x8, /* FC_LONG */ +/* 888 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 890 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ +/* 892 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 818 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 820 */ NdrFcShort( 0x48 ), /* X64 Stack size/offset = 72 */ -/* 822 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 894 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 896 */ NdrFcShort( 0x48 ), /* X64 Stack size/offset = 72 */ +/* 898 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 824 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 826 */ NdrFcShort( 0x50 ), /* X64 Stack size/offset = 80 */ -/* 828 */ 0x8, /* FC_LONG */ +/* 900 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 902 */ NdrFcShort( 0x50 ), /* X64 Stack size/offset = 80 */ +/* 904 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure CancelInstalls */ -/* 830 */ 0x33, /* FC_AUTO_HANDLE */ +/* 906 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 832 */ NdrFcLong( 0x0 ), /* 0 */ -/* 836 */ NdrFcShort( 0xa ), /* 10 */ -/* 838 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 840 */ NdrFcShort( 0x0 ), /* 0 */ -/* 842 */ NdrFcShort( 0x8 ), /* 8 */ -/* 844 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 908 */ NdrFcLong( 0x0 ), /* 0 */ +/* 912 */ NdrFcShort( 0xa ), /* 10 */ +/* 914 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 916 */ NdrFcShort( 0x0 ), /* 0 */ +/* 918 */ NdrFcShort( 0x8 ), /* 8 */ +/* 920 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 846 */ 0xa, /* 10 */ +/* 922 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 848 */ NdrFcShort( 0x0 ), /* 0 */ -/* 850 */ NdrFcShort( 0x0 ), /* 0 */ -/* 852 */ NdrFcShort( 0x0 ), /* 0 */ -/* 854 */ NdrFcShort( 0x0 ), /* 0 */ +/* 924 */ NdrFcShort( 0x0 ), /* 0 */ +/* 926 */ NdrFcShort( 0x0 ), /* 0 */ +/* 928 */ NdrFcShort( 0x0 ), /* 0 */ +/* 930 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 856 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 858 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 860 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 932 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 934 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 936 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Return value */ -/* 862 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 864 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 866 */ 0x8, /* FC_LONG */ +/* 938 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 940 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 942 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure RunInstaller */ -/* 868 */ 0x33, /* FC_AUTO_HANDLE */ +/* 944 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 870 */ NdrFcLong( 0x0 ), /* 0 */ -/* 874 */ NdrFcShort( 0xb ), /* 11 */ -/* 876 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ -/* 878 */ NdrFcShort( 0x0 ), /* 0 */ -/* 880 */ NdrFcShort( 0x8 ), /* 8 */ -/* 882 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 946 */ NdrFcLong( 0x0 ), /* 0 */ +/* 950 */ NdrFcShort( 0xb ), /* 11 */ +/* 952 */ NdrFcShort( 0x40 ), /* X64 Stack size/offset = 64 */ +/* 954 */ NdrFcShort( 0x0 ), /* 0 */ +/* 956 */ NdrFcShort( 0x8 ), /* 8 */ +/* 958 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x7, /* 7 */ -/* 884 */ 0xa, /* 10 */ +/* 960 */ 0xa, /* 10 */ 0x1, /* Ext Flags: new corr desc, */ -/* 886 */ NdrFcShort( 0x0 ), /* 0 */ -/* 888 */ NdrFcShort( 0x0 ), /* 0 */ -/* 890 */ NdrFcShort( 0x0 ), /* 0 */ -/* 892 */ NdrFcShort( 0x0 ), /* 0 */ +/* 962 */ NdrFcShort( 0x0 ), /* 0 */ +/* 964 */ NdrFcShort( 0x0 ), /* 0 */ +/* 966 */ NdrFcShort( 0x0 ), /* 0 */ +/* 968 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 894 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 896 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ -/* 898 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 970 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 972 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */ +/* 974 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter installer_path */ -/* 900 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 902 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ -/* 904 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 976 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 978 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */ +/* 980 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_args */ -/* 906 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 908 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ -/* 910 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 982 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 984 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */ +/* 986 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data */ -/* 912 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 914 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ -/* 916 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 988 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 990 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */ +/* 992 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_settings */ -/* 918 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 920 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ -/* 922 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 994 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 996 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */ +/* 998 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter observer */ -/* 924 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 926 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ -/* 928 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 1000 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 1002 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */ +/* 1004 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 930 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 932 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ -/* 934 */ 0x8, /* FC_LONG */ +/* 1006 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1008 */ NdrFcShort( 0x38 ), /* X64 Stack size/offset = 56 */ +/* 1010 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 @@ -1176,7 +1238,9 @@ 190, 228, 266, - 304 + 304, + 342, + 380 }; static const MIDL_STUBLESS_PROXY_INFO IUpdateState_ProxyInfo = @@ -1200,7 +1264,7 @@ 0, 0, 0}; -CINTERFACE_PROXY_VTABLE(12) _IUpdateStateProxyVtbl = +CINTERFACE_PROXY_VTABLE(14) _IUpdateStateProxyVtbl = { &IUpdateState_ProxyInfo, &IID_IUpdateState, @@ -1215,14 +1279,16 @@ (void *) (INT_PTR) -1 /* IUpdateState::get_installProgress */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCategory */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCode */ , - (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ + (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerText */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerCommandLine */ }; const CInterfaceStubVtbl _IUpdateStateStubVtbl = { &IID_IUpdateState, &IUpdateState_ServerInfo, - 12, + 14, 0, /* pure interpreted */ CStdStubBuffer_METHODS }; @@ -1234,7 +1300,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterRegisterAppCallback_FormatStringOffsetTable[] = { - 342 + 418 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterRegisterAppCallback_ProxyInfo = @@ -1336,8 +1402,8 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterObserver_FormatStringOffsetTable[] = { - 380, - 418 + 456, + 494 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterObserver_ProxyInfo = @@ -1388,7 +1454,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterCallback_FormatStringOffsetTable[] = { - 342 + 418 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterCallback_ProxyInfo = @@ -1438,15 +1504,15 @@ #pragma code_seg(".orpc") static const unsigned short IUpdater_FormatStringOffsetTable[] = { - 456, - 494, 532, - 606, - 644, - 706, - 744, - 830, - 868 + 570, + 608, + 682, + 720, + 782, + 820, + 906, + 944 }; static const MIDL_STUBLESS_PROXY_INFO IUpdater_ProxyInfo =
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.h b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.h index 06347ca..86ae07a 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.h +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.h
@@ -198,6 +198,12 @@ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_extraCode1( /* [retval][out] */ LONG *__MIDL__IUpdateState0008) = 0; + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerText( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_installerCommandLine( + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010) = 0; + }; @@ -267,6 +273,16 @@ IUpdateState * This, /* [retval][out] */ LONG *__MIDL__IUpdateState0008); + DECLSPEC_XFGVIRT(IUpdateState, get_installerText) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerText )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0009); + + DECLSPEC_XFGVIRT(IUpdateState, get_installerCommandLine) + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_installerCommandLine )( + IUpdateState * This, + /* [retval][out] */ BSTR *__MIDL__IUpdateState0010); + END_INTERFACE } IUpdateStateVtbl; @@ -317,6 +333,12 @@ #define IUpdateState_get_extraCode1(This,__MIDL__IUpdateState0008) \ ( (This)->lpVtbl -> get_extraCode1(This,__MIDL__IUpdateState0008) ) +#define IUpdateState_get_installerText(This,__MIDL__IUpdateState0009) \ + ( (This)->lpVtbl -> get_installerText(This,__MIDL__IUpdateState0009) ) + +#define IUpdateState_get_installerCommandLine(This,__MIDL__IUpdateState0010) \ + ( (This)->lpVtbl -> get_installerCommandLine(This,__MIDL__IUpdateState0010) ) + #endif /* COBJMACROS */
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.tlb b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.tlb index 9d20046..d6d2cfb 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.tlb +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl.tlb Binary files differ
diff --git a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl_p.c b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl_p.c index 86e785e..0c16fe0 100644 --- a/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl_p.c +++ b/third_party/win_build_output/midl/chrome/updater/app/server/win/x86/updater_idl_p.c
@@ -50,7 +50,7 @@ #include "updater_idl.h" #define TYPE_FORMAT_STRING_SIZE 145 -#define PROC_FORMAT_STRING_SIZE 895 +#define PROC_FORMAT_STRING_SIZE 967 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 1 @@ -491,38 +491,28 @@ /* 322 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure Run */ - - - /* Procedure Run */ + /* Procedure get_installerText */ /* 324 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 326 */ NdrFcLong( 0x0 ), /* 0 */ -/* 330 */ NdrFcShort( 0x3 ), /* 3 */ +/* 330 */ NdrFcShort( 0xc ), /* 12 */ /* 332 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 334 */ NdrFcShort( 0x8 ), /* 8 */ +/* 334 */ NdrFcShort( 0x0 ), /* 0 */ /* 336 */ NdrFcShort( 0x8 ), /* 8 */ -/* 338 */ 0x44, /* Oi2 Flags: has return, has ext, */ +/* 338 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 340 */ 0x8, /* 8 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 342 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 342 */ NdrFcShort( 0x1 ), /* 1 */ /* 344 */ NdrFcShort( 0x0 ), /* 0 */ /* 346 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter result */ + /* Parameter __MIDL__IUpdateState0009 */ - - /* Parameter status_code */ - -/* 348 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 348 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 350 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 352 */ 0x8, /* FC_LONG */ - 0x0, /* 0 */ - - /* Return value */ - +/* 352 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -531,28 +521,28 @@ /* 358 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnStateChange */ + /* Procedure get_installerCommandLine */ /* 360 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 362 */ NdrFcLong( 0x0 ), /* 0 */ -/* 366 */ NdrFcShort( 0x3 ), /* 3 */ +/* 366 */ NdrFcShort( 0xd ), /* 13 */ /* 368 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 370 */ NdrFcShort( 0x0 ), /* 0 */ /* 372 */ NdrFcShort( 0x8 ), /* 8 */ -/* 374 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 374 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ 0x2, /* 2 */ /* 376 */ 0x8, /* 8 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 378 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 378 */ NdrFcShort( 0x1 ), /* 1 */ /* 380 */ NdrFcShort( 0x0 ), /* 0 */ /* 382 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter update_state */ + /* Parameter __MIDL__IUpdateState0010 */ -/* 384 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 384 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ /* 386 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 388 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ +/* 388 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ /* Return value */ @@ -561,16 +551,19 @@ /* 394 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure OnComplete */ + /* Procedure Run */ + + + /* Procedure Run */ /* 396 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 398 */ NdrFcLong( 0x0 ), /* 0 */ -/* 402 */ NdrFcShort( 0x4 ), /* 4 */ +/* 402 */ NdrFcShort( 0x3 ), /* 3 */ /* 404 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 406 */ NdrFcShort( 0x0 ), /* 0 */ +/* 406 */ NdrFcShort( 0x8 ), /* 8 */ /* 408 */ NdrFcShort( 0x8 ), /* 8 */ -/* 410 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 410 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x2, /* 2 */ /* 412 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ @@ -578,11 +571,18 @@ /* 416 */ NdrFcShort( 0x0 ), /* 0 */ /* 418 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter status */ + /* Parameter result */ -/* 420 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ + + /* Parameter status_code */ + +/* 420 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ /* 422 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 424 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ +/* 424 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + /* Return value */ @@ -591,7 +591,7 @@ /* 430 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure GetVersion */ + /* Procedure OnStateChange */ /* 432 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -600,19 +600,19 @@ /* 440 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 442 */ NdrFcShort( 0x0 ), /* 0 */ /* 444 */ NdrFcShort( 0x8 ), /* 8 */ -/* 446 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ +/* 446 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ /* 448 */ 0x8, /* 8 */ - 0x3, /* Ext Flags: new corr desc, clt corr check, */ -/* 450 */ NdrFcShort( 0x1 ), /* 1 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 450 */ NdrFcShort( 0x0 ), /* 0 */ /* 452 */ NdrFcShort( 0x0 ), /* 0 */ /* 454 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter version */ + /* Parameter update_state */ -/* 456 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 456 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 458 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 460 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ +/* 460 */ NdrFcShort( 0x32 ), /* Type Offset=50 */ /* Return value */ @@ -621,7 +621,7 @@ /* 466 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure CheckForUpdate */ + /* Procedure OnComplete */ /* 468 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ @@ -638,11 +638,11 @@ /* 488 */ NdrFcShort( 0x0 ), /* 0 */ /* 490 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter app_id */ + /* Parameter status */ -/* 492 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 492 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ /* 494 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 496 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 496 */ NdrFcShort( 0x44 ), /* Type Offset=68 */ /* Return value */ @@ -651,355 +651,415 @@ /* 502 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure RegisterApp */ + /* Procedure GetVersion */ /* 504 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 506 */ NdrFcLong( 0x0 ), /* 0 */ -/* 510 */ NdrFcShort( 0x5 ), /* 5 */ -/* 512 */ NdrFcShort( 0x24 ), /* x86 Stack size/offset = 36 */ +/* 510 */ NdrFcShort( 0x3 ), /* 3 */ +/* 512 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ /* 514 */ NdrFcShort( 0x0 ), /* 0 */ /* 516 */ NdrFcShort( 0x8 ), /* 8 */ -/* 518 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x8, /* 8 */ +/* 518 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ /* 520 */ 0x8, /* 8 */ - 0x1, /* Ext Flags: new corr desc, */ -/* 522 */ NdrFcShort( 0x0 ), /* 0 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 522 */ NdrFcShort( 0x1 ), /* 1 */ /* 524 */ NdrFcShort( 0x0 ), /* 0 */ /* 526 */ NdrFcShort( 0x0 ), /* 0 */ - /* Parameter app_id */ - -/* 528 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 530 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 532 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_code */ - -/* 534 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 536 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 538 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter brand_path */ - -/* 540 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 542 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 544 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - - /* Parameter tag */ - -/* 546 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 548 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 550 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ - /* Parameter version */ -/* 552 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 554 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 556 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 528 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 530 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 532 */ NdrFcShort( 0x24 ), /* Type Offset=36 */ - /* Parameter existence_checker_path */ + /* Return value */ -/* 558 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 560 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 562 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 534 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 536 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 538 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ - /* Parameter callback */ + /* Procedure CheckForUpdate */ -/* 564 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 566 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 568 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ +/* 540 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 542 */ NdrFcLong( 0x0 ), /* 0 */ +/* 546 */ NdrFcShort( 0x4 ), /* 4 */ +/* 548 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 550 */ NdrFcShort( 0x0 ), /* 0 */ +/* 552 */ NdrFcShort( 0x8 ), /* 8 */ +/* 554 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 556 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 558 */ NdrFcShort( 0x0 ), /* 0 */ +/* 560 */ NdrFcShort( 0x0 ), /* 0 */ +/* 562 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter app_id */ + +/* 564 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 566 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 568 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Return value */ /* 570 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 572 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 572 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ /* 574 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure RunPeriodicTasks */ + /* Procedure RegisterApp */ /* 576 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 578 */ NdrFcLong( 0x0 ), /* 0 */ -/* 582 */ NdrFcShort( 0x6 ), /* 6 */ -/* 584 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 582 */ NdrFcShort( 0x5 ), /* 5 */ +/* 584 */ NdrFcShort( 0x24 ), /* x86 Stack size/offset = 36 */ /* 586 */ NdrFcShort( 0x0 ), /* 0 */ /* 588 */ NdrFcShort( 0x8 ), /* 8 */ /* 590 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x2, /* 2 */ + 0x8, /* 8 */ /* 592 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ /* 594 */ NdrFcShort( 0x0 ), /* 0 */ /* 596 */ NdrFcShort( 0x0 ), /* 0 */ /* 598 */ NdrFcShort( 0x0 ), /* 0 */ + /* Parameter app_id */ + +/* 600 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 602 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 604 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_code */ + +/* 606 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 608 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 610 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter brand_path */ + +/* 612 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 614 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 616 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter tag */ + +/* 618 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 620 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 622 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter version */ + +/* 624 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 626 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 628 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + + /* Parameter existence_checker_path */ + +/* 630 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 632 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 634 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ + /* Parameter callback */ -/* 600 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 602 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 604 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ +/* 636 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 638 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 640 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ /* Return value */ -/* 606 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 608 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 610 */ 0x8, /* FC_LONG */ +/* 642 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 644 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 646 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure RunPeriodicTasks */ + +/* 648 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 650 */ NdrFcLong( 0x0 ), /* 0 */ +/* 654 */ NdrFcShort( 0x6 ), /* 6 */ +/* 656 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 658 */ NdrFcShort( 0x0 ), /* 0 */ +/* 660 */ NdrFcShort( 0x8 ), /* 8 */ +/* 662 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 664 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 666 */ NdrFcShort( 0x0 ), /* 0 */ +/* 668 */ NdrFcShort( 0x0 ), /* 0 */ +/* 670 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter callback */ + +/* 672 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 674 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 676 */ NdrFcShort( 0x6c ), /* Type Offset=108 */ + + /* Return value */ + +/* 678 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 680 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 682 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Update */ -/* 612 */ 0x33, /* FC_AUTO_HANDLE */ +/* 684 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 614 */ NdrFcLong( 0x0 ), /* 0 */ -/* 618 */ NdrFcShort( 0x7 ), /* 7 */ -/* 620 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 622 */ NdrFcShort( 0x10 ), /* 16 */ -/* 624 */ NdrFcShort( 0x8 ), /* 8 */ -/* 626 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 686 */ NdrFcLong( 0x0 ), /* 0 */ +/* 690 */ NdrFcShort( 0x7 ), /* 7 */ +/* 692 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 694 */ NdrFcShort( 0x10 ), /* 16 */ +/* 696 */ NdrFcShort( 0x8 ), /* 8 */ +/* 698 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x6, /* 6 */ -/* 628 */ 0x8, /* 8 */ +/* 700 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ -/* 630 */ NdrFcShort( 0x0 ), /* 0 */ -/* 632 */ NdrFcShort( 0x0 ), /* 0 */ -/* 634 */ NdrFcShort( 0x0 ), /* 0 */ +/* 702 */ NdrFcShort( 0x0 ), /* 0 */ +/* 704 */ NdrFcShort( 0x0 ), /* 0 */ +/* 706 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 636 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 638 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 640 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 708 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 710 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 712 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 642 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 644 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 646 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 714 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 716 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 718 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 648 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 650 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 652 */ 0x8, /* FC_LONG */ +/* 720 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 722 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 724 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter same_version_update_allowed */ -/* 654 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 656 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 658 */ 0x8, /* FC_LONG */ +/* 726 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 728 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 730 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 660 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 662 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 664 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 732 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 734 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 736 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 666 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 668 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 670 */ 0x8, /* FC_LONG */ +/* 738 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 740 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 742 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure UpdateAll */ -/* 672 */ 0x33, /* FC_AUTO_HANDLE */ +/* 744 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 674 */ NdrFcLong( 0x0 ), /* 0 */ -/* 678 */ NdrFcShort( 0x8 ), /* 8 */ -/* 680 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 682 */ NdrFcShort( 0x0 ), /* 0 */ -/* 684 */ NdrFcShort( 0x8 ), /* 8 */ -/* 686 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 746 */ NdrFcLong( 0x0 ), /* 0 */ +/* 750 */ NdrFcShort( 0x8 ), /* 8 */ +/* 752 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 754 */ NdrFcShort( 0x0 ), /* 0 */ +/* 756 */ NdrFcShort( 0x8 ), /* 8 */ +/* 758 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 688 */ 0x8, /* 8 */ +/* 760 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ -/* 690 */ NdrFcShort( 0x0 ), /* 0 */ -/* 692 */ NdrFcShort( 0x0 ), /* 0 */ -/* 694 */ NdrFcShort( 0x0 ), /* 0 */ +/* 762 */ NdrFcShort( 0x0 ), /* 0 */ +/* 764 */ NdrFcShort( 0x0 ), /* 0 */ +/* 766 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter observer */ -/* 696 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 698 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 700 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 768 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 770 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 772 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 702 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 704 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 706 */ 0x8, /* FC_LONG */ +/* 774 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 776 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 778 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure Install */ -/* 708 */ 0x33, /* FC_AUTO_HANDLE */ +/* 780 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 710 */ NdrFcLong( 0x0 ), /* 0 */ -/* 714 */ NdrFcShort( 0x9 ), /* 9 */ -/* 716 */ NdrFcShort( 0x2c ), /* x86 Stack size/offset = 44 */ -/* 718 */ NdrFcShort( 0x8 ), /* 8 */ -/* 720 */ NdrFcShort( 0x8 ), /* 8 */ -/* 722 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 782 */ NdrFcLong( 0x0 ), /* 0 */ +/* 786 */ NdrFcShort( 0x9 ), /* 9 */ +/* 788 */ NdrFcShort( 0x2c ), /* x86 Stack size/offset = 44 */ +/* 790 */ NdrFcShort( 0x8 ), /* 8 */ +/* 792 */ NdrFcShort( 0x8 ), /* 8 */ +/* 794 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0xa, /* 10 */ -/* 724 */ 0x8, /* 8 */ +/* 796 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ -/* 726 */ NdrFcShort( 0x0 ), /* 0 */ -/* 728 */ NdrFcShort( 0x0 ), /* 0 */ -/* 730 */ NdrFcShort( 0x0 ), /* 0 */ +/* 798 */ NdrFcShort( 0x0 ), /* 0 */ +/* 800 */ NdrFcShort( 0x0 ), /* 0 */ +/* 802 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 732 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 734 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 736 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 804 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 806 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 808 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_code */ -/* 738 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 740 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 742 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 810 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 812 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 814 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter brand_path */ -/* 744 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 746 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 748 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 816 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 818 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 820 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter tag */ -/* 750 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 752 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 754 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 822 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 824 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 826 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter version */ -/* 756 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 758 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 760 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 828 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 830 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 832 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter existence_checker_path */ -/* 762 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 764 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 766 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 834 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 836 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 838 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data_index */ -/* 768 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 770 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 772 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 840 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 842 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 844 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter priority */ -/* 774 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 776 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ -/* 778 */ 0x8, /* FC_LONG */ +/* 846 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 848 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 850 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter observer */ -/* 780 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 782 */ NdrFcShort( 0x24 ), /* x86 Stack size/offset = 36 */ -/* 784 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 852 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 854 */ NdrFcShort( 0x24 ), /* x86 Stack size/offset = 36 */ +/* 856 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 786 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 788 */ NdrFcShort( 0x28 ), /* x86 Stack size/offset = 40 */ -/* 790 */ 0x8, /* FC_LONG */ +/* 858 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 860 */ NdrFcShort( 0x28 ), /* x86 Stack size/offset = 40 */ +/* 862 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure CancelInstalls */ -/* 792 */ 0x33, /* FC_AUTO_HANDLE */ +/* 864 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 794 */ NdrFcLong( 0x0 ), /* 0 */ -/* 798 */ NdrFcShort( 0xa ), /* 10 */ -/* 800 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 802 */ NdrFcShort( 0x0 ), /* 0 */ -/* 804 */ NdrFcShort( 0x8 ), /* 8 */ -/* 806 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 866 */ NdrFcLong( 0x0 ), /* 0 */ +/* 870 */ NdrFcShort( 0xa ), /* 10 */ +/* 872 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 874 */ NdrFcShort( 0x0 ), /* 0 */ +/* 876 */ NdrFcShort( 0x8 ), /* 8 */ +/* 878 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x2, /* 2 */ -/* 808 */ 0x8, /* 8 */ +/* 880 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ -/* 810 */ NdrFcShort( 0x0 ), /* 0 */ -/* 812 */ NdrFcShort( 0x0 ), /* 0 */ -/* 814 */ NdrFcShort( 0x0 ), /* 0 */ +/* 882 */ NdrFcShort( 0x0 ), /* 0 */ +/* 884 */ NdrFcShort( 0x0 ), /* 0 */ +/* 886 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 816 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 818 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 820 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 888 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 890 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 892 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Return value */ -/* 822 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 824 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 826 */ 0x8, /* FC_LONG */ +/* 894 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 896 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 898 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure RunInstaller */ -/* 828 */ 0x33, /* FC_AUTO_HANDLE */ +/* 900 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 830 */ NdrFcLong( 0x0 ), /* 0 */ -/* 834 */ NdrFcShort( 0xb ), /* 11 */ -/* 836 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ -/* 838 */ NdrFcShort( 0x0 ), /* 0 */ -/* 840 */ NdrFcShort( 0x8 ), /* 8 */ -/* 842 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ +/* 902 */ NdrFcLong( 0x0 ), /* 0 */ +/* 906 */ NdrFcShort( 0xb ), /* 11 */ +/* 908 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 910 */ NdrFcShort( 0x0 ), /* 0 */ +/* 912 */ NdrFcShort( 0x8 ), /* 8 */ +/* 914 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ 0x7, /* 7 */ -/* 844 */ 0x8, /* 8 */ +/* 916 */ 0x8, /* 8 */ 0x1, /* Ext Flags: new corr desc, */ -/* 846 */ NdrFcShort( 0x0 ), /* 0 */ -/* 848 */ NdrFcShort( 0x0 ), /* 0 */ -/* 850 */ NdrFcShort( 0x0 ), /* 0 */ +/* 918 */ NdrFcShort( 0x0 ), /* 0 */ +/* 920 */ NdrFcShort( 0x0 ), /* 0 */ +/* 922 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter app_id */ -/* 852 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 854 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 856 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 924 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 926 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 928 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter installer_path */ -/* 858 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 860 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 862 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 930 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 932 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 934 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_args */ -/* 864 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 866 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 868 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 936 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 938 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 940 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_data */ -/* 870 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 872 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 874 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 942 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 944 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 946 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter install_settings */ -/* 876 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 878 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 880 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ +/* 948 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 950 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 952 */ NdrFcShort( 0x58 ), /* Type Offset=88 */ /* Parameter observer */ -/* 882 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ -/* 884 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 886 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ +/* 954 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 956 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 958 */ NdrFcShort( 0x7e ), /* Type Offset=126 */ /* Return value */ -/* 888 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 890 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 892 */ 0x8, /* FC_LONG */ +/* 960 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 962 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 964 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 @@ -1166,7 +1226,9 @@ 180, 216, 252, - 288 + 288, + 324, + 360 }; static const MIDL_STUBLESS_PROXY_INFO IUpdateState_ProxyInfo = @@ -1190,7 +1252,7 @@ 0, 0, 0}; -CINTERFACE_PROXY_VTABLE(12) _IUpdateStateProxyVtbl = +CINTERFACE_PROXY_VTABLE(14) _IUpdateStateProxyVtbl = { &IUpdateState_ProxyInfo, &IID_IUpdateState, @@ -1205,14 +1267,16 @@ (void *) (INT_PTR) -1 /* IUpdateState::get_installProgress */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCategory */ , (void *) (INT_PTR) -1 /* IUpdateState::get_errorCode */ , - (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ + (void *) (INT_PTR) -1 /* IUpdateState::get_extraCode1 */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerText */ , + (void *) (INT_PTR) -1 /* IUpdateState::get_installerCommandLine */ }; const CInterfaceStubVtbl _IUpdateStateStubVtbl = { &IID_IUpdateState, &IUpdateState_ServerInfo, - 12, + 14, 0, /* pure interpreted */ CStdStubBuffer_METHODS }; @@ -1224,7 +1288,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterRegisterAppCallback_FormatStringOffsetTable[] = { - 324 + 396 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterRegisterAppCallback_ProxyInfo = @@ -1326,8 +1390,8 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterObserver_FormatStringOffsetTable[] = { - 360, - 396 + 432, + 468 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterObserver_ProxyInfo = @@ -1378,7 +1442,7 @@ #pragma code_seg(".orpc") static const unsigned short IUpdaterCallback_FormatStringOffsetTable[] = { - 324 + 396 }; static const MIDL_STUBLESS_PROXY_INFO IUpdaterCallback_ProxyInfo = @@ -1428,15 +1492,15 @@ #pragma code_seg(".orpc") static const unsigned short IUpdater_FormatStringOffsetTable[] = { - 432, - 468, 504, + 540, 576, - 612, - 672, - 708, - 792, - 828 + 648, + 684, + 744, + 780, + 864, + 900 }; static const MIDL_STUBLESS_PROXY_INFO IUpdater_ProxyInfo =
diff --git a/tools/ipc_fuzzer/message_lib/BUILD.gn b/tools/ipc_fuzzer/message_lib/BUILD.gn index 2b39551..a47b50e 100644 --- a/tools/ipc_fuzzer/message_lib/BUILD.gn +++ b/tools/ipc_fuzzer/message_lib/BUILD.gn
@@ -4,7 +4,6 @@ import("//components/nacl/features.gni") import("//ppapi/buildflags/buildflags.gni") -import("//remoting/remoting_enable.gni") static_library("ipc_message_lib") { testonly = true @@ -35,7 +34,6 @@ if (enable_ppapi) { public_deps += [ "//ppapi/proxy:ipc" ] } - deps = [ "//remoting/host/base" ] sources = [ "all_messages.h", "message_cracker.h", @@ -49,7 +47,4 @@ if (enable_nacl) { public_deps += [ "//components/nacl/common" ] } - if (enable_remoting) { - public_deps += [ "//remoting/host" ] - } }
diff --git a/tools/ipc_fuzzer/message_lib/DEPS b/tools/ipc_fuzzer/message_lib/DEPS index f29f4b26..ebd8d75 100644 --- a/tools/ipc_fuzzer/message_lib/DEPS +++ b/tools/ipc_fuzzer/message_lib/DEPS
@@ -13,5 +13,4 @@ "+extensions/common", "+gpu/ipc/common", "+media/gpu/ipc", - "+remoting/host", ]
diff --git a/tools/ipc_fuzzer/message_lib/all_messages.h b/tools/ipc_fuzzer/message_lib/all_messages.h index 89210cc..1e079238 100644 --- a/tools/ipc_fuzzer/message_lib/all_messages.h +++ b/tools/ipc_fuzzer/message_lib/all_messages.h
@@ -23,4 +23,3 @@ #endif #include "content/common/all_messages.h" #include "extensions/common/extension_message_generator.h" -#include "remoting/host/chromoting_messages.h"
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 00b02a2..5777527 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -485,10 +485,12 @@ exe += '.exe' args = [ - exe, 'select', - '-model-dir', model_dir, \ - '-out', self.PathJoin(self.ToAbsPath(self.args.path), self.rts_out_dir), - '-checkout', self.chromium_src_dir, + exe, + 'select', + '-gen-inverse', + '-model-dir', model_dir, \ + '-out', self.PathJoin(self.ToAbsPath(self.args.path), self.rts_out_dir), + '-checkout', self.chromium_src_dir, ] if self.args.rts_target_change_recall: if (self.args.rts_target_change_recall < 0 @@ -1334,11 +1336,6 @@ if 'is_skylab=true' in vals['gn_args']: runtime_deps = self._FilterOutUnneededSkylabDeps(runtime_deps) - # For more info about RTS, please see - # //docs/testing/regression-test-selection.md - if self.args.rts: - self.AddFilterFileArg(target, build_dir, command) - canonical_target = target.replace(':','_').replace('/','_') ret = self.WriteIsolateFiles(build_dir, command, canonical_target, runtime_deps, vals, extra_files) @@ -1346,17 +1343,17 @@ return ret return 0 - def AddFilterFileArg(self, target, build_dir, command): - if target in self.banned_from_rts: - self.Print('%s is banned for RTS on this builder' % target) - else: - filter_file = target + '.filter' - filter_file_path = self.PathJoin(self.rts_out_dir, filter_file) - abs_filter_file_path = self.ToAbsPath(build_dir, filter_file_path) + def AddFilterFileArg(self, target, build_dir, command, inverted=False): + filter_file = ('%s_inverted' % target if inverted else target) + '.filter' + filter_file_path = self.PathJoin(self.rts_out_dir, filter_file) + abs_filter_file_path = self.ToAbsPath(build_dir, filter_file_path) - if self.Exists(abs_filter_file_path): - command.append('--test-launcher-filter-file=%s' % filter_file_path) - self.Print('added RTS filter file to command: %s' % filter_file) + filter_exists = self.Exists(abs_filter_file_path) + if filter_exists: + command.append('--test-launcher-filter-file=%s' % filter_file_path) + self.Print('added RTS filter file to command: %s' % filter_file) + + return filter_exists def PossibleRuntimeDepsPaths(self, vals, ninja_targets, isolate_map): """Returns a map of targets to possible .runtime_deps paths. @@ -1556,13 +1553,31 @@ 'list files in directory instead for:' + err) return 1 - self.WriteFile(isolate_path, - json.dumps({ + isolate = { 'variables': { - 'command': command, - 'files': files, + 'command': command, + 'files': files, } - }, sort_keys=True) + '\n') + } + # For more info about RTS, please see + # //docs/testing/regression-test-selection.md + if self.args.rts: + if target in self.banned_from_rts: + self.Print('%s is banned for RTS on this builder' % target) + isolate['variables']['command'] = command + else: + inverted_command = command.copy() + self.AddFilterFileArg(target, build_dir, command, inverted=False) + isolate['variables']['command'] = command + + inverted_filter_exists = self.AddFilterFileArg(target, + build_dir, + inverted_command, + inverted=True) + if inverted_filter_exists: + isolate['variables']['inverted_command'] = inverted_command + + self.WriteFile(isolate_path, json.dumps(isolate, sort_keys=True) + '\n') self.WriteJSON( {
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index afbf243f..5dbebb1 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -329,7 +329,7 @@ }, 'Comparison Mac (reclient)': { 'goma': 'gpu_tests_release_bot_minimal_symbols_no_nacl', - 'reclient': 'gpu_tests_release_bot_minimal_symbols_reclient', + 'reclient': 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', }, 'Comparison Mac arm64 (reclient)': { 'goma': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl', @@ -372,7 +372,7 @@ 'Mac Builder Next': 'mac_arm64_gpu_tests_debug_bot_minimal_symbols_no_nacl', 'Mac deterministic': 'release_bot_mac_strip_minimal_symbols', 'Mac deterministic (dbg)': 'debug_bot', - 'Mac deterministic (reclient shadow)': 'release_bot_mac_strip_minimal_symbols_reclient', + 'Mac deterministic (reclient shadow)': 'release_bot_mac_strip_minimal_symbols_no_nacl_reclient', 'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64_reclient', 'VR Linux': 'vr_release_bot_reclient', 'Win 10 Fast Ring': 'release_trybot_minimal_symbols_reclient', @@ -2738,6 +2738,10 @@ 'gpu_tests', 'release_bot', 'minimal_symbols', 'disable_nacl', ], + 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient': [ + 'gpu_tests', 'release_bot_reclient', 'minimal_symbols', 'disable_nacl', + ], + 'gpu_tests_release_bot_minimal_symbols_reclient': [ 'gpu_tests', 'release_bot_reclient', 'minimal_symbols', ], @@ -3420,8 +3424,8 @@ 'release_bot', 'mac_strip', 'minimal_symbols', 'arm64', ], - 'release_bot_mac_strip_minimal_symbols_reclient': [ - 'release_bot_reclient', 'mac_strip', 'minimal_symbols', + 'release_bot_mac_strip_minimal_symbols_no_nacl_reclient': [ + 'release_bot_reclient', 'mac_strip', 'minimal_symbols', 'disable_nacl', ], 'release_bot_minimal_symbols': [
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index 09d8343..35a0c79 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -95,6 +95,7 @@ "reclient": { "gn_args": { "dcheck_always_on": false, + "enable_nacl": false, "ffmpeg_branding": "Chrome", "is_component_build": false, "is_debug": false, @@ -478,6 +479,7 @@ "Mac deterministic (reclient shadow)": { "gn_args": { "dcheck_always_on": false, + "enable_nacl": false, "enable_stripping": true, "is_component_build": false, "is_debug": false,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index e0d2faf1..c139a05 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -33960,6 +33960,9 @@ label="For ChromeHomePullToRefresh feature."/> <suffix name="ContextualPageActions_PriceTracking" label="For Contextual page actions price tracking feature."/> + <suffix name="ContextualPageActions_PriceTrackingActionChip" + label="For action chip variant of Contextual page actions price + tracking feature."/> <suffix name="ContextualSearch" label="For ContextualSearch feature."/> <suffix name="ContextualSearchInPanelHelp" label="For ContextualSearchInPanelHelp feature."/> @@ -34047,6 +34050,8 @@ <suffix name="NewTabPageHomeButton" label="For NewTabPageHomeButton feature."/> <suffix name="NewTabTip" label="For NewTabTip feature."/> + <suffix name="OverflowMenuTip" + label="For the overflow menu help tip on iOS."/> <suffix name="PageInfo" label="In product help for opening PageInfo."/> <suffix name="PageInfoStoreInfo" label="For PageInfoStoreInfo feature."/> <suffix name="PasswordsAccountStorage"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a2ee6bf..f6155f0 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -41093,6 +41093,7 @@ <int value="4327" label="V8PendingPostBeacon_SetData_Method"/> <int value="4328" label="ContentVisibilityAutoStateChangedHandlerRegistered"/> <int value="4329" label="ReplacedElementPaintedWithLargeOverflow"/> + <int value="4330" label="FlexboxAbsPosJustifyContent"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -57427,6 +57428,8 @@ <int value="-1145246849" label="ThirdPartyDoodles:enabled"/> <int value="-1144754105" label="ScalableStatusArea:enabled"/> <int value="-1144501989" label="UserActivityPredictionMlService:disabled"/> + <int value="-1144296865" + label="ServiceWorkerSkipIgnorableFetchHandler:disabled"/> <int value="-1144170722" label="DisableProcessReuse:enabled"/> <int value="-1143496217" label="enable-oop-rasterization"/> <int value="-1143007275" label="EnableNewStyleLauncher:disabled"/> @@ -57901,6 +57904,8 @@ <int value="-853594220" label="disable-new-avatar-menu"/> <int value="-853455968" label="OmniboxDefaultTypedNavigationsToHttps:disabled"/> + <int value="-853404233" + label="ServiceWorkerSkipIgnorableFetchHandler:enabled"/> <int value="-852804781" label="WebViewSynthesizePageLoadOnlyOnInitialMainDocumentAccess:disabled"/> <int value="-850821337" label="WebContentsForceDark:enabled"/> @@ -59781,6 +59786,7 @@ <int value="348449023" label="DesktopPWAsLocalUpdatingThrottlePersistence:enabled"/> <int value="348854923" label="v8-cache-strategies-for-cache-storage"/> + <int value="348887417" label="HandwritingLibraryDlc:enabled"/> <int value="349469694" label="WebGPUService:disabled"/> <int value="350362421" label="AutofillEnableAugmentedPhoneCountryCode:enabled"/> @@ -61873,6 +61879,7 @@ <int value="1683560662" label="ChromeShareHighlightsAndroid:disabled"/> <int value="1684043382" label="AssistantKeyRemapping:enabled"/> <int value="1685280468" label="AppServiceShelf:enabled"/> + <int value="1687272287" label="HandwritingLibraryDlc:disabled"/> <int value="1687544136" label="AndroidManagedByMenuItem:enabled"/> <int value="1688075820" label="OmniboxExperimentalKeywordMode:disabled"/> <int value="1689001971" label="ProjectorLocalPlayback:enabled"/> @@ -72391,6 +72398,14 @@ <int value="4" label="auto, enabled in trial"/> </enum> +<enum name="OmniboxBuiltinEngineType"> + <int value="0" label="Non built-in engine"/> + <int value="1" label="Prepopulated Engine"/> + <int value="2" label="@bookmarks starter pack engine"/> + <int value="3" label="@history starter pack engine"/> + <int value="4" label="@tabs starter pack engine"/> +</enum> + <enum name="OmniboxDocumentSuggestRequests"> <int value="1" label="requests sent"/> <int value="2" label="requests invalidated"/> @@ -78881,6 +78896,34 @@ <int value="2" label="Deferred to native init"/> </enum> +<enum name="PrerenderActivationNavigationParamsMatch"> + <int value="0" label="kOk"/> + <int value="1" label="kInitiatorFrameToken"/> + <int value="2" label="kHttpRequestHeader"/> + <int value="3" label="kCacheLoadFlags"/> + <int value="4" label="kLoadFlags"/> + <int value="5" label="kSkipServiceWorker"/> + <int value="6" label="kMixedContentContextType"/> + <int value="7" label="kIsFormSubmission"/> + <int value="8" label="kSearchableFormUrl"/> + <int value="9" label="kSearchableFormEncoding"/> + <int value="10" label="kTrustTokenParams"/> + <int value="11" label="kWebBundleToken"/> + <int value="12" label="kRequestContextType"/> + <int value="13" label="kImpressionHasValue"/> + <int value="14" label="kInitiatorOrigin"/> + <int value="15" label="kTransition"/> + <int value="16" label="kNavigationType"/> + <int value="17" label="kBaseUrlForDataUrl"/> + <int value="18" label="kPostData"/> + <int value="19" label="kStartedFromContextMenu"/> + <int value="20" label="kInitiatorOriginTrialFeature"/> + <int value="21" label="kHrefTranslate"/> + <int value="22" label="kIsHistoryNavigationInNewChildFrame"/> + <int value="23" label="kReferrerPolicy"/> + <int value="24" label="kRequestDestination"/> +</enum> + <enum name="PrerenderCancelledInterface"> <int value="0" label="kUnknown"/> <int value="1" label="kGamepadHapticsManager"/> @@ -83660,6 +83703,8 @@ <int value="77" label="InternalInputBlocking"/> <int value="78" label="WebGL"/> <int value="79" label="InternalPostMessageForwarding"/> + <int value="80" label="InternalNavigationCancellation"/> + <int value="81" label="LowPriorityScriptExecution"/> </enum> <enum name="RendererSchedulerTaskUseCase"> @@ -87173,6 +87218,12 @@ <int value="1" label="Got Response"/> </enum> +<enum name="ServiceWorkerFetchHandlerSkipReason"> + <int value="0" label="No Fetch Handler"/> + <int value="1" label="Not Skipped"/> + <int value="2" label="Skipped for Empty Fetch Handler"/> +</enum> + <enum name="ServiceWorkerInstalledScriptsManager.FinishedReason"> <int value="0" label="NOT_FINISHED"/> <int value="1" label="SUCCESS"/> @@ -98322,6 +98373,21 @@ </int> </enum> +<enum name="V8ExternalPointerTableCompactionOutcome"> + <int value="0" label="kSuccess">Table compaction was successful.</int> + <int value="1" label="kPartialSuccess"> + Table compaction was partially successful: marking finished successfully, + and so the table was successfully compacted, but some of the entries in the + evacuated area were already in use again during sweeping, preventing the + underlying OS pages from being deallocated. + </int> + <int value="2" label="kAbortedDuringMarking"> + Table compaction was aborted during marking because not enough evacuation + entries (the new entries into which evacuated entries are moved) could be + allocated. + </int> +</enum> + <enum name="V8InitializerLoadV8SnapshotResult"> <int value="0" label="SUCCESS">Load succeeded</int> <int value="1" label="FAILED_OPEN">Failure to open snapshot file</int>
diff --git a/tools/metrics/histograms/histograms_index.txt b/tools/metrics/histograms/histograms_index.txt index 36479b12..5436c016 100644 --- a/tools/metrics/histograms/histograms_index.txt +++ b/tools/metrics/histograms/histograms_index.txt
@@ -5,6 +5,7 @@ tools/metrics/histograms/metadata/apps/histograms.xml tools/metrics/histograms/metadata/arc/histograms.xml tools/metrics/histograms/metadata/ash/histograms.xml +tools/metrics/histograms/metadata/ash_clipboard/histograms.xml tools/metrics/histograms/metadata/assistant/histograms.xml tools/metrics/histograms/metadata/auth/histograms.xml tools/metrics/histograms/metadata/auto/histograms.xml
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index a7288f6..ecf6c12 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -63,7 +63,7 @@ <variant name="ContentWaived" summary="Waived binding excluding BindingManager bindings"/> <variant name="Moderate" summary="strongest binding of Moderate"/> - <variant name="Not Perceptible" + <variant name="NotPerceptible" summary="strongest binding of Not Perceptible"/> <variant name="Strong" summary="strongest binding of Strong"/> <variant name="Visible" summary="strongest binding of Visible"/>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 2706f7b..7c5d02c 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -1304,243 +1304,6 @@ <token key="TabletOrClamshell" variants="DisplayModes"/> </histogram> -<histogram name="Ash.Clipboard.ConsecutiveCopies" units="times" - expires_after="2022-10-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of consecutive copies in the user session, recorded when a paste - occurs. Warning: This histogram was expired from 2021-09-01 to 2022-01-05; - data may be missing. - </summary> -</histogram> - -<histogram name="Ash.Clipboard.ConsecutivePastes" units="times" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of consecutive pastes in the user session, recorded when a copy - occurs. Includes pastes from Clipboard History. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ConsecutivePastes" units="times" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of consecutive pastes from the clipboard history menu. The count - is reset after a copy or a paste that is not through the clipboard history - menu (such as pressing ctrl-v accelerator or clicking at a context menu - option). Warning: This histogram was expired from 2022-01-02 to 2022-01-05; - data may be missing. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatDeleted" - enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The format of the ClipboardHistoryItemView that was deleted from the - Clipboard History menu. Logged on ClipboardHistoryItemView::ButtonPressed(). - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatPasted" - enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The format of the ClipboardHistoryItemView that was pasted from the - Clipboard History menu. Logged on ClipboardHistoryItemView::ButtonPressed(). - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatShown" - enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The format of the view used to display clipboard data. Logged when the view - is created. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.MenuOptionSelected" - units="index" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The command ID index within the Clipboard History contextual menu that was - selected by the user. Recorded when the menu item is selected. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.NumberOfItemsShown" - units="Items Shown" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of clipboard history items shown in the clipboard history - contextual menu. Recorded when the clipboard history contextual menu model - is built. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.ShowMenu" - enum="ClipboardHistoryTriggerType" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - It records how many times users trigger the clipboard history menu through - different ways respecitvely. Recorded when the clipboard history menu shows. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.ShowPlaceholderString" - enum="ClipboardHistoryPlaceholderStringType" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of placeholder strings shown to users in lieu of actual data, - broken down by placeholder string type. Recorded when the label is requested - from ClipboardHistoryResourceManager. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ContextMenu.UserJourneyTime" units="ms" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The length of the user journey of the context menu version of clipboard - history. Measured as time from starting to construct the menu, to time of - the menu being closed. Recorded every time the menu is closed, regardless of - whether the user selected one of the menu options. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ControlToVDelay" units="ms" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The time between a user pressing control and V when pasting via keyboard. - Recorded in AcceleratorHistory when a V is pressed. Only recorded for the - first pressed V in a sequence, for example: User holds control, waits 200ms, - presses V (histogram logged), presses V again without releasing control (no - histogram logged). This metric is used to set a baseline for an experimental - keyboard combination where a user holds control, then presses V after a - delay to show multipaste. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ImageModelRequest.Lifetime" units="ms" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The lifetime of the ClipboardImageModelRequest object. Logged in the dtor of - ClipboardImageModelRequest. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ImageModelRequest.Runtime" units="ms" - expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The runtime of a request in a ClipboardImageModelRequest. Logged from when - the ClipboardImageModelRequest is Start()-ed to when it is Stop()-ed. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ImageModelRequest.StopReason" - enum="RequestStopReason" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The reason a ClipboardImageModelRequest is stopped. Logged when a request is - Stop()-ed. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.Nudges.{NudgeType}.ShownCount" - enum="BooleanHit" expires_after="2022-10-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of times the clipboard history {NudgeType} has been shown. This - number will be used as the baseline against the number of emits of the - ToFeaturePasteTime and ToFeatureOpenTime histograms. - </summary> - <token key="NudgeType"> - <variant name="NewFeatureBadge" summary="new feature badge"/> - <variant name="OnboardingNudge" summary="onboarding nudge"/> - <variant name="ScreenshotNotificationNudge" - summary="screenshot notification nudge"/> - <variant name="ZeroStateNudge" summary="zero state nudge"/> - </token> -</histogram> - -<histogram name="Ash.ClipboardHistory.Nudges.{NudgeType}.ToFeature{Action}Time" - units="seconds" expires_after="2022-10-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - The number of seconds between the user being shown the clipboard history - {NudgeType} and {Action}. The number of emits to this histogram will also be - used to measure the conversion rate by comparing it to ShownCount histogram - </summary> - <token key="NudgeType"> - <variant name="NewFeatureBadge" summary="new feature badge"/> - <variant name="OnboardingNudge" summary="onboarding nudge"/> - <variant name="ScreenshotNotificationNudge" - summary="screenshot notification nudge"/> - <variant name="ZeroStateNudge" summary="zero state nudge"/> - </token> - <token key="Action"> - <variant name="Open" summary="opening the clipboard history menu"/> - <variant name="Paste" - summary="using the clipboard history to paste something"/> - </token> -</histogram> - -<histogram name="Ash.ClipboardHistory.Operation" - enum="ClipboardHistoryOperation" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - Different operations detected by ClipboardHistory. Debounced, so different - than Clipboard.Read, Clipboard.Write. Any clipboard copy detected here will - result in a new entry in ClipboardHistory. Recorded after a clipboard read - or write is debounced in ClipboardHistory. Warning: This histogram was - expired from 2022-01-02 to 2022-01-05; data may be missing. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.PasteType" - enum="ClipboardHistoryPasteType" expires_after="2022-12-25"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - Emits information about the type (plain vs. rich text) and input source of - each clipboard history paste. - </summary> -</histogram> - -<histogram name="Ash.ClipboardHistory.ReorderType" - enum="ClipboardHistoryReorderType" expires_after="2023-02-12"> - <owner>ckincaid@chromium.org</owner> - <owner>multipaste@google.com</owner> - <summary> - Each time the clipboard history list is reordered, the operation (copy or - paste) initiating that reorder is emitted here. - </summary> -</histogram> - <histogram name="Ash.DarkTheme.Settings.IsDarkModeEnabled" enum="Boolean" expires_after="2023-03-01"> <obsolete>
diff --git a/tools/metrics/histograms/metadata/ash_clipboard/OWNERS b/tools/metrics/histograms/metadata/ash_clipboard/OWNERS new file mode 100644 index 0000000..e5966356 --- /dev/null +++ b/tools/metrics/histograms/metadata/ash_clipboard/OWNERS
@@ -0,0 +1,6 @@ +per-file OWNERS=file://tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS + +# Prefer sending CLs to the owners listed below. +# Use chromium-metrics-reviews@google.com as a backup. +ckincaid@chromium.org +dmblack@google.com
diff --git a/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml new file mode 100644 index 0000000..27205c81 --- /dev/null +++ b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml
@@ -0,0 +1,264 @@ +<!-- +Copyright 2022 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<!-- +This file is used to generate a comprehensive list of ChromeOS clipboard-related +histograms along with a detailed description for each histogram. + +For best practices on writing histogram descriptions, see +https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md + +Please follow the instructions in the OWNERS file in this directory to find a +reviewer. If no OWNERS file exists, please consider signing up at +go/reviewing-metrics (Googlers only), as all subdirectories are expected to +have an OWNERS file. As a last resort you can send the CL to +chromium-metrics-reviews@google.com. +--> + +<histogram-configuration> + +<histograms> + +<histogram name="Ash.Clipboard.ConsecutiveCopies" units="times" + expires_after="2022-10-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of consecutive copies in the user session, recorded when a paste + occurs. Warning: This histogram was expired from 2021-09-01 to 2022-01-05; + data may be missing. + </summary> +</histogram> + +<histogram name="Ash.Clipboard.ConsecutivePastes" units="times" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of consecutive pastes in the user session, recorded when a copy + occurs. Includes pastes from Clipboard History. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ConsecutivePastes" units="times" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of consecutive pastes from the clipboard history menu. The count + is reset after a copy or a paste that is not through the clipboard history + menu (such as pressing ctrl-v accelerator or clicking at a context menu + option). Warning: This histogram was expired from 2022-01-02 to 2022-01-05; + data may be missing. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatDeleted" + enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The format of the ClipboardHistoryItemView that was deleted from the + Clipboard History menu. Logged on ClipboardHistoryItemView::ButtonPressed(). + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatPasted" + enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The format of the ClipboardHistoryItemView that was pasted from the + Clipboard History menu. Logged on ClipboardHistoryItemView::ButtonPressed(). + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.DisplayFormatShown" + enum="ClipboardHistoryDisplayFormat" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The format of the view used to display clipboard data. Logged when the view + is created. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.MenuOptionSelected" + units="index" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The command ID index within the Clipboard History contextual menu that was + selected by the user. Recorded when the menu item is selected. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.NumberOfItemsShown" + units="Items Shown" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of clipboard history items shown in the clipboard history + contextual menu. Recorded when the clipboard history contextual menu model + is built. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.ShowMenu" + enum="ClipboardHistoryTriggerType" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + It records how many times users trigger the clipboard history menu through + different ways respecitvely. Recorded when the clipboard history menu shows. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.ShowPlaceholderString" + enum="ClipboardHistoryPlaceholderStringType" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of placeholder strings shown to users in lieu of actual data, + broken down by placeholder string type. Recorded when the label is requested + from ClipboardHistoryResourceManager. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ContextMenu.UserJourneyTime" units="ms" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The length of the user journey of the context menu version of clipboard + history. Measured as time from starting to construct the menu, to time of + the menu being closed. Recorded every time the menu is closed, regardless of + whether the user selected one of the menu options. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ControlToVDelay" units="ms" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The time between a user pressing control and V when pasting via keyboard. + Recorded in AcceleratorHistory when a V is pressed. Only recorded for the + first pressed V in a sequence, for example: User holds control, waits 200ms, + presses V (histogram logged), presses V again without releasing control (no + histogram logged). This metric is used to set a baseline for an experimental + keyboard combination where a user holds control, then presses V after a + delay to show multipaste. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ImageModelRequest.Lifetime" units="ms" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The lifetime of the ClipboardImageModelRequest object. Logged in the dtor of + ClipboardImageModelRequest. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ImageModelRequest.Runtime" units="ms" + expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The runtime of a request in a ClipboardImageModelRequest. Logged from when + the ClipboardImageModelRequest is Start()-ed to when it is Stop()-ed. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ImageModelRequest.StopReason" + enum="RequestStopReason" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The reason a ClipboardImageModelRequest is stopped. Logged when a request is + Stop()-ed. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.Nudges.{NudgeType}.ShownCount" + enum="BooleanHit" expires_after="2022-10-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of times the clipboard history {NudgeType} has been shown. This + number will be used as the baseline against the number of emits of the + ToFeaturePasteTime and ToFeatureOpenTime histograms. + </summary> + <token key="NudgeType"> + <variant name="NewFeatureBadge" summary="new feature badge"/> + <variant name="OnboardingNudge" summary="onboarding nudge"/> + <variant name="ScreenshotNotificationNudge" + summary="screenshot notification nudge"/> + <variant name="ZeroStateNudge" summary="zero state nudge"/> + </token> +</histogram> + +<histogram name="Ash.ClipboardHistory.Nudges.{NudgeType}.ToFeature{Action}Time" + units="seconds" expires_after="2022-10-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The number of seconds between the user being shown the clipboard history + {NudgeType} and {Action}. The number of emits to this histogram will also be + used to measure the conversion rate by comparing it to ShownCount histogram + </summary> + <token key="NudgeType"> + <variant name="NewFeatureBadge" summary="new feature badge"/> + <variant name="OnboardingNudge" summary="onboarding nudge"/> + <variant name="ScreenshotNotificationNudge" + summary="screenshot notification nudge"/> + <variant name="ZeroStateNudge" summary="zero state nudge"/> + </token> + <token key="Action"> + <variant name="Open" summary="opening the clipboard history menu"/> + <variant name="Paste" + summary="using the clipboard history to paste something"/> + </token> +</histogram> + +<histogram name="Ash.ClipboardHistory.Operation" + enum="ClipboardHistoryOperation" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + Different operations detected by ClipboardHistory. Debounced, so different + than Clipboard.Read, Clipboard.Write. Any clipboard copy detected here will + result in a new entry in ClipboardHistory. Recorded after a clipboard read + or write is debounced in ClipboardHistory. Warning: This histogram was + expired from 2022-01-02 to 2022-01-05; data may be missing. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.PasteType" + enum="ClipboardHistoryPasteType" expires_after="2022-12-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + Emits information about the type (plain vs. rich text) and input source of + each clipboard history paste. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ReorderType" + enum="ClipboardHistoryReorderType" expires_after="2023-02-12"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + Each time the clipboard history list is reordered, the operation (copy or + paste) initiating that reorder is emitted here. + </summary> +</histogram> + +</histograms> + +</histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/assistant/histograms.xml b/tools/metrics/histograms/metadata/assistant/histograms.xml index 32fcb65..2ddc5d9 100644 --- a/tools/metrics/histograms/metadata/assistant/histograms.xml +++ b/tools/metrics/histograms/metadata/assistant/histograms.xml
@@ -210,8 +210,10 @@ </histogram> <histogram name="Assistant.ServiceStartTime" units="ms" - expires_after="2022-08-29"> + expires_after="2023-08-15"> <owner>updowndota@chromium.org</owner> + <owner>xiaohuic@chromium.org</owner> + <owner>assistive-eng@google.com</owner> <summary>Amount of time spent in starting Assistant service.</summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml index f4a5b90..6ecbd8c 100644 --- a/tools/metrics/histograms/metadata/browser/histograms.xml +++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -92,7 +92,8 @@ <summary> Records the overall satisfaction score for HaTS, to be analyzed against other OS metrics like performance or number of crashes. There is one score - per survey type. + per survey type. Emitted when a user answers the first question on a HaTS + survey. </summary> <token key="Survey"> <variant name=".ArcGames"/> @@ -106,6 +107,7 @@ <variant name=".PersonalizationAvatar"/> <variant name=".PersonalizationScreensaver"/> <variant name=".PersonalizationWallpaper"/> + <variant name=".PhotosExperience"/> <variant name=".SmartLock"/> <variant name=".Stability"/> <variant name=".Unlock"/>
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml index 541d306..cdb20803 100644 --- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml +++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -70,6 +70,9 @@ summary="Chrome Home shown after a pull-to-refresh"/> <variant name="IPH_ContextualPageActions_PriceTracking" summary="contextual page price tracking action in the top toolbar"/> + <variant name="IPH_ContextualPageActions_PriceTrackingActionChip" + summary="action chip variant of contextual page price tracking action + in the top toolbar"/> <variant name="IPH_ContextualSearchInPanelHelp" summary="promoting longpress from within the panel"/> <variant name="IPH_ContextualSearchOptIn" @@ -159,6 +162,8 @@ <variant name="IPH_NewTab" summary="new tab"/> <variant name="IPH_NewTabPageHomeButton" summary="new tab page button"/> <variant name="IPH_NewTabTip" summary="new tab tip"/> + <variant name="IPH_OverflowMenuTip" + summary="the Overflow Menu help tip on iOS"/> <variant name="IPH_PageInfo" summary="opening PageInfo"/> <variant name="IPH_PageInfoStoreInfo" summary="PageInfoStoreInfo feature"/> <variant name="IPH_PasswordsAccountStorage"
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml index 0a0c7f0..2f22e88c 100644 --- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -6502,6 +6502,14 @@ <histogram_suffixes name="PageLoadMetricsClientsLoadingPredictor" separator="." ordering="prefix"> + <obsolete> + These suffixes are used to record metrics if LoadingPredictor enabled. As + part of crbug.com/1317494, this suffix is replaced by + Clients.LoadingPredictor2. The difference are 1. + *.Clients.LoadingPredictor2.* include samples from prerendered pages and 2. + the value of the UMAs are modified as activation origined for prerendered + pages. + </obsolete> <suffix base="true" name="Clients.LoadingPredictor" label="PageLoadMetrics with enabled LoadingPredictor"/> <affected-histogram @@ -6510,6 +6518,18 @@ name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/> </histogram_suffixes> +<histogram_suffixes name="PageLoadMetricsClientsLoadingPredictor2" + separator="." ordering="prefix"> + <suffix base="true" name="Clients.LoadingPredictor2" + label="PageLoadMetrics with enabled LoadingPredictor. If the page is + prerendered, the recorded value is modified as activation + origined."/> + <affected-histogram + name="PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/> + <affected-histogram + name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/> +</histogram_suffixes> + <histogram_suffixes name="PageLoadMetricsClientsLoadingPredictorPredictionType" separator="."> <suffix name="Preconnectable" @@ -6519,6 +6539,10 @@ name="PageLoad.Clients.LoadingPredictor.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/> <affected-histogram name="PageLoad.Clients.LoadingPredictor.PaintTiming.NavigationToFirstContentfulPaint"/> + <affected-histogram + name="PageLoad.Clients.LoadingPredictor2.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/> + <affected-histogram + name="PageLoad.Clients.LoadingPredictor2.PaintTiming.NavigationToFirstContentfulPaint"/> </histogram_suffixes> <histogram_suffixes name="PageLoadMetricsClientsMedia" separator="." @@ -7050,6 +7074,7 @@ <affected-histogram name="PasswordProtection.InterstitialAction"/> <affected-histogram name="PasswordProtection.ModalWarningDialogAction"/> <affected-histogram name="PasswordProtection.PageInfoAction"/> + <affected-histogram name="PasswordProtection.PasswordAlertModeOutcome"/> <affected-histogram name="PasswordProtection.RequestOutcome"/> <affected-histogram name="PasswordProtection.Verdict"/> </histogram_suffixes>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 104b91d..f12ecdb 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1542,6 +1542,17 @@ </summary> </histogram> +<histogram name="Prerender.Experimental.ActivationNavigationParamsMatch" + enum="PrerenderActivationNavigationParamsMatch" expires_after="2022-12-05"> + <owner>nhiroki@chromium.org</owner> + <owner>chrome-prerendering@google.com</owner> + <summary> + Records the mismatched parameters between the prerender initial navigation + parameters and the prerender activation navigation parameters. Recorded by + PrerenderHost in the browser process when comparing these two parameters. + </summary> +</histogram> + <histogram name="Prerender.Experimental.DefaultSearchEngine.SearchTermExtractorCorrectness" enum="Boolean" expires_after="2022-07-27">
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml index 83bdc8b8..20540ee 100644 --- a/tools/metrics/histograms/metadata/omnibox/histograms.xml +++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -642,6 +642,24 @@ </summary> </histogram> +<histogram name="Omnibox.EnteredKeywordModeByEngineType" + enum="OmniboxBuiltinEngineType" expires_after="2023-08-15"> + <owner>yoangela@chromium.org</owner> + <owner>chrome-omnibox-team@google.com</owner> + <summary> + Records number of times users enters keyword mode enumerated by the type of + search engine (whether the engine is "built-in"). This is logged + whenever Omnibox.EnteredKeywordMode2 is logged. See also + Omnibox.AcceptedKeywordModeByEngineType for the total number of times a user + completes a search while still in keyword mode. + + Logged each time the user enters keyword mode. If a user enters, then + leaves, then re-enters keyword mode during the same session (i.e. without + selecting a navigtaion), this is logged twice. If the user doesn't accept + the keyword suggestion, this is still logged. + </summary> +</histogram> + <histogram name="Omnibox.Escape" enum="OmniboxEscapeAction" expires_after="2023-02-12"> <owner>manukh@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 0bd10b7a..d3aa461 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -12344,7 +12344,7 @@ </summary> </histogram> -<histogram name="Shutdown.BrowserExit.Time" units="ms" expires_after="M107"> +<histogram name="Shutdown.BrowserExit.Time" units="ms" expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary> @@ -12352,8 +12352,7 @@ </summary> </histogram> -<histogram name="Shutdown.EndSession.Time" units="ms" - expires_after="2023-01-01"> +<histogram name="Shutdown.EndSession.Time" units="ms" expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary> @@ -12362,7 +12361,7 @@ </summary> </histogram> -<histogram name="Shutdown.NotValid.Time" units="ms" expires_after="M107"> +<histogram name="Shutdown.NotValid.Time" units="ms" expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary> @@ -12373,7 +12372,7 @@ </histogram> <histogram name="Shutdown.Renderers.Slow" units="renderers" - expires_after="M107"> + expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary> @@ -12383,7 +12382,7 @@ </histogram> <histogram name="Shutdown.Renderers.Total" units="renderers" - expires_after="M107"> + expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary> @@ -12392,20 +12391,19 @@ </histogram> <histogram name="Shutdown.ShutdownType" enum="ShutdownType" - expires_after="2022-12-18"> + expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary>The type of the last shutdown.</summary> </histogram> -<histogram name="Shutdown.SilentExit.Time" units="ms" expires_after="M107"> +<histogram name="Shutdown.SilentExit.Time" units="ms" expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary>Time for shutdown for a silent exit.</summary> </histogram> -<histogram name="Shutdown.WindowClose.Time" units="ms" - expires_after="2022-12-18"> +<histogram name="Shutdown.WindowClose.Time" units="ms" expires_after="M110"> <owner>etienneb@chromium.org</owner> <owner>gab@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/quick_answers/histograms.xml b/tools/metrics/histograms/metadata/quick_answers/histograms.xml index 815d8d6..06d17aeb 100644 --- a/tools/metrics/histograms/metadata/quick_answers/histograms.xml +++ b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
@@ -137,7 +137,7 @@ </histogram> <histogram name="QuickAnswers.ExitPoint" enum="QuickAnswersExitPoint" - expires_after="2022-09-01"> + expires_after="2023-08-15"> <owner>updowndota@chromium.org</owner> <owner>croissant-eng@chromium.org</owner> <summary> @@ -204,7 +204,7 @@ </histogram> <histogram name="QuickAnswers.RequestTextLength.{IntentType}" - units="characters" expires_after="2022-09-01"> + units="characters" expires_after="2023-08-15"> <owner>updowndota@chromium.org</owner> <owner>croissant-eng@chromium.org</owner> <summary> @@ -279,7 +279,7 @@ <histogram name="QuickAnswers.V2.Consent.Duration{QuickAnswersV2ConsentResultType}" - units="ms" expires_after="2022-09-01"> + units="ms" expires_after="2023-08-15"> <owner>updowndota@chromium.org</owner> <owner>croissant-eng@chromium.org</owner> <summary> @@ -292,7 +292,7 @@ <histogram name="QuickAnswers.V2.Consent.Impression{QuickAnswersV2ConsentResultType}" - units="impressions" expires_after="2022-09-01"> + units="impressions" expires_after="2023-08-15"> <owner>updowndota@chromium.org</owner> <owner>croissant-eng@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml index 64c2397f6..1804a13 100644 --- a/tools/metrics/histograms/metadata/service/histograms.xml +++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -386,6 +386,17 @@ </summary> </histogram> +<histogram name="ServiceWorker.FetchHandler.SkipReason" + enum="ServiceWorkerFetchHandlerSkipReason" expires_after="2023-06-30"> + <owner>yyanagisawa@chromium.org</owner> + <owner>chrome-worker@google.com</owner> + <summary> + The reason why the service worker fetch handler has been skipped. If the + fetch handler has not been skipped for any reasons, it is just recorded as + not skipped instead. + </summary> +</histogram> + <histogram name="ServiceWorker.InstallEvent.All.FetchCount" units="fetches" expires_after="2023-01-26"> <owner>wanderview@chromium.org</owner> @@ -713,6 +724,17 @@ </summary> </histogram> +<histogram name="ServiceWorker.NumberOfRegisteredFetchHandlers" + units="handlers" expires_after="2023-06-30"> + <owner>yyanagisawa@chromium.org</owner> + <owner>chrome-worker@google.com</owner> + <summary> + The number of fetch handlers registered in a service worker script. This + metrics is recorded every time a service worker starts and only includes + fetch event handlers registered at script evaluation time. + </summary> +</histogram> + <histogram name="ServiceWorker.OnBrowserStartup.FirstFindRegistrationForClientUrl.Time" units="ms" expires_after="2023-02-12">
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml index ab2f57d..d49153ae 100644 --- a/tools/metrics/histograms/metadata/v8/histograms.xml +++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -368,6 +368,22 @@ </summary> </histogram> +<histogram name="V8.ExternalPointerTableCompactionOutcome" + enum="V8ExternalPointerTableCompactionOutcome" expires_after="2023-02-12"> + <owner>saelo@chromium.org</owner> + <owner>ishell@chromium.org</owner> + <summary> + The outcome of external pointer table compaction. + + External pointer table compaction may only succeed partially or fail + entirely if the application allocates lots of external pointer table entries + while the table is being compacted. This histogram records this outcome at + the end of a table-compacting GC. The frequency of such failures influences + the heuristics used to decide when to compact the table, and to some degree + also the compaction algorithm itself. + </summary> +</histogram> + <histogram name="V8.GC.Cycle.CollectionRate.Full" units="%" expires_after="M109"> <owner>nikolaos@chromium.org</owner>
diff --git a/tools/metrics/histograms/validate_format.py b/tools/metrics/histograms/validate_format.py index 278206b9..a12d2037 100755 --- a/tools/metrics/histograms/validate_format.py +++ b/tools/metrics/histograms/validate_format.py
@@ -15,7 +15,7 @@ # The allowlist of namespaces that are split across multiple files. _NAMESPACES_IN_MULTIPLE_FILES = [ - 'chromeos', 'fcminvalidations', 'graphics', 'launch' + 'ash', 'chromeos', 'fcminvalidations', 'graphics', 'launch' ]
diff --git a/ui/accessibility/ax_tree_manager.cc b/ui/accessibility/ax_tree_manager.cc index f9f1a3e..311c239 100644 --- a/ui/accessibility/ax_tree_manager.cc +++ b/ui/accessibility/ax_tree_manager.cc
@@ -67,6 +67,24 @@ tree_observation_.Observe(ax_tree()); } +AXTreeID AXTreeManager::GetTreeID() const { + return ax_tree_ ? ax_tree_->data().tree_id : AXTreeIDUnknown(); +} + +AXTreeID AXTreeManager::GetParentTreeID() const { + return ax_tree_ ? ax_tree_->data().parent_tree_id : AXTreeIDUnknown(); +} + +AXNode* AXTreeManager::GetRootAsAXNode() const { + return ax_tree_ ? ax_tree_->root() : nullptr; +} + +void AXTreeManager::WillBeRemovedFromMap() { + if (!ax_tree_) + return; + ax_tree_->NotifyTreeManagerWillBeRemoved(ax_tree_id_); +} + AXTreeManager::~AXTreeManager() { // Stop observing so we don't get a callback for every node being deleted. event_generator_.ReleaseTree();
diff --git a/ui/accessibility/ax_tree_manager.h b/ui/accessibility/ax_tree_manager.h index eaea8876..df43f35 100644 --- a/ui/accessibility/ax_tree_manager.h +++ b/ui/accessibility/ax_tree_manager.h
@@ -43,14 +43,14 @@ virtual AXNode* GetNodeFromTree(const AXNodeID node_id) const = 0; // Returns the tree id of the tree managed by this AXTreeManager. - virtual AXTreeID GetTreeID() const = 0; + AXTreeID GetTreeID() const; // Returns the tree id of the parent tree. // Returns AXTreeIDUnknown if this tree doesn't have a parent tree. - virtual AXTreeID GetParentTreeID() const = 0; + virtual AXTreeID GetParentTreeID() const; // Returns the AXNode that is at the root of the current tree. - virtual AXNode* GetRootAsAXNode() const = 0; + AXNode* GetRootAsAXNode() const; // If this tree has a parent tree, returns the node in the parent tree that // hosts the current tree. Returns nullptr if this tree doesn't have a parent @@ -59,7 +59,7 @@ // Called when the tree manager is about to be removed from the tree map, // `AXTreeManagerMap`. - virtual void WillBeRemovedFromMap() {} + void WillBeRemovedFromMap(); const AXTreeID& ax_tree_id() const { return ax_tree_id_; } AXTree* ax_tree() const { return ax_tree_.get(); }
diff --git a/ui/accessibility/test_ax_tree_manager.cc b/ui/accessibility/test_ax_tree_manager.cc index 6a6e074..392ba91 100644 --- a/ui/accessibility/test_ax_tree_manager.cc +++ b/ui/accessibility/test_ax_tree_manager.cc
@@ -69,18 +69,6 @@ return ax_tree_ ? ax_tree_->GetFromId(node_id) : nullptr; } -AXTreeID TestAXTreeManager::GetTreeID() const { - return ax_tree_ ? ax_tree_->data().tree_id : AXTreeIDUnknown(); -} - -AXTreeID TestAXTreeManager::GetParentTreeID() const { - return ax_tree_ ? ax_tree_->data().parent_tree_id : AXTreeIDUnknown(); -} - -AXNode* TestAXTreeManager::GetRootAsAXNode() const { - return ax_tree_ ? ax_tree_->root() : nullptr; -} - AXNode* TestAXTreeManager::GetParentNodeFromParentTreeAsAXNode() const { AXTreeID parent_tree_id = GetParentTreeID(); TestAXTreeManager* parent_manager =
diff --git a/ui/accessibility/test_ax_tree_manager.h b/ui/accessibility/test_ax_tree_manager.h index ecb0bf4..a3299a3 100644 --- a/ui/accessibility/test_ax_tree_manager.h +++ b/ui/accessibility/test_ax_tree_manager.h
@@ -47,9 +47,6 @@ AXNode* GetNodeFromTree(const AXTreeID tree_id, const AXNodeID node_id) const override; AXNode* GetNodeFromTree(const AXNodeID node_id) const override; - AXTreeID GetTreeID() const override; - AXTreeID GetParentTreeID() const override; - AXNode* GetRootAsAXNode() const override; AXNode* GetParentNodeFromParentTreeAsAXNode() const override; };
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc index 95900db..7862a874 100644 --- a/ui/aura/window_event_dispatcher_unittest.cc +++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -401,16 +401,22 @@ } TEST_F(WindowEventDispatcherTest, DontIgnoreUnknownKeys) { + ui::Event::Properties properties; + properties.emplace(ui::kPropertyKeyboardImeFlag, + std::vector<uint8_t>{ui::kPropertyKeyboardImeIgnoredFlag}); + ConsumeKeyHandler handler; root_window()->AddPreTargetHandler(&handler); ui::KeyEvent unknown_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_NONE); + unknown_event.SetProperties(properties); DispatchEventUsingWindowDispatcher(&unknown_event); EXPECT_TRUE(unknown_event.handled()); EXPECT_EQ(1, handler.num_key_events()); handler.Reset(); ui::KeyEvent known_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); + known_event.SetProperties(properties); DispatchEventUsingWindowDispatcher(&known_event); EXPECT_TRUE(known_event.handled()); EXPECT_EQ(1, handler.num_key_events()); @@ -418,6 +424,7 @@ handler.Reset(); ui::KeyEvent ime_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_IME_FABRICATED_KEY); + ime_event.SetProperties(properties); DispatchEventUsingWindowDispatcher(&ime_event); EXPECT_TRUE(ime_event.handled()); EXPECT_EQ(1, handler.num_key_events()); @@ -426,6 +433,7 @@ ui::KeyEvent unknown_key_with_char_event(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, ui::EF_NONE); unknown_key_with_char_event.set_character(0x00e4 /* "ä" */); + unknown_key_with_char_event.SetProperties(properties); DispatchEventUsingWindowDispatcher(&unknown_key_with_char_event); EXPECT_TRUE(unknown_key_with_char_event.handled()); EXPECT_EQ(1, handler.num_key_events()); @@ -440,6 +448,11 @@ ui::test::TestEventHandler handler; w1->AddPreTargetHandler(&handler); ui::KeyEvent key_press(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); + ui::Event::Properties properties; + properties.emplace(ui::kPropertyKeyboardImeFlag, + std::vector<uint8_t>{ui::kPropertyKeyboardImeIgnoredFlag}); + key_press.SetProperties(properties); + DispatchEventUsingWindowDispatcher(&key_press); EXPECT_TRUE(key_press.handled()); EXPECT_EQ(1, handler.num_key_events());
diff --git a/ui/base/ime/ash/input_method_ash.cc b/ui/base/ime/ash/input_method_ash.cc index e67ef5a2..3d0d6c0 100644 --- a/ui/base/ime/ash/input_method_ash.cc +++ b/ui/base/ime/ash/input_method_ash.cc
@@ -648,9 +648,16 @@ DCHECK(client); if (pending_commit_) { - if (pending_commit_->text.empty()) { + if (handled && NeedInsertChar()) { + for (const auto& ch : pending_commit_->text) { + KeyEvent ch_event(ET_KEY_PRESSED, VKEY_UNKNOWN, EF_NONE); + ch_event.set_character(ch); + client->InsertChar(ch_event); + } + } else if (pending_commit_->text.empty()) { client->InsertText( u"", TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); + composing_text_ = false; } else { // Split the commit into two separate commits, one for the substring // before the cursor and one for the substring after. @@ -668,8 +675,8 @@ after_cursor, TextInputClient::InsertTextCursorBehavior::kMoveCursorBeforeText); } + composing_text_ = false; } - composing_text_ = false; typing_session_manager_.CommitCharacters(pending_commit_->text.length()); }
diff --git a/ui/base/ime/ash/input_method_ash_unittest.cc b/ui/base/ime/ash/input_method_ash_unittest.cc index 02e4d4a..5eb42d06 100644 --- a/ui/base/ime/ash/input_method_ash_unittest.cc +++ b/ui/base/ime/ash/input_method_ash_unittest.cc
@@ -1023,7 +1023,7 @@ u"A", TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); - EXPECT_EQ(u"", inserted_text_); + EXPECT_EQ(0, inserted_char_); // Do callback. std::move(mock_ime_engine_handler_->last_passed_callback()).Run(true); @@ -1036,7 +1036,7 @@ EXPECT_EQ(kFlags, stored_event.flags()); EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled); - EXPECT_EQ(u"A", inserted_text_); + EXPECT_EQ(L'A', inserted_char_); } TEST_F(InputMethodAshKeyEventTest, MultiKeyEventDelayResponseTest) { @@ -1203,7 +1203,7 @@ std::move(mock_ime_engine_handler_->last_passed_callback()) .Run(/*handled=*/true); - EXPECT_EQ(u"a", inserted_text_); + EXPECT_EQ(L'a', inserted_char_); EXPECT_EQ(gfx::Range(0, 1), GetAutocorrectRange()); }
diff --git a/ui/base/ime/init/input_method_initializer.cc b/ui/base/ime/init/input_method_initializer.cc index 0fc2aab1..5a6944c 100644 --- a/ui/base/ime/init/input_method_initializer.cc +++ b/ui/base/ime/init/input_method_initializer.cc
@@ -33,8 +33,7 @@ } void InitializeInputMethodForTesting() { -#if !BUILDFLAG(IS_CHROMEOS_ASH) && defined(USE_AURA) && \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) +#if defined(USE_AURA) && BUILDFLAG(IS_LINUX) GetInputMethodContextFactoryForTest() = base::BindRepeating([](LinuxInputMethodContextDelegate* delegate) -> std::unique_ptr<LinuxInputMethodContext> {
diff --git a/ui/base/interaction/interaction_sequence.cc b/ui/base/interaction/interaction_sequence.cc index 5967b8c..3626c43f 100644 --- a/ui/base/interaction/interaction_sequence.cc +++ b/ui/base/interaction/interaction_sequence.cc
@@ -863,4 +863,44 @@ return element ? element->context() : context(); } +void PrintTo(InteractionSequence::StepType step_type, std::ostream* os) { + const char* const kStepTypeNames[] = { + "StepType::kShown", "StepType::kActivated", "StepType::kHidden", + "StepType::kCustomEvent"}; + constexpr int kCount = sizeof(kStepTypeNames) / sizeof(kStepTypeNames[0]); + static_assert(kCount == + static_cast<int>(InteractionSequence::StepType::kMaxValue) + 1); + const int value = static_cast<int>(step_type); + *os << ((value < 0 || value >= kCount) ? "[invalid StepType]" + : kStepTypeNames[value]); +} + +void PrintTo(InteractionSequence::AbortedReason reason, std::ostream* os) { + const char* const kAbortedReasonNames[] = { + "AbortedReason::kSequenceDestroyed", + "AbortedReason::kElementHiddenBeforeSequenceStart", + "AbortedReason::kElementNotVisibleAtStartOfStep", + "AbortedReason::kElementHiddenDuringStep"}; + constexpr int kCount = + sizeof(kAbortedReasonNames) / sizeof(kAbortedReasonNames[0]); + static_assert( + kCount == + static_cast<int>(InteractionSequence::AbortedReason::kMaxValue) + 1); + const int value = static_cast<int>(reason); + *os << ((value < 0 || value >= kCount) ? "[invalid StepType]" + : kAbortedReasonNames[value]); +} + +extern std::ostream& operator<<(std::ostream& os, + InteractionSequence::StepType step_type) { + PrintTo(step_type, &os); + return os; +} + +extern std::ostream& operator<<(std::ostream& os, + InteractionSequence::AbortedReason reason) { + PrintTo(reason, &os); + return os; +} + } // namespace ui
diff --git a/ui/base/interaction/interaction_sequence.h b/ui/base/interaction/interaction_sequence.h index 392f38e..05fb1c0 100644 --- a/ui/base/interaction/interaction_sequence.h +++ b/ui/base/interaction/interaction_sequence.h
@@ -74,7 +74,9 @@ // Represents a custom event with a specific custom event type. You may // further specify a required element name or ID to filter down which // events you actually want to step on vs. ignore. - kCustomEvent + kCustomEvent, + // Update this if values are added to the enumeration. + kMaxValue = kCustomEvent }; // Details why a sequence was aborted. @@ -86,7 +88,9 @@ // An element should have been visible at the start of a step but was not. kElementNotVisibleAtStartOfStep, // An element should have remained visible during a step but did not. - kElementHiddenDuringStep + kElementHiddenDuringStep, + // Update this if values are added to the enumeration. + kMaxValue = kElementHiddenDuringStep }; // Callback when a step in the sequence starts. If |element| is no longer @@ -408,6 +412,21 @@ base::WeakPtrFactory<InteractionSequence> weak_factory_{this}; }; +COMPONENT_EXPORT(UI_BASE) +extern void PrintTo(InteractionSequence::StepType step_type, std::ostream* os); + +COMPONENT_EXPORT(UI_BASE) +extern void PrintTo(InteractionSequence::AbortedReason reason, + std::ostream* os); + +COMPONENT_EXPORT(UI_BASE) +extern std::ostream& operator<<(std::ostream& os, + InteractionSequence::StepType step_type); + +COMPONENT_EXPORT(UI_BASE) +extern std::ostream& operator<<(std::ostream& os, + InteractionSequence::AbortedReason reason); + } // namespace ui #endif // UI_BASE_INTERACTION_INTERACTION_SEQUENCE_H_
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5 index 7ab7b4c..fa5f746 100644 --- a/ui/chromeos/styles/cros_sys_colors.json5 +++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -130,6 +130,15 @@ generate_per_mode: true, }, + 'sys-base': { + light: '$cros.ref.neutralvariant90', + dark: '$cros.ref.neutralvariant0', + }, + 'sys-base-elevated': { + light: 'rgba($cros.sys.surface3.rgb, 0.9)', + dark: 'rgba($cros.sys.surface3.rgb, 0.9)', + }, + /* Surfaces */ surface: { light: '$cros.ref.neutral99', @@ -171,6 +180,19 @@ light: '$cros.ref.neutral95', dark: 'rgba($cros.ref.neutral0.rgb, 0.6)' }, + 'sys-on-base': { + light: '$cros.ref.neutralvariant95', + dark: 'rgba($cros.ref.neutralvariant40.rgb, 0.4)', + }, + 'sys-primary-container': { + light: '$cros.ref.primary80', + dark: '$cros.ref.primary80', + }, + 'sys-on-primary-container': { + light: '$cros.ref.primary10', + dark: '$cros.ref.primary10', + }, + /* Text and icons */ 'on-surface': {
diff --git a/ui/file_manager/file_manager/background/js/trash.js b/ui/file_manager/file_manager/background/js/trash.js index 8fd4d6f..107c174 100644 --- a/ui/file_manager/file_manager/background/js/trash.js +++ b/ui/file_manager/file_manager/background/js/trash.js
@@ -232,7 +232,8 @@ const infoEntry = await this.writeTrashInfoFile_( trashDirs.info, trashInfoName, path, deletionDate); const filesEntry = await this.moveTo_(entry, trashDirs.files, name); - return new TrashEntry(entry.name, deletionDate, filesEntry, infoEntry); + return new TrashEntry( + entry.name, deletionDate, filesEntry, infoEntry, entry); } /**
diff --git a/ui/file_manager/file_manager/common/js/api.js b/ui/file_manager/file_manager/common/js/api.js index b946b5c..fd0a55b5 100644 --- a/ui/file_manager/file_manager/common/js/api.js +++ b/ui/file_manager/file_manager/common/js/api.js
@@ -230,3 +230,14 @@ return promisify( chrome.fileManagerPrivate.startIOTask, type, entries, params); } + +/** + * Parses .trashinfo files to retrieve the restore path and deletion date. + * @param {!Array<!Entry>} entries + * @returns {!Promise<!Array<!chrome.fileManagerPrivate.ParsedTrashInfoFile>>} + */ +export async function parseTrashInfoFiles(entries) { + return promisify( + chrome.fileManagerPrivate.parseTrashInfoFiles, + entries.map(e => util.unwrapEntry(e))); +}
diff --git a/ui/file_manager/file_manager/common/js/trash.js b/ui/file_manager/file_manager/common/js/trash.js index 6081806..d12a4af 100644 --- a/ui/file_manager/file_manager/common/js/trash.js +++ b/ui/file_manager/file_manager/common/js/trash.js
@@ -22,9 +22,9 @@ import {FilesAppEntry} from '../../externs/files_app_entry_interfaces.js'; import {VolumeManager} from '../../externs/volume_manager.js'; +import {parseTrashInfoFiles} from './api.js'; import {FakeEntryImpl} from './files_app_entry_types.js'; import {metrics} from './metrics.js'; -import {str} from './util.js'; import {VolumeManagerCommon} from './volume_manager_types.js'; /** @@ -172,11 +172,13 @@ * @param {!Date} deletionDate DeletionDate of deleted file from infoEntry. * @param {!Entry} filesEntry trash files entry. * @param {!FileEntry} infoEntry trash info entry. + * @param {!Entry} restoreEntry The entry to restore the item. */ - constructor(name, deletionDate, filesEntry, infoEntry) { + constructor(name, deletionDate, filesEntry, infoEntry, restoreEntry) { this.name = name; this.filesEntry = filesEntry; this.infoEntry = infoEntry; + this.restoreEntry = restoreEntry; /** @private */ this.deletionDate_ = deletionDate; @@ -362,62 +364,25 @@ * Create a trash entry if infoEntry and matching files entry are valid, else * return null. * + * @param {!chrome.fileManagerPrivate.ParsedTrashInfoFile} parsedEntry * @param {!FileEntry} infoEntry trash info entry. - * @return {!Promise<TrashEntry?>} + * @return {?TrashEntry} */ - async createTrashEntry_(infoEntry) { - const error = (msg, text = '') => { - console.warn(`${msg}: ${infoEntry.toURL()}: ${text}`); - return null; - }; - - // Ignore any directories. - if (!infoEntry.isFile) { - return error('Ignoring unexpected trash info directory'); - } - - // Ignore any files not *.trashinfo. - if (!infoEntry.name.endsWith('.trashinfo')) { - return error('Ignoring unexpected trash info file'); - } - - const fileName = infoEntry.name.substring(0, infoEntry.name.length - 10); - const filesEntry = this.filesEntries_[fileName]; - delete this.filesEntries_[fileName]; + createTrashEntry_(parsedEntry, infoEntry) { + const filesEntry = this.filesEntries_[parsedEntry.trashInfoFileName]; + delete this.filesEntries_[parsedEntry.trashInfoFileName]; // Ignore any .trashinfo file with no matching file entry. if (!filesEntry) { - return error('Ignoring trash info file with no matching files entry'); + console.warn('Ignoring trash info file with no matching files entry'); + return null; } - let text; - try { - const file = await new Promise( - (resolve, reject) => infoEntry.file(resolve, reject)); - text = await file.text(); - } catch (e) { - return error('Ignoring removed file'); - } - const path = TrashEntry.parsePath(text); - if (!path) { - return error('Ignoring trash info file with no Path', text); - } + const deletionDate = /** @type {!Date} */ (parsedEntry.deletionDate); - const deletionDate = TrashEntry.parseDeletionDate(text); - if (!deletionDate) { - return error('Ignoring trash info file with invalid DeletionDate', text); - } - - // Show the root label and the whole Path=<path> from infoEntry as the name. - // This allows users to differentiate deleted files such as /a/hello.txt and - // /b/hello.txt. - const parts = path.split('/'); - const firstSegment = this.config_.pathMap[parts[1]]; - if (firstSegment) { - parts[1] = str(firstSegment); - } - const trashName = str(this.config_.rootLabel) + parts.join(' › '); - return new TrashEntry(trashName, deletionDate, filesEntry, infoEntry); + return new TrashEntry( + parsedEntry.restoreEntry.name, deletionDate, filesEntry, infoEntry, + parsedEntry.restoreEntry); } /** @@ -455,7 +420,8 @@ if (!entries.length) { break; } - entries.forEach(entry => this.filesEntries_[entry.name] = entry); + entries.forEach( + entry => this.filesEntries_[entry.name + '.trashinfo'] = entry); } } catch (e) { console.warn('Error reading trash files entries', e); @@ -478,13 +444,29 @@ error(e); return; } + const infoEntryMap = {}; for (const e of entries) { - const trashEntry = await this.createTrashEntry_(e); + if (!e.isFile || !e.name.endsWith('.trashinfo')) { + continue; + } + infoEntryMap[e.name] = e; + } + let parsedEntries = []; + try { + parsedEntries = await parseTrashInfoFiles(entries); + } catch (e) { + console.warn('Error parsing trash info entries', e); + error(e); + return; + } + for (const parsedEntry of parsedEntries) { + const trashEntry = this.createTrashEntry_( + parsedEntry, infoEntryMap[parsedEntry.trashInfoFileName]); if (trashEntry) { result.push(trashEntry); } } - if (!entries.length || result.length) { + if (!parsedEntries.length || result.length) { break; } }
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index 6dc2737..89f0de3 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1758,6 +1758,19 @@ }; /** + * Returns a boolean indicating whether the volume is a GuestOs volume. And + * ANDROID_FILES type volume can also be a GuestOs volume if we are using + * virtio-blk. + * @param {VolumeManagerCommon.VolumeType} type + * @return {boolean} + */ +util.isGuestOs = type => { + return type === VolumeManagerCommon.VolumeType.GUEST_OS || + (type === VolumeManagerCommon.VolumeType.ANDROID_FILES && + util.isArcVirtioBlkForDataEnabled()); +}; + +/** * A kind of error that represents user electing to cancel an operation. We use * this specialization to differentiate between system errors and errors * generated through legitimate user actions.
diff --git a/ui/file_manager/file_manager/foreground/elements/files_password_dialog.js b/ui/file_manager/file_manager/foreground/elements/files_password_dialog.js index 99f73ba..246ecb7 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_password_dialog.js +++ b/ui/file_manager/file_manager/foreground/elements/files_password_dialog.js
@@ -57,9 +57,11 @@ /** * Password dialog. - * @private {!CrDialogElement} + * TODO(https://crbug.com/1353205): This type should be CrDialogElement, and + * an import of that type from cr_dialog.js should be added to this file. + * @private {!HTMLElement} */ - this.dialog_ = /** @type {!CrDialogElement} */ + this.dialog_ = /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#password-dialog')); this.dialog_.consumeKeydownEvent = true;
diff --git a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js index f85b1cf..058f60d 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js +++ b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
@@ -3,9 +3,9 @@ // found in the LICENSE file. import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {assertEquals, assertFalse, assertNotReached} from 'chrome://webui-test/chai_assert.js';
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js index d288a80..ca1b422 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip.js +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip.js
@@ -96,7 +96,7 @@ /** * Adds a target to tooltip. - * @param {!EventTarget} target + * @param {!HTMLElement} target */ addTarget: function(target) { target.addEventListener('mouseover', this.onMouseOver_.bind(this, target)); @@ -287,21 +287,27 @@ }, /** - * @param {Event} event + * @param {?HTMLElement} target Element with 'has-tooltip' attribute or null. + * @param {Event} event The event that triggered this handler. * @private */ onMouseOver_: function(target, event) { const actualTarget = target || this.visibleTooltipTarget_; - this.initShowingTooltip_(actualTarget); + if (actualTarget) { + this.initShowingTooltip_(actualTarget); + } }, /** - * @param {Event} event + * @param {?HTMLElement} target Element with 'has-tooltip' attribute or null. + * @param {Event} event The event that triggered this handler. * @private */ onMouseOut_: function(target, event) { const actualTarget = target || this.visibleTooltipTarget_; - this.initHidingTooltip_(actualTarget); + if (actualTarget) { + this.initHidingTooltip_(actualTarget); + } }, /**
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 6f24006c..71ddac3 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js
@@ -1414,8 +1414,7 @@ this.getCurrentRootType() === VolumeManagerCommon.RootType.CROSTINI) || // TODO(crbug/1293229): Don't redirect if the user is looking at a // different Guest OS folder. - (event.added[0].volumeType === - VolumeManagerCommon.VolumeType.GUEST_OS && + (util.isGuestOs(event.added[0].volumeType) && this.getCurrentRootType() === VolumeManagerCommon.RootType.GUEST_OS)) { // Resolving a display root on FSP volumes is instant, despite the // asynchronous call.
diff --git a/ui/file_manager/integration_tests/file_manager/guest_os.js b/ui/file_manager/integration_tests/file_manager/guest_os.js index 5f36c095..b802804 100644 --- a/ui/file_manager/integration_tests/file_manager/guest_os.js +++ b/ui/file_manager/integration_tests/file_manager/guest_os.js
@@ -174,9 +174,7 @@ `.tree-item[volume-type-for-testing="android_files"][entry-label="${ guestName}"]`; - // TODO(b/215255080): Change this into just one click. await remoteCall.waitAndClickElement(appId, placeholderQuery); - await remoteCall.waitAndClickElement(appId, volumeQuery); // Wait until it's loaded. await remoteCall.waitForElement(
diff --git a/ui/file_manager/integration_tests/file_manager/trash.js b/ui/file_manager/integration_tests/file_manager/trash.js index d4743bd..36277fb 100644 --- a/ui/file_manager/integration_tests/file_manager/trash.js +++ b/ui/file_manager/integration_tests/file_manager/trash.js
@@ -188,7 +188,7 @@ // Navigate to /Trash and ensure the file is shown. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); // Right-click the selected file to validate context menu. chrome.test.assertTrue(!!await remoteCall.callRemoteTestUtil( @@ -210,7 +210,7 @@ // Wait for completion of file restore. await remoteCall.waitForElementLost( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); // Navigate to /My files/Downloads and ensure the file is shown. await navigateWithDirectoryTree(appId, '/My files/Downloads'); @@ -237,7 +237,7 @@ await navigateWithDirectoryTree(appId, '/Trash'); // Select file. - await remoteCall.waitUntilSelected(appId, 'My files › Downloads › hello.txt'); + await remoteCall.waitUntilSelected(appId, 'hello.txt'); // Press 'Delete' key. chrome.test.assertTrue(!!await remoteCall.callRemoteTestUtil( @@ -245,7 +245,7 @@ // Wait for completion of file restore. await remoteCall.waitForElementLost( - appId, '.tre-row input [file-name="My files › Downloads › hello.txt"]'); + appId, '.tre-row input [file-name="hello.txt"]'); // Navigate to /My files/Downloads and ensure the file is shown. await navigateWithDirectoryTree(appId, '/My files/Downloads'); @@ -271,7 +271,7 @@ // Navigate to /Trash and ensure the file is shown. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); // Empty trash and confirm delete (dialog shown). await remoteCall.waitAndClickElement(appId, '#empty-trash-button'); @@ -280,7 +280,7 @@ // Wait for completion of file deletion. await remoteCall.waitForElementLost( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); }; /** @@ -302,7 +302,7 @@ // Navigate to /Trash and ensure the file is shown. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); // Press Ctrl+Shift+Delete key. chrome.test.assertTrue(!!await remoteCall.callRemoteTestUtil( @@ -315,7 +315,7 @@ // Wait for completion of file deletion. await remoteCall.waitForElementLost( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); }; /** @@ -337,7 +337,7 @@ // Navigate to /Trash and ensure the file is shown. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); // Delete selected item. await remoteCall.waitAndClickElement(appId, '#delete-button'); @@ -357,7 +357,7 @@ // Wait for completion of file deletion. await remoteCall.waitForElementLost( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); }; /** @@ -384,7 +384,7 @@ // hidden. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); await remoteCall.waitForElement(appId, '#tasks[hidden]'); }; @@ -413,13 +413,12 @@ // Navigate to /Trash and ensure the file is shown. await navigateWithDirectoryTree(appId, '/Trash'); await remoteCall.waitAndClickElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + appId, '#file-list [file-name="hello.txt"]'); await remoteCall.waitForElement(appId, '#tasks[hidden]'); // Double-click the file and ensure an alert dialog is displayed. await remoteCall.callRemoteTestUtil( - 'fakeMouseDoubleClick', appId, - ['#file-list [file-name="My files › Downloads › hello.txt"]']); + 'fakeMouseDoubleClick', appId, ['#file-list [file-name="hello.txt"]']); await remoteCall.waitForElement(appId, '.files-alert-dialog'); }; @@ -561,8 +560,7 @@ await navigateWithDirectoryTree(appId, '/Trash'); // Wait for the element to appear in the Trash. - await remoteCall.waitForElement( - appId, '#file-list [file-name="My files › Downloads › hello.txt"]'); + await remoteCall.waitForElement(appId, '#file-list [file-name="hello.txt"]'); }; /**
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.cc b/ui/ozone/platform/wayland/host/wayland_event_source.cc index a0c8398..33eab9fa 100644 --- a/ui/ozone/platform/wayland/host/wayland_event_source.cc +++ b/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -120,16 +120,16 @@ WaylandEventSource::PointerScrollData::operator=(PointerScrollData&&) = default; // WaylandEventSource::PointerFrame implementation -WaylandEventSource::PointerFrame::PointerFrame(const MouseEvent& e, +WaylandEventSource::PointerFrame::PointerFrame(const Event& e, base::OnceCallback<void()> cb) : event(e.Clone()), completion_cb(std::move(cb)) {} WaylandEventSource::PointerFrame::~PointerFrame() = default; // WaylandEventSource::TouchFrame implementation -WaylandEventSource::TouchFrame::TouchFrame(const TouchEvent& e, +WaylandEventSource::TouchFrame::TouchFrame(const Event& e, base::OnceCallback<void()> cb) - : event(e), completion_cb(std::move(cb)) {} + : event(e.Clone()), completion_cb(std::move(cb)) {} WaylandEventSource::TouchFrame::~TouchFrame() = default; @@ -537,16 +537,16 @@ // In case there are touch stylus information, override the current 'event' // instance, given that PointerDetails is 'const'. - auto pointer_details_with_stylus_data = - AmendStylusData(touch_frame->event.pointer_details().id); + auto pointer_details_with_stylus_data = AmendStylusData( + touch_frame->event->AsTouchEvent()->pointer_details().id); if (pointer_details_with_stylus_data) { - auto old_event = touch_frame->event; - touch_frame->event = TouchEvent( - old_event.type(), old_event.location_f(), old_event.root_location_f(), - old_event.time_stamp(), pointer_details_with_stylus_data.value(), - old_event.flags()); + auto old_event = std::move(touch_frame->event); + touch_frame->event = std::make_unique<TouchEvent>( + old_event->type(), old_event->AsTouchEvent()->location_f(), + old_event->AsTouchEvent()->root_location_f(), old_event->time_stamp(), + pointer_details_with_stylus_data.value(), old_event->flags()); } - SetTouchTargetAndDispatchTouchEvent(&(touch_frame->event)); + SetTouchTargetAndDispatchTouchEvent(touch_frame->event->AsTouchEvent()); if (!touch_frame->completion_cb.is_null()) std::move(touch_frame->completion_cb).Run(); }
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.h b/ui/ozone/platform/wayland/host/wayland_event_source.h index 50b85057..960c806 100644 --- a/ui/ozone/platform/wayland/host/wayland_event_source.h +++ b/ui/ozone/platform/wayland/host/wayland_event_source.h
@@ -184,8 +184,7 @@ // TODO(https://crrev.com/c/1298504): Unify |PointerFrame| and |TouchFrame| // and make them non-copyable/move-only. struct PointerFrame { - PointerFrame(const MouseEvent& event, - base::OnceCallback<void()> completion_cb); + PointerFrame(const Event& event, base::OnceCallback<void()> completion_cb); PointerFrame(const PointerFrame& other) = delete; PointerFrame(PointerFrame&&) = delete; ~PointerFrame(); @@ -195,13 +194,12 @@ }; struct TouchFrame { - TouchFrame(const TouchEvent& event, - base::OnceCallback<void()> completion_cb); + TouchFrame(const Event& event, base::OnceCallback<void()> completion_cb); TouchFrame(const TouchFrame& other) = delete; TouchFrame(TouchFrame&&) = delete; ~TouchFrame(); - TouchEvent event; + std::unique_ptr<Event> event; base::OnceCallback<void()> completion_cb; };
diff --git a/ui/views/accessibility/views_ax_tree_manager.cc b/ui/views/accessibility/views_ax_tree_manager.cc index 47d96ea3..8e3d657 100644 --- a/ui/views/accessibility/views_ax_tree_manager.cc +++ b/ui/views/accessibility/views_ax_tree_manager.cc
@@ -75,23 +75,12 @@ return ax_tree_->GetFromId(node_id); } -ui::AXTreeID ViewsAXTreeManager::GetTreeID() const { - return ax_tree_id_; -} - ui::AXTreeID ViewsAXTreeManager::GetParentTreeID() const { // TODO(nektar): Implement stiching of AXTrees, e.g. a dialog to the main // window. return ui::AXTreeIDUnknown(); } -ui::AXNode* ViewsAXTreeManager::GetRootAsAXNode() const { - if (!widget_ || !widget_->GetRootView() || !ax_tree_) - return nullptr; - - return ax_tree_->root(); -} - ui::AXNode* ViewsAXTreeManager::GetParentNodeFromParentTreeAsAXNode() const { // TODO(nektar): Implement stiching of AXTrees, e.g. a dialog to the main // window.
diff --git a/ui/views/accessibility/views_ax_tree_manager.h b/ui/views/accessibility/views_ax_tree_manager.h index 8c28fdb..651c013 100644 --- a/ui/views/accessibility/views_ax_tree_manager.h +++ b/ui/views/accessibility/views_ax_tree_manager.h
@@ -82,9 +82,7 @@ ui::AXNode* GetNodeFromTree(const ui::AXTreeID tree_id, const ui::AXNodeID node_id) const override; ui::AXNode* GetNodeFromTree(const ui::AXNodeID node_id) const override; - ui::AXTreeID GetTreeID() const override; ui::AXTreeID GetParentTreeID() const override; - ui::AXNode* GetRootAsAXNode() const override; ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override; // AXActionHandlerBase implementation.
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 7efde3e..a0a5dd7 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -1579,7 +1579,14 @@ void Textfield::ExtendSelectionAndDelete(size_t before, size_t after) { gfx::Range range = GetRenderText()->selection(); - DCHECK_GE(range.start(), before); + // Discard out-of-bound operations. + // TODO(crbug.com/1344096): this is a temporary fix to prevent the + // checked_cast failure in gfx::Range. There does not seem to be any + // observable bad behaviors before checked_cast was added. However, range + // clipping or dropping should be the last resort because a checkfail + // indicates that we run into bad states somewhere earlier on the stack. + if (range.start() < before) + return; range.set_start(range.start() - before); range.set_end(range.end() + after);
diff --git a/ui/views/style/typography.h b/ui/views/style/typography.h index 3a4e869..6bcae3e 100644 --- a/ui/views/style/typography.h +++ b/ui/views/style/typography.h
@@ -93,6 +93,14 @@ // Disabled "greyed out" text. STYLE_DISABLED, + // Used to draw attention to a section of body text such as an extension name + // or hostname. + STYLE_EMPHASIZED, + + // Emphasized secondary style. Like STYLE_EMPHASIZED but styled to match + // surrounding STYLE_SECONDARY text. + STYLE_EMPHASIZED_SECONDARY, + // The style used for links. Usually a solid shade of blue. STYLE_LINK,
diff --git a/ui/views/style/typography_provider.cc b/ui/views/style/typography_provider.cc index 492a090..9122bd2a 100644 --- a/ui/views/style/typography_provider.cc +++ b/ui/views/style/typography_provider.cc
@@ -95,6 +95,9 @@ ui::ResourceBundle::FontDetails TypographyProvider::GetFontDetails( int context, int style) const { + DCHECK(StyleAllowedForContext(context, style)) + << "context: " << context << " style: " << style; + ui::ResourceBundle::FontDetails details; switch (context) { @@ -126,6 +129,10 @@ .GetFontWeight()); } break; + case style::STYLE_EMPHASIZED: + case style::STYLE_EMPHASIZED_SECONDARY: + details.weight = gfx::Font::Weight::SEMIBOLD; + break; } return details; @@ -146,6 +153,13 @@ return GetFont(context, style).GetHeight(); } +bool TypographyProvider::StyleAllowedForContext(int context, int style) const { + // TODO(https://crbug.com/1352340): Limit emphasizing text to contexts where + // it's obviously correct. chrome_typography_provider.cc implements this + // correctly, but that does not cover uses outside of //chrome or //ash. + return true; +} + // static gfx::Font::Weight TypographyProvider::MediumWeightForUI() { #if BUILDFLAG(IS_MAC)
diff --git a/ui/views/style/typography_provider.h b/ui/views/style/typography_provider.h index 7cff3e1..f3ec44d 100644 --- a/ui/views/style/typography_provider.h +++ b/ui/views/style/typography_provider.h
@@ -44,6 +44,9 @@ // Gets the line spacing. By default this is the font height. virtual int GetLineHeight(int context, int style) const; + // Returns whether the given style can be used in the given context. + virtual bool StyleAllowedForContext(int context, int style) const; + // Returns the weight that will result in the ResourceBundle returning an // appropriate "medium" weight for UI. This caters for systems that are known // to be unable to provide a system font with weight other than NORMAL or BOLD
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 0a6e753..bcba5db 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -166,7 +166,6 @@ checked_in_dts_files = [ "cr_elements/cr_button/cr_button.m.d.ts", "cr_elements/cr_checkbox/cr_checkbox.d.ts", - "cr_elements/cr_container_shadow_behavior.m.d.ts", "cr_elements/cr_dialog/cr_dialog.d.ts", "cr_elements/cr_icon_button/cr_icon_button.d.ts", "cr_elements/cr_input/cr_input.m.d.ts", @@ -248,6 +247,7 @@ "cr_components/chromeos/smb_shares/smb_browser_proxy.d.ts", "cr_components/chromeos/traffic_counters/traffic_counters.d.ts", "cr_components/chromeos/traffic_counters/traffic_counters_adapter.d.ts", + "cr_elements/cr_container_shadow_behavior.m.d.ts", "js/cr/ui/grid.m.d.ts", "js/cr/ui/list.m.d.ts", "js/list_property_update_behavior.d.ts",
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_dialog.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_dialog.js index 9746a534..12b58a49 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_dialog.js +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_dialog.js
@@ -10,7 +10,6 @@ */ import '../../../cr_elements/cr_button/cr_button.m.js'; -import '../../../cr_elements/cr_dialog/cr_dialog.js'; import '../../../cr_elements/cr_input/cr_input.m.js'; import '../../../cr_elements/hidden_style_css.m.js'; import '../../../js/cr.m.js'; @@ -19,6 +18,7 @@ import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrDialogElement} from '../../../cr_elements/cr_dialog/cr_dialog.js'; import {assert} from '../../../js/assert.m.js'; import {I18nBehavior} from '../../../js/i18n_behavior.m.js';
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.ts b/ui/webui/resources/cr_components/history_clusters/clusters.ts index 6acf6ab6..ddcbdf8 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.ts +++ b/ui/webui/resources/cr_components/history_clusters/clusters.ts
@@ -238,16 +238,6 @@ } /** - * Called when the value of the search field changes. - */ - private onSearchChanged_(event: CustomEvent<string>) { - // Update the query based on the value of the search field, if necessary. - if (event.detail !== this.query) { - this.query = event.detail; - } - } - - /** * Called when the scrollable area has been scrolled nearly to the bottom. */ private onScrolledToBottom_() {
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn index b250e85c..0eaaf14 100644 --- a/ui/webui/resources/cr_elements/BUILD.gn +++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -132,7 +132,6 @@ "cr_actionable_row_style.m.js", "cr_button/cr_button.m.js", "cr_checkbox/cr_checkbox.js", - "cr_container_shadow_behavior.m.js", "cr_dialog/cr_dialog.js", "cr_icon_button/cr_icon_button.js", "cr_icons_css.m.js", @@ -157,7 +156,10 @@ ] if (is_chromeos_ash) { - in_files += [ "chromeos/cros_color_overrides.m.js" ] + in_files += [ + "chromeos/cros_color_overrides.m.js", + "cr_container_shadow_behavior.m.js", + ] } } } @@ -257,10 +259,11 @@ } js_modulizer("modulize") { - input_files = [ - "cr_container_shadow_behavior.js", - "cr_scrollable_behavior.js", - ] + input_files = [ "cr_scrollable_behavior.js" ] + + if (is_chromeos_ash) { + input_files += [ "cr_container_shadow_behavior.js" ] + } } } @@ -296,20 +299,22 @@ if (include_polymer) { js_type_check("cr_elements_module_resources") { is_polymer3 = true - deps = [ - ":cr_container_shadow_behavior.m", - ":cr_scrollable_behavior.m", - ] + deps = [ ":cr_scrollable_behavior.m" ] if (is_chromeos_ash) { - deps += [ ":find_shortcut_behavior" ] + deps += [ + ":cr_container_shadow_behavior.m", + ":find_shortcut_behavior", + ] } } - js_library("cr_container_shadow_behavior.m") { - sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.js" ] - deps = [ "//ui/webui/resources/js:assert.m" ] - extra_deps = [ ":modulize" ] + if (is_chromeos_ash) { + js_library("cr_container_shadow_behavior.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.js" ] + deps = [ "//ui/webui/resources/js:assert.m" ] + extra_deps = [ ":modulize" ] + } } js_library("cr_scrollable_behavior.m") {
diff --git a/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn b/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn index 6a2207b..5efc5d3 100644 --- a/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn +++ b/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn
@@ -16,7 +16,6 @@ js_library("cr_dialog") { deps = [ - "..:cr_container_shadow_behavior.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert.m", ]
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.d.ts b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.d.ts index 9c92c69..6f4938c3 100644 --- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.d.ts +++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.d.ts
@@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js'; -import {CrContainerShadowBehavior} from '../cr_container_shadow_behavior.m.js'; - -interface CrDialogElement extends CrContainerShadowBehavior, LegacyElementMixin, - HTMLElement { +interface CrDialogElement extends HTMLElement { open: boolean; closeText: string|null|undefined; ignorePopstate: boolean;
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js index c8f54b7..19c9097 100644 --- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js +++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
@@ -19,96 +19,119 @@ * width/height (as well as other available mixins to style other parts of the * dialog contents). */ -import {Polymer, html} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {assert} from '../../js/assert.m.js'; -import {CrContainerShadowBehavior} from '../cr_container_shadow_behavior.m.js'; import '../cr_icon_button/cr_icon_button.js'; import '../cr_icons_css.m.js'; import '../hidden_style_css.m.js'; import '../shared_vars_css.m.js'; -Polymer({ - is: 'cr-dialog', +import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - _template: html`{__html_template__}`, +import {assert} from '../../js/assert.m.js'; +import {CrContainerShadowMixin} from '../cr_container_shadow_mixin.js'; - behaviors: [CrContainerShadowBehavior], +class CrContainerShadowMixinInterface { + /** @param {boolean} enable */ + enableShadowBehavior(enable) {} - properties: { - open: { - type: Boolean, - value: false, - reflectToAttribute: true, - }, + showDropShadows() {} +} - /** - * Alt-text for the dialog close button. - */ - closeText: String, +/** + * @constructor + * @extends {PolymerElement} + * @implements {CrContainerShadowMixinInterface} + */ +const CrDialogElementBase = CrContainerShadowMixin(PolymerElement); - /** - * True if the dialog should remain open on 'popstate' events. This is used - * for navigable dialogs that have their separate navigation handling code. - */ - ignorePopstate: { - type: Boolean, - value: false, - }, +/** @polymer */ +export class CrDialogElement extends CrDialogElementBase { + static get is() { + return 'cr-dialog'; + } - /** - * True if the dialog should ignore 'Enter' keypresses. - */ - ignoreEnterKey: { - type: Boolean, - value: false, - }, + static get template() { + return html`{__html_template__}`; + } - /** - * True if the dialog should consume 'keydown' events. If ignoreEnterKey - * is true, 'Enter' key won't be consumed. - */ - consumeKeydownEvent: { - type: Boolean, - value: false, - }, + static get properties() { + return { + open: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, - /** - * True if the dialog should not be able to be cancelled, which will prevent - * 'Escape' key presses from closing the dialog. - */ - noCancel: { - type: Boolean, - value: false, - }, + /** + * Alt-text for the dialog close button. + */ + closeText: String, - // True if dialog should show the 'X' close button. - showCloseButton: { - type: Boolean, - value: false, - }, + /** + * True if the dialog should remain open on 'popstate' events. This is + * used for navigable dialogs that have their separate navigation handling + * code. + */ + ignorePopstate: { + type: Boolean, + value: false, + }, - showOnAttach: { - type: Boolean, - value: false, - }, - }, + /** + * True if the dialog should ignore 'Enter' keypresses. + */ + ignoreEnterKey: { + type: Boolean, + value: false, + }, - listeners: { - 'pointerdown': 'onPointerdown_', - }, + /** + * True if the dialog should consume 'keydown' events. If ignoreEnterKey + * is true, 'Enter' key won't be consumed. + */ + consumeKeydownEvent: { + type: Boolean, + value: false, + }, - /** @private {?IntersectionObserver} */ - intersectionObserver_: null, + /** + * True if the dialog should not be able to be cancelled, which will + * prevent 'Escape' key presses from closing the dialog. + */ + noCancel: { + type: Boolean, + value: false, + }, - /** @private {?MutationObserver} */ - mutationObserver_: null, + // True if dialog should show the 'X' close button. + showCloseButton: { + type: Boolean, + value: false, + }, - /** @private {?Function} */ - boundKeydown_: null, + showOnAttach: { + type: Boolean, + value: false, + }, + }; + } + + constructor() { + super(); + + /** @private {?IntersectionObserver} */ + this.intersectionObserver_ = null; + + /** @private {?MutationObserver} */ + this.mutationObserver_ = null; + + /** @private {?Function} */ + this.boundKeydown_ = null; + } /** @override */ ready() { + super.ready(); + // If the active history entry changes (i.e. user clicks back button), // all open dialogs should be cancelled. window.addEventListener('popstate', function() { @@ -120,10 +143,14 @@ if (!this.ignoreEnterKey) { this.addEventListener('keypress', this.onKeypress_.bind(this)); } - }, + this.addEventListener( + 'pointerdown', + e => this.onPointerdown_(/** @type {!PointerEvent} */ (e))); + } /** @override */ - attached() { + connectedCallback() { + super.connectedCallback(); const mutationObserverCallback = function() { if (this.$.dialog.open) { this.enableShadowBehavior(true); @@ -146,16 +173,17 @@ if (this.showOnAttach) { this.showModal(); } - }, + } /** @override */ - detached() { + disconnectedCallback() { + super.disconnectedCallback(); this.removeKeydownListener_(); if (this.mutationObserver_) { this.mutationObserver_.disconnect(); this.mutationObserver_ = null; } - }, + } /** @private */ addKeydownListener_() { @@ -171,7 +199,7 @@ // will bypass cr-dialog. We should consume those events too in order to // behave modally. This prevents accidentally triggering keyboard commands. document.body.addEventListener('keydown', this.boundKeydown_); - }, + } /** @private */ removeKeydownListener_() { @@ -182,27 +210,29 @@ this.removeEventListener('keydown', this.boundKeydown_); document.body.removeEventListener('keydown', this.boundKeydown_); this.boundKeydown_ = null; - }, + } showModal() { this.$.dialog.showModal(); assert(this.$.dialog.open); this.open = true; - this.fire('cr-dialog-open'); - }, + this.dispatchEvent( + new CustomEvent('cr-dialog-open', {bubbles: true, composed: true})); + } cancel() { - this.fire('cancel'); + this.dispatchEvent( + new CustomEvent('cancel', {bubbles: true, composed: true})); this.$.dialog.close(); assert(!this.$.dialog.open); this.open = false; - }, + } close() { this.$.dialog.close('success'); assert(!this.$.dialog.open); this.open = false; - }, + } /** * Set the title of the dialog for a11y reader. @@ -211,7 +241,7 @@ setTitleAriaLabel(title) { this.$.dialog.removeAttribute('aria-labelledby'); this.$.dialog.setAttribute('aria-label', title); - }, + } /** * @private @@ -221,7 +251,7 @@ // Because the dialog may have a default Enter key handler, prevent // keypress events from bubbling up from this element. e.stopPropagation(); - }, + } /** * @param {!Event} e @@ -235,8 +265,9 @@ // Catch and re-fire the 'close' event such that it bubbles across Shadow // DOM v1. - this.fire('close'); - }, + this.dispatchEvent( + new CustomEvent('close', {bubbles: true, composed: true})); + } /** * @param {!Event} e @@ -259,8 +290,9 @@ // Catch and re-fire the native 'cancel' event such that it bubbles across // Shadow DOM v1. - this.fire('cancel'); - }, + this.dispatchEvent( + new CustomEvent('cancel', {bubbles: true, composed: true})); + } /** * Expose the inner native <dialog> for some rare cases where it needs to be @@ -270,7 +302,7 @@ */ getNative() { return /** @type {!HTMLDialogElement} */ (this.$.dialog); - }, + } /** * @param {!Event} e @@ -298,7 +330,7 @@ actionButton.click(); e.preventDefault(); } - }, + } /** * @param {!Event} e @@ -317,7 +349,7 @@ // Stop propagation to behave modally. e.stopPropagation(); - }, + } /** @param {!PointerEvent} e */ onPointerdown_(e) { @@ -343,9 +375,11 @@ // Prevent any text from being selected within the dialog when clicking in // the backdrop area. e.preventDefault(); - }, + } focus() { - this.$$('.title-container').focus(); - }, -}); + this.shadowRoot.querySelector('.title-container').focus(); + } +} + +customElements.define(CrDialogElement.is, CrDialogElement);